diff --git a/kernel/drivers/module-bbswitch/pspec.xml b/kernel/drivers/module-bbswitch/pspec.xml
index 922cfc8d..d6bf5948 100644
--- a/kernel/drivers/module-bbswitch/pspec.xml
+++ b/kernel/drivers/module-bbswitch/pspec.xml
@@ -11,7 +11,7 @@
Kernel module allowing to switch dedicated graphics card on Optimus laptops
kernel module allowing to switch dedicated graphics card on Optimus laptops
- kernel-module-headers
+ kernel-module-headers
https://github.com/Bumblebee-Project/bbswitch/archive/v0.8.tar.gz
@@ -20,7 +20,7 @@
module-bbswitch
- kernel
+ kernel
/lib/modules
@@ -34,6 +34,13 @@
+
+ 2015-09-23
+ 0.8
+ Rebuild for kernel-4.1.8.
+ Ertuğrul Erata
+ ertugrulerata@gmail.com
+
2015-09-18
0.8
diff --git a/kernel/drivers/module-broadcom-wl/pspec.xml b/kernel/drivers/module-broadcom-wl/pspec.xml
index 06dc2432..85888a5a 100644
--- a/kernel/drivers/module-broadcom-wl/pspec.xml
+++ b/kernel/drivers/module-broadcom-wl/pspec.xml
@@ -15,7 +15,7 @@
http://www.broadcom.com/docs/linux_sta/hybrid-v35-nodebug-pcoem-6_30_223_248.tar.gz
http://www.broadcom.com/docs/linux_sta/hybrid-v35_64-nodebug-pcoem-6_30_223_248.tar.gz
- kernel-module-headers
+ kernel-module-headers
patch/linux-40.patch
@@ -30,7 +30,7 @@
module-broadcom-wl
- kernel
+ kernel
module-broadcom-wl-userspace
@@ -62,6 +62,13 @@
+
+ 2015-09-23
+ 6.30.223.248
+ Rebuild for kernel 4.1.8.
+ Ertuğrul Erata
+ ertugrulerata@gmail.com
+
2015-09-18
6.30.223.248
diff --git a/kernel/drivers/module-virtualbox-guest/pspec.xml b/kernel/drivers/module-virtualbox-guest/pspec.xml
index 734a0576..21fb6d31 100644
--- a/kernel/drivers/module-virtualbox-guest/pspec.xml
+++ b/kernel/drivers/module-virtualbox-guest/pspec.xml
@@ -14,14 +14,14 @@
This package provides the kernel modules needed for mouse integration and shared folder support between VirtualBox host and guest systems.
http://source.pisilinux.org/1.0/module-virtualbox-guest-4.3.28.tar.xz
- kernel-module-headers
+ kernel-module-headers
module-virtualbox-guest
- kernel
+ kernel
baselayout
module-virtualbox-guest-userspace
@@ -52,7 +52,14 @@
-
+
+ 2015-08-23
+ 4.3.28
+ Rebuild for kernel-4.1.8.
+ Ertuğrul Erata
+ ertugrulerata@gmail.com
+
+
2015-08-18
4.3.28
Rebuild for kernel-4.1.7.
diff --git a/kernel/drivers/module-virtualbox/pspec.xml b/kernel/drivers/module-virtualbox/pspec.xml
index 5b0de905..bf9bdafe 100644
--- a/kernel/drivers/module-virtualbox/pspec.xml
+++ b/kernel/drivers/module-virtualbox/pspec.xml
@@ -14,14 +14,14 @@
This package provides the kernel support for VirtualBox.
http://source.pisilinux.org/1.0/module-virtualbox-4.3.28.tar.xz
- kernel-module-headers
+ kernel-module-headers
module-virtualbox
- kernel
+ kernel
module-virtualbox-userspace
@@ -47,6 +47,13 @@
+
+ 2015-09-23
+ 4.3.28
+ Rebuild for kernel-4.1.8.
+ Ertuğrul Erata
+ ertugrulerata@gmail.com
+
2015-09-18
4.3.28
diff --git a/kernel/drivers/ndiswrapper/pspec.xml b/kernel/drivers/ndiswrapper/pspec.xml
index 52c2a0ee..ce9dd73c 100644
--- a/kernel/drivers/ndiswrapper/pspec.xml
+++ b/kernel/drivers/ndiswrapper/pspec.xml
@@ -15,7 +15,7 @@
module-ndiswrapper allows you to use Windows XP drivers for WLAN cards without proper Linux drivers.
http://download.sourceforge.net/ndiswrapper/ndiswrapper-1.59.tar.gz
- kernel-module-headers
+ kernel-module-headers
support_kernel-4.0.patch
@@ -28,7 +28,7 @@
ndiswrapper
- kernel
+ kernel
/lib/modules
@@ -44,7 +44,14 @@
-
+
+ 2014-09-23
+ 1.59
+ Rebuild for kernel-4.1.8.
+ PisiLinux Community
+ admins@pisilinux.org
+
+
2014-08-18
1.59
Rebuild for kernel-4.1.6.
diff --git a/kernel/kernel/files/configs/kernel-x86_64-config b/kernel/kernel/files/configs/kernel-x86_64-config
index 39d4fc93..e5d999ba 100644
--- a/kernel/kernel/files/configs/kernel-x86_64-config
+++ b/kernel/kernel/files/configs/kernel-x86_64-config
@@ -1,6 +1,6 @@
#
# Automatically generated file; DO NOT EDIT.
-# Linux/x86_64 4.1.7 Kernel Configuration
+# Linux/x86_64 4.1.8 Kernel Configuration
#
CONFIG_64BIT=y
CONFIG_X86_64=y
diff --git a/kernel/kernel/files/patches/linux/patch-4.1.8.xz b/kernel/kernel/files/patches/linux/patch-4.1.8.xz
new file mode 100644
index 00000000..c2d46113
Binary files /dev/null and b/kernel/kernel/files/patches/linux/patch-4.1.8.xz differ
diff --git a/kernel/kernel/files/patches/mageia.old/3rd-3rdparty-1.0-tree.patch b/kernel/kernel/files/patches/mageia.old/3rd-3rdparty-1.0-tree.patch
new file mode 100644
index 00000000..233389b4
--- /dev/null
+++ b/kernel/kernel/files/patches/mageia.old/3rd-3rdparty-1.0-tree.patch
@@ -0,0 +1,181 @@
+
+ 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/kernel/files/patches/mageia.old/3rd-3rdparty-merge.patch b/kernel/kernel/files/patches/mageia.old/3rd-3rdparty-merge.patch
new file mode 100644
index 00000000..8c1f8421
--- /dev/null
+++ b/kernel/kernel/files/patches/mageia.old/3rd-3rdparty-merge.patch
@@ -0,0 +1,181 @@
+
+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 | 31 +++++++++++++++++--------------
+ 8 files changed, 29 insertions(+), 15 deletions(-)
+
+diff -Nurp linux-4.1/arch/alpha/Kconfig linux-4.1-3rd/arch/alpha/Kconfig
+--- linux-4.1/arch/alpha/Kconfig 2015-06-22 07:05:43.000000000 +0200
++++ linux-4.1-3rd/arch/alpha/Kconfig 2015-06-25 20:44:03.221647317 +0200
+@@ -750,3 +750,4 @@ source "crypto/Kconfig"
+
+ source "lib/Kconfig"
+
++source "3rdparty/Kconfig"
+diff -Nurp linux-4.1/arch/ia64/Kconfig linux-4.1-3rd/arch/ia64/Kconfig
+--- linux-4.1/arch/ia64/Kconfig 2015-06-22 07:05:43.000000000 +0200
++++ linux-4.1-3rd/arch/ia64/Kconfig 2015-06-25 20:44:03.231647227 +0200
+@@ -636,3 +636,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.1/arch/mips/Kconfig linux-4.1-3rd/arch/mips/Kconfig
+--- linux-4.1/arch/mips/Kconfig 2015-06-22 07:05:43.000000000 +0200
++++ linux-4.1-3rd/arch/mips/Kconfig 2015-06-25 20:44:03.231647227 +0200
+@@ -2893,3 +2893,5 @@ source "crypto/Kconfig"
+ source "lib/Kconfig"
+
+ source "arch/mips/kvm/Kconfig"
++
++source "3rdparty/Kconfig"
+diff -Nurp linux-4.1/arch/powerpc/Kconfig linux-4.1-3rd/arch/powerpc/Kconfig
+--- linux-4.1/arch/powerpc/Kconfig 2015-06-22 07:05:43.000000000 +0200
++++ linux-4.1-3rd/arch/powerpc/Kconfig 2015-06-25 20:44:03.231647227 +0200
+@@ -1090,3 +1090,5 @@ config PPC_LIB_RHEAP
+ bool
+
+ source "arch/powerpc/kvm/Kconfig"
++
++source "3rdparty/Kconfig"
+diff -Nurp linux-4.1/arch/sparc/Kconfig linux-4.1-3rd/arch/sparc/Kconfig
+--- linux-4.1/arch/sparc/Kconfig 2015-06-22 07:05:43.000000000 +0200
++++ linux-4.1-3rd/arch/sparc/Kconfig 2015-06-25 20:44:03.231647227 +0200
+@@ -569,3 +569,5 @@ source "security/Kconfig"
+ source "crypto/Kconfig"
+
+ source "lib/Kconfig"
++
++source "3rdparty/Kconfig"
+diff -Nurp linux-4.1/arch/x86/Kconfig linux-4.1-3rd/arch/x86/Kconfig
+--- linux-4.1/arch/x86/Kconfig 2015-06-22 07:05:43.000000000 +0200
++++ linux-4.1-3rd/arch/x86/Kconfig 2015-06-25 20:44:03.231647227 +0200
+@@ -2594,3 +2594,5 @@ source "crypto/Kconfig"
+ source "arch/x86/kvm/Kconfig"
+
+ source "lib/Kconfig"
++
++source "3rdparty/Kconfig"
+diff -Nurp linux-4.1/Makefile linux-4.1-3rd/Makefile
+--- linux-4.1/Makefile 2015-06-22 07:05:43.000000000 +0200
++++ linux-4.1-3rd/Makefile 2015-06-25 20:44:03.231647227 +0200
+@@ -556,7 +556,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.1/scripts/kconfig/Makefile linux-4.1-3rd/scripts/kconfig/Makefile
+--- linux-4.1/scripts/kconfig/Makefile 2015-06-22 07:05:43.000000000 +0200
++++ linux-4.1-3rd/scripts/kconfig/Makefile 2015-06-25 20:47:50.109596717 +0200
+@@ -18,26 +18,26 @@ 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
+ $< $(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 \
+@@ -80,7 +80,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
+@@ -88,12 +88,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
+@@ -101,7 +101,7 @@ else
+ $(Q)$< $(silent) --defconfig=arch/$(SRCARCH)/configs/$(KBUILD_DEFCONFIG) $(Kconfig)
+ 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/$@)
+@@ -112,12 +112,12 @@ configfiles=$(wildcard $(srctree)/kernel
+ +$(Q)yes "" | $(MAKE) -f $(srctree)/Makefile oldconfig
+
+ PHONY += kvmconfig
+-kvmconfig: kvm_guest.config
++kvmconfig: kvm_guest.config 3rdparty/Makefile
+ @:
+
+ PHONY += tinyconfig
+ tinyconfig:
+- $(Q)$(MAKE) -f $(srctree)/Makefile allnoconfig tiny.config
++ $(Q)$(MAKE) -f $(srctree)/Makefile allnoconfig tiny.config 3rdparty/Makefile
+
+ # Help text used by make help
+ help:
+@@ -176,6 +176,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/kernel/files/patches/mageia.old/3rd-acerhk-0.5.35.patch b/kernel/kernel/files/patches/mageia.old/3rd-acerhk-0.5.35.patch
new file mode 100644
index 00000000..5d61570f
--- /dev/null
+++ b/kernel/kernel/files/patches/mageia.old/3rd-acerhk-0.5.35.patch
@@ -0,0 +1,4212 @@
+ 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/kernel/files/patches/mageia.old/3rd-acerhk-2.6.36-buildfix.patch b/kernel/kernel/files/patches/mageia.old/3rd-acerhk-2.6.36-buildfix.patch
new file mode 100644
index 00000000..47a71053
--- /dev/null
+++ b/kernel/kernel/files/patches/mageia.old/3rd-acerhk-2.6.36-buildfix.patch
@@ -0,0 +1,20 @@
+--- 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/kernel/files/patches/mageia.old/3rd-acerhk-extra-cflags.patch b/kernel/kernel/files/patches/mageia.old/3rd-acerhk-extra-cflags.patch
new file mode 100644
index 00000000..7971c699
--- /dev/null
+++ b/kernel/kernel/files/patches/mageia.old/3rd-acerhk-extra-cflags.patch
@@ -0,0 +1,33 @@
+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/kernel/files/patches/mageia.old/3rd-acerhk-fix-build-with-function-tracer.patch b/kernel/kernel/files/patches/mageia.old/3rd-acerhk-fix-build-with-function-tracer.patch
new file mode 100644
index 00000000..c8d000b5
--- /dev/null
+++ b/kernel/kernel/files/patches/mageia.old/3rd-acerhk-fix-build-with-function-tracer.patch
@@ -0,0 +1,22 @@
+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/kernel/files/patches/mageia.old/3rd-acerhk-fix-include.patch b/kernel/kernel/files/patches/mageia.old/3rd-acerhk-fix-include.patch
new file mode 100644
index 00000000..cba26984
--- /dev/null
+++ b/kernel/kernel/files/patches/mageia.old/3rd-acerhk-fix-include.patch
@@ -0,0 +1,23 @@
+
+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/kernel/files/patches/mageia.old/3rd-acerhk-kbuild.patch b/kernel/kernel/files/patches/mageia.old/3rd-acerhk-kbuild.patch
new file mode 100644
index 00000000..f0c419ad
--- /dev/null
+++ b/kernel/kernel/files/patches/mageia.old/3rd-acerhk-kbuild.patch
@@ -0,0 +1,37 @@
+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/kernel/files/patches/mageia.old/3rd-acerhk-proc_dir_entry-owner.patch b/kernel/kernel/files/patches/mageia.old/3rd-acerhk-proc_dir_entry-owner.patch
new file mode 100644
index 00000000..e5821d46
--- /dev/null
+++ b/kernel/kernel/files/patches/mageia.old/3rd-acerhk-proc_dir_entry-owner.patch
@@ -0,0 +1,67 @@
+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/kernel/files/patches/mageia.old/3rd-aes2501-kbuild.patch b/kernel/kernel/files/patches/mageia.old/3rd-aes2501-kbuild.patch
new file mode 100644
index 00000000..1dcf8fa0
--- /dev/null
+++ b/kernel/kernel/files/patches/mageia.old/3rd-aes2501-kbuild.patch
@@ -0,0 +1,47 @@
+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/kernel/files/patches/mageia.old/3rd-aes2501-r19.patch b/kernel/kernel/files/patches/mageia.old/3rd-aes2501-r19.patch
new file mode 100644
index 00000000..a5f95e79
--- /dev/null
+++ b/kernel/kernel/files/patches/mageia.old/3rd-aes2501-r19.patch
@@ -0,0 +1,2356 @@
+ 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/kernel/files/patches/mageia.old/3rd-aes2501-rmmod-oops-fix.patch b/kernel/kernel/files/patches/mageia.old/3rd-aes2501-rmmod-oops-fix.patch
new file mode 100644
index 00000000..f11cc2e5
--- /dev/null
+++ b/kernel/kernel/files/patches/mageia.old/3rd-aes2501-rmmod-oops-fix.patch
@@ -0,0 +1,21 @@
+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/kernel/files/patches/mageia.old/3rd-ndiswrapper-1.59.patch b/kernel/kernel/files/patches/mageia.old/3rd-ndiswrapper-1.59.patch
new file mode 100644
index 00000000..63ccc093
--- /dev/null
+++ b/kernel/kernel/files/patches/mageia.old/3rd-ndiswrapper-1.59.patch
@@ -0,0 +1,26399 @@
+diff -Nurp linux-3.12.2/3rdparty/ndiswrapper/crt.c linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/crt.c
+--- linux-3.12.2/3rdparty/ndiswrapper/crt.c 1970-01-01 02:00:00.000000000 +0200
++++ linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/crt.c 2013-11-28 21:42:10.000000000 +0200
+@@ -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)
++{
++ net_srandom(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-3.12.2/3rdparty/ndiswrapper/divdi3.c linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/divdi3.c
+--- linux-3.12.2/3rdparty/ndiswrapper/divdi3.c 1970-01-01 02:00:00.000000000 +0200
++++ linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/divdi3.c 2013-11-28 21:42:10.000000000 +0200
+@@ -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-3.12.2/3rdparty/ndiswrapper/hal.c linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/hal.c
+--- linux-3.12.2/3rdparty/ndiswrapper/hal.c 1970-01-01 02:00:00.000000000 +0200
++++ linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/hal.c 2013-11-28 21:42:10.000000000 +0200
+@@ -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-3.12.2/3rdparty/ndiswrapper/iw_ndis.c linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/iw_ndis.c
+--- linux-3.12.2/3rdparty/ndiswrapper/iw_ndis.c 1970-01-01 02:00:00.000000000 +0200
++++ linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/iw_ndis.c 2013-11-28 21:42:10.000000000 +0200
+@@ -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-3.12.2/3rdparty/ndiswrapper/iw_ndis.h linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/iw_ndis.h
+--- linux-3.12.2/3rdparty/ndiswrapper/iw_ndis.h 1970-01-01 02:00:00.000000000 +0200
++++ linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/iw_ndis.h 2013-11-28 21:42:10.000000000 +0200
+@@ -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-3.12.2/3rdparty/ndiswrapper/lin2win.h linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/lin2win.h
+--- linux-3.12.2/3rdparty/ndiswrapper/lin2win.h 1970-01-01 02:00:00.000000000 +0200
++++ linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/lin2win.h 2013-11-28 21:42:10.000000000 +0200
+@@ -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-3.12.2/3rdparty/ndiswrapper/lin2win.S linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/lin2win.S
+--- linux-3.12.2/3rdparty/ndiswrapper/lin2win.S 1970-01-01 02:00:00.000000000 +0200
++++ linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/lin2win.S 2013-11-28 21:42:10.000000000 +0200
+@@ -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-3.12.2/3rdparty/ndiswrapper/loader.c linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/loader.c
+--- linux-3.12.2/3rdparty/ndiswrapper/loader.c 1970-01-01 02:00:00.000000000 +0200
++++ linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/loader.c 2013-11-28 21:42:10.000000000 +0200
+@@ -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-3.12.2/3rdparty/ndiswrapper/loader.h linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/loader.h
+--- linux-3.12.2/3rdparty/ndiswrapper/loader.h 1970-01-01 02:00:00.000000000 +0200
++++ linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/loader.h 2013-11-28 21:42:10.000000000 +0200
+@@ -0,0 +1,108 @@
++/*
++ * 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_
++
++#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-3.12.2/3rdparty/ndiswrapper/longlong.h linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/longlong.h
+--- linux-3.12.2/3rdparty/ndiswrapper/longlong.h 1970-01-01 02:00:00.000000000 +0200
++++ linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/longlong.h 2013-11-28 21:42:10.000000000 +0200
+@@ -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-3.12.2/3rdparty/ndiswrapper/Makefile linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/Makefile
+--- linux-3.12.2/3rdparty/ndiswrapper/Makefile 1970-01-01 02:00:00.000000000 +0200
++++ linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/Makefile 2013-11-28 21:42:10.000000000 +0200
+@@ -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-3.12.2/3rdparty/ndiswrapper/mkexport.sh linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/mkexport.sh
+--- linux-3.12.2/3rdparty/ndiswrapper/mkexport.sh 1970-01-01 02:00:00.000000000 +0200
++++ linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/mkexport.sh 2013-11-28 21:42:11.000000000 +0200
+@@ -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-3.12.2/3rdparty/ndiswrapper/mkstubs.sh linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/mkstubs.sh
+--- linux-3.12.2/3rdparty/ndiswrapper/mkstubs.sh 1970-01-01 02:00:00.000000000 +0200
++++ linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/mkstubs.sh 2013-11-28 21:42:11.000000000 +0200
+@@ -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-3.12.2/3rdparty/ndiswrapper/ndis.c linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/ndis.c
+--- linux-3.12.2/3rdparty/ndiswrapper/ndis.c 1970-01-01 02:00:00.000000000 +0200
++++ linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/ndis.c 2013-11-28 21:42:11.000000000 +0200
+@@ -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 (strnicmp(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 (strnicmp(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-3.12.2/3rdparty/ndiswrapper/ndis.h linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/ndis.h
+--- linux-3.12.2/3rdparty/ndiswrapper/ndis.h 1970-01-01 02:00:00.000000000 +0200
++++ linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/ndis.h 2013-11-28 21:42:11.000000000 +0200
+@@ -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-3.12.2/3rdparty/ndiswrapper/ndiswrapper.h linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/ndiswrapper.h
+--- linux-3.12.2/3rdparty/ndiswrapper/ndiswrapper.h 1970-01-01 02:00:00.000000000 +0200
++++ linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/ndiswrapper.h 2013-11-28 21:42:11.000000000 +0200
+@@ -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.59"
++#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-3.12.2/3rdparty/ndiswrapper/ntoskernel.c linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/ntoskernel.c
+--- linux-3.12.2/3rdparty/ndiswrapper/ntoskernel.c 1970-01-01 02:00:00.000000000 +0200
++++ linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/ntoskernel.c 2013-11-28 21:42:11.000000000 +0200
+@@ -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-3.12.2/3rdparty/ndiswrapper/ntoskernel.h linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/ntoskernel.h
+--- linux-3.12.2/3rdparty/ndiswrapper/ntoskernel.h 1970-01-01 02:00:00.000000000 +0200
++++ linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/ntoskernel.h 2013-11-28 21:42:11.000000000 +0200
+@@ -0,0 +1,1083 @@
++/*
++ * 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
++
++#ifdef INIT_COMPLETION
++static inline void reinit_completion(struct completion *x)
++{
++ INIT_COMPLETION(*x);
++}
++#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_no_resched(); \
++ local_irq_restore(flags); \
++ preempt_check_resched(); \
++} 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-3.12.2/3rdparty/ndiswrapper/ntoskernel_io.c linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/ntoskernel_io.c
+--- linux-3.12.2/3rdparty/ndiswrapper/ntoskernel_io.c 1970-01-01 02:00:00.000000000 +0200
++++ linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/ntoskernel_io.c 2013-11-28 21:42:11.000000000 +0200
+@@ -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-3.12.2/3rdparty/ndiswrapper/pe_linker.c linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/pe_linker.c
+--- linux-3.12.2/3rdparty/ndiswrapper/pe_linker.c 1970-01-01 02:00:00.000000000 +0200
++++ linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/pe_linker.c 2013-11-28 21:42:11.000000000 +0200
+@@ -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-3.12.2/3rdparty/ndiswrapper/pe_linker.h linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/pe_linker.h
+--- linux-3.12.2/3rdparty/ndiswrapper/pe_linker.h 1970-01-01 02:00:00.000000000 +0200
++++ linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/pe_linker.h 2013-11-28 21:42:11.000000000 +0200
+@@ -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-3.12.2/3rdparty/ndiswrapper/pnp.c linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/pnp.c
+--- linux-3.12.2/3rdparty/ndiswrapper/pnp.c 1970-01-01 02:00:00.000000000 +0200
++++ linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/pnp.c 2013-11-28 21:42:11.000000000 +0200
+@@ -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-3.12.2/3rdparty/ndiswrapper/pnp.h linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/pnp.h
+--- linux-3.12.2/3rdparty/ndiswrapper/pnp.h 1970-01-01 02:00:00.000000000 +0200
++++ linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/pnp.h 2013-11-28 21:42:11.000000000 +0200
+@@ -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-3.12.2/3rdparty/ndiswrapper/proc.c linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/proc.c
+--- linux-3.12.2/3rdparty/ndiswrapper/proc.c 1970-01-01 02:00:00.000000000 +0200
++++ linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/proc.c 2013-11-28 21:42:11.000000000 +0200
+@@ -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-3.12.2/3rdparty/ndiswrapper/rtl.c linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/rtl.c
+--- linux-3.12.2/3rdparty/ndiswrapper/rtl.c 1970-01-01 02:00:00.000000000 +0200
++++ linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/rtl.c 2013-11-28 21:42:11.000000000 +0200
+@@ -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-3.12.2/3rdparty/ndiswrapper/usb.c linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/usb.c
+--- linux-3.12.2/3rdparty/ndiswrapper/usb.c 1970-01-01 02:00:00.000000000 +0200
++++ linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/usb.c 2013-11-28 21:42:11.000000000 +0200
+@@ -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-3.12.2/3rdparty/ndiswrapper/usb.h linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/usb.h
+--- linux-3.12.2/3rdparty/ndiswrapper/usb.h 1970-01-01 02:00:00.000000000 +0200
++++ linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/usb.h 2013-11-28 21:42:11.000000000 +0200
+@@ -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-3.12.2/3rdparty/ndiswrapper/win2lin_stubs.S linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/win2lin_stubs.S
+--- linux-3.12.2/3rdparty/ndiswrapper/win2lin_stubs.S 1970-01-01 02:00:00.000000000 +0200
++++ linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/win2lin_stubs.S 2013-11-28 21:42:11.000000000 +0200
+@@ -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-3.12.2/3rdparty/ndiswrapper/winnt_types.h linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/winnt_types.h
+--- linux-3.12.2/3rdparty/ndiswrapper/winnt_types.h 1970-01-01 02:00:00.000000000 +0200
++++ linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/winnt_types.h 2013-11-28 21:42:11.000000000 +0200
+@@ -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-3.12.2/3rdparty/ndiswrapper/workqueue.c linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/workqueue.c
+--- linux-3.12.2/3rdparty/ndiswrapper/workqueue.c 1970-01-01 02:00:00.000000000 +0200
++++ linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/workqueue.c 2013-11-28 21:42:11.000000000 +0200
+@@ -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-3.12.2/3rdparty/ndiswrapper/wrapmem.c linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/wrapmem.c
+--- linux-3.12.2/3rdparty/ndiswrapper/wrapmem.c 1970-01-01 02:00:00.000000000 +0200
++++ linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/wrapmem.c 2013-11-28 21:42:11.000000000 +0200
+@@ -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-3.12.2/3rdparty/ndiswrapper/wrapmem.h linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/wrapmem.h
+--- linux-3.12.2/3rdparty/ndiswrapper/wrapmem.h 1970-01-01 02:00:00.000000000 +0200
++++ linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/wrapmem.h 2013-11-28 21:42:11.000000000 +0200
+@@ -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-3.12.2/3rdparty/ndiswrapper/wrapndis.c linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/wrapndis.c
+--- linux-3.12.2/3rdparty/ndiswrapper/wrapndis.c 1970-01-01 02:00:00.000000000 +0200
++++ linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/wrapndis.c 2013-11-28 21:42:11.000000000 +0200
+@@ -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-3.12.2/3rdparty/ndiswrapper/wrapndis.h linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/wrapndis.h
+--- linux-3.12.2/3rdparty/ndiswrapper/wrapndis.h 1970-01-01 02:00:00.000000000 +0200
++++ linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/wrapndis.h 2013-11-28 21:42:11.000000000 +0200
+@@ -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-3.12.2/3rdparty/ndiswrapper/wrapper.c linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/wrapper.c
+--- linux-3.12.2/3rdparty/ndiswrapper/wrapper.c 1970-01-01 02:00:00.000000000 +0200
++++ linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/wrapper.c 2013-11-28 21:42:11.000000000 +0200
+@@ -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-3.12.2/3rdparty/ndiswrapper/wrapper.h linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/wrapper.h
+--- linux-3.12.2/3rdparty/ndiswrapper/wrapper.h 1970-01-01 02:00:00.000000000 +0200
++++ linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/wrapper.h 2013-11-28 21:42:11.000000000 +0200
+@@ -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/kernel/files/patches/mageia.old/3rd-ndiswrapper-4.0-buildfix.patch b/kernel/kernel/files/patches/mageia.old/3rd-ndiswrapper-4.0-buildfix.patch
new file mode 100644
index 00000000..52f39680
--- /dev/null
+++ b/kernel/kernel/files/patches/mageia.old/3rd-ndiswrapper-4.0-buildfix.patch
@@ -0,0 +1,32 @@
+
+Adapt for strnicmp has been replaced by strncasecmp,
+and removed upstream in v4.0-rc1~98:
+
+From af3cd13501eb04ca61d017ff4406f1cbffafdc04 Mon Sep 17 00:00:00 2001
+From: Rasmus Villemoes
+Date: Thu, 12 Feb 2015 15:02:15 -0800
+Subject: lib/string.c: remove strnicmp()
+
+
+Signed-off-by: Thomas Backlund
+
+--- linux/3rdparty/ndiswrapper/ndis.c.orig
++++ linux/3rdparty/ndiswrapper/ndis.c
+@@ -438,7 +438,7 @@ static int read_setting(struct nt_list *
+ struct wrap_device_setting *setting;
+ mutex_lock(&loader_mutex);
+ nt_list_for_each_entry(setting, setting_list, list) {
+- if (strnicmp(keyname, setting->name, length) == 0) {
++ if (strncasecmp(keyname, setting->name, length) == 0) {
+ TRACE2("setting %s='%s'", keyname, setting->value);
+ mutex_unlock(&loader_mutex);
+ *param = ndis_encode_setting(setting, type);
+@@ -502,7 +502,7 @@ wstdcall void WIN_FUNC(NdisWriteConfigur
+
+ mutex_lock(&loader_mutex);
+ nt_list_for_each_entry(setting, &nmb->wnd->wd->settings, list) {
+- if (strnicmp(keyname, setting->name, ansi.length) == 0) {
++ if (strncasecmp(keyname, setting->name, ansi.length) == 0) {
+ mutex_unlock(&loader_mutex);
+ if (ndis_decode_setting(setting, param))
+ *status = NDIS_STATUS_FAILURE;
diff --git a/kernel/kernel/files/patches/mageia.old/3rd-ndiswrapper-Kconfig.patch b/kernel/kernel/files/patches/mageia.old/3rd-ndiswrapper-Kconfig.patch
new file mode 100644
index 00000000..f7d26e62
--- /dev/null
+++ b/kernel/kernel/files/patches/mageia.old/3rd-ndiswrapper-Kconfig.patch
@@ -0,0 +1,7 @@
+--- 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/kernel/files/patches/mageia.old/3rd-ndiswrapper-Makefile-build-fix.patch b/kernel/kernel/files/patches/mageia.old/3rd-ndiswrapper-Makefile-build-fix.patch
new file mode 100644
index 00000000..b44f4b29
--- /dev/null
+++ b/kernel/kernel/files/patches/mageia.old/3rd-ndiswrapper-Makefile-build-fix.patch
@@ -0,0 +1,45 @@
+--- 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/kernel/files/patches/mageia.old/3rd-ndiswrapper-linux-3.14-buildfix.patch b/kernel/kernel/files/patches/mageia.old/3rd-ndiswrapper-linux-3.14-buildfix.patch
new file mode 100644
index 00000000..6550b9f2
--- /dev/null
+++ b/kernel/kernel/files/patches/mageia.old/3rd-ndiswrapper-linux-3.14-buildfix.patch
@@ -0,0 +1,33 @@
+
+Fix build with kernel-3.14
+
+Signed-off-by: Thomas Backlund
+
+ 3rdparty/ndiswrapper/crt.c | 2 +-
+ 3rdparty/ndiswrapper/ntoskernel.h | 3 +--
+ 2 files changed, 2 insertions(+), 3 deletions(-)
+
+--- linux/3rdparty/ndiswrapper/crt.c.orig 2014-04-26 19:10:55.000000000 +0300
++++ linux/3rdparty/ndiswrapper/crt.c 2014-04-26 19:25:27.766116082 +0300
+@@ -467,7 +467,7 @@ noregparm int WIN_FUNC(_win_memcmp,3)
+ noregparm void WIN_FUNC(_win_srand,1)
+ (UINT seed)
+ {
+- net_srandom(seed);
++ prandom_seed((__force u32) seed);
+ }
+
+ noregparm int WIN_FUNC(rand,0)
+--- linux/3rdparty/ndiswrapper/ntoskernel.h.orig 2014-04-26 19:42:32.000000000 +0300
++++ linux/3rdparty/ndiswrapper/ntoskernel.h 2014-04-26 19:59:13.662522942 +0300
+@@ -798,9 +798,8 @@ do { \
+ #define nt_spin_unlock_irqrestore(lock, flags) \
+ do { \
+ nt_spin_unlock(lock); \
+- preempt_enable_no_resched(); \
++ preempt_enable(); \
+ local_irq_restore(flags); \
+- preempt_check_resched(); \
+ } while (0)
+
+ static inline ULONG SPAN_PAGES(void *ptr, SIZE_T length)
diff --git a/kernel/kernel/files/patches/mageia.old/3rd-rfswitch-1.3.patch b/kernel/kernel/files/patches/mageia.old/3rd-rfswitch-1.3.patch
new file mode 100644
index 00000000..e87bf7e0
--- /dev/null
+++ b/kernel/kernel/files/patches/mageia.old/3rd-rfswitch-1.3.patch
@@ -0,0 +1,978 @@
+ 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/kernel/files/patches/mageia.old/3rd-rfswitch-3.0-buildfix.patch b/kernel/kernel/files/patches/mageia.old/3rd-rfswitch-3.0-buildfix.patch
new file mode 100644
index 00000000..7bfc2c64
--- /dev/null
+++ b/kernel/kernel/files/patches/mageia.old/3rd-rfswitch-3.0-buildfix.patch
@@ -0,0 +1,19 @@
+
+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/kernel/files/patches/mageia.old/3rd-rfswitch-build-fix.patch b/kernel/kernel/files/patches/mageia.old/3rd-rfswitch-build-fix.patch
new file mode 100644
index 00000000..ab1c279c
--- /dev/null
+++ b/kernel/kernel/files/patches/mageia.old/3rd-rfswitch-build-fix.patch
@@ -0,0 +1,51 @@
+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/kernel/files/patches/mageia.old/3rd-rtl8723bs-buildfix.patch b/kernel/kernel/files/patches/mageia.old/3rd-rtl8723bs-buildfix.patch
new file mode 100644
index 00000000..61c96c46
--- /dev/null
+++ b/kernel/kernel/files/patches/mageia.old/3rd-rtl8723bs-buildfix.patch
@@ -0,0 +1,23 @@
+From 842e61cb85813b1ed8a1646cbe6739950c0c9822 Mon Sep 17 00:00:00 2001
+From: Larry Finger
+Date: Thu, 7 May 2015 19:08:17 +0000
+Subject: [PATCH] rtl8723bs: Fix Makefile to allow warnings
+
+Signed-off-by: Larry Finger
+---
+ Makefile | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git linux.old/3rdparty/rtl8723bs/Makefile linux/3rdparty/rtl8723bs/Makefile
+index a4d9f45..4da73fa 100644
+--- linux.old/3rdparty/rtl8723bs/Makefile
++++ linux/3rdparty/rtl8723bs/Makefile
+@@ -3,7 +3,7 @@ EXTRA_CFLAGS += -O1
+ #EXTRA_CFLAGS += -O3
+ #EXTRA_CFLAGS += -Wall
+ #EXTRA_CFLAGS += -Wextra
+-EXTRA_CFLAGS += -Werror
++#EXTRA_CFLAGS += -Werror
+ #EXTRA_CFLAGS += -pedantic
+ #EXTRA_CFLAGS += -Wshadow -Wpointer-arith -Wcast-qual -Wstrict-prototypes -Wmissing-prototypes
+
diff --git a/kernel/kernel/files/patches/mageia.old/3rd-rtl8723bs-updates.patch b/kernel/kernel/files/patches/mageia.old/3rd-rtl8723bs-updates.patch
new file mode 100644
index 00000000..a620e888
--- /dev/null
+++ b/kernel/kernel/files/patches/mageia.old/3rd-rtl8723bs-updates.patch
@@ -0,0 +1,28991 @@
+
+Updates / cleanups from:
+
+git://github.com/hadess/rtl8723bs.git
+
+Topmost commit:
+
+commit 8d329c00dba5d8805a738ecea2bddde8eb0e4945
+Author: Bastien Nocera
+Date: Tue May 5 18:30:38 2015 +0200
+
+ ioctl_linux: Fix compiling with Wake-On-LAN support
+
+
+
+Signed-off-by: Thomas backlund
+
+diff -Nurp linux/3rdparty/rtl8723bs.old/core/rtw_ap.c linux/3rdparty/rtl8723bs/core/rtw_ap.c
+--- linux/3rdparty/rtl8723bs.old/core/rtw_ap.c 2015-05-10 14:36:05.663667846 +0300
++++ linux/3rdparty/rtl8723bs/core/rtw_ap.c 2015-05-07 17:46:55.000000000 +0300
+@@ -21,9 +21,6 @@
+
+ #include
+
+-
+-#ifdef CONFIG_AP_MODE
+-
+ extern unsigned char RTW_WPA_OUI[];
+ extern unsigned char WMM_OUI[];
+ extern unsigned char WPS_OUI[];
+@@ -32,7 +29,6 @@ extern unsigned char WFD_OUI[];
+
+ void init_mlme_ap_info(_adapter *padapter)
+ {
+- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
+@@ -71,9 +67,9 @@ void free_mlme_ap_info(_adapter *padapte
+
+ //free bc/mc sta_info
+ psta = rtw_get_bcmc_stainfo(padapter);
+- _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
++ spin_lock_bh(&(pstapriv->sta_hash_lock));
+ rtw_free_stainfo(padapter, psta);
+- _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
++ spin_unlock_bh(&(pstapriv->sta_hash_lock));
+ }
+
+ static void update_BCNTIM(_adapter *padapter)
+@@ -191,7 +187,7 @@ static void update_BCNTIM(_adapter *pada
+ {
+ memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen);
+
+- rtw_mfree(pbackup_remainder_ie, remainder_ielen);
++ kfree(pbackup_remainder_ie);
+ }
+
+ offset = (uint)(dst_ie - pie);
+@@ -200,122 +196,6 @@ static void update_BCNTIM(_adapter *pada
+ }
+ }
+
+-void rtw_add_bcn_ie(_adapter *padapter, WLAN_BSSID_EX *pnetwork, u8 index, u8 *data, u8 len)
+-{
+- PNDIS_802_11_VARIABLE_IEs pIE;
+- u8 bmatch = false;
+- u8 *pie = pnetwork->IEs;
+- u8 *p=NULL, *dst_ie=NULL, *premainder_ie=NULL, *pbackup_remainder_ie=NULL;
+- u32 i, offset, ielen, ie_offset, remainder_ielen = 0;
+-
+- for (i = sizeof(NDIS_802_11_FIXED_IEs); i < pnetwork->IELength;)
+- {
+- pIE = (PNDIS_802_11_VARIABLE_IEs)(pnetwork->IEs + i);
+-
+- if (pIE->ElementID > index)
+- {
+- break;
+- }
+- else if(pIE->ElementID == index) // already exist the same IE
+- {
+- p = (u8 *)pIE;
+- ielen = pIE->Length;
+- bmatch = true;
+- break;
+- }
+-
+- p = (u8 *)pIE;
+- ielen = pIE->Length;
+- i += (pIE->Length + 2);
+- }
+-
+- if (p != NULL && ielen>0)
+- {
+- ielen += 2;
+-
+- premainder_ie = p+ielen;
+-
+- ie_offset = (sint)(p -pie);
+-
+- remainder_ielen = pnetwork->IELength - ie_offset - ielen;
+-
+- if(bmatch)
+- dst_ie = p;
+- else
+- dst_ie = (p+ielen);
+- }
+-
+- if(dst_ie == NULL)
+- return;
+-
+- 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++=index;
+- *dst_ie++=len;
+-
+- memcpy(dst_ie, data, len);
+- dst_ie+=len;
+-
+- //copy remainder IE
+- if(pbackup_remainder_ie)
+- {
+- memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen);
+-
+- rtw_mfree(pbackup_remainder_ie, remainder_ielen);
+- }
+-
+- offset = (uint)(dst_ie - pie);
+- pnetwork->IELength = offset + remainder_ielen;
+-}
+-
+-void rtw_remove_bcn_ie(_adapter *padapter, WLAN_BSSID_EX *pnetwork, u8 index)
+-{
+- u8 *p, *dst_ie=NULL, *premainder_ie=NULL, *pbackup_remainder_ie=NULL;
+- uint offset, ielen, ie_offset, remainder_ielen = 0;
+- u8 *pie = pnetwork->IEs;
+-
+- p = rtw_get_ie(pie + _FIXED_IE_LENGTH_, index, &ielen, pnetwork->IELength - _FIXED_IE_LENGTH_);
+- if (p != NULL && ielen>0)
+- {
+- ielen += 2;
+-
+- premainder_ie = p+ielen;
+-
+- ie_offset = (sint)(p -pie);
+-
+- remainder_ielen = pnetwork->IELength - ie_offset - ielen;
+-
+- dst_ie = p;
+- }
+- else {
+- return;
+- }
+-
+- 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);
+- }
+-
+- //copy remainder IE
+- if(pbackup_remainder_ie)
+- {
+- memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen);
+-
+- rtw_mfree(pbackup_remainder_ie, remainder_ielen);
+- }
+-
+- offset = (uint)(dst_ie - pie);
+- pnetwork->IELength = offset + remainder_ielen;
+-}
+-
+-
+ u8 chk_sta_is_alive(struct sta_info *psta);
+ u8 chk_sta_is_alive(struct sta_info *psta)
+ {
+@@ -349,19 +229,19 @@ void expire_timeout_chk(_adapter *padapt
+ int i;
+
+
+- _enter_critical_bh(&pstapriv->auth_list_lock, &irqL);
++ spin_lock_bh(&pstapriv->auth_list_lock);
+
+ phead = &pstapriv->auth_list;
+ plist = get_next(phead);
+
+ //check auth_queue
+ #ifdef DBG_EXPIRATION_CHK
+- if (rtw_end_of_queue_search(phead, plist) == false) {
++ if (phead != plist) {
+ DBG_871X(FUNC_NDEV_FMT" auth_list, cnt:%u\n"
+ , FUNC_NDEV_ARG(padapter->pnetdev), pstapriv->auth_list_cnt);
+ }
+ #endif
+- while ((rtw_end_of_queue_search(phead, plist)) == false)
++ while (phead != plist)
+ {
+ psta = LIST_CONTAINOR(plist, struct sta_info, auth_list);
+
+@@ -372,41 +252,41 @@ void expire_timeout_chk(_adapter *padapt
+ psta->expire_to--;
+ if (psta->expire_to == 0)
+ {
+- rtw_list_delete(&psta->auth_list);
++ 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]);
+
+- _exit_critical_bh(&pstapriv->auth_list_lock, &irqL);
++ spin_unlock_bh(&pstapriv->auth_list_lock);
+
+- _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
++ spin_lock_bh(&(pstapriv->sta_hash_lock));
+ rtw_free_stainfo(padapter, psta);
+- _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
++ spin_unlock_bh(&(pstapriv->sta_hash_lock));
+
+- _enter_critical_bh(&pstapriv->auth_list_lock, &irqL);
++ spin_lock_bh(&pstapriv->auth_list_lock);
+ }
+ }
+
+ }
+
+- _exit_critical_bh(&pstapriv->auth_list_lock, &irqL);
++ spin_unlock_bh(&pstapriv->auth_list_lock);
+ psta = NULL;
+
+
+- _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
++ spin_lock_bh(&pstapriv->asoc_list_lock);
+
+ phead = &pstapriv->asoc_list;
+ plist = get_next(phead);
+
+ //check asoc_queue
+ #ifdef DBG_EXPIRATION_CHK
+- if (rtw_end_of_queue_search(phead, plist) == false) {
++ if (phead != plist) {
+ DBG_871X(FUNC_NDEV_FMT" asoc_list, cnt:%u\n"
+ , FUNC_NDEV_ARG(padapter->pnetdev), pstapriv->asoc_list_cnt);
+ }
+ #endif
+- while ((rtw_end_of_queue_search(phead, plist)) == false)
++ while (phead != plist)
+ {
+ psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
+ plist = get_next(plist);
+@@ -417,14 +297,13 @@ void expire_timeout_chk(_adapter *padapt
+ if (chk_sta_is_alive(psta) || !psta->expire_to) {
+ psta->expire_to = pstapriv->expire_to;
+ psta->keep_alive_trycnt = 0;
+- #ifdef CONFIG_TX_MCAST2UNI
+ psta->under_exist_checking = 0;
+- #endif // CONFIG_TX_MCAST2UNI
+ } else {
+- psta->expire_to--;
++ if (psta->expire_to > 0)
++ psta->expire_to--;
+ }
+
+- if (psta->expire_to <= 0)
++ if (psta->expire_to == 0)
+ {
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+
+@@ -460,7 +339,7 @@ void expire_timeout_chk(_adapter *padapt
+
+ continue;
+ }
+- rtw_list_delete(&psta->asoc_list);
++ 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);
+@@ -479,7 +358,7 @@ void expire_timeout_chk(_adapter *padapt
+ }
+ }
+
+- _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
++ spin_unlock_bh(&pstapriv->asoc_list_lock);
+
+ if (chk_alive_num) {
+
+@@ -521,13 +400,13 @@ if (chk_alive_num) {
+
+ psta->keep_alive_trycnt = 0;
+ DBG_871X("asoc expire "MAC_FMT", state=0x%x\n", MAC_ARG(psta->hwaddr), psta->state);
+- _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+- if (rtw_is_list_empty(&psta->asoc_list)==false) {
+- rtw_list_delete(&psta->asoc_list);
++ 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);
+ }
+- _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
++ spin_unlock_bh(&pstapriv->asoc_list_lock);
+
+ }
+
+@@ -544,13 +423,10 @@ void add_RATid(_adapter *padapter, struc
+ u8 rf_type;
+ unsigned char sta_band = 0, shortGIrate = false;
+ unsigned int tx_ra_bitmap=0;
+- struct ht_priv *psta_ht = NULL;
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ WLAN_BSSID_EX *pcur_network = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network;
+
+- if(psta)
+- psta_ht = &psta->htpriv;
+- else
++ if(!psta)
+ return;
+
+ if(!(psta->state & _FW_LINKED))
+@@ -672,9 +548,9 @@ void update_bmc_sta(_adapter *padapter)
+
+ rtw_sta_media_status_rpt(padapter, psta, 1);
+
+- _enter_critical_bh(&psta->lock, &irqL);
++ spin_lock_bh(&psta->lock);
+ psta->state = _FW_LINKED;
+- _exit_critical_bh(&psta->lock, &irqL);
++ spin_unlock_bh(&psta->lock);
+
+ }
+ else
+@@ -815,9 +691,9 @@ void update_sta_info_apmode(_adapter *pa
+ //add_RATid(padapter, psta);//move to ap_sta_info_defer_update()
+
+
+- _enter_critical_bh(&psta->lock, &irqL);
++ spin_lock_bh(&psta->lock);
+ psta->state |= _FW_LINKED;
+- _exit_critical_bh(&psta->lock, &irqL);
++ spin_unlock_bh(&psta->lock);
+
+
+ }
+@@ -826,7 +702,6 @@ static void update_ap_info(_adapter *pad
+ {
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ WLAN_BSSID_EX *pnetwork = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network;
+- struct security_priv *psecuritypriv = &padapter->securitypriv;
+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
+ struct ht_priv *phtpriv_ap = &pmlmepriv->htpriv;
+
+@@ -875,7 +750,6 @@ static void update_hw_ht_param(_adapter
+ {
+ 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);
+
+@@ -933,8 +807,7 @@ void start_bss_network(_adapter *padapte
+ WLAN_BSSID_EX *pnetwork_mlmeext = &(pmlmeinfo->network);
+ struct HT_info_element *pht_info=NULL;
+ u8 cbw40_enable=0;
+- u8 change_band = false;
+-
++
+ //DBG_871X("%s\n", __FUNCTION__);
+
+ bcn_interval = (u16)pnetwork->Configuration.BeaconPeriod;
+@@ -1114,15 +987,12 @@ int rtw_check_beacon_data(_adapter *pada
+ u8 channel, network_type, supportRate[NDIS_802_11_LENGTH_RATES_EX];
+ int supportRateNum = 0;
+ u8 OUI1[] = {0x00, 0x50, 0xf2,0x01};
+- u8 wps_oui[4]={0x0,0x50,0xf2,0x04};
+ 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);
+ WLAN_BSSID_EX *pbss_network = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network;
+- struct sta_priv *pstapriv = &padapter->stapriv;
+ u8 *ie = pbss_network->IEs;
+- u8 vht_cap=false;
+
+ /* SSID */
+ /* Supported rates */
+@@ -1483,12 +1353,12 @@ int rtw_acl_add_sta(_adapter *padapter,
+ return (-1);
+
+
+- _enter_critical_bh(&(pacl_node_q->lock), &irqL);
++ spin_lock_bh(&(pacl_node_q->lock));
+
+ phead = get_list_head(pacl_node_q);
+ plist = get_next(phead);
+
+- while ((rtw_end_of_queue_search(phead, plist)) == false)
++ while (phead != plist)
+ {
+ paclnode = LIST_CONTAINOR(plist, struct rtw_wlan_acl_node, list);
+ plist = get_next(plist);
+@@ -1504,14 +1374,14 @@ int rtw_acl_add_sta(_adapter *padapter,
+ }
+ }
+
+- _exit_critical_bh(&(pacl_node_q->lock), &irqL);
++ spin_unlock_bh(&(pacl_node_q->lock));
+
+
+ if(added == true)
+ return ret;
+
+
+- _enter_critical_bh(&(pacl_node_q->lock), &irqL);
++ spin_lock_bh(&(pacl_node_q->lock));
+
+ for(i=0; i< NUM_ACL; i++)
+ {
+@@ -1519,13 +1389,13 @@ int rtw_acl_add_sta(_adapter *padapter,
+
+ if(paclnode->valid == false)
+ {
+- _rtw_init_listhead(&paclnode->list);
++ INIT_LIST_HEAD(&paclnode->list);
+
+ memcpy(paclnode->addr, addr, ETH_ALEN);
+
+ paclnode->valid = true;
+
+- rtw_list_insert_tail(&paclnode->list, get_list_head(pacl_node_q));
++ list_add_tail(&paclnode->list, get_list_head(pacl_node_q));
+
+ pacl_list->num++;
+
+@@ -1535,7 +1405,7 @@ int rtw_acl_add_sta(_adapter *padapter,
+
+ DBG_871X("%s, acl_num=%d\n", __func__, pacl_list->num);
+
+- _exit_critical_bh(&(pacl_node_q->lock), &irqL);
++ spin_unlock_bh(&(pacl_node_q->lock));
+
+ return ret;
+ }
+@@ -1553,12 +1423,12 @@ int rtw_acl_remove_sta(_adapter *padapte
+
+ DBG_871X("%s(acl_num=%d)=" MAC_FMT "\n", __func__, pacl_list->num, MAC_ARG(addr));
+
+- _enter_critical_bh(&(pacl_node_q->lock), &irqL);
++ spin_lock_bh(&(pacl_node_q->lock));
+
+ phead = get_list_head(pacl_node_q);
+ plist = get_next(phead);
+
+- while ((rtw_end_of_queue_search(phead, plist)) == false)
++ while (phead != plist)
+ {
+ paclnode = LIST_CONTAINOR(plist, struct rtw_wlan_acl_node, list);
+ plist = get_next(plist);
+@@ -1569,14 +1439,14 @@ int rtw_acl_remove_sta(_adapter *padapte
+ {
+ paclnode->valid = false;
+
+- rtw_list_delete(&paclnode->list);
++ list_del_init(&paclnode->list);
+
+ pacl_list->num--;
+ }
+ }
+ }
+
+- _exit_critical_bh(&(pacl_node_q->lock), &irqL);
++ spin_unlock_bh(&(pacl_node_q->lock));
+
+ DBG_871X("%s, acl_num=%d\n", __func__, pacl_list->num);
+
+@@ -1599,7 +1469,7 @@ u8 rtw_ap_set_pairwise_key(_adapter *pad
+
+ psetstakey_para = (struct set_stakey_parm*)rtw_zmalloc(sizeof(struct set_stakey_parm));
+ if(psetstakey_para==NULL){
+- rtw_mfree((u8 *) ph2c, sizeof(struct cmd_obj));
++ kfree((u8 *) ph2c);
+ res=_FAIL;
+ goto exit;
+ }
+@@ -1639,7 +1509,7 @@ static int rtw_ap_set_key(_adapter *pada
+ }
+ psetkeyparm=(struct setkey_parm*)rtw_zmalloc(sizeof(struct setkey_parm));
+ if(psetkeyparm==NULL){
+- rtw_mfree((unsigned char *)pcmd, sizeof(struct cmd_obj));
++ kfree((unsigned char *)pcmd);
+ res= _FAIL;
+ goto exit;
+ }
+@@ -1678,7 +1548,7 @@ static int rtw_ap_set_key(_adapter *pada
+ pcmd->rspsz = 0;
+
+
+- _rtw_init_listhead(&pcmd->list);
++ INIT_LIST_HEAD(&pcmd->list);
+
+ res = rtw_enqueue_cmd(pcmdpriv, pcmd);
+
+@@ -1715,8 +1585,6 @@ int rtw_ap_set_wep_key(_adapter *padapte
+ return rtw_ap_set_key(padapter, key, alg, keyid, set_tx);
+ }
+
+-#ifdef CONFIG_NATIVEAP_MLME
+-
+ static void update_bcn_fixed_ie(_adapter *padapter)
+ {
+ DBG_871X("%s\n", __FUNCTION__);
+@@ -1838,7 +1706,7 @@ static void update_bcn_wps_ie(_adapter *
+ }
+
+ if(pbackup_remainder_ie)
+- rtw_mfree(pbackup_remainder_ie, remainder_ielen);
++ kfree(pbackup_remainder_ie);
+
+ // deal with the case without set_tx_beacon_cmd() in update_beacon()
+ #if defined( CONFIG_INTERRUPT_BASED_TXBCN )
+@@ -1907,7 +1775,7 @@ void update_beacon(_adapter *padapter, u
+ if(false == pmlmeext->bstart_bss)
+ return;
+
+- _enter_critical_bh(&pmlmepriv->bcn_update_lock, &irqL);
++ spin_lock_bh(&pmlmepriv->bcn_update_lock);
+
+ switch(ie_id)
+ {
+@@ -1959,7 +1827,7 @@ void update_beacon(_adapter *padapter, u
+
+ pmlmepriv->update_bcn = true;
+
+- _exit_critical_bh(&pmlmepriv->bcn_update_lock, &irqL);
++ spin_unlock_bh(&pmlmepriv->bcn_update_lock);
+
+ #ifndef CONFIG_INTERRUPT_BASED_TXBCN
+ if(tx)
+@@ -2064,13 +1932,13 @@ void associated_clients_update(_adapter
+ struct sta_info *psta=NULL;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+
+- _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
++ spin_lock_bh(&pstapriv->asoc_list_lock);
+
+ phead = &pstapriv->asoc_list;
+ plist = get_next(phead);
+
+ //check asoc_queue
+- while ((rtw_end_of_queue_search(phead, plist)) == false)
++ while (phead != plist)
+ {
+ psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
+
+@@ -2079,7 +1947,7 @@ void associated_clients_update(_adapter
+ VCS_update(padapter, psta);
+ }
+
+- _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
++ spin_unlock_bh(&pstapriv->asoc_list_lock);
+
+ }
+
+@@ -2332,8 +2200,6 @@ u8 ap_free_sta(_adapter *padapter, struc
+ {
+ _irqL irqL;
+ u8 beacon_updated = false;
+- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+- struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
+ struct sta_priv *pstapriv = &padapter->stapriv;
+
+ if(!psta)
+@@ -2360,9 +2226,9 @@ u8 ap_free_sta(_adapter *padapter, struc
+ rtw_clearstakey_cmd(padapter, psta, true);
+
+
+- _enter_critical_bh(&psta->lock, &irqL);
++ spin_lock_bh(&psta->lock);
+ psta->state &= ~_FW_LINKED;
+- _exit_critical_bh(&psta->lock, &irqL);
++ spin_unlock_bh(&psta->lock);
+
+ rtw_cfg80211_indicate_sta_disassoc(padapter, psta->hwaddr, reason);
+
+@@ -2370,52 +2236,15 @@ u8 ap_free_sta(_adapter *padapter, struc
+
+ beacon_updated = bss_cap_update_on_sta_leave(padapter, psta);
+
+- _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
++ spin_lock_bh(&(pstapriv->sta_hash_lock));
+ rtw_free_stainfo(padapter, psta);
+- _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
++ spin_unlock_bh(&(pstapriv->sta_hash_lock));
+
+
+ return beacon_updated;
+
+ }
+
+-int rtw_ap_inform_ch_switch(_adapter *padapter, u8 new_ch, u8 ch_offset)
+-{
+- _irqL irqL;
+- _list *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};
+-
+- if((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
+- return ret;
+-
+- DBG_871X(FUNC_NDEV_FMT" with ch:%u, offset:%u\n",
+- FUNC_NDEV_ARG(padapter->pnetdev), new_ch, ch_offset);
+-
+- _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+- phead = &pstapriv->asoc_list;
+- plist = get_next(phead);
+-
+- /* for each sta in asoc_queue */
+- while ((rtw_end_of_queue_search(phead, plist)) == false)
+- {
+- psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
+- plist = get_next(plist);
+-
+- issue_action_spct_ch_switch(padapter, psta->hwaddr, new_ch, ch_offset);
+- psta->expire_to = ((pstapriv->expire_to * 2) > 5) ? 5 : (pstapriv->expire_to * 2);
+- }
+- _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+-
+- issue_action_spct_ch_switch(padapter, bc_addr, new_ch, ch_offset);
+-
+- return ret;
+-}
+-
+ int rtw_sta_flush(_adapter *padapter)
+ {
+ _irqL irqL;
+@@ -2433,25 +2262,25 @@ int rtw_sta_flush(_adapter *padapter)
+ return ret;
+
+
+- _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
++ spin_lock_bh(&pstapriv->asoc_list_lock);
+ phead = &pstapriv->asoc_list;
+ plist = get_next(phead);
+
+ //free sta asoc_queue
+- while ((rtw_end_of_queue_search(phead, plist)) == false)
++ while (phead != plist)
+ {
+ psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
+
+ plist = get_next(plist);
+
+- rtw_list_delete(&psta->asoc_list);
++ list_del_init(&psta->asoc_list);
+ pstapriv->asoc_list_cnt--;
+
+- //_exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
++ //spin_unlock_bh(&pstapriv->asoc_list_lock);
+ ap_free_sta(padapter, psta, true, WLAN_REASON_DEAUTH_LEAVING);
+- //_enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
++ //spin_lock_bh(&pstapriv->asoc_list_lock);
+ }
+- _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
++ spin_unlock_bh(&pstapriv->asoc_list_lock);
+
+
+ issue_deauth(padapter, bc_addr, WLAN_REASON_DEAUTH_LEAVING);
+@@ -2516,7 +2345,6 @@ void rtw_ap_restore_network(_adapter *pa
+ {
+ struct mlme_priv *mlmepriv = &padapter->mlmepriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
+ struct sta_priv * pstapriv = &padapter->stapriv;
+ struct sta_info *psta;
+ struct security_priv* psecuritypriv=&(padapter->securitypriv);
+@@ -2539,12 +2367,12 @@ void rtw_ap_restore_network(_adapter *pa
+ rtw_set_key(padapter, psecuritypriv, psecuritypriv->dot118021XGrpKeyid, 0,false);
+ }
+
+- _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
++ spin_lock_bh(&pstapriv->asoc_list_lock);
+
+ phead = &pstapriv->asoc_list;
+ plist = get_next(phead);
+
+- while ((rtw_end_of_queue_search(phead, plist)) == false) {
++ while (phead != plist) {
+ int stainfo_offset;
+
+ psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
+@@ -2556,7 +2384,7 @@ void rtw_ap_restore_network(_adapter *pa
+ }
+ }
+
+- _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
++ 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]);
+@@ -2619,12 +2447,12 @@ void start_ap_mode(_adapter *padapter)
+
+
+ //for ACL
+- _rtw_init_listhead(&(pacl_list->acl_node_q.queue));
++ INIT_LIST_HEAD(&(pacl_list->acl_node_q.queue));
+ pacl_list->num = 0;
+ pacl_list->mode = 0;
+ for(i = 0; i < NUM_ACL; i++)
+ {
+- _rtw_init_listhead(&pacl_list->aclnode[i].list);
++ INIT_LIST_HEAD(&pacl_list->aclnode[i].list);
+ pacl_list->aclnode[i].valid = false;
+ }
+
+@@ -2651,10 +2479,10 @@ void stop_ap_mode(_adapter *padapter)
+ padapter->securitypriv.ndisencryptstatus = Ndis802_11WEPDisabled;
+
+ //for ACL
+- _enter_critical_bh(&(pacl_node_q->lock), &irqL);
++ spin_lock_bh(&(pacl_node_q->lock));
+ phead = get_list_head(pacl_node_q);
+ plist = get_next(phead);
+- while ((rtw_end_of_queue_search(phead, plist)) == false)
++ while (phead != plist)
+ {
+ paclnode = LIST_CONTAINOR(plist, struct rtw_wlan_acl_node, list);
+ plist = get_next(plist);
+@@ -2663,12 +2491,12 @@ void stop_ap_mode(_adapter *padapter)
+ {
+ paclnode->valid = false;
+
+- rtw_list_delete(&paclnode->list);
++ list_del_init(&paclnode->list);
+
+ pacl_list->num--;
+ }
+ }
+- _exit_critical_bh(&(pacl_node_q->lock), &irqL);
++ spin_unlock_bh(&(pacl_node_q->lock));
+
+ DBG_871X("%s, free acl_node_queue, num=%d\n", __func__, pacl_list->num);
+
+@@ -2678,9 +2506,9 @@ void stop_ap_mode(_adapter *padapter)
+ rtw_free_all_stainfo(padapter);
+
+ psta = rtw_get_bcmc_stainfo(padapter);
+- _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
++ spin_lock_bh(&(pstapriv->sta_hash_lock));
+ rtw_free_stainfo(padapter, psta);
+- _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
++ spin_unlock_bh(&(pstapriv->sta_hash_lock));
+
+ rtw_init_bcmc_stainfo(padapter);
+
+@@ -2688,8 +2516,3 @@ void stop_ap_mode(_adapter *padapter)
+
+ rtw_btcoex_MediaStatusNotify(padapter, 0); //disconnect
+ }
+-
+-#endif //CONFIG_NATIVEAP_MLME
+-
+-#endif //CONFIG_AP_MODE
+-
+diff -Nurp linux/3rdparty/rtl8723bs.old/core/rtw_btcoex.c linux/3rdparty/rtl8723bs/core/rtw_btcoex.c
+--- linux/3rdparty/rtl8723bs.old/core/rtw_btcoex.c 2015-05-10 14:36:05.663667846 +0300
++++ linux/3rdparty/rtl8723bs/core/rtw_btcoex.c 2015-05-07 17:46:55.000000000 +0300
+@@ -108,16 +108,6 @@ void rtw_btcoex_HaltNotify(PADAPTER pada
+ hal_btcoex_HaltNotify(padapter);
+ }
+
+-void rtw_btcoex_SwitchBtTRxMask(PADAPTER padapter)
+-{
+- hal_btcoex_SwitchBtTRxMask(padapter);
+-}
+-
+-void rtw_btcoex_Switch(PADAPTER padapter, u8 enable)
+-{
+- hal_btcoex_SetBTCoexist(padapter, enable);
+-}
+-
+ u8 rtw_btcoex_IsBtDisabled(PADAPTER padapter)
+ {
+ return hal_btcoex_IsBtDisabled(padapter);
+@@ -137,15 +127,6 @@ s32 rtw_btcoex_IsBTCoexCtrlAMPDUSize(PAD
+ return coexctrl;
+ }
+
+-u32 rtw_btcoex_GetAMPDUSize(PADAPTER padapter)
+-{
+- u32 size;
+-
+- size = hal_btcoex_GetAMPDUSize(padapter);
+-
+- return size;
+-}
+-
+ void rtw_btcoex_SetManualControl(PADAPTER padapter, u8 manual)
+ {
+ if (true == manual)
+@@ -158,11 +139,6 @@ void rtw_btcoex_SetManualControl(PADAPTE
+ }
+ }
+
+-u8 rtw_btcoex_1Ant(PADAPTER padapter)
+-{
+- return hal_btcoex_1Ant(padapter);
+-}
+-
+ u8 rtw_btcoex_IsBtControlLps(PADAPTER padapter)
+ {
+ return hal_btcoex_IsBtControlLps(padapter);
+@@ -198,11 +174,6 @@ void rtw_btcoex_SetPGAntNum(PADAPTER pad
+ hal_btcoex_SetPgAntNum(padapter, antNum);
+ }
+
+-u8 rtw_btcoex_GetPGAntNum(PADAPTER padapter)
+-{
+- return hal_btcoex_GetPgAntNum(padapter);
+-}
+-
+ void rtw_btcoex_SetSingleAntPath(PADAPTER padapter, u8 singleAntPath)
+ {
+ hal_btcoex_SetSingleAntPath(padapter, singleAntPath);
+@@ -233,16 +204,6 @@ u32 rtw_btcoex_GetDBG(PADAPTER padapter,
+ return hal_btcoex_GetDBG(padapter, pStrBuf, bufSize);
+ }
+
+-u8 rtw_btcoex_IncreaseScanDeviceNum(PADAPTER padapter)
+-{
+- return hal_btcoex_IncreaseScanDeviceNum(padapter);
+-}
+-
+-u8 rtw_btcoex_IsBtLinkExist(PADAPTER padapter)
+-{
+- return hal_btcoex_IsBtLinkExist(padapter);
+-}
+-
+ // ==================================================
+ // Below Functions are called by BT-Coex
+ // ==================================================
+diff -Nurp linux/3rdparty/rtl8723bs.old/core/rtw_cmd.c linux/3rdparty/rtl8723bs/core/rtw_cmd.c
+--- linux/3rdparty/rtl8723bs.old/core/rtw_cmd.c 2015-05-10 14:36:05.665667868 +0300
++++ linux/3rdparty/rtl8723bs/core/rtw_cmd.c 2015-05-07 17:46:55.000000000 +0300
+@@ -255,10 +255,10 @@ _func_enter_;
+ void *c2h;
+ if ((c2h = rtw_cbuf_pop(pevtpriv->c2h_queue)) != NULL
+ && c2h != (void *)pevtpriv) {
+- rtw_mfree(c2h, 16);
++ kfree(c2h);
+ }
+ }
+- rtw_cbuf_free(pevtpriv->c2h_queue);
++ kfree(pevtpriv->c2h_queue);
+
+ RT_TRACE(_module_rtl871x_cmd_c_,_drv_info_,("-_rtw_free_evt_priv \n"));
+
+@@ -272,10 +272,10 @@ _func_enter_;
+
+ if(pcmdpriv){
+ if (pcmdpriv->cmd_allocated_buf)
+- rtw_mfree(pcmdpriv->cmd_allocated_buf, MAX_CMDSZ + CMDBUFF_ALIGN_SZ);
++ kfree(pcmdpriv->cmd_allocated_buf);
+
+ if (pcmdpriv->rsp_allocated_buf)
+- rtw_mfree(pcmdpriv->rsp_allocated_buf, MAX_RSPSZ + 4);
++ kfree(pcmdpriv->rsp_allocated_buf);
+
+ mutex_destroy(&pcmdpriv->sctx_mutex);
+ }
+@@ -301,13 +301,13 @@ _func_enter_;
+ if (obj == NULL)
+ goto exit;
+
+- //_enter_critical_bh(&queue->lock, &irqL);
+- _enter_critical(&queue->lock, &irqL);
++ //spin_lock_bh(&queue->lock);
++ spin_lock_irqsave(&queue->lock, irqL);
+
+- rtw_list_insert_tail(&obj->list, &queue->queue);
++ list_add_tail(&obj->list, &queue->queue);
+
+- //_exit_critical_bh(&queue->lock, &irqL);
+- _exit_critical(&queue->lock, &irqL);
++ //spin_unlock_bh(&queue->lock);
++ spin_unlock_irqrestore(&queue->lock, irqL);
+
+ exit:
+
+@@ -323,18 +323,18 @@ struct cmd_obj *_rtw_dequeue_cmd(_queue
+
+ _func_enter_;
+
+- //_enter_critical_bh(&(queue->lock), &irqL);
+- _enter_critical(&queue->lock, &irqL);
+- if (rtw_is_list_empty(&(queue->queue)))
++ //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);
+- rtw_list_delete(&obj->list);
++ list_del_init(&obj->list);
+ }
+
+- //_exit_critical_bh(&(queue->lock), &irqL);
+- _exit_critical(&queue->lock, &irqL);
++ //spin_unlock_bh(&(queue->lock));
++ spin_unlock_irqrestore(&queue->lock, irqL);
+
+ _func_exit_;
+
+@@ -442,14 +442,6 @@ _func_exit_;
+ return cmd_obj;
+ }
+
+-void rtw_cmd_clr_isr(struct cmd_priv *pcmdpriv)
+-{
+-_func_enter_;
+- pcmdpriv->cmd_done_cnt++;
+- //up(&(pcmdpriv->cmd_done_sema));
+-_func_exit_;
+-}
+-
+ void rtw_free_cmd_obj(struct cmd_obj *pcmd)
+ {
+ _func_enter_;
+@@ -457,7 +449,7 @@ _func_enter_;
+ if((pcmd->cmdcode!=_JoinBss_CMD_) &&(pcmd->cmdcode!= _CreateBss_CMD_))
+ {
+ //free parmbuf in cmd_obj
+- rtw_mfree((unsigned char*)pcmd->parmbuf, pcmd->cmdsz);
++ kfree((unsigned char*)pcmd->parmbuf);
+ }
+
+ if(pcmd->rsp!=NULL)
+@@ -465,12 +457,12 @@ _func_enter_;
+ if(pcmd->rspsz!= 0)
+ {
+ //free rsp in cmd_obj
+- rtw_mfree((unsigned char*)pcmd->rsp, pcmd->rspsz);
++ kfree((unsigned char*)pcmd->rsp);
+ }
+ }
+
+ //free cmd_obj
+- rtw_mfree((unsigned char*)pcmd, sizeof(struct cmd_obj));
++ kfree((unsigned char*)pcmd);
+
+ _func_exit_;
+ }
+@@ -533,7 +525,7 @@ _func_enter_;
+ break;
+ }
+
+- if(rtw_is_list_empty(&(pcmdpriv->cmd_queue.queue)))
++ if(list_empty(&(pcmdpriv->cmd_queue.queue)))
+ {
+ //DBG_871X("%s: cmd queue is empty!\n", __func__);
+ continue;
+@@ -573,7 +565,7 @@ _next:
+
+ memcpy(pcmdbuf, pcmd->parmbuf, pcmd->cmdsz);
+
+- if(pcmd->cmdcode < (sizeof(wlancmds) /sizeof(struct cmd_hdl)))
++ if(pcmd->cmdcode < ARRAY_SIZE(wlancmds))
+ {
+ cmd_hdl = wlancmds[pcmd->cmdcode].h2cfuns;
+
+@@ -594,18 +586,18 @@ _next:
+
+ post_process:
+
+- _enter_critical_mutex(&(pcmd->padapter->cmdpriv.sctx_mutex), NULL);
+- 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);
++ 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));
+ }
+- _exit_critical_mutex(&(pcmd->padapter->cmdpriv.sctx_mutex), NULL);
+-
+
+ if((cmd_process_time = jiffies_to_msecs(jiffies - cmd_start_time)) > 1000)
+ {
+@@ -627,7 +619,7 @@ post_process:
+ }
+
+ //call callback function for post-processed
+- if(pcmd->cmdcode < (sizeof(rtw_cmd_callback) /sizeof(struct _cmd_callback)))
++ if(pcmd->cmdcode < ARRAY_SIZE(rtw_cmd_callback))
+ {
+ pcmd_callback = rtw_cmd_callback[pcmd->cmdcode].callback;
+ if(pcmd_callback == NULL)
+@@ -666,7 +658,7 @@ post_process:
+ 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) {
+- rtw_mfree(extra_parm->pbuf, extra_parm->size);
++ kfree(extra_parm->pbuf);
+ }
+ }
+
+@@ -682,42 +674,6 @@ _func_exit_;
+
+ }
+
+-u8 rtw_setstandby_cmd(_adapter *padapter, uint action)
+-{
+- struct cmd_obj* ph2c;
+- struct usb_suspend_parm* psetusbsuspend;
+- struct cmd_priv *pcmdpriv=&padapter->cmdpriv;
+-
+- u8 ret = _SUCCESS;
+-
+-_func_enter_;
+-
+- ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));
+- if (ph2c == NULL) {
+- ret = _FAIL;
+- goto exit;
+- }
+-
+- psetusbsuspend = (struct usb_suspend_parm*)rtw_zmalloc(sizeof(struct usb_suspend_parm));
+- if (psetusbsuspend == NULL) {
+- rtw_mfree((u8 *) ph2c, sizeof(struct cmd_obj));
+- ret = _FAIL;
+- goto exit;
+- }
+-
+- psetusbsuspend->action = action;
+-
+- init_h2fwcmd_w_parm_no_rsp(ph2c, psetusbsuspend, GEN_CMD_CODE(_SetUsbSuspend));
+-
+- ret = rtw_enqueue_cmd(pcmdpriv, ph2c);
+-
+-exit:
+-
+-_func_exit_;
+-
+- return ret;
+-}
+-
+ /*
+ rtw_sitesurvey_cmd(~)
+ ### NOTE:#### (!!!!)
+@@ -744,7 +700,7 @@ _func_enter_;
+
+ psurveyPara = (struct sitesurvey_parm*)rtw_zmalloc(sizeof(struct sitesurvey_parm));
+ if (psurveyPara == NULL) {
+- rtw_mfree((unsigned char*) ph2c, sizeof(struct cmd_obj));
++ kfree((unsigned char*) ph2c);
+ return _FAIL;
+ }
+
+@@ -793,8 +749,6 @@ _func_enter_;
+
+ pmlmepriv->scan_start_time = jiffies;
+ _set_timer(&pmlmepriv->scan_to_timer, SCANNING_TIMEOUT);
+-
+- rtw_led_control(padapter, LED_CTL_SITE_SURVEY);
+ } else {
+ _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
+ }
+@@ -821,7 +775,7 @@ _func_enter_;
+
+ pbsetdataratepara = (struct setdatarate_parm*)rtw_zmalloc(sizeof(struct setdatarate_parm));
+ if (pbsetdataratepara == NULL) {
+- rtw_mfree((u8 *) ph2c, sizeof(struct cmd_obj));
++ kfree((u8 *) ph2c);
+ res = _FAIL;
+ goto exit;
+ }
+@@ -838,243 +792,17 @@ _func_exit_;
+ return res;
+ }
+
+-u8 rtw_setbasicrate_cmd(_adapter *padapter, u8 *rateset)
+-{
+- struct cmd_obj* ph2c;
+- struct setbasicrate_parm* pssetbasicratepara;
+- struct cmd_priv* pcmdpriv=&padapter->cmdpriv;
+- u8 res = _SUCCESS;
+-
+-_func_enter_;
+-
+- ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));
+- if (ph2c == NULL) {
+- res= _FAIL;
+- goto exit;
+- }
+- pssetbasicratepara = (struct setbasicrate_parm*)rtw_zmalloc(sizeof(struct setbasicrate_parm));
+-
+- if (pssetbasicratepara == NULL) {
+- rtw_mfree((u8*) ph2c, sizeof(struct cmd_obj));
+- res = _FAIL;
+- goto exit;
+- }
+-
+- init_h2fwcmd_w_parm_no_rsp(ph2c, pssetbasicratepara, _SetBasicRate_CMD_);
+-
+- memcpy(pssetbasicratepara->basicrates, rateset, NumRates);
+-
+- res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+-exit:
+-
+-_func_exit_;
+-
+- return res;
+-}
+-
+-
+-/*
+-unsigned char rtw_setphy_cmd(unsigned char *adapter)
+-
+-1. be called only after rtw_update_registrypriv_dev_network( ~) or mp testing program
+-2. for AdHoc/Ap mode or mp mode?
+-
+-*/
+-u8 rtw_setphy_cmd(_adapter *padapter, u8 modem, u8 ch)
+-{
+- struct cmd_obj* ph2c;
+- struct setphy_parm* psetphypara;
+- struct cmd_priv *pcmdpriv=&padapter->cmdpriv;
+-// struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+-// struct registry_priv* pregistry_priv = &padapter->registrypriv;
+- u8 res=_SUCCESS;
+-
+-_func_enter_;
+-
+- ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));
+- if(ph2c==NULL){
+- res= _FAIL;
+- goto exit;
+- }
+- psetphypara = (struct setphy_parm*)rtw_zmalloc(sizeof(struct setphy_parm));
+-
+- if(psetphypara==NULL){
+- rtw_mfree((u8 *) ph2c, sizeof(struct cmd_obj));
+- res= _FAIL;
+- goto exit;
+- }
+-
+- init_h2fwcmd_w_parm_no_rsp(ph2c, psetphypara, _SetPhy_CMD_);
+-
+- RT_TRACE(_module_rtl871x_cmd_c_,_drv_info_,("CH=%d, modem=%d", ch, modem));
+-
+- psetphypara->modem = modem;
+- psetphypara->rfchannel = ch;
+-
+- res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+-exit:
+-_func_exit_;
+- return res;
+-}
+-
+-u8 rtw_setbbreg_cmd(_adapter*padapter, u8 offset, u8 val)
+-{
+- struct cmd_obj* ph2c;
+- struct writeBB_parm* pwritebbparm;
+- struct cmd_priv *pcmdpriv=&padapter->cmdpriv;
+- u8 res=_SUCCESS;
+-_func_enter_;
+- ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));
+- if(ph2c==NULL){
+- res= _FAIL;
+- goto exit;
+- }
+- pwritebbparm = (struct writeBB_parm*)rtw_zmalloc(sizeof(struct writeBB_parm));
+-
+- if(pwritebbparm==NULL){
+- rtw_mfree((u8 *) ph2c, sizeof(struct cmd_obj));
+- res= _FAIL;
+- goto exit;
+- }
+-
+- init_h2fwcmd_w_parm_no_rsp(ph2c, pwritebbparm, GEN_CMD_CODE(_SetBBReg));
+-
+- pwritebbparm->offset = offset;
+- pwritebbparm->value = val;
+-
+- res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+-exit:
+-_func_exit_;
+- return res;
+-}
+-
+-u8 rtw_getbbreg_cmd(_adapter *padapter, u8 offset, u8 *pval)
+-{
+- struct cmd_obj* ph2c;
+- struct readBB_parm* prdbbparm;
+- struct cmd_priv *pcmdpriv=&padapter->cmdpriv;
+- u8 res=_SUCCESS;
+-
+-_func_enter_;
+- ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));
+- if(ph2c==NULL){
+- res=_FAIL;
+- goto exit;
+- }
+- prdbbparm = (struct readBB_parm*)rtw_zmalloc(sizeof(struct readBB_parm));
+-
+- if(prdbbparm ==NULL){
+- rtw_mfree((unsigned char *) ph2c, sizeof(struct cmd_obj));
+- return _FAIL;
+- }
+-
+- _rtw_init_listhead(&ph2c->list);
+- ph2c->cmdcode =GEN_CMD_CODE(_GetBBReg);
+- ph2c->parmbuf = (unsigned char *)prdbbparm;
+- ph2c->cmdsz = sizeof(struct readBB_parm);
+- ph2c->rsp = pval;
+- ph2c->rspsz = sizeof(struct readBB_rsp);
+-
+- prdbbparm ->offset = offset;
+-
+- res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+-exit:
+-_func_exit_;
+- return res;
+-}
+-
+-u8 rtw_setrfreg_cmd(_adapter *padapter, u8 offset, u32 val)
+-{
+- struct cmd_obj* ph2c;
+- struct writeRF_parm* pwriterfparm;
+- struct cmd_priv *pcmdpriv=&padapter->cmdpriv;
+- u8 res=_SUCCESS;
+-_func_enter_;
+- ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));
+- if(ph2c==NULL){
+- res= _FAIL;
+- goto exit;
+- }
+- pwriterfparm = (struct writeRF_parm*)rtw_zmalloc(sizeof(struct writeRF_parm));
+-
+- if(pwriterfparm==NULL){
+- rtw_mfree((u8 *) ph2c, sizeof(struct cmd_obj));
+- res= _FAIL;
+- goto exit;
+- }
+-
+- init_h2fwcmd_w_parm_no_rsp(ph2c, pwriterfparm, GEN_CMD_CODE(_SetRFReg));
+-
+- pwriterfparm->offset = offset;
+- pwriterfparm->value = val;
+-
+- res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+-exit:
+-_func_exit_;
+- return res;
+-}
+-
+-u8 rtw_getrfreg_cmd(_adapter *padapter, u8 offset, u8 *pval)
+-{
+- struct cmd_obj* ph2c;
+- struct readRF_parm* prdrfparm;
+- struct cmd_priv *pcmdpriv=&padapter->cmdpriv;
+- u8 res=_SUCCESS;
+-
+-_func_enter_;
+-
+- ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));
+- if(ph2c==NULL){
+- res= _FAIL;
+- goto exit;
+- }
+-
+- prdrfparm = (struct readRF_parm*)rtw_zmalloc(sizeof(struct readRF_parm));
+- if(prdrfparm ==NULL){
+- rtw_mfree((u8 *) ph2c, sizeof(struct cmd_obj));
+- res= _FAIL;
+- goto exit;
+- }
+-
+- _rtw_init_listhead(&ph2c->list);
+- ph2c->cmdcode =GEN_CMD_CODE(_GetRFReg);
+- ph2c->parmbuf = (unsigned char *)prdrfparm;
+- ph2c->cmdsz = sizeof(struct readRF_parm);
+- ph2c->rsp = pval;
+- ph2c->rspsz = sizeof(struct readRF_rsp);
+-
+- prdrfparm ->offset = offset;
+-
+- res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+-
+-exit:
+-
+-_func_exit_;
+-
+- return res;
+-}
+-
+ void rtw_getbbrfreg_cmdrsp_callback(_adapter* padapter, struct cmd_obj *pcmd)
+ {
+ _func_enter_;
+
+ //rtw_free_cmd_obj(pcmd);
+- rtw_mfree((unsigned char*) pcmd->parmbuf, pcmd->cmdsz);
+- rtw_mfree((unsigned char*) pcmd, sizeof(struct cmd_obj));
++ kfree((unsigned char*) pcmd->parmbuf);
++ kfree((unsigned char*) pcmd);
+
+ _func_exit_;
+ }
+
+-void rtw_readtssi_cmdrsp_callback(_adapter* padapter, struct cmd_obj *pcmd)
+-{
+- _func_enter_;
+-
+- rtw_mfree((unsigned char*) pcmd->parmbuf, pcmd->cmdsz);
+- rtw_mfree((unsigned char*) pcmd, sizeof(struct cmd_obj));
+-
+-_func_exit_;
+-}
+-
+ u8 rtw_createbss_cmd(_adapter *padapter)
+ {
+ struct cmd_obj* pcmd;
+@@ -1085,8 +813,6 @@ u8 rtw_createbss_cmd(_adapter *padapter
+
+ _func_enter_;
+
+- rtw_led_control(padapter, LED_CTL_START_TO_LINK);
+-
+ 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 {
+@@ -1099,7 +825,7 @@ _func_enter_;
+ goto exit;
+ }
+
+- _rtw_init_listhead(&pcmd->list);
++ INIT_LIST_HEAD(&pcmd->list);
+ pcmd->cmdcode = _CreateBss_CMD_;
+ pcmd->parmbuf = (unsigned char *)pdev_network;
+ pcmd->cmdsz = get_WLAN_BSSID_EX_sz((WLAN_BSSID_EX*)pdev_network);
+@@ -1117,36 +843,6 @@ _func_exit_;
+ return res;
+ }
+
+-u8 rtw_createbss_cmd_ex(_adapter *padapter, unsigned char *pbss, unsigned int sz)
+-{
+- struct cmd_obj* pcmd;
+- struct cmd_priv *pcmdpriv=&padapter->cmdpriv;
+- u8 res=_SUCCESS;
+-
+-_func_enter_;
+-
+- pcmd = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));
+- if(pcmd==NULL){
+- res= _FAIL;
+- goto exit;
+- }
+-
+- _rtw_init_listhead(&pcmd->list);
+- pcmd->cmdcode = GEN_CMD_CODE(_CreateBss);
+- pcmd->parmbuf = pbss;
+- pcmd->cmdsz = sz;
+- pcmd->rsp = NULL;
+- pcmd->rspsz = 0;
+-
+- res = rtw_enqueue_cmd(pcmdpriv, pcmd);
+-
+-exit:
+-
+-_func_exit_;
+-
+- return res;
+-}
+-
+ u8 rtw_startbss_cmd(_adapter *padapter, int flags)
+ {
+ struct cmd_obj* pcmd;
+@@ -1167,7 +863,7 @@ _func_enter_;
+ goto exit;
+ }
+
+- _rtw_init_listhead(&pcmd->list);
++ INIT_LIST_HEAD(&pcmd->list);
+ pcmd->cmdcode = GEN_CMD_CODE(_CreateBss);
+ pcmd->parmbuf = NULL;
+ pcmd->cmdsz = 0;
+@@ -1183,10 +879,11 @@ _func_enter_;
+
+ if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
+ rtw_sctx_wait(&sctx, __func__);
+- _enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
+- if (sctx.status == RTW_SCTX_SUBMITTED)
+- pcmd->sctx = NULL;
+- _exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
++ if (mutex_lock_interruptible(&pcmdpriv->sctx_mutex) == 0) {
++ if (sctx.status == RTW_SCTX_SUBMITTED)
++ pcmd->sctx = NULL;
++ mutex_unlock(&pcmdpriv->sctx_mutex);
++ }
+ }
+ }
+
+@@ -1216,8 +913,6 @@ u8 rtw_joinbss_cmd(_adapter *padapter,
+ u8 *ptmp=NULL;
+ _func_enter_;
+
+- rtw_led_control(padapter, LED_CTL_START_TO_LINK);
+-
+ if (pmlmepriv->assoc_ssid.SsidLength == 0){
+ RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("+Join cmd: Any SSid\n"));
+ } else {
+@@ -1267,7 +962,7 @@ _func_enter_;
+ if(psecnetwork==NULL)
+ {
+ if(pcmd !=NULL)
+- rtw_mfree((unsigned char *)pcmd, sizeof(struct cmd_obj));
++ kfree((unsigned char *)pcmd);
+
+ res=_FAIL;
+
+@@ -1348,7 +1043,7 @@ _func_enter_;
+
+ pcmd->cmdsz = get_WLAN_BSSID_EX_sz(psecnetwork);//get cmdsz before endian conversion
+
+- _rtw_init_listhead(&pcmd->list);
++ INIT_LIST_HEAD(&pcmd->list);
+ pcmd->cmdcode = _JoinBss_CMD_;//GEN_CMD_CODE(_JoinBss)
+ pcmd->parmbuf = (unsigned char *)psecnetwork;
+ pcmd->rsp = NULL;
+@@ -1387,7 +1082,7 @@ _func_enter_;
+ cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));
+ if (cmdobj == NULL) {
+ res = _FAIL;
+- rtw_mfree((u8 *)param, sizeof(*param));
++ kfree((u8 *)param);
+ goto exit;
+ }
+ init_h2fwcmd_w_parm_no_rsp(cmdobj, param, _DisConnect_CMD_);
+@@ -1396,7 +1091,7 @@ _func_enter_;
+ /* no need to enqueue, do the cmd hdl directly and free cmd parameter */
+ if (H2C_SUCCESS != disconnect_hdl(padapter, (u8 *)param))
+ res = _FAIL;
+- rtw_mfree((u8 *)param, sizeof(*param));
++ kfree((u8 *)param);
+ }
+
+ exit:
+@@ -1426,7 +1121,7 @@ _func_enter_;
+ if(enqueue){
+ ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));
+ if(ph2c==NULL){
+- rtw_mfree((u8 *)psetop, sizeof(*psetop));
++ kfree((u8 *)psetop);
+ res= _FAIL;
+ goto exit;
+ }
+@@ -1436,7 +1131,7 @@ _func_enter_;
+ }
+ else{
+ setopmode_hdl(padapter, (u8 *)psetop);
+- rtw_mfree((u8 *)psetop, sizeof(*psetop));
++ kfree((u8 *)psetop);
+ }
+ exit:
+
+@@ -1486,15 +1181,15 @@ _func_enter_;
+ {
+ ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));
+ if ( ph2c == NULL){
+- rtw_mfree((u8 *) psetstakey_para, sizeof(struct set_stakey_parm));
++ 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){
+- rtw_mfree((u8 *) ph2c, sizeof(struct cmd_obj));
+- rtw_mfree((u8 *) psetstakey_para, sizeof(struct set_stakey_parm));
++ kfree((u8 *) ph2c);
++ kfree((u8 *) psetstakey_para);
+ res=_FAIL;
+ goto exit;
+ }
+@@ -1506,7 +1201,7 @@ _func_enter_;
+ }
+ else{
+ set_stakey_hdl(padapter, (u8 *)psetstakey_para);
+- rtw_mfree((u8 *) psetstakey_para, sizeof(struct set_stakey_parm));
++ kfree((u8 *) psetstakey_para);
+ }
+ exit:
+
+@@ -1546,15 +1241,15 @@ _func_enter_;
+
+ psetstakey_para = (struct set_stakey_parm*)rtw_zmalloc(sizeof(struct set_stakey_parm));
+ if(psetstakey_para==NULL){
+- rtw_mfree((u8 *) ph2c, sizeof(struct cmd_obj));
++ kfree((u8 *) ph2c);
+ res=_FAIL;
+ goto exit;
+ }
+
+ psetstakey_rsp = (struct set_stakey_rsp*)rtw_zmalloc(sizeof(struct set_stakey_rsp));
+ if(psetstakey_rsp == NULL){
+- rtw_mfree((u8 *) ph2c, sizeof(struct cmd_obj));
+- rtw_mfree((u8 *) psetstakey_para, sizeof(struct set_stakey_parm));
++ kfree((u8 *) ph2c);
++ kfree((u8 *) psetstakey_para);
+ res=_FAIL;
+ goto exit;
+ }
+@@ -1578,123 +1273,6 @@ _func_exit_;
+ return res;
+ }
+
+-u8 rtw_setrttbl_cmd(_adapter *padapter, struct setratable_parm *prate_table)
+-{
+- struct cmd_obj* ph2c;
+- struct setratable_parm * psetrttblparm;
+- struct cmd_priv *pcmdpriv=&padapter->cmdpriv;
+- u8 res=_SUCCESS;
+-_func_enter_;
+-
+- ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));
+- if(ph2c==NULL){
+- res= _FAIL;
+- goto exit;
+- }
+- psetrttblparm = (struct setratable_parm*)rtw_zmalloc(sizeof(struct setratable_parm));
+-
+- if(psetrttblparm==NULL){
+- rtw_mfree((unsigned char *) ph2c, sizeof(struct cmd_obj));
+- res= _FAIL;
+- goto exit;
+- }
+-
+- init_h2fwcmd_w_parm_no_rsp(ph2c, psetrttblparm, GEN_CMD_CODE(_SetRaTable));
+-
+- memcpy(psetrttblparm,prate_table,sizeof(struct setratable_parm));
+-
+- res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+-exit:
+-_func_exit_;
+- return res;
+-
+-}
+-
+-u8 rtw_getrttbl_cmd(_adapter *padapter, struct getratable_rsp *pval)
+-{
+- struct cmd_obj* ph2c;
+- struct getratable_parm * pgetrttblparm;
+- struct cmd_priv *pcmdpriv=&padapter->cmdpriv;
+- u8 res=_SUCCESS;
+-_func_enter_;
+-
+- ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));
+- if(ph2c==NULL){
+- res= _FAIL;
+- goto exit;
+- }
+- pgetrttblparm = (struct getratable_parm*)rtw_zmalloc(sizeof(struct getratable_parm));
+-
+- if(pgetrttblparm==NULL){
+- rtw_mfree((unsigned char *) ph2c, sizeof(struct cmd_obj));
+- res= _FAIL;
+- goto exit;
+- }
+-
+-// init_h2fwcmd_w_parm_no_rsp(ph2c, psetrttblparm, GEN_CMD_CODE(_SetRaTable));
+-
+- _rtw_init_listhead(&ph2c->list);
+- ph2c->cmdcode =GEN_CMD_CODE(_GetRaTable);
+- ph2c->parmbuf = (unsigned char *)pgetrttblparm;
+- ph2c->cmdsz = sizeof(struct getratable_parm);
+- ph2c->rsp = (u8*)pval;
+- ph2c->rspsz = sizeof(struct getratable_rsp);
+-
+- pgetrttblparm ->rsvd = 0x0;
+-
+- res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+-exit:
+-_func_exit_;
+- return res;
+-
+-}
+-
+-u8 rtw_setassocsta_cmd(_adapter *padapter, u8 *mac_addr)
+-{
+- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+- struct cmd_obj* ph2c;
+- struct set_assocsta_parm *psetassocsta_para;
+- struct set_stakey_rsp *psetassocsta_rsp = NULL;
+-
+- u8 res=_SUCCESS;
+-
+-_func_enter_;
+-
+- ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));
+- if(ph2c==NULL){
+- res= _FAIL;
+- goto exit;
+- }
+-
+- psetassocsta_para = (struct set_assocsta_parm*)rtw_zmalloc(sizeof(struct set_assocsta_parm));
+- if(psetassocsta_para==NULL){
+- rtw_mfree((u8 *) ph2c, sizeof(struct cmd_obj));
+- res=_FAIL;
+- goto exit;
+- }
+-
+- psetassocsta_rsp = (struct set_stakey_rsp*)rtw_zmalloc(sizeof(struct set_assocsta_rsp));
+- if(psetassocsta_rsp==NULL){
+- rtw_mfree((u8 *) ph2c, sizeof(struct cmd_obj));
+- rtw_mfree((u8 *) psetassocsta_para, sizeof(struct set_assocsta_parm));
+- return _FAIL;
+- }
+-
+- init_h2fwcmd_w_parm_no_rsp(ph2c, psetassocsta_para, _SetAssocSta_CMD_);
+- ph2c->rsp = (u8 *) psetassocsta_rsp;
+- ph2c->rspsz = sizeof(struct set_assocsta_rsp);
+-
+- memcpy(psetassocsta_para->addr, mac_addr,ETH_ALEN);
+-
+- res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+-
+-exit:
+-
+-_func_exit_;
+-
+- return res;
+- }
+-
+ u8 rtw_addbareq_cmd(_adapter*padapter, u8 tid, u8 *addr)
+ {
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+@@ -1713,7 +1291,7 @@ _func_enter_;
+
+ paddbareq_parm = (struct addBaReq_parm*)rtw_zmalloc(sizeof(struct addBaReq_parm));
+ if(paddbareq_parm==NULL){
+- rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
++ kfree((unsigned char *)ph2c);
+ res= _FAIL;
+ goto exit;
+ }
+@@ -1752,7 +1330,7 @@ _func_enter_;
+
+ pdrvextra_cmd_parm = (struct drvextra_cmd_parm*)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
+ if(pdrvextra_cmd_parm==NULL){
+- rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
++ kfree((unsigned char *)ph2c);
+ res= _FAIL;
+ goto exit;
+ }
+@@ -1793,7 +1371,7 @@ _func_enter_;
+
+ pdrvextra_cmd_parm = (struct drvextra_cmd_parm*)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
+ if(pdrvextra_cmd_parm==NULL){
+- rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
++ kfree((unsigned char *)ph2c);
+ res= _FAIL;
+ goto exit;
+ }
+@@ -1835,7 +1413,7 @@ _func_enter_;
+
+ pdrvextra_cmd_parm = (struct drvextra_cmd_parm*)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
+ if(pdrvextra_cmd_parm==NULL){
+- rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
++ kfree((unsigned char *)ph2c);
+ res= _FAIL;
+ goto exit;
+ }
+@@ -1858,61 +1436,6 @@ _func_exit_;
+
+ }
+
+-u8 rtw_set_ch_cmd(_adapter*padapter, u8 ch, u8 bw, u8 ch_offset, u8 enqueue)
+-{
+- struct cmd_obj *pcmdobj;
+- struct set_ch_parm *set_ch_parm;
+- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+-
+- u8 res=_SUCCESS;
+-
+-_func_enter_;
+-
+- DBG_871X(FUNC_NDEV_FMT" ch:%u, bw:%u, ch_offset:%u\n",
+- FUNC_NDEV_ARG(padapter->pnetdev), ch, bw, ch_offset);
+-
+- /* check input parameter */
+-
+- /* prepare cmd parameter */
+- set_ch_parm = (struct set_ch_parm *)rtw_zmalloc(sizeof(*set_ch_parm));
+- if (set_ch_parm == NULL) {
+- res= _FAIL;
+- goto exit;
+- }
+- set_ch_parm->ch = ch;
+- set_ch_parm->bw = bw;
+- set_ch_parm->ch_offset = ch_offset;
+-
+- if (enqueue) {
+- /* need enqueue, prepare cmd_obj and enqueue */
+- pcmdobj = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));
+- if(pcmdobj == NULL){
+- rtw_mfree((u8 *)set_ch_parm, sizeof(*set_ch_parm));
+- res=_FAIL;
+- goto exit;
+- }
+-
+- init_h2fwcmd_w_parm_no_rsp(pcmdobj, set_ch_parm, GEN_CMD_CODE(_SetChannel));
+- res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
+- } else {
+- /* no need to enqueue, do the cmd hdl directly and free cmd parameter */
+- if( H2C_SUCCESS !=set_ch_hdl(padapter, (u8 *)set_ch_parm) )
+- res = _FAIL;
+-
+- rtw_mfree((u8 *)set_ch_parm, sizeof(*set_ch_parm));
+- }
+-
+- /* do something based on res... */
+-
+-exit:
+-
+- DBG_871X(FUNC_NDEV_FMT" res:%u\n", FUNC_NDEV_ARG(padapter->pnetdev), res);
+-
+-_func_exit_;
+-
+- return res;
+-}
+-
+ u8 rtw_set_chplan_cmd(_adapter*padapter, u8 chplan, u8 enqueue, u8 swconfig)
+ {
+ struct cmd_obj* pcmdobj;
+@@ -1951,7 +1474,7 @@ _func_enter_;
+ //need enqueue, prepare cmd_obj and enqueue
+ pcmdobj = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));
+ if(pcmdobj == NULL){
+- rtw_mfree((u8 *)setChannelPlan_param, sizeof(struct SetChannelPlan_param));
++ kfree((u8 *)setChannelPlan_param);
+ res=_FAIL;
+ goto exit;
+ }
+@@ -1965,7 +1488,7 @@ _func_enter_;
+ if( H2C_SUCCESS !=set_chplan_hdl(padapter, (unsigned char *)setChannelPlan_param) )
+ res = _FAIL;
+
+- rtw_mfree((u8 *)setChannelPlan_param, sizeof(struct SetChannelPlan_param));
++ kfree((u8 *)setChannelPlan_param);
+ }
+
+ //do something based on res...
+@@ -1979,92 +1502,6 @@ _func_exit_;
+ return res;
+ }
+
+-u8 rtw_led_blink_cmd(_adapter*padapter, void * pLed)
+-{
+- struct cmd_obj* pcmdobj;
+- struct LedBlink_param *ledBlink_param;
+- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+-
+- u8 res=_SUCCESS;
+-
+-_func_enter_;
+-
+- RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+rtw_led_blink_cmd\n"));
+-
+- pcmdobj = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));
+- if(pcmdobj == NULL){
+- res=_FAIL;
+- goto exit;
+- }
+-
+- ledBlink_param = (struct LedBlink_param *)rtw_zmalloc(sizeof(struct LedBlink_param));
+- if(ledBlink_param == NULL) {
+- rtw_mfree((u8 *)pcmdobj, sizeof(struct cmd_obj));
+- res= _FAIL;
+- goto exit;
+- }
+-
+- ledBlink_param->pLed=pLed;
+-
+- init_h2fwcmd_w_parm_no_rsp(pcmdobj, ledBlink_param, GEN_CMD_CODE(_LedBlink));
+- res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
+-
+-exit:
+-
+-_func_exit_;
+-
+- return res;
+-}
+-
+-u8 rtw_set_csa_cmd(_adapter*padapter, u8 new_ch_no)
+-{
+- struct cmd_obj* pcmdobj;
+- struct SetChannelSwitch_param*setChannelSwitch_param;
+- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+-
+- u8 res=_SUCCESS;
+-
+-_func_enter_;
+-
+- RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+rtw_set_csa_cmd\n"));
+-
+- pcmdobj = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));
+- if(pcmdobj == NULL){
+- res=_FAIL;
+- goto exit;
+- }
+-
+- setChannelSwitch_param = (struct SetChannelSwitch_param *)rtw_zmalloc(sizeof(struct SetChannelSwitch_param));
+- if(setChannelSwitch_param == NULL) {
+- rtw_mfree((u8 *)pcmdobj, sizeof(struct cmd_obj));
+- res= _FAIL;
+- goto exit;
+- }
+-
+- setChannelSwitch_param->new_ch_no=new_ch_no;
+-
+- init_h2fwcmd_w_parm_no_rsp(pcmdobj, setChannelSwitch_param, GEN_CMD_CODE(_SetChannelSwitch));
+- res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
+-
+-exit:
+-
+-_func_exit_;
+-
+- return res;
+-}
+-
+-u8 rtw_tdls_cmd(_adapter *padapter, u8 *addr, u8 option)
+-{
+- u8 res=_SUCCESS;
+-
+-_func_enter_;
+-
+-_func_exit_;
+-
+- return res;
+-}
+-
+ static void collect_traffic_statistics(_adapter *padapter)
+ {
+ struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
+@@ -2150,8 +1587,6 @@ u8 traffic_status_watchdog(_adapter *pad
+ TRAFFIC_PROTECT_PERIOD_MS,
+ link_detect->NumTxOkInPeriod,
+ link_detect->NumRxUnicastOkInPeriod);
+-
+- rtw_lock_traffic_suspend_timeout(TRAFFIC_PROTECT_PERIOD_MS);
+ }
+ #endif
+
+@@ -2250,12 +1685,10 @@ static void dynamic_chk_wk_hdl(_adapter
+ struct mlme_priv *pmlmepriv;
+ pmlmepriv = &(padapter->mlmepriv);
+
+-#ifdef CONFIG_AP_MODE
+ if(check_fwstate(pmlmepriv, WIFI_AP_STATE) == true)
+ {
+ expire_timeout_chk(padapter);
+ }
+-#endif
+
+ //for debug purpose
+ _linked_info_dump(padapter);
+@@ -2370,7 +1803,7 @@ _func_enter_;
+
+ pdrvextra_cmd_parm = (struct drvextra_cmd_parm*)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
+ if(pdrvextra_cmd_parm==NULL){
+- rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
++ kfree((unsigned char *)ph2c);
+ res= _FAIL;
+ goto exit;
+ }
+@@ -2418,7 +1851,7 @@ u8 rtw_dm_in_lps_wk_cmd(_adapter*padapte
+
+ pdrvextra_cmd_parm = (struct drvextra_cmd_parm*)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
+ if(pdrvextra_cmd_parm==NULL){
+- rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
++ kfree((unsigned char *)ph2c);
+ res= _FAIL;
+ goto exit;
+ }
+@@ -2470,43 +1903,6 @@ static void rtw_lps_change_dtim_hdl(_ada
+ up(&pwrpriv->lock);
+ }
+
+-u8 rtw_lps_change_dtim_cmd(_adapter*padapter, u8 dtim)
+-{
+- 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){
+- rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
+- res= _FAIL;
+- goto exit;
+- }
+-
+- pdrvextra_cmd_parm->ec_id = LPS_CHANGE_DTIM_CID;
+- pdrvextra_cmd_parm->type = dtim;
+- 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_dm_ra_mask_hdl(_adapter *padapter, struct sta_info *psta)
+ {
+ if (psta) {
+@@ -2530,7 +1926,7 @@ u8 rtw_dm_ra_mask_wk_cmd(_adapter*padapt
+
+ pdrvextra_cmd_parm = (struct drvextra_cmd_parm*)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
+ if(pdrvextra_cmd_parm==NULL){
+- rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
++ kfree((unsigned char *)ph2c);
+ res= _FAIL;
+ goto exit;
+ }
+@@ -2583,7 +1979,7 @@ _func_enter_;
+
+ pdrvextra_cmd_parm = (struct drvextra_cmd_parm*)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
+ if(pdrvextra_cmd_parm==NULL){
+- rtw_mfree((unsigned char *)ppscmd, sizeof(struct cmd_obj));
++ kfree((unsigned char *)ppscmd);
+ res= _FAIL;
+ goto exit;
+ }
+@@ -2604,8 +2000,6 @@ _func_exit_;
+
+ }
+
+-#ifdef CONFIG_AP_MODE
+-
+ extern u32 g_wait_hiq_empty;
+
+ static void rtw_chk_hi_queue_hdl(_adapter *padapter)
+@@ -2666,7 +2060,7 @@ u8 rtw_chk_hi_queue_cmd(_adapter*padapte
+
+ pdrvextra_cmd_parm = (struct drvextra_cmd_parm*)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
+ if(pdrvextra_cmd_parm==NULL){
+- rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
++ kfree((unsigned char *)ph2c);
+ res= _FAIL;
+ goto exit;
+ }
+@@ -2685,7 +2079,6 @@ exit:
+ return res;
+
+ }
+-#endif
+
+ struct btinfo {
+ u8 cid;
+@@ -2751,50 +2144,6 @@ static void rtw_btinfo_hdl(_adapter *ada
+ rtw_btcoex_BtInfoNotify(adapter ,len+1, &buf[1]);
+ }
+
+-u8 rtw_btinfo_cmd(_adapter *adapter, u8 *buf, u16 len)
+-{
+- struct cmd_obj *ph2c;
+- struct drvextra_cmd_parm *pdrvextra_cmd_parm;
+- u8 *btinfo;
+- struct cmd_priv *pcmdpriv = &adapter->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) {
+- rtw_mfree((u8*)ph2c, sizeof(struct cmd_obj));
+- res = _FAIL;
+- goto exit;
+- }
+-
+- btinfo = rtw_zmalloc(len);
+- if (btinfo == NULL) {
+- rtw_mfree((u8*)ph2c, sizeof(struct cmd_obj));
+- rtw_mfree((u8*)pdrvextra_cmd_parm, sizeof(struct drvextra_cmd_parm));
+- res = _FAIL;
+- goto exit;
+- }
+-
+- pdrvextra_cmd_parm->ec_id = BTINFO_WK_CID;
+- pdrvextra_cmd_parm->type = 0;
+- pdrvextra_cmd_parm->size = len;
+- pdrvextra_cmd_parm->pbuf = btinfo;
+-
+- memcpy(btinfo, buf, len);
+-
+- 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;
+-}
+-
+ u8 rtw_c2h_packet_wk_cmd(PADAPTER padapter, u8 *pbuf, u16 length)
+ {
+ struct cmd_obj *ph2c;
+@@ -2810,7 +2159,7 @@ u8 rtw_c2h_packet_wk_cmd(PADAPTER padapt
+
+ pdrvextra_cmd_parm = (struct drvextra_cmd_parm*)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
+ if (pdrvextra_cmd_parm == NULL) {
+- rtw_mfree((u8*)ph2c, sizeof(struct cmd_obj));
++ kfree((u8*)ph2c);
+ res = _FAIL;
+ goto exit;
+ }
+@@ -2845,7 +2194,7 @@ u8 rtw_c2h_wk_cmd(PADAPTER padapter, u8
+
+ pdrvextra_cmd_parm = (struct drvextra_cmd_parm*)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
+ if (pdrvextra_cmd_parm == NULL) {
+- rtw_mfree((u8*)ph2c, sizeof(struct cmd_obj));
++ kfree((u8*)ph2c);
+ res = _FAIL;
+ goto exit;
+ }
+@@ -2864,42 +2213,6 @@ exit:
+ return res;
+ }
+
+-u8 rtw_run_in_thread_cmd(PADAPTER padapter, void (*func)(void*), void* context)
+-{
+- struct cmd_priv *pcmdpriv;
+- struct cmd_obj *ph2c;
+- struct RunInThread_param *parm;
+- s32 res = _SUCCESS;
+-
+-_func_enter_;
+-
+- pcmdpriv = &padapter->cmdpriv;
+-
+- ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));
+- if (NULL == ph2c) {
+- res = _FAIL;
+- goto exit;
+- }
+-
+- parm = (struct RunInThread_param*)rtw_zmalloc(sizeof(struct RunInThread_param));
+- if (NULL == parm) {
+- rtw_mfree((u8*)ph2c, sizeof(struct cmd_obj));
+- res = _FAIL;
+- goto exit;
+- }
+-
+- parm->func = func;
+- parm->context = context;
+- init_h2fwcmd_w_parm_no_rsp(ph2c, parm, GEN_CMD_CODE(_RunInThreadCMD));
+-
+- res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+-exit:
+-
+-_func_exit_;
+-
+- return res;
+-}
+-
+ static void c2h_wk_callback(_workitem *work)
+ {
+ struct evt_priv *evtpriv = container_of(work, struct evt_priv, c2h_wk);
+@@ -2916,7 +2229,7 @@ static void c2h_wk_callback(_workitem *w
+ } else if ((c2h_evt = (u8 *)rtw_malloc(16)) != NULL) {
+ /* This C2H event is not read, read & clear now */
+ if (rtw_hal_c2h_evt_read(adapter, c2h_evt) != _SUCCESS) {
+- rtw_mfree(c2h_evt, 16);
++ kfree(c2h_evt);
+ continue;
+ }
+ }
+@@ -2926,14 +2239,14 @@ static void c2h_wk_callback(_workitem *w
+ continue;
+
+ if (!rtw_hal_c2h_valid(adapter, c2h_evt)) {
+- rtw_mfree(c2h_evt, 16);
++ kfree(c2h_evt);
+ continue;
+ }
+
+ if (ccx_id_filter(c2h_evt) == true) {
+ /* Handle CCX report here */
+ rtw_hal_c2h_handler(adapter, c2h_evt);
+- rtw_mfree(c2h_evt, 16);
++ kfree(c2h_evt);
+ } else {
+ /* Enqueue into cmd_thread for others */
+ rtw_c2h_wk_cmd(adapter, c2h_evt);
+@@ -2969,11 +2282,9 @@ u8 rtw_drvextra_cmd_hdl(_adapter *padapt
+ case LPS_CHANGE_DTIM_CID:
+ rtw_lps_change_dtim_hdl(padapter, (u8)pdrvextra_cmd->type);
+ break;
+-#ifdef CONFIG_AP_MODE
+ case CHECK_HIQ_WK_CID:
+ rtw_chk_hi_queue_hdl(padapter);
+ break;
+-#endif //CONFIG_AP_MODE
+ #ifdef CONFIG_INTEL_WIDI
+ case INTEl_WIDI_WK_CID:
+ intel_widi_wk_hdl(padapter, pdrvextra_cmd->type, pdrvextra_cmd->pbuf);
+@@ -3001,7 +2312,7 @@ u8 rtw_drvextra_cmd_hdl(_adapter *padapt
+
+ if (pdrvextra_cmd->pbuf && pdrvextra_cmd->size>0)
+ {
+- rtw_mfree(pdrvextra_cmd->pbuf, pdrvextra_cmd->size);
++ kfree(pdrvextra_cmd->pbuf);
+ }
+
+ return H2C_SUCCESS;
+@@ -3038,9 +2349,9 @@ _func_enter_;
+
+ if (pcmd->res != H2C_SUCCESS)
+ {
+- _enter_critical_bh(&pmlmepriv->lock, &irqL);
++ spin_lock_bh(&pmlmepriv->lock);
+ set_fwstate(pmlmepriv, _FW_LINKED);
+- _exit_critical_bh(&pmlmepriv->lock, &irqL);
++ spin_unlock_bh(&pmlmepriv->lock);
+
+ RT_TRACE(_module_rtl871x_cmd_c_,_drv_err_,("\n ***Error: disconnect_cmd_callback Fail ***\n."));
+
+@@ -3100,7 +2411,7 @@ _func_enter_;
+
+ _cancel_timer(&pmlmepriv->assoc_timer, &timer_cancelled);
+
+- _enter_critical_bh(&pmlmepriv->lock, &irqL);
++ spin_lock_bh(&pmlmepriv->lock);
+
+
+ if(check_fwstate(pmlmepriv, WIFI_AP_STATE) )
+@@ -3123,28 +2434,28 @@ _func_enter_;
+ _irqL irqL;
+
+ pwlan = _rtw_alloc_network(pmlmepriv);
+- _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
++ 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"));
+- _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
++ spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
+ goto createbss_cmd_fail;
+ }
+ pwlan->last_scanned = jiffies;
+ }
+ else
+ {
+- rtw_list_insert_tail(&(pwlan->list), &pmlmepriv->scanned_queue.queue);
++ 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;
+
+- //rtw_list_insert_tail(&(pwlan->list), &pmlmepriv->scanned_queue.queue);
++ //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)));
+@@ -3154,14 +2465,14 @@ _func_enter_;
+
+ _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
+
+- _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
++ 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:
+
+- _exit_critical_bh(&pmlmepriv->lock, &irqL);
++ spin_unlock_bh(&pmlmepriv->lock);
+ exit:
+ rtw_free_cmd_obj(pcmd);
+
+@@ -3214,28 +2525,16 @@ _func_enter_;
+
+ psta->aid = psta->mac_id = passocsta_rsp->cam_id;
+
+- _enter_critical_bh(&pmlmepriv->lock, &irqL);
++ 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);
+- _exit_critical_bh(&pmlmepriv->lock, &irqL);
++ spin_unlock_bh(&pmlmepriv->lock);
+
+ exit:
+ rtw_free_cmd_obj(pcmd);
+
+ _func_exit_;
+ }
+-
+-void rtw_getrttbl_cmd_cmdrsp_callback(_adapter* padapter, struct cmd_obj *pcmd);
+-void rtw_getrttbl_cmd_cmdrsp_callback(_adapter* padapter, struct cmd_obj *pcmd)
+-{
+-_func_enter_;
+-
+- rtw_free_cmd_obj(pcmd);
+-
+-_func_exit_;
+-
+-}
+-
+diff -Nurp linux/3rdparty/rtl8723bs.old/core/rtw_debug.c linux/3rdparty/rtl8723bs/core/rtw_debug.c
+--- linux/3rdparty/rtl8723bs.old/core/rtw_debug.c 2015-05-10 14:36:05.666667879 +0300
++++ linux/3rdparty/rtl8723bs/core/rtw_debug.c 2015-05-07 17:46:55.000000000 +0300
+@@ -62,7 +62,7 @@ u32 GlobalDebugLevel = _drv_err_;
+
+ void dump_drv_version(void *sel)
+ {
+- DBG_871X_SEL_NL(sel, "%s %s\n", DRV_NAME, DRIVERVERSION);
++ DBG_871X_SEL_NL(sel, "%s %s\n", "rtl8723bs", DRIVERVERSION);
+ }
+
+ void dump_log_level(void *sel)
+@@ -309,7 +309,6 @@ int proc_get_mlmext_state(struct seq_fil
+ return 0;
+ }
+
+-#ifdef CONFIG_LAYER2_ROAMING
+ int proc_get_roam_flags(struct seq_file *m, void *v)
+ {
+ struct net_device *dev = m->private;
+@@ -411,7 +410,6 @@ ssize_t proc_set_roam_tgt_addr(struct fi
+
+ return count;
+ }
+-#endif /* CONFIG_LAYER2_ROAMING */
+
+ int proc_get_qos_option(struct seq_file *m, void *v)
+ {
+@@ -463,18 +461,19 @@ int proc_get_survey_info(struct seq_file
+ s16 notify_noise = 0;
+ u16 index = 0;
+
+- _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
++ 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)) {
+- _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
++ 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 (rtw_end_of_queue_search(phead,plist)== true)
++ if (phead == plist)
+ break;
+
+ pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
+@@ -504,7 +503,7 @@ int proc_get_survey_info(struct seq_file
+ pnetwork->network.Ssid.Ssid);
+ plist = get_next(plist);
+ }
+- _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
++ spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
+
+ return 0;
+ }
+@@ -1325,9 +1324,6 @@ ssize_t proc_set_rssi_disp(struct file *
+
+ }
+
+-
+-#ifdef CONFIG_AP_MODE
+-
+ int proc_get_all_sta_info(struct seq_file *m, void *v)
+ {
+ struct net_device *dev = m->private;
+@@ -1341,14 +1337,14 @@ int proc_get_all_sta_info(struct seq_fil
+
+ DBG_871X_SEL_NL(m, "sta_dz_bitmap=0x%x, tim_bitmap=0x%x\n", pstapriv->sta_dz_bitmap, pstapriv->tim_bitmap);
+
+- _enter_critical_bh(&pstapriv->sta_hash_lock, &irqL);
++ spin_lock_bh(&pstapriv->sta_hash_lock);
+
+ for(i=0; i< NUM_STA; i++)
+ {
+ phead = &(pstapriv->sta_hash[i]);
+ plist = get_next(phead);
+
+- while ((rtw_end_of_queue_search(phead, plist)) == false)
++ while (phead != plist)
+ {
+ psta = LIST_CONTAINOR(plist, struct sta_info, hash_list);
+
+@@ -1394,12 +1390,10 @@ int proc_get_all_sta_info(struct seq_fil
+
+ }
+
+- _exit_critical_bh(&pstapriv->sta_hash_lock, &irqL);
++ spin_unlock_bh(&pstapriv->sta_hash_lock);
+
+ return 0;
+ }
+-
+-#endif
+
+ int proc_get_btcoex_dbg(struct seq_file *m, void *v)
+ {
+@@ -1497,7 +1491,7 @@ int proc_get_btcoex_info(struct seq_file
+
+ DBG_871X_SEL(m, "%s\n", pbuf);
+
+- rtw_mfree(pbuf, bufsize);
++ kfree(pbuf);
+
+ return 0;
+ }
+diff -Nurp linux/3rdparty/rtl8723bs.old/core/rtw_eeprom.c linux/3rdparty/rtl8723bs/core/rtw_eeprom.c
+--- linux/3rdparty/rtl8723bs.old/core/rtw_eeprom.c 2015-05-10 14:36:05.666667879 +0300
++++ linux/3rdparty/rtl8723bs/core/rtw_eeprom.c 1970-01-01 02:00:00.000000000 +0200
+@@ -1,381 +0,0 @@
+-/******************************************************************************
+- *
+- * 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.
+- *
+- * 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.,
+- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+- *
+- *
+- ******************************************************************************/
+-#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>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);
+-
+- if(addr_2align_odd) //read that start at high part: e.g 1,3,5,7,9,...
+- {
+- 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/3rdparty/rtl8723bs.old/core/rtw_efuse.c linux/3rdparty/rtl8723bs/core/rtw_efuse.c
+--- linux/3rdparty/rtl8723bs.old/core/rtw_efuse.c 2015-05-10 14:36:05.666667879 +0300
++++ linux/3rdparty/rtl8723bs/core/rtw_efuse.c 2015-05-07 17:46:55.000000000 +0300
+@@ -121,18 +121,8 @@ Efuse_PowerSwitch(
+ pAdapter->HalFunc.EfusePowerSwitch(pAdapter, bWrite, PwrState);
+ }
+
+-void
+-BTEfuse_PowerSwitch(
+- IN PADAPTER pAdapter,
+- IN u8 bWrite,
+- IN u8 PwrState)
+-{
+- if(pAdapter->HalFunc.BTEfusePowerSwitch)
+- pAdapter->HalFunc.BTEfusePowerSwitch(pAdapter, bWrite, PwrState);
+-}
+-
+ /*-----------------------------------------------------------------------------
+- * Function: efuse_GetCurrentSize
++ * Function: Efuse_GetCurrentSize
+ *
+ * Overview: Get current efuse size!!!
+ *
+@@ -174,68 +164,6 @@ Efuse_CalculateWordCnts(IN u8 word_en)
+
+ //
+ // Description:
+-// Execute E-Fuse read byte operation.
+-// 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.
+-//
+-void
+-ReadEFuseByte(
+- PADAPTER Adapter,
+- u16 _offset,
+- u8 *pbuf,
+- IN bool bPseudoTest)
+-{
+- u32 value32;
+- u8 readbyte;
+- u16 retry;
+-
+- if(bPseudoTest)
+- {
+- Efuse_Read1ByteFromFakeContent(Adapter, _offset, pbuf);
+- return;
+- }
+- // <20130121, Kordan> For SMIC S55 EFUSE specificatoin.
+- //0x34[11]: SW force PGMEN input of efuse to high. (for the bank selected by 0x34[9:8])
+- PHY_SetMacReg(Adapter, EFUSE_TEST, BIT11, 0);
+-
+- //Write Address
+- rtw_write8(Adapter, EFUSE_CTRL+1, (_offset & 0xff));
+- readbyte = rtw_read8(Adapter, EFUSE_CTRL+2);
+- rtw_write8(Adapter, EFUSE_CTRL+2, ((_offset >> 8) & 0x03) | (readbyte & 0xfc));
+-
+- //Write bit 32 0
+- readbyte = rtw_read8(Adapter, EFUSE_CTRL+3);
+- rtw_write8(Adapter, EFUSE_CTRL+3, (readbyte & 0x7f));
+-
+- //Check bit 32 read-ready
+- retry = 0;
+- value32 = rtw_read32(Adapter, EFUSE_CTRL);
+- //while(!(((value32 >> 24) & 0xff) & 0x80) && (retry<10))
+- while(!(((value32 >> 24) & 0xff) & 0x80) && (retry<10000))
+- {
+- value32 = rtw_read32(Adapter, EFUSE_CTRL);
+- retry++;
+- }
+-
+- // 20100205 Joseph: Add delay suggested by SD1 Victor.
+- // This fix the problem that Efuse read error in high temperature condition.
+- // Designer says that there shall be some delay after ready bit is set, or the
+- // result will always stay on last data we read.
+- udelay(50);
+- value32 = rtw_read32(Adapter, EFUSE_CTRL);
+-
+- *pbuf = (u8)(value32 & 0xff);
+- //DBG_871X("ReadEFuseByte _offset:%08u, in %d ms\n",_offset ,jiffies_to_msecs(jiffies - start));
+-
+-}
+-
+-//
+-// Description:
+ // 1. Execute E-Fuse read byte operation according as map offset and
+ // save to E-Fuse table.
+ // 2. Refered from SD1 Richard.
+@@ -350,76 +278,6 @@ EFUSE_Read1Byte(
+
+ }/* EFUSE_Read1Byte */
+
+-/*-----------------------------------------------------------------------------
+- * Function: EFUSE_Write1Byte
+- *
+- * Overview: Copy from WMAC fot EFUSE write 1 byte.
+- *
+- * Input: NONE
+- *
+- * Output: NONE
+- *
+- * Return: NONE
+- *
+- * Revised History:
+- * When Who Remark
+- * 09/23/2008 MHC Copy from WMAC.
+- *
+- *---------------------------------------------------------------------------*/
+-
+-void
+-EFUSE_Write1Byte(
+- IN PADAPTER Adapter,
+- IN u16 Address,
+- IN u8 Value);
+-void
+-EFUSE_Write1Byte(
+- IN PADAPTER Adapter,
+- IN u16 Address,
+- IN u8 Value)
+-{
+- u8 Bytetemp = {0x00};
+- u8 temp = {0x00};
+- u32 k=0;
+- u16 contentLen=0;
+-
+- //RT_TRACE(COMP_EFUSE, DBG_LOUD, ("Addr=%x Data =%x\n", Address, Value));
+- EFUSE_GetEfuseDefinition(Adapter, EFUSE_WIFI , TYPE_EFUSE_REAL_CONTENT_LEN, (void *)&contentLen, false);
+-
+- if( Address < contentLen) //E-fuse 512Byte
+- {
+- rtw_write8(Adapter, EFUSE_CTRL, Value);
+-
+- //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]=1
+- Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+3);
+- temp = Bytetemp | 0x80;
+- rtw_write8(Adapter, EFUSE_CTRL+3, temp);
+-
+- //Wait Write-ready (0x30[31]=0)
+- Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+3);
+- while(Bytetemp & 0x80)
+- {
+- Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+3);
+- k++;
+- if(k==100)
+- {
+- k=0;
+- break;
+- }
+- }
+- }
+-}/* EFUSE_Write1Byte */
+-
+-
+ /* 11/16/2008 MH Read one byte from real Efuse. */
+ u8
+ efuse_OneByteRead(
+@@ -642,289 +500,6 @@ Efuse_WordEnableDataWrite( IN PADAPTER p
+ return ret;
+ }
+
+-static u8 efuse_read8(PADAPTER padapter, u16 address, u8 *value)
+-{
+- return efuse_OneByteRead(padapter,address, value, false);
+-}
+-
+-static u8 efuse_write8(PADAPTER padapter, u16 address, u8 *value)
+-{
+- return efuse_OneByteWrite(padapter,address, *value, false);
+-}
+-
+-/*
+- * read/wirte raw efuse data
+- */
+-u8 rtw_efuse_access(PADAPTER padapter, u8 bWrite, u16 start_addr, u16 cnts, u8 *data)
+-{
+- int i = 0;
+- u16 real_content_len = 0, max_available_size = 0;
+- u8 res = _FAIL ;
+- u8 (*rw8)(PADAPTER, u16, u8*);
+-
+- EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_REAL_CONTENT_LEN, (void *)&real_content_len, false);
+- EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false);
+-
+- if (start_addr > real_content_len)
+- return _FAIL;
+-
+- if (true == bWrite) {
+- if ((start_addr + cnts) > max_available_size)
+- return _FAIL;
+- rw8 = &efuse_write8;
+- } else
+- rw8 = &efuse_read8;
+-
+- Efuse_PowerSwitch(padapter, bWrite, true);
+-
+- // e-fuse one byte read / write
+- for (i = 0; i < cnts; i++) {
+- if (start_addr >= real_content_len) {
+- res = _FAIL;
+- break;
+- }
+-
+- res = rw8(padapter, start_addr++, data++);
+- if (_FAIL == res) break;
+- }
+-
+- Efuse_PowerSwitch(padapter, bWrite, false);
+-
+- return res;
+-}
+-//------------------------------------------------------------------------------
+-u16 efuse_GetMaxSize(PADAPTER padapter)
+-{
+- u16 max_size;
+- EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI , TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_size, false);
+- return max_size;
+-}
+-//------------------------------------------------------------------------------
+-u8 efuse_GetCurrentSize(PADAPTER padapter, u16 *size)
+-{
+- Efuse_PowerSwitch(padapter, false, true);
+- *size = Efuse_GetCurrentSize(padapter, EFUSE_WIFI, false);
+- Efuse_PowerSwitch(padapter, false, false);
+-
+- return _SUCCESS;
+-}
+-//------------------------------------------------------------------------------
+-u8 rtw_efuse_map_read(PADAPTER padapter, u16 addr, u16 cnts, u8 *data)
+-{
+- u16 mapLen=0;
+-
+- EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, false);
+-
+- if ((addr + cnts) > mapLen)
+- return _FAIL;
+-
+- Efuse_PowerSwitch(padapter, false, true);
+-
+- efuse_ReadEFuse(padapter, EFUSE_WIFI, addr, cnts, data, false);
+-
+- Efuse_PowerSwitch(padapter, false, false);
+-
+- return _SUCCESS;
+-}
+-
+-u8 rtw_BT_efuse_map_read(PADAPTER padapter, u16 addr, u16 cnts, u8 *data)
+-{
+- u16 mapLen=0;
+-
+- EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, false);
+-
+- if ((addr + cnts) > mapLen)
+- return _FAIL;
+-
+- Efuse_PowerSwitch(padapter, false, true);
+-
+- efuse_ReadEFuse(padapter, EFUSE_BT, addr, cnts, data, false);
+-
+- Efuse_PowerSwitch(padapter, false, false);
+-
+- return _SUCCESS;
+-}
+-//------------------------------------------------------------------------------
+-u8 rtw_efuse_map_write(PADAPTER padapter, u16 addr, u16 cnts, u8 *data)
+-{
+-#define RT_ASSERT_RET(expr) \
+- if(!(expr)) { \
+- printk( "Assertion failed! %s at ......\n", #expr); \
+- printk( " ......%s,%s,line=%d\n",__FILE__,__FUNCTION__,__LINE__); \
+- return _FAIL; \
+- }
+-
+- u8 offset, word_en;
+- u8 *map;
+- u8 newdata[PGPKT_DATA_SIZE];
+- s32 i, j, idx;
+- u8 ret = _SUCCESS;
+- u16 mapLen=0;
+- EEPROM_EFUSE_PRIV *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
+- HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
+-
+- EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, false);
+-
+- if ((addr + cnts) > mapLen)
+- return _FAIL;
+-
+- RT_ASSERT_RET(PGPKT_DATA_SIZE == 8); // have to be 8 byte alignment
+- RT_ASSERT_RET((mapLen & 0x7) == 0); // have to be PGPKT_DATA_SIZE alignment for memcpy
+-
+- map = rtw_zmalloc(mapLen);
+- if(map == NULL){
+- return _FAIL;
+- }
+-
+- memset(map, 0xFF, mapLen);
+-
+- ret = rtw_efuse_map_read(padapter, 0, mapLen, map);
+- if (ret == _FAIL) goto exit;
+-
+- Efuse_PowerSwitch(padapter, true, true);
+-
+- idx = 0;
+- offset = (addr >> 3);
+- while (idx < cnts)
+- {
+- word_en = 0xF;
+- j = (addr + idx) & 0x7;
+- memcpy(newdata, &map[offset << 3], PGPKT_DATA_SIZE);
+- for (i = j; i> 1);
+- newdata[i] = data[idx];
+-
+- if( addr + idx == 0x8)
+- {
+- if (IS_C_CUT(pHalData->VersionID) || IS_B_CUT(pHalData->VersionID))
+- {
+- if(pEEPROM->adjuseVoltageVal == 6)
+- {
+- newdata[i] = map[addr + idx];
+- DBG_8192C(" %s ,\n adjuseVoltageVal = %d ,newdata[%d] = %x \n",__func__,pEEPROM->adjuseVoltageVal,i,newdata[i]);
+- }
+- }
+- }
+- }
+- }
+-
+- if (word_en != 0xF) {
+- ret = Efuse_PgPacketWrite(padapter, offset, word_en, newdata, false);
+- DBG_871X("offset=%x \n",offset);
+- DBG_871X("word_en=%x \n",word_en);
+-
+- for(i=0;i mapLen)
+- return _FAIL;
+-
+- RT_ASSERT_RET(PGPKT_DATA_SIZE == 8); // have to be 8 byte alignment
+- RT_ASSERT_RET((mapLen & 0x7) == 0); // have to be PGPKT_DATA_SIZE alignment for memcpy
+-
+- map = rtw_zmalloc(mapLen);
+- if(map == NULL){
+- return _FAIL;
+- }
+-
+- ret = rtw_BT_efuse_map_read(padapter, 0, mapLen, map);
+- if (ret == _FAIL) goto exit;
+- DBG_871X("OFFSET\tVALUE(hex)\n");
+- for (i=0; i<1024; i+=16) // set 512 because the iwpriv's extra size have limit 0x7FF
+- {
+- DBG_871X("0x%03x\t", i);
+- for (j=0; j<8; j++) {
+- DBG_871X("%02X ", map[i+j]);
+- }
+- DBG_871X("\t");
+- for (; j<16; j++) {
+- DBG_871X("%02X ", map[i+j]);
+- }
+- DBG_871X("\n");
+- }
+- DBG_871X("\n");
+- Efuse_PowerSwitch(padapter, true, true);
+-
+- idx = 0;
+- offset = (addr >> 3);
+- while (idx < cnts)
+- {
+- word_en = 0xF;
+- j = (addr + idx) & 0x7;
+- memcpy(newdata, &map[offset << 3], PGPKT_DATA_SIZE);
+- for (i = j; i> 1);
+- newdata[i] = data[idx];
+- }
+- }
+-
+- if (word_en != 0xF) {
+- DBG_871X("offset=%x \n",offset);
+- DBG_871X("word_en=%x \n",word_en);
+- DBG_871X("%s: data=", __FUNCTION__);
+- for(i=0;ipio_queue;
+- struct io_priv *pio_priv = &adapter->iopriv;
+- struct intf_hdl *pintfhdl = (struct intf_hdl*)(&(pio_priv->intf));
+- int (*_writeN)(struct intf_hdl *pintfhdl, u32 addr,u32 length, u8 *pdata);
+- int ret;
+- _func_enter_;
+- _writeN = pintfhdl->io_ops._writeN;
+-
+- ret = _writeN(pintfhdl, addr,length,pdata);
+- _func_exit_;
+-
+- return RTW_STATUS_CODE(ret);
+-}
+-
+ u8 _rtw_sd_f0_read8(_adapter *adapter, u32 addr)
+ {
+ u8 r_val = 0x00;
+@@ -178,129 +160,6 @@ u8 _rtw_sd_f0_read8(_adapter *adapter, u
+ return r_val;
+ }
+
+-int _rtw_write8_async(_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_async)(struct intf_hdl *pintfhdl, u32 addr, u8 val);
+- int ret;
+- _func_enter_;
+- _write8_async = pintfhdl->io_ops._write8_async;
+-
+- ret = _write8_async(pintfhdl, addr, val);
+- _func_exit_;
+-
+- return RTW_STATUS_CODE(ret);
+-}
+-int _rtw_write16_async(_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_async)(struct intf_hdl *pintfhdl, u32 addr, u16 val);
+- int ret;
+- _func_enter_;
+- _write16_async = pintfhdl->io_ops._write16_async;
+- val = rtw_cpu_to_le16(val);
+- ret = _write16_async(pintfhdl, addr, val);
+- _func_exit_;
+-
+- return RTW_STATUS_CODE(ret);
+-}
+-int _rtw_write32_async(_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_async)(struct intf_hdl *pintfhdl, u32 addr, u32 val);
+- int ret;
+- _func_enter_;
+- _write32_async = pintfhdl->io_ops._write32_async;
+- val = rtw_cpu_to_le32(val);
+- ret = _write32_async(pintfhdl, addr, val);
+- _func_exit_;
+-
+- return RTW_STATUS_CODE(ret);
+-}
+-
+-void _rtw_read_mem(_adapter *adapter, u32 addr, u32 cnt, u8 *pmem)
+-{
+- void (*_read_mem)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pmem);
+- //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);
+-
+- _func_enter_;
+-
+- if( (adapter->bDriverStopped ==true) || (adapter->bSurpriseRemoved == true))
+- {
+- RT_TRACE(_module_rtl871x_io_c_, _drv_info_, ("rtw_read_mem:bDriverStopped(%d) OR bSurpriseRemoved(%d)", adapter->bDriverStopped, adapter->bSurpriseRemoved));
+- return;
+- }
+-
+- _read_mem = pintfhdl->io_ops._read_mem;
+-
+- _read_mem(pintfhdl, addr, cnt, pmem);
+-
+- _func_exit_;
+-
+-}
+-
+-void _rtw_write_mem(_adapter *adapter, u32 addr, u32 cnt, u8 *pmem)
+-{
+- void (*_write_mem)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pmem);
+- //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);
+-
+- _func_enter_;
+-
+- _write_mem = pintfhdl->io_ops._write_mem;
+-
+- _write_mem(pintfhdl, addr, cnt, pmem);
+-
+- _func_exit_;
+-
+-}
+-
+-void _rtw_read_port(_adapter *adapter, u32 addr, u32 cnt, u8 *pmem)
+-{
+- u32 (*_read_port)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pmem);
+- //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);
+-
+- _func_enter_;
+-
+- if( (adapter->bDriverStopped ==true) || (adapter->bSurpriseRemoved == true))
+- {
+- RT_TRACE(_module_rtl871x_io_c_, _drv_info_, ("rtw_read_port:bDriverStopped(%d) OR bSurpriseRemoved(%d)", adapter->bDriverStopped, adapter->bSurpriseRemoved));
+- return;
+- }
+-
+- _read_port = pintfhdl->io_ops._read_port;
+-
+- _read_port(pintfhdl, addr, cnt, pmem);
+-
+- _func_exit_;
+-
+-}
+-
+-void _rtw_read_port_cancel(_adapter *adapter)
+-{
+- void (*_read_port_cancel)(struct intf_hdl *pintfhdl);
+- struct io_priv *pio_priv = &adapter->iopriv;
+- struct intf_hdl *pintfhdl = &(pio_priv->intf);
+-
+- _read_port_cancel = pintfhdl->io_ops._read_port_cancel;
+-
+- RTW_DISABLE_FUNC(adapter, DF_RX_BIT);
+-
+- if(_read_port_cancel)
+- _read_port_cancel(pintfhdl);
+-}
+-
+ u32 _rtw_write_port(_adapter *adapter, u32 addr, u32 cnt, u8 *pmem)
+ {
+ u32 (*_write_port)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pmem);
+@@ -320,36 +179,6 @@ u32 _rtw_write_port(_adapter *adapter, u
+ return ret;
+ }
+
+-u32 _rtw_write_port_and_wait(_adapter *adapter, u32 addr, u32 cnt, u8 *pmem, int timeout_ms)
+-{
+- int ret = _SUCCESS;
+- struct xmit_buf *pxmitbuf = (struct xmit_buf *)pmem;
+- struct submit_ctx sctx;
+-
+- rtw_sctx_init(&sctx, timeout_ms);
+- pxmitbuf->sctx = &sctx;
+-
+- ret = _rtw_write_port(adapter, addr, cnt, pmem);
+-
+- if (ret == _SUCCESS)
+- ret = rtw_sctx_wait(&sctx, __func__);
+-
+- return ret;
+-}
+-
+-void _rtw_write_port_cancel(_adapter *adapter)
+-{
+- void (*_write_port_cancel)(struct intf_hdl *pintfhdl);
+- struct io_priv *pio_priv = &adapter->iopriv;
+- struct intf_hdl *pintfhdl = &(pio_priv->intf);
+-
+- _write_port_cancel = pintfhdl->io_ops._write_port_cancel;
+-
+- RTW_DISABLE_FUNC(adapter, DF_TX_BIT);
+-
+- if(_write_port_cancel)
+- _write_port_cancel(pintfhdl);
+-}
+ int rtw_init_io_priv(_adapter *padapter, void (*set_intf_ops)(_adapter *padapter,struct _io_ops *pops))
+ {
+ struct io_priv *piopriv = &padapter->iopriv;
+diff -Nurp linux/3rdparty/rtl8723bs.old/core/rtw_ioctl_set.c linux/3rdparty/rtl8723bs/core/rtw_ioctl_set.c
+--- linux/3rdparty/rtl8723bs.old/core/rtw_ioctl_set.c 2015-05-10 14:36:05.668667902 +0300
++++ linux/3rdparty/rtl8723bs/core/rtw_ioctl_set.c 2015-05-07 17:46:55.000000000 +0300
+@@ -89,7 +89,7 @@ u8 rtw_do_join(_adapter * padapter)
+
+ _func_enter_;
+
+- _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
++ spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
+ phead = get_list_head(queue);
+ plist = get_next(phead);
+
+@@ -103,9 +103,9 @@ _func_enter_;
+
+ pmlmepriv->to_join = true;
+
+- if(_rtw_queue_empty(queue)== true)
++ if(list_empty(&queue->queue))
+ {
+- _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
++ 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
+@@ -133,7 +133,7 @@ _func_enter_;
+ else
+ {
+ int select_ret;
+- _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
++ spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
+ if((select_ret=rtw_select_and_join_from_scanned_queue(pmlmepriv))==_SUCCESS)
+ {
+ pmlmepriv->to_join = false;
+@@ -224,7 +224,7 @@ _func_enter_;
+ goto exit;
+ }
+
+- _enter_critical_bh(&pmlmepriv->lock, &irqL);
++ spin_lock_bh(&pmlmepriv->lock);
+
+
+ DBG_871X("Set BSSID under fw_state=0x%08x\n", get_fwstate(pmlmepriv));
+@@ -279,7 +279,7 @@ handle_tkip_countermeasure:
+ }
+
+ release_mlme_lock:
+- _exit_critical_bh(&pmlmepriv->lock, &irqL);
++ spin_unlock_bh(&pmlmepriv->lock);
+
+ exit:
+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
+@@ -311,7 +311,7 @@ _func_enter_;
+ goto exit;
+ }
+
+- _enter_critical_bh(&pmlmepriv->lock, &irqL);
++ 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) {
+@@ -400,7 +400,7 @@ handle_tkip_countermeasure:
+ }
+
+ release_mlme_lock:
+- _exit_critical_bh(&pmlmepriv->lock, &irqL);
++ spin_unlock_bh(&pmlmepriv->lock);
+
+ exit:
+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
+@@ -443,7 +443,7 @@ _func_enter_;
+ goto exit;
+ }
+
+- _enter_critical_bh(&pmlmepriv->lock, &irqL);
++ 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));
+@@ -480,7 +480,7 @@ handle_tkip_countermeasure:
+ }
+
+ release_mlme_lock:
+- _exit_critical_bh(&pmlmepriv->lock, &irqL);
++ spin_unlock_bh(&pmlmepriv->lock);
+
+ exit:
+
+@@ -512,13 +512,11 @@ _func_enter_;
+ {
+ //change to other mode from Ndis802_11APMode
+ cur_network->join_res = -1;
+-
+-#ifdef CONFIG_NATIVEAP_MLME
++
+ stop_ap_mode(padapter);
+-#endif
+ }
+
+- _enter_critical_bh(&pmlmepriv->lock, &irqL);
++ spin_lock_bh(&pmlmepriv->lock);
+
+ if((check_fwstate(pmlmepriv, _FW_LINKED)== true) ||(*pold_state==Ndis802_11IBSS))
+ rtw_disassoc_cmd(padapter, 0, true);
+@@ -551,11 +549,9 @@ _func_enter_;
+
+ case Ndis802_11APMode:
+ set_fwstate(pmlmepriv, WIFI_AP_STATE);
+-#ifdef CONFIG_NATIVEAP_MLME
+ start_ap_mode(padapter);
+ //rtw_indicate_connect(padapter);
+-#endif
+-
++
+ break;
+
+ case Ndis802_11AutoUnknown:
+@@ -568,7 +564,7 @@ _func_enter_;
+ //RT_TRACE(COMP_OID_SET, DBG_LOUD, ("set_infrastructure: fw_state:%x after changing mode\n",
+ // get_fwstate(pmlmepriv) ));
+
+- _exit_critical_bh(&pmlmepriv->lock, &irqL);
++ spin_unlock_bh(&pmlmepriv->lock);
+ }
+
+ _func_exit_;
+@@ -584,7 +580,7 @@ u8 rtw_set_802_11_disassociate(_adapter
+
+ _func_enter_;
+
+- _enter_critical_bh(&pmlmepriv->lock, &irqL);
++ spin_lock_bh(&pmlmepriv->lock);
+
+ if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
+ {
+@@ -598,7 +594,7 @@ _func_enter_;
+ DBG_871X("%s(): rtw_pwr_wakeup fail !!!\n",__FUNCTION__);
+ }
+
+- _exit_critical_bh(&pmlmepriv->lock, &irqL);
++ spin_unlock_bh(&pmlmepriv->lock);
+
+ _func_exit_;
+
+@@ -644,11 +640,11 @@ _func_enter_;
+ return _SUCCESS;
+ }
+
+- _enter_critical_bh(&pmlmepriv->lock, &irqL);
++ spin_lock_bh(&pmlmepriv->lock);
+
+ res = rtw_sitesurvey_cmd(padapter, pssid, ssid_max_num, NULL, 0);
+
+- _exit_critical_bh(&pmlmepriv->lock, &irqL);
++ spin_unlock_bh(&pmlmepriv->lock);
+ }
+ exit:
+
+@@ -674,11 +670,6 @@ _func_enter_;
+ if(psecuritypriv->ndisauthtype>3)
+ psecuritypriv->dot11AuthAlgrthm=dot11AuthAlgrthm_8021X;
+
+-#ifdef CONFIG_WAPI_SUPPORT
+- if(psecuritypriv->ndisauthtype == 6)
+- psecuritypriv->dot11AuthAlgrthm=dot11AuthAlgrthm_WAPI;
+-#endif
+-
+ res=rtw_set_auth(padapter,psecuritypriv);
+
+ if(res==_SUCCESS)
+@@ -755,467 +746,6 @@ _func_exit_;
+
+ }
+
+-u8 rtw_set_802_11_remove_wep(_adapter* padapter, u32 keyindex){
+-
+- u8 ret=_SUCCESS;
+-
+-_func_enter_;
+-
+- if (keyindex >= 0x80000000 || padapter == NULL){
+-
+- ret=false;
+- goto exit;
+-
+- }
+- else
+- {
+- int res;
+- struct security_priv* psecuritypriv=&(padapter->securitypriv);
+- if( keyindex < 4 ){
+-
+- memset(&psecuritypriv->dot11DefKey[keyindex], 0, 16);
+-
+- res=rtw_set_key(padapter,psecuritypriv,keyindex, 0, true);
+-
+- psecuritypriv->dot11DefKeylen[keyindex]=0;
+-
+- if(res==_FAIL)
+- ret=_FAIL;
+-
+- }
+- else
+- {
+- ret=_FAIL;
+- }
+-
+- }
+-
+-exit:
+-
+-_func_exit_;
+-
+- return ret;
+-
+-}
+-
+-u8 rtw_set_802_11_add_key(_adapter* padapter, NDIS_802_11_KEY *key){
+-
+- uint encryptionalgo;
+- u8 * pbssid;
+- struct sta_info *stainfo;
+- u8 bgroup = false;
+- u8 bgrouptkey = false;//can be remove later
+- u8 ret=_SUCCESS;
+-
+-_func_enter_;
+-
+- if (((key->KeyIndex & 0x80000000) == 0) && ((key->KeyIndex & 0x40000000) > 0)){
+-
+- // It is invalid to clear bit 31 and set bit 30. If the miniport driver encounters this combination,
+- // it must fail the request and return NDIS_STATUS_INVALID_DATA.
+- RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_info_,("rtw_set_802_11_add_key: ((key->KeyIndex & 0x80000000) == 0)[=%d] ",(int)(key->KeyIndex & 0x80000000) == 0));
+- RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_info_,("rtw_set_802_11_add_key:((key->KeyIndex & 0x40000000) > 0)[=%d]" , (int)(key->KeyIndex & 0x40000000) > 0));
+- RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_info_,("rtw_set_802_11_add_key: key->KeyIndex=%d \n" ,(int)key->KeyIndex));
+- ret= _FAIL;
+- goto exit;
+- }
+-
+- if(key->KeyIndex & 0x40000000)
+- {
+- // Pairwise key
+-
+- RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("OID_802_11_ADD_KEY: +++++ Pairwise key +++++\n"));
+-
+- pbssid=get_bssid(&padapter->mlmepriv);
+- stainfo=rtw_get_stainfo(&padapter->stapriv, pbssid);
+-
+- if((stainfo!=NULL)&&(padapter->securitypriv.dot11AuthAlgrthm==dot11AuthAlgrthm_8021X)){
+- RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("OID_802_11_ADD_KEY:( stainfo!=NULL)&&(Adapter->securitypriv.dot11AuthAlgrthm==dot11AuthAlgrthm_8021X)\n"));
+- encryptionalgo=stainfo->dot118021XPrivacy;
+- }
+- else{
+- RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("OID_802_11_ADD_KEY: stainfo==NULL)||(Adapter->securitypriv.dot11AuthAlgrthm!=dot11AuthAlgrthm_8021X)\n"));
+- encryptionalgo=padapter->securitypriv.dot11PrivacyAlgrthm;
+- }
+-
+- RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("rtw_set_802_11_add_key: (encryptionalgo ==%d)!\n",encryptionalgo ));
+- RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("rtw_set_802_11_add_key: (Adapter->securitypriv.dot11PrivacyAlgrthm ==%d)!\n",padapter->securitypriv.dot11PrivacyAlgrthm));
+- RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("rtw_set_802_11_add_key: (Adapter->securitypriv.dot11AuthAlgrthm ==%d)!\n",padapter->securitypriv.dot11AuthAlgrthm));
+-
+- if((stainfo!=NULL)){
+- RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("rtw_set_802_11_add_key: (stainfo->dot118021XPrivacy ==%d)!\n", stainfo->dot118021XPrivacy));
+- }
+-
+- if(key->KeyIndex & 0x000000FF){
+- // The key index is specified in the lower 8 bits by values of zero to 255.
+- // The key index should be set to zero for a Pairwise key, and the driver should fail with
+- // NDIS_STATUS_INVALID_DATA if the lower 8 bits is not zero
+- RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,(" key->KeyIndex & 0x000000FF.\n"));
+- ret= _FAIL;
+- goto exit;
+- }
+-
+- // check BSSID
+- if (IS_MAC_ADDRESS_BROADCAST(key->BSSID) == true){
+-
+- RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("MacAddr_isBcst(key->BSSID)\n"));
+- ret= false;
+- goto exit;
+- }
+-
+- // Check key length for TKIP.
+- //if(encryptionAlgorithm == RT_ENC_TKIP_ENCRYPTION && key->KeyLength != 32)
+- if((encryptionalgo== _TKIP_)&& (key->KeyLength != 32)){
+- RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("TKIP KeyLength:0x%x != 32\n", key->KeyLength));
+- ret=_FAIL;
+- goto exit;
+-
+- }
+-
+- // Check key length for AES.
+- if((encryptionalgo== _AES_)&& (key->KeyLength != 16)) {
+- // For our supplicant, EAPPkt9x.vxd, cannot differentiate TKIP and AES case.
+- if(key->KeyLength == 32) {
+- key->KeyLength = 16;
+- } else {
+- ret= _FAIL;
+- goto exit;
+- }
+- }
+-
+- // Check key length for WEP. For NDTEST, 2005.01.27, by rcnjko.
+- if( (encryptionalgo== _WEP40_|| encryptionalgo== _WEP104_) && (key->KeyLength != 5 || key->KeyLength != 13)) {
+- RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("WEP KeyLength:0x%x != 5 or 13\n", key->KeyLength));
+- ret=_FAIL;
+- goto exit;
+- }
+-
+- bgroup = false;
+-
+- // Check the pairwise key. Added by Annie, 2005-07-06.
+- RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("------------------------------------------\n"));
+- RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("[Pairwise Key set]\n"));
+- RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("------------------------------------------\n"));
+- RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("key index: 0x%8x(0x%8x)\n", key->KeyIndex,(key->KeyIndex&0x3)));
+- RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("key Length: %d\n", key->KeyLength));
+- RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("------------------------------------------\n"));
+-
+- }
+- else
+- {
+- // Group key - KeyIndex(BIT30==0)
+- RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("OID_802_11_ADD_KEY: +++++ Group key +++++\n"));
+-
+-
+- // when add wep key through add key and didn't assigned encryption type before
+- if((padapter->securitypriv.ndisauthtype<=3)&&(padapter->securitypriv.dot118021XGrpPrivacy==0))
+- {
+- RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("keylen=%d( Adapter->securitypriv.dot11PrivacyAlgrthm=%x )padapter->securitypriv.dot118021XGrpPrivacy(%x)\n", key->KeyLength,padapter->securitypriv.dot11PrivacyAlgrthm,padapter->securitypriv.dot118021XGrpPrivacy));
+-
+- switch(key->KeyLength)
+- {
+- case 5:
+- padapter->securitypriv.dot11PrivacyAlgrthm=_WEP40_;
+- RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("Adapter->securitypriv.dot11PrivacyAlgrthm= %x key->KeyLength=%u\n", padapter->securitypriv.dot11PrivacyAlgrthm,key->KeyLength));
+- break;
+- case 13:
+- padapter->securitypriv.dot11PrivacyAlgrthm=_WEP104_;
+- RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("Adapter->securitypriv.dot11PrivacyAlgrthm= %x key->KeyLength=%u\n", padapter->securitypriv.dot11PrivacyAlgrthm,key->KeyLength));
+- break;
+- default:
+- padapter->securitypriv.dot11PrivacyAlgrthm=_NO_PRIVACY_;
+- RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("Adapter->securitypriv.dot11PrivacyAlgrthm= %x key->KeyLength=%u \n", padapter->securitypriv.dot11PrivacyAlgrthm,key->KeyLength));
+- break;
+- }
+-
+- encryptionalgo=padapter->securitypriv.dot11PrivacyAlgrthm;
+-
+- RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,(" Adapter->securitypriv.dot11PrivacyAlgrthm=%x\n", padapter->securitypriv.dot11PrivacyAlgrthm));
+-
+- }
+- else
+- {
+- encryptionalgo=padapter->securitypriv.dot118021XGrpPrivacy;
+- RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("( Adapter->securitypriv.dot11PrivacyAlgrthm=%x )encryptionalgo(%x)=padapter->securitypriv.dot118021XGrpPrivacy(%x)keylen=%d\n", padapter->securitypriv.dot11PrivacyAlgrthm,encryptionalgo,padapter->securitypriv.dot118021XGrpPrivacy,key->KeyLength));
+-
+- }
+-
+- if((check_fwstate(&padapter->mlmepriv, WIFI_ADHOC_STATE)==true) && (IS_MAC_ADDRESS_BROADCAST(key->BSSID) == false)) {
+- RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,(" IBSS but BSSID is not Broadcast Address.\n"));
+- ret= _FAIL;
+- goto exit;
+- }
+-
+- // Check key length for TKIP
+- if((encryptionalgo== _TKIP_) && (key->KeyLength != 32)) {
+-
+- RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,(" TKIP GTK KeyLength:%u != 32\n", key->KeyLength));
+- ret= _FAIL;
+- goto exit;
+-
+- } else if(encryptionalgo== _AES_ && (key->KeyLength != 16 && key->KeyLength != 32) ) {
+-
+- // Check key length for AES
+- // For NDTEST, we allow keylen=32 in this case. 2005.01.27, by rcnjko.
+- RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("<=== SetInfo, OID_802_11_ADD_KEY: AES GTK KeyLength:%u != 16 or 32\n", key->KeyLength));
+- ret= _FAIL;
+- goto exit;
+- }
+-
+- // Change the key length for EAPPkt9x.vxd. Added by Annie, 2005-11-03.
+- if((encryptionalgo== _AES_) && (key->KeyLength == 32) ) {
+- key->KeyLength = 16;
+- RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("AES key length changed: %u\n", key->KeyLength) );
+- }
+-
+- if(key->KeyIndex & 0x8000000) {//error ??? 0x8000_0000
+- bgrouptkey = true;
+- }
+-
+- if((check_fwstate(&padapter->mlmepriv, WIFI_ADHOC_STATE)==true)&&(check_fwstate(&padapter->mlmepriv, _FW_LINKED)==true))
+- {
+- bgrouptkey = true;
+- }
+-
+- bgroup = true;
+-
+- RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("------------------------------------------\n") );
+- RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("[Group Key set]\n") );
+- RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("------------------------------------------\n")) ;
+- RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("key index: 0x%8x(0x%8x)\n", key->KeyIndex,(key->KeyIndex&0x3)));
+- RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("key Length: %d\n", key->KeyLength)) ;
+- RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("------------------------------------------\n"));
+-
+- }
+-
+- // If WEP encryption algorithm, just call rtw_set_802_11_add_wep().
+- if((padapter->securitypriv.dot11AuthAlgrthm !=dot11AuthAlgrthm_8021X)&&(encryptionalgo== _WEP40_ || encryptionalgo== _WEP104_))
+- {
+- u8 ret;
+- u32 keyindex;
+- u32 len = FIELD_OFFSET(NDIS_802_11_KEY, KeyMaterial) + key->KeyLength;
+- NDIS_802_11_WEP *wep = &padapter->securitypriv.ndiswep;
+-
+- RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("OID_802_11_ADD_KEY: +++++ WEP key +++++\n"));
+-
+- wep->Length = len;
+- keyindex = key->KeyIndex&0x7fffffff;
+- wep->KeyIndex = keyindex ;
+- wep->KeyLength = key->KeyLength;
+-
+- RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("OID_802_11_ADD_KEY:Before memcpy \n"));
+-
+- memcpy(wep->KeyMaterial, key->KeyMaterial, key->KeyLength);
+- memcpy(&(padapter->securitypriv.dot11DefKey[keyindex].skey[0]), key->KeyMaterial, key->KeyLength);
+-
+- padapter->securitypriv.dot11DefKeylen[keyindex]=key->KeyLength;
+- padapter->securitypriv.dot11PrivacyKeyIndex=keyindex;
+-
+- ret = rtw_set_802_11_add_wep(padapter, wep);
+-
+- goto exit;
+-
+- }
+-
+- if(key->KeyIndex & 0x20000000){
+- // SetRSC
+- RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("OID_802_11_ADD_KEY: +++++ SetRSC+++++\n"));
+- if(bgroup == true)
+- {
+- NDIS_802_11_KEY_RSC keysrc=key->KeyRSC & 0x00FFFFFFFFFFFFULL;
+- memcpy(&padapter->securitypriv.dot11Grprxpn, &keysrc, 8);
+- }
+- else
+- {
+- NDIS_802_11_KEY_RSC keysrc=key->KeyRSC & 0x00FFFFFFFFFFFFULL;
+- memcpy(&padapter->securitypriv.dot11Grptxpn, &keysrc, 8);
+- }
+-
+- }
+-
+- // Indicate this key idx is used for TX
+- // Save the key in KeyMaterial
+- if(bgroup == true) // Group transmit key
+- {
+- int res;
+-
+- if(bgrouptkey == true)
+- {
+- padapter->securitypriv.dot118021XGrpKeyid=(u8)key->KeyIndex;
+- }
+-
+- if((key->KeyIndex&0x3) == 0){
+- ret = _FAIL;
+- goto exit;
+- }
+-
+- memset(&padapter->securitypriv.dot118021XGrpKey[(u8)((key->KeyIndex) & 0x03)], 0, 16);
+- memset(&padapter->securitypriv.dot118021XGrptxmickey[(u8)((key->KeyIndex) & 0x03)], 0, 16);
+- memset(&padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex) & 0x03)], 0, 16);
+-
+- if((key->KeyIndex & 0x10000000))
+- {
+- memcpy(&padapter->securitypriv.dot118021XGrptxmickey[(u8)((key->KeyIndex) & 0x03)], key->KeyMaterial + 16, 8);
+- memcpy(&padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex) & 0x03)], key->KeyMaterial + 24, 8);
+-
+- RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("\n rtw_set_802_11_add_key:rx mic :0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n",
+- padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex) & 0x03)].skey[0],padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex-1) & 0x03)].skey[1],
+- padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex) & 0x03)].skey[2],padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex-1) & 0x03)].skey[3],
+- padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex) & 0x03)].skey[4],padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex-1) & 0x03)].skey[5],
+- padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex) & 0x03)].skey[6],padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex-1) & 0x03)].skey[7]));
+- RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("\n rtw_set_802_11_add_key:set Group mic key!!!!!!!!\n"));
+-
+- }
+- else
+- {
+- memcpy(&padapter->securitypriv.dot118021XGrptxmickey[(u8)((key->KeyIndex) & 0x03)], key->KeyMaterial + 24, 8);
+- memcpy(&padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex) & 0x03)], key->KeyMaterial + 16, 8);
+-
+- RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("\n rtw_set_802_11_add_key:rx mic :0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n",
+- padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex) & 0x03)].skey[0],padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex-1) & 0x03)].skey[1],
+- padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex) & 0x03)].skey[2],padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex-1) & 0x03)].skey[3],
+- padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex) & 0x03)].skey[4],padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex-1) & 0x03)].skey[5],
+- padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex) & 0x03)].skey[6],padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex-1) & 0x03)].skey[7]));
+- RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("\n rtw_set_802_11_add_key:set Group mic key!!!!!!!!\n"));
+-
+- }
+-
+- //set group key by index
+- memcpy(&padapter->securitypriv.dot118021XGrpKey[(u8)((key->KeyIndex) & 0x03)], key->KeyMaterial, key->KeyLength);
+-
+- key->KeyIndex=key->KeyIndex & 0x03;
+-
+- padapter->securitypriv.binstallGrpkey=true;
+-
+- padapter->securitypriv.bcheck_grpkey=false;
+-
+- RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("reset group key"));
+-
+- res=rtw_set_key(padapter,&padapter->securitypriv, key->KeyIndex, 1, true);
+-
+- if(res==_FAIL)
+- ret= _FAIL;
+-
+- goto exit;
+-
+- }
+- else // Pairwise Key
+- {
+- u8 res;
+-
+- pbssid=get_bssid(&padapter->mlmepriv);
+- stainfo=rtw_get_stainfo(&padapter->stapriv , pbssid );
+-
+- if(stainfo!=NULL)
+- {
+- memset( &stainfo->dot118021x_UncstKey, 0, 16);// clear keybuffer
+-
+- memcpy(&stainfo->dot118021x_UncstKey, key->KeyMaterial, 16);
+-
+- if(encryptionalgo== _TKIP_)
+- {
+- padapter->securitypriv.busetkipkey=false;
+-
+- //_set_timer(&padapter->securitypriv.tkip_timer, 50);
+-
+- RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("\n ==========_set_timer\n"));
+-
+- // if TKIP, save the Receive/Transmit MIC key in KeyMaterial[128-255]
+- if((key->KeyIndex & 0x10000000)){
+- memcpy(&stainfo->dot11tkiptxmickey, key->KeyMaterial + 16, 8);
+- memcpy(&stainfo->dot11tkiprxmickey, key->KeyMaterial + 24, 8);
+-
+- } else {
+- memcpy(&stainfo->dot11tkiptxmickey, key->KeyMaterial + 24, 8);
+- memcpy(&stainfo->dot11tkiprxmickey, key->KeyMaterial + 16, 8);
+-
+- }
+-
+- }
+- else if(encryptionalgo == _AES_)
+- {
+-
+- }
+-
+-
+- //Set key to CAM through H2C command
+- if(bgrouptkey)//never go to here
+- {
+- res=rtw_setstakey_cmd(padapter, stainfo, false, true);
+- RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("\n rtw_set_802_11_add_key:rtw_setstakey_cmd(group)\n"));
+- }
+- else{
+- res=rtw_setstakey_cmd(padapter, stainfo, true, true);
+- RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("\n rtw_set_802_11_add_key:rtw_setstakey_cmd(unicast)\n"));
+- }
+-
+- if(res ==false)
+- ret= _FAIL;
+-
+- }
+-
+- }
+-
+-exit:
+-
+-_func_exit_;
+-
+- return ret;
+-}
+-
+-u8 rtw_set_802_11_remove_key(_adapter* padapter, NDIS_802_11_REMOVE_KEY *key){
+-
+- uint encryptionalgo;
+- u8 * pbssid;
+- struct sta_info *stainfo;
+- u8 bgroup = (key->KeyIndex & 0x4000000) > 0 ? false: true;
+- u8 keyIndex = (u8)key->KeyIndex & 0x03;
+- u8 ret=_SUCCESS;
+-
+-_func_enter_;
+-
+- if ((key->KeyIndex & 0xbffffffc) > 0) {
+- ret=_FAIL;
+- goto exit;
+- }
+-
+- if (bgroup == true) {
+- encryptionalgo= padapter->securitypriv.dot118021XGrpPrivacy;
+- // clear group key by index
+- //NdisZeroMemory(Adapter->MgntInfo.SecurityInfo.KeyBuf[keyIndex], MAX_WEP_KEY_LEN);
+- //Adapter->MgntInfo.SecurityInfo.KeyLen[keyIndex] = 0;
+-
+- memset(&padapter->securitypriv.dot118021XGrpKey[keyIndex], 0, 16);
+-
+- //! \todo Send a H2C Command to Firmware for removing this Key in CAM Entry.
+-
+- } else {
+-
+- pbssid=get_bssid(&padapter->mlmepriv);
+- stainfo=rtw_get_stainfo(&padapter->stapriv , pbssid );
+- if(stainfo !=NULL){
+- encryptionalgo=stainfo->dot118021XPrivacy;
+-
+- // clear key by BSSID
+- memset(&stainfo->dot118021x_UncstKey, 0, 16);
+-
+- //! \todo Send a H2C Command to Firmware for disable this Key in CAM Entry.
+-
+- }
+- else{
+- ret= _FAIL;
+- goto exit;
+- }
+- }
+-
+-exit:
+-
+-_func_exit_;
+-
+- return true;
+-
+-}
+-
+ /*
+ * rtw_get_cur_max_rate -
+ * @adapter: pointer to _adapter structure
+@@ -1267,87 +797,3 @@ u16 rtw_get_cur_max_rate(_adapter *adapt
+
+ return max_rate;
+ }
+-
+-/*
+-* rtw_set_scan_mode -
+-* @adapter: pointer to _adapter structure
+-* @scan_mode:
+-*
+-* Return _SUCCESS or _FAIL
+-*/
+-int rtw_set_scan_mode(_adapter *adapter, RT_SCAN_TYPE scan_mode)
+-{
+- if(scan_mode != SCAN_ACTIVE && scan_mode != SCAN_PASSIVE)
+- return _FAIL;
+-
+- adapter->mlmepriv.scan_mode = scan_mode;
+-
+- return _SUCCESS;
+-}
+-
+-/*
+-* rtw_set_channel_plan -
+-* @adapter: pointer to _adapter structure
+-* @channel_plan:
+-*
+-* Return _SUCCESS or _FAIL
+-*/
+-int rtw_set_channel_plan(_adapter *adapter, u8 channel_plan)
+-{
+- struct registry_priv *pregistrypriv = &adapter->registrypriv;
+- struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
+-
+- //handle by cmd_thread to sync with scan operation
+- return rtw_set_chplan_cmd(adapter, channel_plan, 1, 1);
+-}
+-
+-/*
+-* rtw_set_country -
+-* @adapter: pointer to _adapter structure
+-* @country_code: string of country code
+-*
+-* Return _SUCCESS or _FAIL
+-*/
+-int rtw_set_country(_adapter *adapter, const char *country_code)
+-{
+- int channel_plan = RT_CHANNEL_DOMAIN_WORLD_WIDE_5G;
+-
+- DBG_871X("%s country_code:%s\n", __func__, country_code);
+-
+- //TODO: should have a table to match country code and RT_CHANNEL_DOMAIN
+- //TODO: should consider 2-character and 3-character country code
+- if(0 == strcmp(country_code, "US"))
+- channel_plan = RT_CHANNEL_DOMAIN_FCC;
+- else if(0 == strcmp(country_code, "EU"))
+- channel_plan = RT_CHANNEL_DOMAIN_ETSI;
+- else if(0 == strcmp(country_code, "JP"))
+- channel_plan = RT_CHANNEL_DOMAIN_MKK;
+- else if(0 == strcmp(country_code, "CN"))
+- channel_plan = RT_CHANNEL_DOMAIN_CHINA;
+- else if(0 == strcmp(country_code, "IN"))
+- channel_plan = RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN;
+- else
+- DBG_871X("%s unknown country_code:%s\n", __FUNCTION__, country_code);
+-
+- return rtw_set_channel_plan(adapter, channel_plan);
+-}
+-
+-/*
+-* rtw_set_band -
+-* @adapter: pointer to _adapter structure
+-* @band: band to set
+-*
+-* Return _SUCCESS or _FAIL
+-*/
+-int rtw_set_band(_adapter *adapter, enum _BAND band)
+-{
+- if (rtw_band_valid(band)) {
+- DBG_871X(FUNC_ADPT_FMT" band:%d\n", FUNC_ADPT_ARG(adapter), band);
+- adapter->setband = band;
+- return _SUCCESS;
+- }
+-
+- DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" band:%d fail\n", FUNC_ADPT_ARG(adapter), band);
+- return _FAIL;
+-}
+-
+diff -Nurp linux/3rdparty/rtl8723bs.old/core/rtw_mlme.c linux/3rdparty/rtl8723bs/core/rtw_mlme.c
+--- linux/3rdparty/rtl8723bs.old/core/rtw_mlme.c 2015-05-10 14:36:05.670667924 +0300
++++ linux/3rdparty/rtl8723bs/core/rtw_mlme.c 2015-05-07 17:46:55.000000000 +0300
+@@ -37,7 +37,7 @@ sint _rtw_init_mlme_priv (_adapter* pada
+
+ _func_enter_;
+
+- // We don't need to memset padapter->XXX to zero, because adapter is allocated by rtw_zvmalloc().
++ // 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;
+@@ -56,7 +56,7 @@ _func_enter_;
+
+ memset(&pmlmepriv->assoc_ssid,0,sizeof(NDIS_802_11_SSID));
+
+- pbuf = rtw_zvmalloc(MAX_BSS_CNT * (sizeof(struct wlan_network)));
++ pbuf = vzalloc(MAX_BSS_CNT * (sizeof(struct wlan_network)));
+
+ if (pbuf == NULL){
+ res=_FAIL;
+@@ -68,9 +68,9 @@ _func_enter_;
+
+ for(i = 0; i < MAX_BSS_CNT; i++)
+ {
+- _rtw_init_listhead(&(pnetwork->list));
++ INIT_LIST_HEAD(&(pnetwork->list));
+
+- rtw_list_insert_tail(&(pnetwork->list), &(pmlmepriv->free_bss_pool.queue));
++ list_add_tail(&(pnetwork->list), &(pmlmepriv->free_bss_pool.queue));
+
+ pnetwork++;
+ }
+@@ -79,17 +79,14 @@ _func_enter_;
+
+ rtw_clear_scan_deny(padapter);
+
+-#ifdef CONFIG_LAYER2_ROAMING
+ #define RTW_ROAM_SCAN_RESULT_EXP_MS 5*1000
+ #define RTW_ROAM_RSSI_DIFF_TH 10
+ #define RTW_ROAM_SCAN_INTERVAL_MS 10*1000
+
+ pmlmepriv->roam_flags = 0
+ | RTW_ROAM_ON_EXPIRED
+- #ifdef CONFIG_LAYER2_ROAMING_RESUME
+ | RTW_ROAM_ON_RESUME
+- #endif
+- #ifdef CONFIG_LAYER2_ROAMING_ACTIVE
++ #ifdef CONFIG_LAYER2_ROAMING_ACTIVE //FIXME
+ | RTW_ROAM_ACTIVE
+ #endif
+ ;
+@@ -97,7 +94,6 @@ _func_enter_;
+ 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;
+-#endif /* CONFIG_LAYER2_ROAMING */
+
+ rtw_init_mlme_timer(padapter);
+
+@@ -112,7 +108,7 @@ static void rtw_free_mlme_ie_data(u8 **p
+ {
+ if(*ppie)
+ {
+- rtw_mfree(*ppie, *plen);
++ kfree(*ppie);
+ *plen = 0;
+ *ppie=NULL;
+ }
+@@ -120,20 +116,18 @@ static void rtw_free_mlme_ie_data(u8 **p
+
+ void rtw_free_mlme_priv_ie_data(struct mlme_priv *pmlmepriv)
+ {
+-#if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)
+ 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);
+-#endif
+ }
+
+ void _rtw_free_mlme_priv (struct mlme_priv *pmlmepriv)
+@@ -144,34 +138,12 @@ _func_enter_;
+
+ if(pmlmepriv){
+ if (pmlmepriv->free_bss_buf) {
+- rtw_vmfree(pmlmepriv->free_bss_buf, MAX_BSS_CNT * sizeof(struct wlan_network));
++ vfree(pmlmepriv->free_bss_buf);
+ }
+ }
+ _func_exit_;
+ }
+
+-sint _rtw_enqueue_network(_queue *queue, struct wlan_network *pnetwork)
+-{
+- _irqL irqL;
+-
+-_func_enter_;
+-
+- if (pnetwork == NULL)
+- goto exit;
+-
+- _enter_critical_bh(&queue->lock, &irqL);
+-
+- rtw_list_insert_tail(&pnetwork->list, &queue->queue);
+-
+- _exit_critical_bh(&queue->lock, &irqL);
+-
+-exit:
+-
+-_func_exit_;
+-
+- return _SUCCESS;
+-}
+-
+ /*
+ struct wlan_network *_rtw_dequeue_network(_queue *queue)
+ {
+@@ -181,9 +153,9 @@ struct wlan_network *_rtw_dequeue_networ
+
+ _func_enter_;
+
+- _enter_critical_bh(&queue->lock, &irqL);
++ spin_lock_bh(&queue->lock);
+
+- if (_rtw_queue_empty(queue) == true)
++ if (list_empty(&queue->queue))
+
+ pnetwork = NULL;
+
+@@ -191,10 +163,10 @@ _func_enter_;
+ {
+ pnetwork = LIST_CONTAINOR(get_next(&queue->queue), struct wlan_network, list);
+
+- rtw_list_delete(&(pnetwork->list));
++ list_del_init(&(pnetwork->list));
+ }
+
+- _exit_critical_bh(&queue->lock, &irqL);
++ spin_unlock_bh(&queue->lock);
+
+ _func_exit_;
+
+@@ -211,9 +183,9 @@ struct wlan_network *_rtw_alloc_network(
+
+ _func_enter_;
+
+- _enter_critical_bh(&free_queue->lock, &irqL);
++ spin_lock_bh(&free_queue->lock);
+
+- if (_rtw_queue_empty(free_queue) == true) {
++ if (list_empty(&free_queue->queue)) {
+ pnetwork=NULL;
+ goto exit;
+ }
+@@ -221,7 +193,7 @@ _func_enter_;
+
+ pnetwork = LIST_CONTAINOR(plist , struct wlan_network, list);
+
+- rtw_list_delete(&pnetwork->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;
+@@ -233,7 +205,7 @@ _func_enter_;
+ pmlmepriv->num_of_scanned ++;
+
+ exit:
+- _exit_critical_bh(&free_queue->lock, &irqL);
++ spin_unlock_bh(&free_queue->lock);
+
+ _func_exit_;
+
+@@ -266,18 +238,18 @@ _func_enter_;
+ goto exit;
+ }
+
+- _enter_critical_bh(&free_queue->lock, &irqL);
++ spin_lock_bh(&free_queue->lock);
+
+- rtw_list_delete(&(pnetwork->list));
++ list_del_init(&(pnetwork->list));
+
+- rtw_list_insert_tail(&(pnetwork->list),&(free_queue->queue));
++ list_add_tail(&(pnetwork->list),&(free_queue->queue));
+
+ pmlmepriv->num_of_scanned --;
+
+
+ //DBG_871X("_rtw_free_network:SSID=%s\n", pnetwork->network.Ssid.Ssid);
+
+- _exit_critical_bh(&free_queue->lock, &irqL);
++ spin_unlock_bh(&free_queue->lock);
+
+ exit:
+
+@@ -298,15 +270,15 @@ _func_enter_;
+ if (pnetwork->fixed == true)
+ goto exit;
+
+- //_enter_critical(&free_queue->lock, &irqL);
++ //spin_lock_irqsave(&free_queue->lock, irqL);
+
+- rtw_list_delete(&(pnetwork->list));
++ list_del_init(&(pnetwork->list));
+
+- rtw_list_insert_tail(&(pnetwork->list), get_list_head(free_queue));
++ list_add_tail(&(pnetwork->list), get_list_head(free_queue));
+
+ pmlmepriv->num_of_scanned --;
+
+- //_exit_critical(&free_queue->lock, &irqL);
++ //spin_unlock_irqrestore(&free_queue->lock, irqL);
+
+ exit:
+
+@@ -335,7 +307,7 @@ _func_enter_;
+ goto exit;
+ }
+
+- //_enter_critical_bh(&scanned_queue->lock, &irqL);
++ //spin_lock_bh(&scanned_queue->lock);
+
+ phead = get_list_head(scanned_queue);
+ plist = get_next(phead);
+@@ -353,7 +325,7 @@ _func_enter_;
+ if(plist == phead)
+ pnetwork = NULL;
+
+- //_exit_critical_bh(&scanned_queue->lock, &irqL);
++ //spin_unlock_bh(&scanned_queue->lock);
+
+ exit:
+
+@@ -375,12 +347,12 @@ void _rtw_free_network_queue(_adapter *p
+ _func_enter_;
+
+
+- _enter_critical_bh(&scanned_queue->lock, &irqL);
++ spin_lock_bh(&scanned_queue->lock);
+
+ phead = get_list_head(scanned_queue);
+ plist = get_next(phead);
+
+- while (rtw_end_of_queue_search(phead, plist) == false)
++ while (phead != plist)
+ {
+
+ pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
+@@ -391,7 +363,7 @@ _func_enter_;
+
+ }
+
+- _exit_critical_bh(&scanned_queue->lock, &irqL);
++ spin_unlock_bh(&scanned_queue->lock);
+
+ _func_exit_;
+
+@@ -450,11 +422,6 @@ _func_exit_;
+ return le16_to_cpu(val);
+ }
+
+-u8 *rtw_get_timestampe_from_ie(u8 *ie)
+-{
+- return (ie + 0);
+-}
+-
+ u8 *rtw_get_beacon_interval_from_ie(u8 *ie)
+ {
+ return (ie + 8);
+@@ -478,16 +445,6 @@ _func_enter_;
+ _func_exit_;
+ }
+
+-int rtw_enqueue_network(_queue *queue, struct wlan_network *pnetwork);
+-int rtw_enqueue_network(_queue *queue, struct wlan_network *pnetwork)
+-{
+- int res;
+-_func_enter_;
+- res = _rtw_enqueue_network(queue, pnetwork);
+-_func_exit_;
+- return res;
+-}
+-
+ /*
+ static struct wlan_network *rtw_dequeue_network(_queue *queue)
+ {
+@@ -509,15 +466,6 @@ _func_exit_;
+ return pnetwork;
+ }
+
+-void rtw_free_network(struct mlme_priv *pmlmepriv, struct wlan_network *pnetwork, u8 is_freeall);
+-void rtw_free_network(struct mlme_priv *pmlmepriv, struct wlan_network *pnetwork, u8 is_freeall)//(struct wlan_network *pnetwork, _queue *free_queue)
+-{
+-_func_enter_;
+- RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("rtw_free_network==> ssid = %s \n\n" , pnetwork->network.Ssid.Ssid));
+- _rtw_free_network(pmlmepriv, pnetwork, is_freeall);
+-_func_exit_;
+-}
+-
+ void rtw_free_network_nolock(_adapter * padapter, struct wlan_network *pnetwork );
+ void rtw_free_network_nolock(_adapter * padapter, struct wlan_network *pnetwork )
+ {
+@@ -632,22 +580,6 @@ struct wlan_network *_rtw_find_same_netw
+ return found;
+ }
+
+-struct wlan_network *rtw_find_same_network(_queue *scanned_queue, struct wlan_network *network)
+-{
+- _irqL irqL;
+- struct wlan_network *found = NULL;
+-
+- if (scanned_queue == NULL || network == NULL)
+- goto exit;
+-
+- _enter_critical_bh(&scanned_queue->lock, &irqL);
+- found = _rtw_find_same_network(scanned_queue, network);
+- _exit_critical_bh(&scanned_queue->lock, &irqL);
+-
+-exit:
+- return found;
+-}
+-
+ struct wlan_network * rtw_get_oldest_wlan_network(_queue *scanned_queue)
+ {
+ _list *plist, *phead;
+@@ -663,7 +595,7 @@ _func_enter_;
+ while(1)
+ {
+
+- if (rtw_end_of_queue_search(phead,plist)== true)
++ if (phead == plist)
+ break;
+
+ pwlan= LIST_CONTAINOR(plist, struct wlan_network, list);
+@@ -799,13 +731,13 @@ void rtw_update_scanned_network(_adapter
+
+ _func_enter_;
+
+- _enter_critical_bh(&queue->lock, &irqL);
++ spin_lock_bh(&queue->lock);
+ phead = get_list_head(queue);
+ plist = get_next(phead);
+
+ while(1)
+ {
+- if (rtw_end_of_queue_search(phead,plist)== true)
++ if (phead == plist)
+ break;
+
+ pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
+@@ -832,9 +764,9 @@ _func_enter_;
+
+ /* If we didn't find a match, then get a new network slot to initialize
+ * with this beacon's information */
+- //if (rtw_end_of_queue_search(phead,plist)== true) {
++ //if (phead == plist) {
+ if (!target_find) {
+- if (_rtw_queue_empty(&(pmlmepriv->free_bss_pool)) == true) {
++ if (list_empty(&pmlmepriv->free_bss_pool.queue)) {
+ /* If there are no more slots, expire the oldest */
+ //list_del_init(&oldest->list);
+ pnetwork = oldest;
+@@ -875,7 +807,7 @@ _func_enter_;
+ if (pnetwork->network.PhyInfo.SignalQuality == 101)
+ pnetwork->network.PhyInfo.SignalQuality = 0;
+
+- rtw_list_insert_tail(&(pnetwork->list),&(queue->queue));
++ list_add_tail(&(pnetwork->list),&(queue->queue));
+
+ }
+ }
+@@ -906,7 +838,7 @@ _func_enter_;
+ }
+
+ exit:
+- _exit_critical_bh(&queue->lock, &irqL);
++ spin_unlock_bh(&queue->lock);
+
+ _func_exit_;
+ }
+@@ -918,13 +850,13 @@ void rtw_add_network(_adapter *adapter,
+
+ _func_enter_;
+
+- //_enter_critical_bh(&queue->lock, &irqL);
++ //spin_lock_bh(&queue->lock);
+
+ update_current_network(adapter, pnetwork);
+
+ rtw_update_scanned_network(adapter, pnetwork);
+
+- //_exit_critical_bh(&queue->lock, &irqL);
++ //spin_unlock_bh(&queue->lock);
+
+ _func_exit_;
+ }
+@@ -1028,7 +960,7 @@ _func_enter_;
+ }
+
+
+- _enter_critical_bh(&pmlmepriv->lock, &irqL);
++ spin_lock_bh(&pmlmepriv->lock);
+
+ // update IBSS_network 's timestamp
+ if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) == true)
+@@ -1040,15 +972,15 @@ _func_enter_;
+ _irqL irqL;
+
+ memcpy(pmlmepriv->cur_network.network.IEs, pnetwork->IEs, 8);
+- _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
++ 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);
+- _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
++ spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
+ goto exit;
+ }
+- _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
++ spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
+ }
+ }
+
+@@ -1064,7 +996,7 @@ _func_enter_;
+
+ exit:
+
+- _exit_critical_bh(&pmlmepriv->lock, &irqL);
++ spin_unlock_bh(&pmlmepriv->lock);
+
+ _func_exit_;
+
+@@ -1081,12 +1013,12 @@ void rtw_surveydone_event_callback(_adap
+
+ _func_enter_;
+
+- _enter_critical_bh(&pmlmepriv->lock, &irqL);
++ spin_lock_bh(&pmlmepriv->lock);
+ if(pmlmepriv->wps_probe_req_ie)
+ {
+ u32 free_len = pmlmepriv->wps_probe_req_ie_len;
+ pmlmepriv->wps_probe_req_ie_len = 0;
+- rtw_mfree(pmlmepriv->wps_probe_req_ie, free_len);
++ kfree(pmlmepriv->wps_probe_req_ie);
+ pmlmepriv->wps_probe_req_ie = NULL;
+ }
+
+@@ -1105,13 +1037,13 @@ _func_enter_;
+
+ RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("nic status =%x, survey done event comes too late!\n", get_fwstate(pmlmepriv)));
+ }
+- _exit_critical_bh(&pmlmepriv->lock, &irqL);
++ spin_unlock_bh(&pmlmepriv->lock);
+
+ if(timer_cancelled)
+ _cancel_timer(&pmlmepriv->scan_to_timer, &timer_cancelled);
+
+
+- _enter_critical_bh(&pmlmepriv->lock, &irqL);
++ spin_lock_bh(&pmlmepriv->lock);
+
+ rtw_set_signal_stat_timer(&adapter->recvpriv);
+
+@@ -1213,7 +1145,7 @@ _func_enter_;
+
+ //DBG_871X("scan complete in %dms\n",jiffies_to_msecs(jiffies - pmlmepriv->scan_start_time));
+
+- _exit_critical_bh(&pmlmepriv->lock, &irqL);
++ spin_unlock_bh(&pmlmepriv->lock);
+
+ rtw_os_xmit_schedule(adapter);
+
+@@ -1245,8 +1177,8 @@ static void free_scanqueue(struct mlme_p
+ _func_enter_;
+
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("+free_scanqueue\n"));
+- _enter_critical_bh(&scan_queue->lock, &irqL0);
+- _enter_critical_bh(&free_queue->lock, &irqL);
++ spin_lock_bh(&scan_queue->lock);
++ spin_lock_bh(&free_queue->lock);
+
+ phead = get_list_head(scan_queue);
+ plist = get_next(phead);
+@@ -1254,14 +1186,14 @@ _func_enter_;
+ while (plist != phead)
+ {
+ ptemp = get_next(plist);
+- rtw_list_delete(plist);
+- rtw_list_insert_tail(plist, &free_queue->queue);
++ list_del_init(plist);
++ list_add_tail(plist, &free_queue->queue);
+ plist =ptemp;
+ pmlmepriv->num_of_scanned --;
+ }
+
+- _exit_critical_bh(&free_queue->lock, &irqL);
+- _exit_critical_bh(&scan_queue->lock, &irqL0);
++ spin_unlock_bh(&free_queue->lock);
++ spin_unlock_bh(&scan_queue->lock);
+
+ _func_exit_;
+ }
+@@ -1299,10 +1231,10 @@ _func_enter_;
+ struct sta_info* psta;
+
+ psta = rtw_get_stainfo(&adapter->stapriv, tgt_network->network.MacAddress);
+- _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
++ spin_lock_bh(&(pstapriv->sta_hash_lock));
+ rtw_free_stainfo(adapter, psta);
+
+- _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
++ spin_unlock_bh(&(pstapriv->sta_hash_lock));
+
+ }
+
+@@ -1313,15 +1245,15 @@ _func_enter_;
+ rtw_free_all_stainfo(adapter);
+
+ psta = rtw_get_bcmc_stainfo(adapter);
+- _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
++ spin_lock_bh(&(pstapriv->sta_hash_lock));
+ rtw_free_stainfo(adapter, psta);
+- _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
++ spin_unlock_bh(&(pstapriv->sta_hash_lock));
+
+ rtw_init_bcmc_stainfo(adapter);
+ }
+
+ if(lock_scanned_queue)
+- _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
++ spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
+
+ pwlan = rtw_find_network(&pmlmepriv->scanned_queue, tgt_network->network.MacAddress);
+ if(pwlan)
+@@ -1341,7 +1273,7 @@ _func_enter_;
+ }
+
+ if(lock_scanned_queue)
+- _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
++ spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
+
+ adapter->securitypriv.key_mask = 0;
+
+@@ -1369,8 +1301,6 @@ _func_enter_;
+
+ set_fwstate(pmlmepriv, _FW_LINKED);
+
+- rtw_led_control(padapter, LED_CTL_LINK);
+-
+ rtw_os_indicate_connect(padapter);
+ }
+
+@@ -1411,19 +1341,6 @@ _func_enter_;
+ if(rtw_to_roam(padapter) > 0)
+ _clr_fwstate_(pmlmepriv, _FW_LINKED);
+
+-#ifdef CONFIG_WAPI_SUPPORT
+- psta = rtw_get_stainfo(pstapriv,cur_network->MacAddress);
+- if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
+- {
+- rtw_wapi_return_one_sta_info(padapter, psta->hwaddr);
+- }
+- else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) ||
+- check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE))
+- {
+- rtw_wapi_return_all_sta_info(padapter);
+- }
+-#endif
+-
+ if(check_fwstate(&padapter->mlmepriv, _FW_LINKED)
+ || (rtw_to_roam(padapter) <= 0)
+ )
+@@ -1435,8 +1352,6 @@ _func_enter_;
+
+ _clr_fwstate_(pmlmepriv, _FW_LINKED);
+
+- rtw_led_control(padapter, LED_CTL_NO_LINK);
+-
+ rtw_clear_scan_deny(padapter);
+ }
+
+@@ -1539,9 +1454,7 @@ static struct sta_info *rtw_joinbss_upda
+
+ memset((u8 *)&psta->dot11txpn, 0, sizeof (union pn48));
+ psta->dot11txpn.val = psta->dot11txpn.val + 1;
+-#ifdef CONFIG_IEEE80211W
+ memset((u8 *)&psta->dot11wtxpn, 0, sizeof (union pn48));
+-#endif //CONFIG_IEEE80211W
+ memset((u8 *)&psta->dot11rxpn, 0, sizeof (union pn48));
+ }
+
+@@ -1708,16 +1621,16 @@ _func_enter_;
+ goto ignore_joinbss_callback;
+ }
+
+- _enter_critical_bh(&pmlmepriv->lock, &irqL);
++ 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 !! _enter_critical \n"));
++ RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("\n rtw_joinbss_event_callback !! spin_lock_irqsave \n"));
+
+ if(pnetwork->join_res > 0)
+ {
+- _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
++ spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
+ retry = 0;
+ if (check_fwstate(pmlmepriv,_FW_UNDER_LINKING) )
+ {
+@@ -1735,9 +1648,9 @@ _func_enter_;
+
+ pcur_sta = rtw_get_stainfo(pstapriv, cur_network->network.MacAddress);
+ if(pcur_sta){
+- _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL2);
++ spin_lock_bh(&(pstapriv->sta_hash_lock));
+ rtw_free_stainfo(adapter, pcur_sta);
+- _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL2);
++ spin_unlock_bh(&(pstapriv->sta_hash_lock));
+ }
+
+ ptarget_wlan = rtw_find_network(&pmlmepriv->scanned_queue, pnetwork->network.MacAddress);
+@@ -1763,7 +1676,7 @@ _func_enter_;
+ else
+ {
+ DBG_871X_LEVEL(_drv_always_, "Can't find ptarget_wlan when joinbss_event callback\n");
+- _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
++ spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
+ goto ignore_joinbss_callback;
+ }
+
+@@ -1775,7 +1688,7 @@ _func_enter_;
+ if(ptarget_sta==NULL)
+ {
+ RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("Can't update stainfo when joinbss_event callback\n"));
+- _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
++ spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
+ goto ignore_joinbss_callback;
+ }
+ }
+@@ -1802,11 +1715,11 @@ _func_enter_;
+ else
+ {
+ RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("rtw_joinbss_event_callback err: fw_state:%x", get_fwstate(pmlmepriv)));
+- _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
++ spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
+ goto ignore_joinbss_callback;
+ }
+
+- _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
++ spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
+
+ }
+ else if(pnetwork->join_res == -4)
+@@ -1861,7 +1774,7 @@ _func_enter_;
+
+ ignore_joinbss_callback:
+
+- _exit_critical_bh(&pmlmepriv->lock, &irqL);
++ spin_unlock_bh(&pmlmepriv->lock);
+ _func_exit_;
+ }
+
+@@ -1903,7 +1816,6 @@ _func_enter_;
+ if(rtw_access_ctrl(adapter, pstassoc->macaddr) == false)
+ return;
+
+-#if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)
+ if(check_fwstate(pmlmepriv, WIFI_AP_STATE))
+ {
+ psta = rtw_get_stainfo(&adapter->stapriv, pstassoc->macaddr);
+@@ -1920,7 +1832,7 @@ _func_enter_;
+
+ //report to upper layer
+ DBG_871X("indicate_sta_assoc_event to upper layer - hostapd\n");
+- _enter_critical_bh(&psta->lock, &irqL);
++ spin_lock_bh(&psta->lock);
+ if(psta->passoc_req && psta->assoc_req_len>0)
+ {
+ passoc_req = rtw_zmalloc(psta->assoc_req_len);
+@@ -1929,24 +1841,23 @@ _func_enter_;
+ assoc_req_len = psta->assoc_req_len;
+ memcpy(passoc_req, psta->passoc_req, assoc_req_len);
+
+- rtw_mfree(psta->passoc_req , psta->assoc_req_len);
++ kfree(psta->passoc_req);
+ psta->passoc_req = NULL;
+ psta->assoc_req_len = 0;
+ }
+ }
+- _exit_critical_bh(&psta->lock, &irqL);
++ spin_unlock_bh(&psta->lock);
+
+ if(passoc_req && assoc_req_len>0)
+ {
+ rtw_cfg80211_indicate_sta_assoc(adapter, passoc_req, assoc_req_len);
+
+- rtw_mfree(passoc_req, assoc_req_len);
++ kfree(passoc_req);
+ }
+ #endif //!CONFIG_AUTO_AP_MODE
+ }
+ goto exit;
+ }
+-#endif //defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)
+
+ //for AD-HOC mode
+ psta = rtw_get_stainfo(&adapter->stapriv, pstassoc->macaddr);
+@@ -1981,24 +1892,24 @@ _func_enter_;
+
+ psta->ieee8021x_blocked = false;
+
+- _enter_critical_bh(&pmlmepriv->lock, &irqL);
++ 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)
+ {
+- _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
++ 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;
+- _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
++ spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
+ // a sta + bc/mc_stainfo (not Ibss_stainfo)
+ rtw_indicate_connect(adapter);
+ }
+ }
+
+- _exit_critical_bh(&pmlmepriv->lock, &irqL);
++ spin_unlock_bh(&pmlmepriv->lock);
+
+
+ mlmeext_sta_add_event_callback(adapter, psta);
+@@ -2050,7 +1961,7 @@ _func_enter_;
+
+ mlmeext_sta_del_event_callback(adapter);
+
+- _enter_critical_bh(&pmlmepriv->lock, &irqL2);
++ spin_lock_bh(&pmlmepriv->lock);
+
+ if(check_fwstate(pmlmepriv, WIFI_STATION_STATE) )
+ {
+@@ -2058,7 +1969,6 @@ _func_enter_;
+ bool roam = false;
+ struct wlan_network *roam_target = NULL;
+
+- #ifdef CONFIG_LAYER2_ROAMING
+ if(adapter->registrypriv.wifi_spec==1) {
+ roam = false;
+ } else if (reason == WLAN_REASON_EXPIRATION_CHK && rtw_chk_roam_flags(adapter, RTW_ROAM_ON_EXPIRED)) {
+@@ -2081,21 +1991,20 @@ _func_enter_;
+ } else {
+ rtw_set_to_roam(adapter, 0);
+ }
+- #endif /* CONFIG_LAYER2_ROAMING */
+
+ rtw_free_uc_swdec_pending_queue(adapter);
+
+ rtw_free_assoc_resources(adapter, 1);
+ rtw_indicate_disconnect(adapter);
+
+- _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
++ 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);
+ }
+- _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
++ spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
+
+ #ifdef CONFIG_INTEL_WIDI
+ if (!rtw_to_roam(adapter))
+@@ -2109,14 +2018,14 @@ _func_enter_;
+ check_fwstate(pmlmepriv,WIFI_ADHOC_STATE))
+ {
+
+- _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
++ spin_lock_bh(&(pstapriv->sta_hash_lock));
+ rtw_free_stainfo(adapter, psta);
+- _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
++ spin_unlock_bh(&(pstapriv->sta_hash_lock));
+
+ if(adapter->stapriv.asoc_sta_count== 1) //a sta + bc/mc_stainfo (not Ibss_stainfo)
+ {
+ //rtw_indicate_disconnect(adapter);//removed@20091105
+- _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
++ 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);
+@@ -2125,7 +2034,7 @@ _func_enter_;
+ pwlan->fixed = false;
+ rtw_free_network_nolock(adapter, pwlan);
+ }
+- _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
++ spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
+ //re-create ibss
+ pdev_network = &(adapter->registrypriv.dev_network);
+ pibss = adapter->registrypriv.dev_network.MacAddress;
+@@ -2157,7 +2066,7 @@ _func_enter_;
+
+ }
+
+- _exit_critical_bh(&pmlmepriv->lock, &irqL2);
++ spin_unlock_bh(&pmlmepriv->lock);
+
+ _func_exit_;
+
+@@ -2208,9 +2117,8 @@ _func_enter_;
+ return;
+
+
+- _enter_critical_bh(&pmlmepriv->lock, &irqL);
++ spin_lock_bh(&pmlmepriv->lock);
+
+- #ifdef CONFIG_LAYER2_ROAMING
+ if (rtw_to_roam(adapter) > 0) { /* join timeout caused by roaming */
+ while(1) {
+ rtw_dec_to_roam(adapter);
+@@ -2238,7 +2146,6 @@ _func_enter_;
+ }
+
+ } else
+- #endif
+ {
+ rtw_indicate_disconnect(adapter);
+ free_scanqueue(pmlmepriv);//???
+@@ -2248,7 +2155,7 @@ _func_enter_;
+
+ }
+
+- _exit_critical_bh(&pmlmepriv->lock, &irqL);
++ spin_unlock_bh(&pmlmepriv->lock);
+
+ _func_exit_;
+
+@@ -2265,11 +2172,11 @@ void rtw_scan_timeout_handler (_adapter
+
+ DBG_871X(FUNC_ADPT_FMT" fw_state=%x\n", FUNC_ADPT_ARG(adapter), get_fwstate(pmlmepriv));
+
+- _enter_critical_bh(&pmlmepriv->lock, &irqL);
++ spin_lock_bh(&pmlmepriv->lock);
+
+ _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
+
+- _exit_critical_bh(&pmlmepriv->lock, &irqL);
++ spin_unlock_bh(&pmlmepriv->lock);
+
+ rtw_indicate_scan_done(adapter, true);
+ }
+@@ -2286,11 +2193,9 @@ void rtw_mlme_reset_auto_scan_int(_adapt
+ }
+ else if(adapter->registrypriv.wifi_spec && is_client_associated_to_ap(adapter) == true) {
+ mlme->auto_scan_int_ms = 60*1000;
+-#ifdef CONFIG_LAYER2_ROAMING
+ } 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;
+-#endif
+ } else {
+ mlme->auto_scan_int_ms = 0; /* disabled */
+ }
+@@ -2410,7 +2315,6 @@ void rtw_set_scan_deny(_adapter *adapter
+ _set_timer(&mlmepriv->set_scan_deny_timer, ms);
+ }
+
+-#ifdef CONFIG_LAYER2_ROAMING
+ /*
+ * Select a new roaming candidate from the original @param candidate and @param competitor
+ * @return true: candidate is updated
+@@ -2478,13 +2382,13 @@ _func_enter_;
+ goto exit;
+ }
+
+- _enter_critical_bh(&(mlme->scanned_queue.lock), &irqL);
++ spin_lock_bh(&(mlme->scanned_queue.lock));
+ phead = get_list_head(queue);
+ adapter = (_adapter *)mlme->nic_hdl;
+
+ mlme->pscanned = get_next(phead);
+
+- while (!rtw_end_of_queue_search(phead, mlme->pscanned)) {
++ while (phead != mlme->pscanned) {
+
+ pnetwork = LIST_CONTAINOR(mlme->pscanned, struct wlan_network, list);
+ if(pnetwork==NULL){
+@@ -2522,11 +2426,10 @@ _func_enter_;
+
+ ret = _SUCCESS;
+ exit:
+- _exit_critical_bh(&(mlme->scanned_queue.lock), &irqL);
++ spin_unlock_bh(&(mlme->scanned_queue.lock));
+
+ return ret;
+ }
+-#endif /* CONFIG_LAYER2_ROAMING */
+
+ /*
+ * Select a new join candidate from the original @param candidate and @param competitor
+@@ -2557,15 +2460,13 @@ static int rtw_check_join_candidate(stru
+ if(rtw_is_desired_network(adapter, competitor) == false)
+ goto exit;
+
+-#ifdef CONFIG_LAYER2_ROAMING
+ 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;
+ }
+-#endif
+-
++
+ if(*candidate == NULL ||(*candidate)->network.Rssinetwork.Rssi )
+ {
+ *candidate = competitor;
+@@ -2574,15 +2475,11 @@ static int rtw_check_join_candidate(stru
+
+ if(updated){
+ DBG_871X("[by_bssid:%u][assoc_ssid:%s]"
+- #ifdef CONFIG_LAYER2_ROAMING
+ "[to_roam:%u] "
+- #endif
+ "new candidate: %s("MAC_FMT", ch%u) rssi:%d\n",
+ mlme->assoc_by_bssid,
+ mlme->assoc_ssid.Ssid,
+- #ifdef CONFIG_LAYER2_ROAMING
+ rtw_to_roam(adapter),
+- #endif
+ (*candidate)->network.Ssid.Ssid,
+ MAC_ARG((*candidate)->network.MacAddress),
+ (*candidate)->network.Configuration.DSConfig,
+@@ -2619,20 +2516,18 @@ _func_enter_;
+
+ adapter = (_adapter *)pmlmepriv->nic_hdl;
+
+- _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
++ spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
+
+- #ifdef CONFIG_LAYER2_ROAMING
+ if (pmlmepriv->roam_network) {
+ candidate = pmlmepriv->roam_network;
+ pmlmepriv->roam_network = NULL;
+ goto candidate_exist;
+ }
+- #endif
+
+ phead = get_list_head(queue);
+ pmlmepriv->pscanned = get_next(phead);
+
+- while (!rtw_end_of_queue_search(phead, pmlmepriv->pscanned)) {
++ while (phead != pmlmepriv->pscanned) {
+
+ pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned, struct wlan_network, list);
+ if(pnetwork==NULL){
+@@ -2683,7 +2578,7 @@ candidate_exist:
+ ret = rtw_joinbss_cmd(adapter, candidate);
+
+ exit:
+- _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
++ spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
+
+ _func_exit_;
+
+@@ -2707,7 +2602,7 @@ _func_enter_;
+
+ psetauthparm=(struct setauth_parm*)rtw_zmalloc(sizeof(struct setauth_parm));
+ if(psetauthparm==NULL){
+- rtw_mfree((unsigned char *)pcmd, sizeof(struct cmd_obj));
++ kfree((unsigned char *)pcmd);
+ res= _FAIL;
+ goto exit;
+ }
+@@ -2722,7 +2617,7 @@ _func_enter_;
+ pcmd->rspsz = 0;
+
+
+- _rtw_init_listhead(&pcmd->list);
++ INIT_LIST_HEAD(&pcmd->list);
+
+ RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("after enqueue set_auth_cmd, auth_mode=%x\n", psecuritypriv->dot11AuthAlgrthm));
+
+@@ -2794,7 +2689,7 @@ _func_enter_;
+ 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;
+- rtw_mfree((unsigned char *)psetkeyparm, sizeof(struct setkey_parm));
++ kfree((unsigned char *)psetkeyparm);
+ goto exit;
+ }
+
+@@ -2802,7 +2697,7 @@ _func_enter_;
+ if(enqueue){
+ pcmd = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));
+ if(pcmd==NULL){
+- rtw_mfree((unsigned char *)psetkeyparm, sizeof(struct setkey_parm));
++ kfree((unsigned char *)psetkeyparm);
+ res= _FAIL; //try again
+ goto exit;
+ }
+@@ -2813,7 +2708,7 @@ _func_enter_;
+ pcmd->rsp = NULL;
+ pcmd->rspsz = 0;
+
+- _rtw_init_listhead(&pcmd->list);
++ INIT_LIST_HEAD(&pcmd->list);
+
+ //sema_init(&(pcmd->cmd_sem), 0);
+
+@@ -2821,7 +2716,7 @@ _func_enter_;
+ }
+ else{
+ setkey_hdl(adapter, (u8 *)psetkeyparm);
+- rtw_mfree((u8 *) psetkeyparm, sizeof(struct setkey_parm));
++ kfree((u8 *) psetkeyparm);
+ }
+ exit:
+ _func_exit_;
+@@ -3301,9 +3196,7 @@ unsigned int rtw_restructure_ht_ie(_adap
+ ht_capie.cap_info |= IEEE80211_HT_CAP_SM_PS;
+
+ if (TEST_FLAG(phtpriv->stbc_cap, STBC_HT_ENABLE_RX)) {
+- if((pregistrypriv->rx_stbc == 0x3) || /* enable for 2.4/5 GHz */
+- ((channel <= 14) && (pregistrypriv->rx_stbc == 0x1)) || /* enable for 2.4GHz */
+- ((channel > 14) && (pregistrypriv->rx_stbc == 0x2)) || /* enable for 5GHz */
++ 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");
+@@ -3612,7 +3505,6 @@ void rtw_append_exented_cap(_adapter *pa
+ pframe = rtw_set_ie(out_ie+*pout_len, EID_EXTCapability, 8, cap_content , pout_len);
+ }
+
+-#ifdef CONFIG_LAYER2_ROAMING
+ inline void rtw_set_to_roam(_adapter *adapter, u8 to_roam)
+ {
+ if (to_roam == 0)
+@@ -3636,9 +3528,9 @@ void rtw_roaming(_adapter *padapter, str
+ _irqL irqL;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+- _enter_critical_bh(&pmlmepriv->lock, &irqL);
++ spin_lock_bh(&pmlmepriv->lock);
+ _rtw_roaming(padapter, tgt_network);
+- _exit_critical_bh(&pmlmepriv->lock, &irqL);
++ spin_unlock_bh(&pmlmepriv->lock);
+ }
+ void _rtw_roaming(_adapter *padapter, struct wlan_network *tgt_network)
+ {
+@@ -3654,10 +3546,6 @@ void _rtw_roaming(_adapter *padapter, st
+
+ pmlmepriv->assoc_by_bssid = false;
+
+-#ifdef CONFIG_WAPI_SUPPORT
+- rtw_wapi_return_all_sta_info(padapter);
+-#endif
+-
+ while(1) {
+ if( _SUCCESS==(do_join_r=rtw_do_join(padapter)) ) {
+ break;
+@@ -3677,7 +3565,6 @@ void _rtw_roaming(_adapter *padapter, st
+ }
+
+ }
+-#endif /* CONFIG_LAYER2_ROAMING */
+
+ sint rtw_linked_check(_adapter *padapter)
+ {
+diff -Nurp linux/3rdparty/rtl8723bs.old/core/rtw_mlme_ext.c linux/3rdparty/rtl8723bs/core/rtw_mlme_ext.c
+--- linux/3rdparty/rtl8723bs.old/core/rtw_mlme_ext.c 2015-05-10 14:36:05.673667957 +0300
++++ linux/3rdparty/rtl8723bs/core/rtw_mlme_ext.c 2015-05-07 17:46:55.000000000 +0300
+@@ -45,7 +45,6 @@ static struct mlme_handler mlme_sta_tbl[
+ {WIFI_ACTION_NOACK,"OnActionNoAck", &OnAction},
+ };
+
+-#ifdef _CONFIG_NATIVEAP_MLME_
+ struct mlme_handler mlme_ap_tbl[]={
+ {WIFI_ASSOCREQ, "OnAssocReq", &OnAssocReq},
+ {WIFI_ASSOCRSP, "OnAssocRsp", &OnAssocRsp},
+@@ -67,7 +66,6 @@ struct mlme_handler mlme_ap_tbl[]={
+ {WIFI_ACTION, "OnAction", &OnAction},
+ {WIFI_ACTION_NOACK,"OnActionNoAck", &OnAction},
+ };
+-#endif
+
+ static struct action_handler OnAction_tbl[]={
+ {RTW_WLAN_CATEGORY_SPECTRUM_MGMT, "ACTION_SPECTRUM_MGMT", on_action_spct},
+@@ -78,12 +76,7 @@ static struct action_handler OnAction_tb
+ {RTW_WLAN_CATEGORY_RADIO_MEASUREMENT, "ACTION_RADIO_MEASUREMENT", &DoReserved},
+ {RTW_WLAN_CATEGORY_FT, "ACTION_FT", &DoReserved},
+ {RTW_WLAN_CATEGORY_HT, "ACTION_HT", &OnAction_ht},
+-#ifdef CONFIG_IEEE80211W
+ {RTW_WLAN_CATEGORY_SA_QUERY, "ACTION_SA_QUERY", &OnAction_sa_query},
+-#else
+- {RTW_WLAN_CATEGORY_SA_QUERY, "ACTION_SA_QUERY", &DoReserved},
+-#endif //CONFIG_IEEE80211W
+- //add for CONFIG_IEEE80211W
+ {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},
+@@ -354,11 +347,9 @@ static void init_mlme_ext_priv_value(_ad
+
+ atomic_set(&pmlmeext->event_seq, 0);
+ pmlmeext->mgnt_seq = 0;//reset to zero when disconnect at client mode
+-#ifdef CONFIG_IEEE80211W
+ pmlmeext->sa_query_seq = 0;
+ pmlmeext->mgnt_80211w_IPN=0;
+ pmlmeext->mgnt_80211w_IPN_rx=0;
+-#endif //CONFIG_IEEE80211W
+ pmlmeext->cur_channel = padapter->registrypriv.channel;
+ pmlmeext->cur_bwmode = CHANNEL_WIDTH_20;
+ pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+@@ -491,15 +482,6 @@ static u8 init_channel_set(_adapter* pad
+ Index2G = RTW_ChannelPlanMap[ChannelPlan].Index2G;
+ }
+
+- if(IsSupported5G(padapter->registrypriv.wireless_mode))
+- {
+- b5GBand = true;
+- if(RT_CHANNEL_DOMAIN_REALTEK_DEFINE == ChannelPlan)
+- Index5G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.Index5G;
+- else
+- Index5G = RTW_ChannelPlanMap[ChannelPlan].Index5G;
+- }
+-
+ if(b2_4GBand)
+ {
+ for(index=0;indexmlmepriv);
+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
+
+- // We don't need to memset padapter->XXX to zero, because adapter is allocated by rtw_zvmalloc().
++ // 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;
+@@ -573,9 +555,7 @@ int init_mlme_ext_priv(_adapter* padapte
+
+ init_mlme_ext_timer(padapter);
+
+-#ifdef CONFIG_AP_MODE
+ init_mlme_ap_info(padapter);
+-#endif
+
+ 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);
+@@ -630,9 +610,7 @@ void mgt_dispatcher(_adapter *padapter,
+ {
+ int index;
+ struct mlme_handler *ptable;
+-#ifdef CONFIG_AP_MODE
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+-#endif //CONFIG_AP_MODE
+ 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));
+@@ -682,7 +660,6 @@ void mgt_dispatcher(_adapter *padapter,
+ psta->RxMgmtFrameSeqNum = precv_frame->u.hdr.attrib.seq_num;
+ }
+
+-#ifdef CONFIG_AP_MODE
+ switch (GetFrameSubType(pframe))
+ {
+ case WIFI_AUTH:
+@@ -707,16 +684,8 @@ void mgt_dispatcher(_adapter *padapter,
+ break;
+ default:
+ _mgt_dispatcher(padapter, ptable, precv_frame);
+- if(check_fwstate(pmlmepriv, WIFI_AP_STATE) == true)
+- rtw_hostapd_mlme_rx(padapter, precv_frame);
+ break;
+ }
+-#else
+-
+- _mgt_dispatcher(padapter, ptable, precv_frame);
+-
+-#endif
+-
+ }
+
+ /****************************************************************************
+@@ -795,14 +764,14 @@ unsigned int OnProbeReq(_adapter *padapt
+ return _SUCCESS;
+ }
+
+- _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+- if (rtw_is_list_empty(&psta->asoc_list))
++ spin_lock_bh(&pstapriv->asoc_list_lock);
++ if (list_empty(&psta->asoc_list))
+ {
+ psta->expire_to = pstapriv->expire_to;
+- rtw_list_insert_tail(&psta->asoc_list, &pstapriv->asoc_list);
++ list_add_tail(&psta->asoc_list, &pstapriv->asoc_list);
+ pstapriv->asoc_list_cnt++;
+ }
+- _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
++ spin_unlock_bh(&pstapriv->asoc_list_lock);
+
+ //generate pairing ID
+ mac_addr = myid(&(padapter->eeprompriv));
+@@ -847,9 +816,9 @@ unsigned int OnProbeReq(_adapter *padapt
+
+ memset((void*)&psta->sta_stats, 0, sizeof(struct stainfo_stats));
+
+- _enter_critical_bh(&psta->lock, &irqL);
++ spin_lock_bh(&psta->lock);
+ psta->state |= _FW_LINKED;
+- _exit_critical_bh(&psta->lock, &irqL);
++ spin_unlock_bh(&psta->lock);
+
+ report_add_sta_event(padapter, psta->hwaddr, psta->aid);
+
+@@ -961,7 +930,7 @@ unsigned int OnBeacon(_adapter *padapter
+ update_network(&(pmlmepriv->cur_network.network), pbss, padapter, true);
+ rtw_get_bcn_info(&(pmlmepriv->cur_network));
+ }
+- rtw_mfree((u8*)pbss, sizeof(WLAN_BSSID_EX));
++ kfree((u8*)pbss);
+ }
+
+ //check the vendor of the assoc AP
+@@ -1049,7 +1018,6 @@ _END_ONBEACON_:
+
+ unsigned int OnAuth(_adapter *padapter, union recv_frame *precv_frame)
+ {
+-#ifdef CONFIG_AP_MODE
+ _irqL irqL;
+ unsigned int auth_mode, seq, ie_len;
+ unsigned char *sa, *p;
+@@ -1143,31 +1111,31 @@ unsigned int OnAuth(_adapter *padapter,
+ else
+ {
+
+- _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+- if(rtw_is_list_empty(&pstat->asoc_list)==false)
++ spin_lock_bh(&pstapriv->asoc_list_lock);
++ if(list_empty(&pstat->asoc_list)==false)
+ {
+- rtw_list_delete(&pstat->asoc_list);
++ list_del_init(&pstat->asoc_list);
+ pstapriv->asoc_list_cnt--;
+ if (pstat->expire_to > 0)
+ {
+ //TODO: STA re_auth within expire_to
+ }
+ }
+- _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
++ spin_unlock_bh(&pstapriv->asoc_list_lock);
+
+ if (seq==1) {
+ //TODO: STA re_auth and auth timeout
+ }
+ }
+
+- _enter_critical_bh(&pstapriv->auth_list_lock, &irqL);
+- if (rtw_is_list_empty(&pstat->auth_list))
++ spin_lock_bh(&pstapriv->auth_list_lock);
++ if (list_empty(&pstat->auth_list))
+ {
+
+- rtw_list_insert_tail(&pstat->auth_list, &pstapriv->auth_list);
++ list_add_tail(&pstat->auth_list, &pstapriv->auth_list);
+ pstapriv->auth_list_cnt++;
+ }
+- _exit_critical_bh(&pstapriv->auth_list_lock, &irqL);
++ spin_unlock_bh(&pstapriv->auth_list_lock);
+
+ if (pstat->auth_seq == 0)
+ pstat->expire_to = pstapriv->auth_to;
+@@ -1253,10 +1221,8 @@ unsigned int OnAuth(_adapter *padapter,
+
+ // Now, we are going to issue_auth...
+ pstat->auth_seq = seq + 1;
+-
+-#ifdef CONFIG_NATIVEAP_MLME
++
+ issue_auth(padapter, pstat, (unsigned short)(_STATS_SUCCESSFUL_));
+-#endif
+
+ if (pstat->state & WIFI_FW_AUTH_SUCCESS)
+ pstat->auth_seq = 0;
+@@ -1273,12 +1239,9 @@ auth_fail:
+ memset((char *)pstat, '\0', sizeof(stat));
+ pstat->auth_seq = 2;
+ memcpy(pstat->hwaddr, sa, 6);
+-
+-#ifdef CONFIG_NATIVEAP_MLME
++
+ issue_auth(padapter, pstat, (unsigned short)status);
+-#endif
+
+-#endif
+ return _FAIL;
+
+ }
+@@ -1386,7 +1349,6 @@ authclnt_fail:
+
+ unsigned int OnAssocReq(_adapter *padapter, union recv_frame *precv_frame)
+ {
+-#ifdef CONFIG_AP_MODE
+ _irqL irqL;
+ u16 capab_info, listen_interval;
+ struct rtw_ieee802_11_elems elems;
+@@ -1838,27 +1800,26 @@ unsigned int OnAssocReq(_adapter *padapt
+ pstat->state &= (~WIFI_FW_ASSOC_STATE);
+ pstat->state |= WIFI_FW_ASSOC_SUCCESS;
+
+- _enter_critical_bh(&pstapriv->auth_list_lock, &irqL);
+- if (!rtw_is_list_empty(&pstat->auth_list))
++ spin_lock_bh(&pstapriv->auth_list_lock);
++ if (!list_empty(&pstat->auth_list))
+ {
+- rtw_list_delete(&pstat->auth_list);
++ list_del_init(&pstat->auth_list);
+ pstapriv->auth_list_cnt--;
+ }
+- _exit_critical_bh(&pstapriv->auth_list_lock, &irqL);
++ spin_unlock_bh(&pstapriv->auth_list_lock);
+
+- _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+- if (rtw_is_list_empty(&pstat->asoc_list))
++ spin_lock_bh(&pstapriv->asoc_list_lock);
++ if (list_empty(&pstat->asoc_list))
+ {
+ pstat->expire_to = pstapriv->expire_to;
+- rtw_list_insert_tail(&pstat->asoc_list, &pstapriv->asoc_list);
++ list_add_tail(&pstat->asoc_list, &pstapriv->asoc_list);
+ pstapriv->asoc_list_cnt++;
+ }
+- _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
++ 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))
+ {
+-#ifdef CONFIG_NATIVEAP_MLME
+ //.1 bss_cap_update & sta_info_update
+ bss_cap_update_on_sta_join(padapter, pstat);
+ sta_info_update(padapter, pstat);
+@@ -1869,10 +1830,10 @@ unsigned int OnAssocReq(_adapter *padapt
+ else
+ issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP);
+
+- _enter_critical_bh(&pstat->lock, &irqL);
++ spin_lock_bh(&pstat->lock);
+ if(pstat->passoc_req)
+ {
+- rtw_mfree(pstat->passoc_req, pstat->assoc_req_len);
++ kfree(pstat->passoc_req);
+ pstat->passoc_req = NULL;
+ pstat->assoc_req_len = 0;
+ }
+@@ -1883,40 +1844,29 @@ unsigned int OnAssocReq(_adapter *padapt
+ memcpy(pstat->passoc_req, pframe, pkt_len);
+ pstat->assoc_req_len = pkt_len;
+ }
+- _exit_critical_bh(&pstat->lock, &irqL);
++ spin_unlock_bh(&pstat->lock);
+
+ //.3-(1) report sta add event
+ report_add_sta_event(padapter, pstat->hwaddr, pstat->aid);
+-
+-#endif //CONFIG_NATIVEAP_MLME
+ }
+
+ return _SUCCESS;
+
+ asoc_class2_error:
+
+-#ifdef CONFIG_NATIVEAP_MLME
+ issue_deauth(padapter, (void *)GetAddr2Ptr(pframe), status);
+-#endif
+
+ return _FAIL;
+
+ OnAssocReqFail:
+
+-
+-#ifdef CONFIG_NATIVEAP_MLME
+ pstat->aid = 0;
+ if (frame_type == WIFI_ASSOCREQ)
+ issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP);
+ else
+ issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP);
+-#endif
+-
+-
+-#endif /* CONFIG_AP_MODE */
+-
+- return _FAIL;
+
++ return _FAIL;
+ }
+
+ unsigned int OnAssocRsp(_adapter *padapter, union recv_frame *precv_frame)
+@@ -1981,12 +1931,6 @@ unsigned int OnAssocRsp(_adapter *padapt
+ }
+ break;
+
+-#ifdef CONFIG_WAPI_SUPPORT
+- case _WAPI_IE_:
+- pWapiIE = pIE;
+- break;
+-#endif
+-
+ case _HT_CAPABILITY_IE_: //HT caps
+ HT_caps_handler(padapter, pIE);
+ break;
+@@ -2005,10 +1949,6 @@ unsigned int OnAssocRsp(_adapter *padapt
+ i += (pIE->Length + 2);
+ }
+
+-#ifdef CONFIG_WAPI_SUPPORT
+- rtw_wapi_on_assoc_ok(padapter, pIE);
+-#endif
+-
+ pmlmeinfo->state &= (~WIFI_FW_ASSOC_STATE);
+ pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
+
+@@ -2043,18 +1983,15 @@ unsigned int OnDeAuth(_adapter *padapter
+
+ DBG_871X("%s Reason code(%d)\n", __FUNCTION__,reason);
+
+- rtw_lock_rx_suspend_timeout(8000);
+-
+-#ifdef CONFIG_AP_MODE
+ if(check_fwstate(pmlmepriv, WIFI_AP_STATE) == true)
+ {
+ _irqL irqL;
+ struct sta_info *psta;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+
+- //_enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
++ //spin_lock_bh(&(pstapriv->sta_hash_lock));
+ //rtw_free_stainfo(padapter, psta);
+- //_exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
++ //spin_unlock_bh(&(pstapriv->sta_hash_lock));
+
+ DBG_871X_LEVEL(_drv_always_, "ap recv deauth reason code(%d) sta:%pM\n",
+ reason, GetAddr2Ptr(pframe));
+@@ -2064,15 +2001,15 @@ unsigned int OnDeAuth(_adapter *padapter
+ {
+ u8 updated = false;
+
+- _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+- if(rtw_is_list_empty(&psta->asoc_list)==false)
++ spin_lock_bh(&pstapriv->asoc_list_lock);
++ if(list_empty(&psta->asoc_list)==false)
+ {
+- rtw_list_delete(&psta->asoc_list);
++ list_del_init(&psta->asoc_list);
+ pstapriv->asoc_list_cnt--;
+ updated = ap_free_sta(padapter, psta, false, reason);
+
+ }
+- _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
++ spin_unlock_bh(&pstapriv->asoc_list_lock);
+
+ associated_clients_update(padapter, updated);
+ }
+@@ -2081,7 +2018,6 @@ unsigned int OnDeAuth(_adapter *padapter
+ return _SUCCESS;
+ }
+ else
+-#endif
+ {
+ int ignore_received_deauth = 0;
+
+@@ -2131,18 +2067,15 @@ unsigned int OnDisassoc(_adapter *padapt
+
+ DBG_871X("%s Reason code(%d)\n", __FUNCTION__,reason);
+
+- rtw_lock_rx_suspend_timeout(8000);
+-
+-#ifdef CONFIG_AP_MODE
+ if(check_fwstate(pmlmepriv, WIFI_AP_STATE) == true)
+ {
+ _irqL irqL;
+ struct sta_info *psta;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+
+- //_enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
++ //spin_lock_bh(&(pstapriv->sta_hash_lock));
+ //rtw_free_stainfo(padapter, psta);
+- //_exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
++ //spin_unlock_bh(&(pstapriv->sta_hash_lock));
+
+ DBG_871X_LEVEL(_drv_always_, "ap recv disassoc reason code(%d) sta:%pM\n",
+ reason, GetAddr2Ptr(pframe));
+@@ -2152,15 +2085,15 @@ unsigned int OnDisassoc(_adapter *padapt
+ {
+ u8 updated = false;
+
+- _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+- if(rtw_is_list_empty(&psta->asoc_list)==false)
++ spin_lock_bh(&pstapriv->asoc_list_lock);
++ if(list_empty(&psta->asoc_list)==false)
+ {
+- rtw_list_delete(&psta->asoc_list);
++ list_del_init(&psta->asoc_list);
+ pstapriv->asoc_list_cnt--;
+ updated = ap_free_sta(padapter, psta, false, reason);
+
+ }
+- _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
++ spin_unlock_bh(&pstapriv->asoc_list_lock);
+
+ associated_clients_update(padapter, updated);
+ }
+@@ -2168,7 +2101,6 @@ unsigned int OnDisassoc(_adapter *padapt
+ return _SUCCESS;
+ }
+ else
+-#endif
+ {
+ DBG_871X_LEVEL(_drv_always_, "sta recv disassoc reason code(%d) sta:%pM\n",
+ reason, GetAddr3Ptr(pframe));
+@@ -2500,7 +2432,6 @@ exit:
+ return _SUCCESS;
+ }
+
+-#ifdef CONFIG_IEEE80211W
+ unsigned int OnAction_sa_query(_adapter *padapter, union recv_frame *precv_frame)
+ {
+ u8 *pframe = precv_frame->u.hdr.rx_data;
+@@ -2537,7 +2468,6 @@ unsigned int OnAction_sa_query(_adapter
+
+ return _SUCCESS;
+ }
+-#endif //CONFIG_IEEE80211W
+
+ unsigned int OnAction(_adapter *padapter, union recv_frame *precv_frame)
+ {
+@@ -2608,12 +2538,6 @@ inline struct xmit_frame *alloc_mgtxmitf
+ return _alloc_mgtxmitframe(pxmitpriv, false);
+ }
+
+-inline struct xmit_frame *alloc_mgtxmitframe_once(struct xmit_priv *pxmitpriv)
+-{
+- return _alloc_mgtxmitframe(pxmitpriv, true);
+-}
+-
+-
+ /****************************************************************************
+
+ Following are some TX fuctions for WiFi MLME
+@@ -2715,9 +2639,9 @@ s32 dump_mgntframe_and_wait(_adapter *pa
+ if (ret == _SUCCESS)
+ ret = rtw_sctx_wait(&sctx, __func__);
+
+- _enter_critical(&pxmitpriv->lock_sctx, &irqL);
++ spin_lock_irqsave(&pxmitpriv->lock_sctx, irqL);
+ pxmitbuf->sctx = NULL;
+- _exit_critical(&pxmitpriv->lock_sctx, &irqL);
++ spin_unlock_irqrestore(&pxmitpriv->lock_sctx, irqL);
+
+ return ret;
+ }
+@@ -2737,16 +2661,17 @@ s32 dump_mgntframe_and_wait_ack(_adapter
+ return -1;
+ }
+
+- _enter_critical_mutex(&pxmitpriv->ack_tx_mutex, NULL);
+- 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);
+- }
++ 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;
+- _exit_critical_mutex(&pxmitpriv->ack_tx_mutex, NULL);
++ pxmitpriv->ack_tx = false;
++ mutex_unlock(&pxmitpriv->ack_tx_mutex);
++ }
+
+ return ret;
+ }
+@@ -2798,10 +2723,8 @@ void issue_beacon(_adapter *padapter, in
+ unsigned short *fctrl;
+ unsigned int rate_len;
+ struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
+-#if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)
+ _irqL irqL;
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+-#endif //#if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)
+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
+ WLAN_BSSID_EX *cur_network = &(pmlmeinfo->network);
+@@ -2814,9 +2737,8 @@ void issue_beacon(_adapter *padapter, in
+ DBG_871X("%s, alloc mgnt frame fail\n", __FUNCTION__);
+ return;
+ }
+-#if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)
+- _enter_critical_bh(&pmlmepriv->bcn_update_lock, &irqL);
+-#endif //#if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)
++
++ spin_lock_bh(&pmlmepriv->bcn_update_lock);
+
+ //update attribute
+ pattrib = &pmgntframe->attrib;
+@@ -2932,11 +2854,9 @@ void issue_beacon(_adapter *padapter, in
+
+ _issue_bcn:
+
+-#if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)
+ pmlmepriv->update_bcn = false;
+-
+- _exit_critical_bh(&pmlmepriv->bcn_update_lock, &irqL);
+-#endif //#if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)
++
++ spin_unlock_bh(&pmlmepriv->bcn_update_lock);
+
+ if ((pattrib->pktlen + TXDESC_SIZE) > 512)
+ {
+@@ -2963,11 +2883,10 @@ void issue_probersp(_adapter *padapter,
+ unsigned short *fctrl;
+ unsigned char *mac, *bssid;
+ struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
+-#if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)
++
+ u8 *pwps_ie;
+ uint wps_ielen;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+-#endif //#if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)
+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
+ WLAN_BSSID_EX *cur_network = &(pmlmeinfo->network);
+@@ -3015,7 +2934,6 @@ void issue_probersp(_adapter *padapter,
+ if(cur_network->IELength>MAX_IE_SZ)
+ return;
+
+-#if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)
+ 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);
+@@ -3091,11 +3009,9 @@ void issue_probersp(_adapter *padapter,
+ pattrib->pktlen += ssid_ielen_diff;
+ }
+ }
+- }
+- else
+-#endif
++ }
++ else
+ {
+-
+ //timestamp will be inserted by hardware
+ pframe += 8;
+ pattrib->pktlen += 8;
+@@ -3387,13 +3303,10 @@ void issue_auth(_adapter *padapter, stru
+
+ if(psta)// for AP mode
+ {
+-#ifdef CONFIG_NATIVEAP_MLME
+-
+ 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;
+
+@@ -3422,7 +3335,6 @@ void issue_auth(_adapter *padapter, stru
+ {
+ pframe = rtw_set_ie(pframe, _CHLGETXT_IE_, 128, psta->chg_txt, &(pattrib->pktlen));
+ }
+-#endif
+ }
+ else
+ {
+@@ -3493,7 +3405,6 @@ void issue_auth(_adapter *padapter, stru
+
+ void issue_asocrsp(_adapter *padapter, unsigned short status, struct sta_info *pstat, int pkt_type)
+ {
+-#ifdef CONFIG_AP_MODE
+ struct xmit_frame *pmgntframe;
+ struct rtw_ieee80211_hdr *pwlanhdr;
+ struct pkt_attrib *pattrib;
+@@ -3634,8 +3545,6 @@ void issue_asocrsp(_adapter *padapter, u
+ pattrib->last_txcmdsz = pattrib->pktlen;
+
+ dump_mgntframe(padapter, pmgntframe);
+-
+-#endif
+ }
+
+ void issue_assocreq(_adapter *padapter)
+@@ -3827,10 +3736,6 @@ void issue_assocreq(_adapter *padapter)
+ }
+
+
+-#ifdef CONFIG_WAPI_SUPPORT
+- rtw_build_assoc_req_wapi_ie(padapter, pframe, pattrib);
+-#endif
+-
+ pattrib->last_txcmdsz = pattrib->pktlen;
+ dump_mgntframe(padapter, pmgntframe);
+
+@@ -4262,71 +4167,6 @@ exit:
+ return ret;
+ }
+
+-void issue_action_spct_ch_switch(_adapter *padapter, u8 *ra, u8 new_ch, u8 ch_offset)
+-{
+- _irqL irqL;
+- _list *plist, *phead;
+- struct xmit_frame *pmgntframe;
+- struct pkt_attrib *pattrib;
+- unsigned char *pframe;
+- struct rtw_ieee80211_hdr *pwlanhdr;
+- unsigned short *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);
+-
+-
+- DBG_871X(FUNC_NDEV_FMT" ra="MAC_FMT", ch:%u, offset:%u\n",
+- FUNC_NDEV_ARG(padapter->pnetdev), MAC_ARG(ra), new_ch, ch_offset);
+-
+- if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == 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 rtw_ieee80211_hdr *)pframe;
+-
+- fctrl = &(pwlanhdr->frame_ctl);
+- *(fctrl) = 0;
+-
+- memcpy(pwlanhdr->addr1, ra, ETH_ALEN); /* RA */
+- memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); /* TA */
+- memcpy(pwlanhdr->addr3, ra, ETH_ALEN); /* DA = RA */
+-
+- SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+- pmlmeext->mgnt_seq++;
+- SetFrameSubType(pframe, WIFI_ACTION);
+-
+- pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
+- pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
+-
+- /* category, action */
+- {
+- u8 category, action;
+- category = RTW_WLAN_CATEGORY_SPECTRUM_MGMT;
+- action = RTW_WLAN_ACTION_SPCT_CHL_SWITCH;
+-
+- pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
+- pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
+- }
+-
+- pframe = rtw_set_ie_ch_switch(pframe, &(pattrib->pktlen), 0, new_ch, 0);
+- pframe = rtw_set_ie_secondary_ch_offset(pframe, &(pattrib->pktlen),
+- hal_ch_offset_to_secondary_ch_offset(ch_offset));
+-
+- pattrib->last_txcmdsz = pattrib->pktlen;
+-
+- dump_mgntframe(padapter, pmgntframe);
+-
+-}
+-
+-#ifdef CONFIG_IEEE80211W
+ void issue_action_SA_Query(_adapter *padapter, unsigned char *raddr, unsigned char action, unsigned short tid)
+ {
+ u8 category = RTW_WLAN_CATEGORY_SA_QUERY;
+@@ -4402,7 +4242,6 @@ void issue_action_SA_Query(_adapter *pad
+
+ dump_mgntframe(padapter, pmgntframe);
+ }
+-#endif //CONFIG_IEEE80211W
+
+ void issue_action_BA(_adapter *padapter, unsigned char *raddr, unsigned char action, unsigned short status)
+ {
+@@ -4658,7 +4497,7 @@ static void issue_action_BSSCoexistPacke
+ {
+ int i;
+
+- _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
++ spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
+
+ phead = get_list_head(queue);
+ plist = get_next(phead);
+@@ -4669,7 +4508,7 @@ static void issue_action_BSSCoexistPacke
+ u8 *p;
+ WLAN_BSSID_EX *pbss_network;
+
+- if (rtw_end_of_queue_search(phead,plist)== true)
++ if (phead == plist)
+ break;
+
+ pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
+@@ -4692,7 +4531,7 @@ static void issue_action_BSSCoexistPacke
+
+ }
+
+- _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
++ spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
+
+
+ for(i= 0;i<8;i++)
+@@ -4839,22 +4678,6 @@ Following are some utitity fuctions for
+
+ *****************************************************************************/
+
+-bool IsLegal5GChannel(
+- IN PADAPTER Adapter,
+- IN u8 channel)
+-{
+-
+- int i=0;
+- u8 Channel_5G[45] = {36,38,40,42,44,46,48,50,52,54,56,58,
+- 60,62,64,100,102,104,106,108,110,112,114,116,118,120,122,
+- 124,126,128,130,132,134,136,138,140,149,151,153,155,157,159,
+- 161,163,165};
+- for(i=0;iauth_algo == dot11AuthAlgrthm_8021X)? 0xcc: 0xcf;
+
+-#ifdef CONFIG_WAPI_SUPPORT
+- if (padapter->wapiInfo.bWapiEnable && pmlmeinfo->auth_algo == dot11AuthAlgrthm_WAPI)
+- {
+- //Disable TxUseDefaultKey, RxUseDefaultKey, RxBroadcastUseDefaultKey.
+- val8 = 0x4c;
+- }
+-#endif
+ rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
+
+ // Because of AP's not receiving deauth before
+@@ -5413,7 +5229,6 @@ unsigned int receive_disconnect(_adapter
+ return _SUCCESS;
+ }
+
+-#ifdef CONFIG_80211D
+ static void process_80211d(PADAPTER padapter, WLAN_BSSID_EX *bssid)
+ {
+ struct registry_priv *pregistrypriv;
+@@ -5678,7 +5493,6 @@ static void process_80211d(PADAPTER pada
+ i++;
+ }
+ }
+-#endif
+
+ /****************************************************************************
+
+@@ -5713,11 +5527,11 @@ void report_survey_event(_adapter *padap
+ cmdsz = (sizeof(struct survey_event) + sizeof(struct C2HEvent_Header));
+ if ((pevtcmd = (u8*)rtw_zmalloc(cmdsz)) == NULL)
+ {
+- rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj));
++ kfree((u8 *)pcmd_obj);
+ return;
+ }
+
+- _rtw_init_listhead(&pcmd_obj->list);
++ INIT_LIST_HEAD(&pcmd_obj->list);
+
+ pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
+ pcmd_obj->cmdsz = cmdsz;
+@@ -5735,14 +5549,12 @@ void report_survey_event(_adapter *padap
+
+ if (collect_bss_info(padapter, precv_frame, (WLAN_BSSID_EX *)&psurvey_evt->bss) == _FAIL)
+ {
+- rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj));
+- rtw_mfree((u8 *)pevtcmd, cmdsz);
++ kfree((u8 *)pcmd_obj);
++ kfree((u8 *)pevtcmd);
+ return;
+ }
+
+-#ifdef CONFIG_80211D
+ process_80211d(padapter, &psurvey_evt->bss);
+-#endif
+
+ rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
+
+@@ -5770,11 +5582,11 @@ void report_surveydone_event(_adapter *p
+ cmdsz = (sizeof(struct surveydone_event) + sizeof(struct C2HEvent_Header));
+ if ((pevtcmd = (u8*)rtw_zmalloc(cmdsz)) == NULL)
+ {
+- rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj));
++ kfree((u8 *)pcmd_obj);
+ return;
+ }
+
+- _rtw_init_listhead(&pcmd_obj->list);
++ INIT_LIST_HEAD(&pcmd_obj->list);
+
+ pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
+ pcmd_obj->cmdsz = cmdsz;
+@@ -5818,11 +5630,11 @@ void report_join_res(_adapter *padapter,
+ cmdsz = (sizeof(struct joinbss_event) + sizeof(struct C2HEvent_Header));
+ if ((pevtcmd = (u8*)rtw_zmalloc(cmdsz)) == NULL)
+ {
+- rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj));
++ kfree((u8 *)pcmd_obj);
+ return;
+ }
+
+- _rtw_init_listhead(&pcmd_obj->list);
++ INIT_LIST_HEAD(&pcmd_obj->list);
+
+ pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
+ pcmd_obj->cmdsz = cmdsz;
+@@ -5871,11 +5683,11 @@ void report_wmm_edca_update(_adapter *pa
+ cmdsz = (sizeof(struct wmm_event) + sizeof(struct C2HEvent_Header));
+ if ((pevtcmd = (u8*)rtw_zmalloc(cmdsz)) == NULL)
+ {
+- rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj));
++ kfree((u8 *)pcmd_obj);
+ return;
+ }
+
+- _rtw_init_listhead(&pcmd_obj->list);
++ INIT_LIST_HEAD(&pcmd_obj->list);
+
+ pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
+ pcmd_obj->cmdsz = cmdsz;
+@@ -5918,11 +5730,11 @@ void report_del_sta_event(_adapter *pada
+ cmdsz = (sizeof(struct stadel_event) + sizeof(struct C2HEvent_Header));
+ if ((pevtcmd = (u8*)rtw_zmalloc(cmdsz)) == NULL)
+ {
+- rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj));
++ kfree((u8 *)pcmd_obj);
+ return;
+ }
+
+- _rtw_init_listhead(&pcmd_obj->list);
++ INIT_LIST_HEAD(&pcmd_obj->list);
+
+ pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
+ pcmd_obj->cmdsz = cmdsz;
+@@ -5974,11 +5786,11 @@ void report_add_sta_event(_adapter *pada
+ cmdsz = (sizeof(struct stassoc_event) + sizeof(struct C2HEvent_Header));
+ if ((pevtcmd = (u8*)rtw_zmalloc(cmdsz)) == NULL)
+ {
+- rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj));
++ kfree((u8 *)pcmd_obj);
+ return;
+ }
+
+- _rtw_init_listhead(&pcmd_obj->list);
++ INIT_LIST_HEAD(&pcmd_obj->list);
+
+ pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
+ pcmd_obj->cmdsz = cmdsz;
+@@ -6075,9 +5887,9 @@ void update_sta_info(_adapter *padapter,
+
+ update_ldpc_stbc_cap(psta);
+
+- _enter_critical_bh(&psta->lock, &irqL);
++ spin_lock_bh(&psta->lock);
+ psta->state = _FW_LINKED;
+- _exit_critical_bh(&psta->lock, &irqL);
++ spin_unlock_bh(&psta->lock);
+
+ }
+
+@@ -6335,10 +6147,10 @@ void _linked_info_dump(_adapter *padapte
+ struct sta_info *psta=NULL;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+
+- _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
++ spin_lock_bh(&pstapriv->asoc_list_lock);
+ phead = &pstapriv->asoc_list;
+ plist = get_next(phead);
+- while ((rtw_end_of_queue_search(phead, plist)) == false)
++ while (phead != plist)
+ {
+ psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
+ plist = get_next(plist);
+@@ -6346,7 +6158,7 @@ void _linked_info_dump(_adapter *padapte
+ DBG_871X("STA[" MAC_FMT "]:UndecoratedSmoothedPWDB:%d\n",
+ MAC_ARG(psta->hwaddr),psta->rssi_stat.UndecoratedSmoothedPWDB);
+ }
+- _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
++ spin_unlock_bh(&pstapriv->asoc_list_lock);
+
+ }
+ for(i=0; imlmeextpriv;
+ struct mlme_priv * pmlmepriv = &padapter->mlmepriv;
+ _irqL irqL;
+ //disconnect
+- _enter_critical_bh(&pmlmepriv->lock, &irqL);
++ spin_lock_bh(&pmlmepriv->lock);
+
+ if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
+ {
+@@ -6677,10 +6488,9 @@ void sa_query_timer_hdl(_adapter *padapt
+ rtw_free_assoc_resources(padapter, 1);
+ }
+
+- _exit_critical_bh(&pmlmepriv->lock, &irqL);
++ spin_unlock_bh(&pmlmepriv->lock);
+ DBG_871X("SA query timeout disconnect\n");
+ }
+-#endif //CONFIG_IEEE80211W
+
+ u8 NULL_hdl(_adapter *padapter, u8 *pbuf)
+ {
+@@ -6688,15 +6498,6 @@ u8 NULL_hdl(_adapter *padapter, u8 *pbuf
+ }
+
+ #ifdef CONFIG_AUTO_AP_MODE
+-void rtw_start_auto_ap(_adapter *adapter)
+-{
+- DBG_871X("%s\n", __FUNCTION__);
+-
+- rtw_set_802_11_infrastructure_mode(adapter, Ndis802_11APMode);
+-
+- rtw_setopmode_cmd(adapter, Ndis802_11APMode,true);
+-}
+-
+ static int rtw_auto_ap_start_beacon(_adapter *adapter)
+ {
+ int ret=0;
+@@ -6792,7 +6593,7 @@ static int rtw_auto_ap_start_beacon(_ada
+ }
+
+
+- rtw_mfree(pbuf, len);
++ kfree(pbuf);
+
+ return ret;
+
+@@ -6810,9 +6611,7 @@ u8 setopmode_hdl(_adapter *padapter, u8
+ {
+ pmlmeinfo->state = WIFI_FW_AP_STATE;
+ type = _HW_STATE_AP_;
+-#ifdef CONFIG_NATIVEAP_MLME
+ //start_ap_mode(padapter);
+-#endif
+ }
+ else if(psetop->mode == Ndis802_11Infrastructure)
+ {
+@@ -6869,14 +6668,12 @@ u8 createbss_hdl(_adapter *padapter, u8
+ WLAN_BSSID_EX *pnetwork = (WLAN_BSSID_EX*)(&(pmlmeinfo->network));
+ struct joinbss_parm *pparm = (struct joinbss_parm *)pbuf;
+ //u32 initialgain;
+-
+-#ifdef CONFIG_AP_MODE
++
+ if (pmlmeinfo->state == WIFI_FW_AP_STATE) {
+ WLAN_BSSID_EX *network = &padapter->mlmepriv.cur_network.network;
+ start_bss_network(padapter, (u8*)network);
+ return H2C_SUCCESS;
+ }
+-#endif
+
+ //below is for ad-hoc master
+ if(pparm->network.InfrastructureMode == Ndis802_11IBSS)
+@@ -6959,10 +6756,6 @@ u8 join_cmd_hdl(_adapter *padapter, u8 *
+ rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, NULL);
+ }
+
+-#ifdef CONFIG_WAPI_SUPPORT
+- rtw_wapi_clear_all_cam_entry(padapter);
+-#endif
+-
+ rtw_joinbss_reset(padapter);
+
+ pmlmeext->cur_bwmode = CHANNEL_WIDTH_20;
+@@ -7297,10 +7090,8 @@ u8 setkey_hdl(_adapter *padapter, u8 *pb
+ ,cam_id, MAC_ARG(addr), pparm->keyid, security_type_str(pparm->algorithm));
+ }
+
+- #ifdef DYNAMIC_CAMID_ALLOC
+ if (cam_id >=0 && cam_id <=3)
+ rtw_hal_set_hwreg(padapter, HW_VAR_SEC_DK_CFG, (u8*)true);
+- #endif
+
+ //allow multicast packets to driver
+ padapter->HalFunc.SetHwRegHandler(padapter, HW_VAR_ON_RCR_AM, null_addr);
+@@ -7427,7 +7218,7 @@ _func_enter_;
+
+ if ((ptxBeacon_parm = (struct Tx_Beacon_param *)rtw_zmalloc(sizeof(struct Tx_Beacon_param))) == NULL)
+ {
+- rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
++ kfree((unsigned char *)ph2c);
+ res= _FAIL;
+ goto exit;
+ }
+@@ -7531,7 +7322,6 @@ u8 h2c_msg_hdl(_adapter *padapter, unsig
+
+ u8 chk_bmc_sleepq_hdl(_adapter *padapter, unsigned char *pbuf)
+ {
+-#ifdef CONFIG_AP_MODE
+ _irqL irqL;
+ struct sta_info *psta_bmc;
+ _list *xmitframe_plist, *xmitframe_phead;
+@@ -7548,19 +7338,19 @@ u8 chk_bmc_sleepq_hdl(_adapter *padapter
+ {
+ msleep(10);// 10ms, ATIM(HIQ) Windows
+
+- //_enter_critical_bh(&psta_bmc->sleep_q.lock, &irqL);
+- _enter_critical_bh(&pxmitpriv->lock, &irqL);
++ //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 ((rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist)) == false)
++ while (xmitframe_phead != xmitframe_plist)
+ {
+ pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list);
+
+ xmitframe_plist = get_next(xmitframe_plist);
+
+- rtw_list_delete(&pxmitframe->list);
++ list_del_init(&pxmitframe->list);
+
+ psta_bmc->sleepq_len--;
+ if(psta_bmc->sleepq_len>0)
+@@ -7576,13 +7366,12 @@ u8 chk_bmc_sleepq_hdl(_adapter *padapter
+ rtw_hal_xmitframe_enqueue(padapter, pxmitframe);
+ }
+
+- //_exit_critical_bh(&psta_bmc->sleep_q.lock, &irqL);
+- _exit_critical_bh(&pxmitpriv->lock, &irqL);
++ //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);
+ }
+-#endif
+
+ return H2C_SUCCESS;
+ }
+@@ -7601,58 +7390,6 @@ u8 tx_beacon_hdl(_adapter *padapter, uns
+ return H2C_SUCCESS;
+ }
+
+-void change_band_update_ie(_adapter *padapter, WLAN_BSSID_EX *pnetwork)
+-{
+- u8 network_type,rate_len, total_rate_len,remainder_rate_len;
+- struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
+- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
+- u8 erpinfo=0x4;
+-
+- //DBG_871X("%s\n", __FUNCTION__);
+-
+- if(pmlmeext->cur_channel >= 36)
+- {
+- network_type = WIRELESS_11A;
+- total_rate_len = IEEE80211_NUM_OFDM_RATESLEN;
+- DBG_871X("%s(): change to 5G Band\n",__FUNCTION__);
+- rtw_remove_bcn_ie(padapter, pnetwork, _ERPINFO_IE_);
+- }
+- else
+- {
+- network_type = WIRELESS_11BG;
+- total_rate_len = IEEE80211_CCK_RATE_LEN+IEEE80211_NUM_OFDM_RATESLEN;
+- DBG_871X("%s(): change to 2.4G Band\n",__FUNCTION__);
+- rtw_add_bcn_ie(padapter, pnetwork, _ERPINFO_IE_, &erpinfo, 1);
+- }
+-
+- rtw_set_supported_rate(pnetwork->SupportedRates, network_type);
+-
+- UpdateBrateTbl(padapter, pnetwork->SupportedRates);
+- rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, pnetwork->SupportedRates);
+-
+- if(total_rate_len > 8)
+- {
+- rate_len = 8;
+- remainder_rate_len = total_rate_len - 8;
+- }
+- else
+- {
+- rate_len = total_rate_len;
+- remainder_rate_len = 0;
+- }
+-
+- rtw_add_bcn_ie(padapter, pnetwork, _SUPPORTEDRATES_IE_, pnetwork->SupportedRates, rate_len);
+-
+- if(remainder_rate_len)
+- {
+- rtw_add_bcn_ie(padapter, pnetwork, _EXT_SUPPORTEDRATES_IE_, (pnetwork->SupportedRates+8), remainder_rate_len);
+- }
+- else
+- {
+- rtw_remove_bcn_ie(padapter, pnetwork, _EXT_SUPPORTEDRATES_IE_);
+- }
+-}
+-
+ int rtw_chk_start_clnt_join(_adapter *padapter, u8 *ch, u8 *bw, u8 *offset)
+ {
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+diff -Nurp linux/3rdparty/rtl8723bs.old/core/rtw_pwrctrl.c linux/3rdparty/rtl8723bs/core/rtw_pwrctrl.c
+--- linux/3rdparty/rtl8723bs.old/core/rtw_pwrctrl.c 2015-05-10 14:36:05.674667968 +0300
++++ linux/3rdparty/rtl8723bs/core/rtw_pwrctrl.c 2015-05-07 17:46:55.000000000 +0300
+@@ -24,53 +24,6 @@
+ #include
+
+
+-int rtw_fw_ps_state(PADAPTER padapter)
+-{
+- struct dvobj_priv *psdpriv = padapter->dvobj;
+- struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
+- int ret=_FAIL, dont_care=0;
+- u16 fw_ps_state=0;
+- u32 start_time;
+- struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
+- struct registry_priv *registry_par = &padapter->registrypriv;
+-
+- if(registry_par->check_fw_ps != 1)
+- return _SUCCESS;
+-
+- down(&pwrpriv->check_32k_lock);
+-
+- if ((padapter->bSurpriseRemoved == true))
+- {
+- DBG_871X("%s: bSurpriseRemoved=%d , hw_init_completed=%d, bDriverStopped=%d \n", __FUNCTION__, padapter->bSurpriseRemoved,
+- padapter->hw_init_completed,padapter->bDriverStopped);
+- goto exit_fw_ps_state;
+- }
+- rtw_hal_set_hwreg(padapter, HW_VAR_SET_REQ_FW_PS, (u8 *)&dont_care);
+- {
+- //4. if 0x88[7]=1, driver set cmd to leave LPS/IPS.
+- //Else, hw will keep in active mode.
+- //debug info:
+- //0x88[7] = 32kpermission,
+- //0x88[6:0] = current_ps_state
+- //0x89[7:0] = last_rpwm
+-
+- rtw_hal_get_hwreg(padapter, HW_VAR_FW_PS_STATE, (u8 *)&fw_ps_state);
+-
+- if((fw_ps_state & 0x80) == 0)
+- ret=_SUCCESS;
+- else
+- {
+- pdbgpriv->dbg_poll_fail_cnt++;
+- DBG_871X("%s: fw_ps_state=%04x \n", __FUNCTION__, fw_ps_state);
+- }
+- }
+-
+-
+-exit_fw_ps_state:
+- up(&pwrpriv->check_32k_lock);
+- return ret;
+-}
+-
+ void _ips_enter(_adapter * padapter)
+ {
+ struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
+@@ -152,9 +105,6 @@ int ips_leave(_adapter * padapter)
+ up(&pwrpriv->lock);
+
+ if (_SUCCESS == ret)
+- ODM_DMReset(&GET_HAL_DATA(padapter)->odmpriv);
+-
+- if (_SUCCESS == ret)
+ rtw_btcoex_IpsNotify(padapter, IPS_NONE);
+
+ return ret;
+@@ -1264,68 +1214,6 @@ _func_exit_;
+ }
+
+ /*
+- * Caller: rx_isr
+- *
+- * Calling Context: Dispatch/ISR
+- *
+- * Return Value:
+- * _SUCCESS
+- * _FAIL
+- */
+-s32 rtw_register_rx_alive(PADAPTER padapter)
+-{
+- struct pwrctrl_priv *pwrctrl;
+-
+-_func_enter_;
+-
+- pwrctrl = adapter_to_pwrctl(padapter);
+-
+- down(&pwrctrl->lock);
+-
+- register_task_alive(pwrctrl, RECV_ALIVE);
+- RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
+- ("rtw_register_rx_alive: cpwm=0x%02x alives=0x%08x\n",
+- pwrctrl->cpwm, pwrctrl->alives));
+-
+- up(&pwrctrl->lock);
+-
+-_func_exit_;
+-
+- return _SUCCESS;
+-}
+-
+-/*
+- * Caller: evt_isr or evt_thread
+- *
+- * Calling Context: Dispatch/ISR or Passive
+- *
+- * Return Value:
+- * _SUCCESS
+- * _FAIL
+- */
+-s32 rtw_register_evt_alive(PADAPTER padapter)
+-{
+- struct pwrctrl_priv *pwrctrl;
+-
+-_func_enter_;
+-
+- pwrctrl = adapter_to_pwrctl(padapter);
+-
+- down(&pwrctrl->lock);
+-
+- register_task_alive(pwrctrl, EVT_ALIVE);
+- RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
+- ("rtw_register_evt_alive: cpwm=0x%02x alives=0x%08x\n",
+- pwrctrl->cpwm, pwrctrl->alives));
+-
+- up(&pwrctrl->lock);
+-
+-_func_exit_;
+-
+- return _SUCCESS;
+-}
+-
+-/*
+ * Caller: ISR
+ *
+ * If ISR's txdone,
+@@ -1425,49 +1313,6 @@ _func_enter_;
+ _func_exit_;
+ }
+
+-/*
+- * Caller: ISR
+- */
+-void rtw_unregister_rx_alive(PADAPTER padapter)
+-{
+- struct pwrctrl_priv *pwrctrl;
+-
+-_func_enter_;
+-
+- pwrctrl = adapter_to_pwrctl(padapter);
+-
+- down(&pwrctrl->lock);
+-
+- unregister_task_alive(pwrctrl, RECV_ALIVE);
+-
+- RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
+- ("rtw_unregister_rx_alive: cpwm=0x%02x alives=0x%08x\n",
+- pwrctrl->cpwm, pwrctrl->alives));
+-
+- up(&pwrctrl->lock);
+-
+-_func_exit_;
+-}
+-
+-void rtw_unregister_evt_alive(PADAPTER padapter)
+-{
+- struct pwrctrl_priv *pwrctrl;
+-
+-_func_enter_;
+-
+- pwrctrl = adapter_to_pwrctl(padapter);
+-
+- unregister_task_alive(pwrctrl, EVT_ALIVE);
+-
+- RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
+- ("rtw_unregister_evt_alive: cpwm=0x%02x alives=0x%08x\n",
+- pwrctrl->cpwm, pwrctrl->alives));
+-
+- up(&pwrctrl->lock);
+-
+-_func_exit_;
+-}
+-
+ void rtw_init_pwrctrl_priv(PADAPTER padapter)
+ {
+ struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter);
+@@ -1558,15 +1403,6 @@ _func_enter_;
+ _func_exit_;
+ }
+
+-u8 rtw_interface_ps_func(_adapter *padapter,HAL_INTF_PS_FUNC efunc_id,u8* val)
+-{
+- u8 bResult = true;
+- rtw_hal_intf_ps_func(padapter,efunc_id,val);
+-
+- return bResult;
+-}
+-
+-
+ inline void rtw_set_ips_deny(_adapter *padapter, u32 ms)
+ {
+ struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
+diff -Nurp linux/3rdparty/rtl8723bs.old/core/rtw_recv.c linux/3rdparty/rtl8723bs/core/rtw_recv.c
+--- linux/3rdparty/rtl8723bs.old/core/rtw_recv.c 2015-05-10 14:36:05.676667990 +0300
++++ linux/3rdparty/rtl8723bs/core/rtw_recv.c 2015-05-07 17:46:55.000000000 +0300
+@@ -53,7 +53,7 @@ sint _rtw_init_recv_priv(struct recv_pri
+
+ _func_enter_;
+
+- // We don't need to memset padapter->XXX to zero, because adapter is allocated by rtw_zvmalloc().
++ // 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);
+@@ -66,9 +66,7 @@ _func_enter_;
+
+ precvpriv->free_recvframe_cnt = NR_RECVFRAME;
+
+- rtw_os_recv_resource_init(precvpriv, padapter);
+-
+- precvpriv->pallocated_frame_buf = rtw_zvmalloc(NR_RECVFRAME * sizeof(union recv_frame) + RXFRAME_ALIGN_SZ);
++ precvpriv->pallocated_frame_buf = vzalloc(NR_RECVFRAME * sizeof(union recv_frame) + RXFRAME_ALIGN_SZ);
+
+ if(precvpriv->pallocated_frame_buf==NULL){
+ res= _FAIL;
+@@ -85,9 +83,9 @@ _func_enter_;
+
+ for(i=0; i < NR_RECVFRAME ; i++)
+ {
+- _rtw_init_listhead(&(precvframe->u.list));
++ INIT_LIST_HEAD(&(precvframe->u.list));
+
+- rtw_list_insert_tail(&(precvframe->u.list), &(precvpriv->free_recv_queue.queue));
++ list_add_tail(&(precvframe->u.list), &(precvpriv->free_recv_queue.queue));
+
+ res = rtw_os_recv_resource_alloc(padapter, precvframe);
+
+@@ -126,7 +124,7 @@ _func_enter_;
+ rtw_os_recv_resource_free(precvpriv);
+
+ if(precvpriv->pallocated_frame_buf) {
+- rtw_vmfree(precvpriv->pallocated_frame_buf, NR_RECVFRAME * sizeof(union recv_frame) + RXFRAME_ALIGN_SZ);
++ vfree(precvpriv->pallocated_frame_buf);
+ }
+
+ rtw_hal_free_recv_priv(padapter);
+@@ -144,7 +142,7 @@ union recv_frame *_rtw_alloc_recvframe (
+ struct recv_priv *precvpriv;
+ _func_enter_;
+
+- if(_rtw_queue_empty(pfree_recv_queue) == true)
++ if(list_empty(&pfree_recv_queue->queue))
+ {
+ precvframe = NULL;
+ }
+@@ -156,7 +154,7 @@ _func_enter_;
+
+ precvframe = LIST_CONTAINOR(plist, union recv_frame, u);
+
+- rtw_list_delete(&precvframe->u.hdr.list);
++ list_del_init(&precvframe->u.hdr.list);
+ padapter=precvframe->u.hdr.adapter;
+ if(padapter !=NULL){
+ precvpriv=&padapter->recvpriv;
+@@ -176,23 +174,15 @@ union recv_frame *rtw_alloc_recvframe (_
+ _irqL irqL;
+ union recv_frame *precvframe;
+
+- _enter_critical_bh(&pfree_recv_queue->lock, &irqL);
++ spin_lock_bh(&pfree_recv_queue->lock);
+
+ precvframe = _rtw_alloc_recvframe(pfree_recv_queue);
+
+- _exit_critical_bh(&pfree_recv_queue->lock, &irqL);
++ spin_unlock_bh(&pfree_recv_queue->lock);
+
+ return precvframe;
+ }
+
+-void rtw_init_recvframe(union recv_frame *precvframe, struct recv_priv *precvpriv)
+-{
+- /* Perry: This can be removed */
+- _rtw_init_listhead(&precvframe->u.hdr.list);
+-
+- precvframe->u.hdr.len=0;
+-}
+-
+ int rtw_free_recvframe(union recv_frame *precvframe, _queue *pfree_recv_queue)
+ {
+ _irqL irqL;
+@@ -204,20 +194,20 @@ _func_enter_;
+ rtw_os_free_recvframe(precvframe);
+
+
+- _enter_critical_bh(&pfree_recv_queue->lock, &irqL);
++ spin_lock_bh(&pfree_recv_queue->lock);
+
+- rtw_list_delete(&(precvframe->u.hdr.list));
++ list_del_init(&(precvframe->u.hdr.list));
+
+ precvframe->u.hdr.len = 0;
+
+- rtw_list_insert_tail(&(precvframe->u.hdr.list), get_list_head(pfree_recv_queue));
++ 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++;
+ }
+
+- _exit_critical_bh(&pfree_recv_queue->lock, &irqL);
++ spin_unlock_bh(&pfree_recv_queue->lock);
+
+ _func_exit_;
+
+@@ -236,11 +226,11 @@ sint _rtw_enqueue_recvframe(union recv_f
+
+ _func_enter_;
+
+- //_rtw_init_listhead(&(precvframe->u.hdr.list));
+- rtw_list_delete(&(precvframe->u.hdr.list));
++ //INIT_LIST_HEAD(&(precvframe->u.hdr.list));
++ list_del_init(&(precvframe->u.hdr.list));
+
+
+- rtw_list_insert_tail(&(precvframe->u.hdr.list), get_list_head(queue));
++ list_add_tail(&(precvframe->u.hdr.list), get_list_head(queue));
+
+ if (padapter != NULL) {
+ if (queue == &precvpriv->free_recv_queue)
+@@ -258,10 +248,10 @@ sint rtw_enqueue_recvframe(union recv_fr
+ _irqL irqL;
+
+ //_spinlock(&pfree_recv_queue->lock);
+- _enter_critical_bh(&queue->lock, &irqL);
++ spin_lock_bh(&queue->lock);
+ ret = _rtw_enqueue_recvframe(precvframe, queue);
+ //spin_unlock(&pfree_recv_queue->lock);
+- _exit_critical_bh(&queue->lock, &irqL);
++ spin_unlock_bh(&queue->lock);
+
+ return ret;
+ }
+@@ -295,13 +285,13 @@ _func_enter_;
+ phead = get_list_head(pframequeue);
+ plist = get_next(phead);
+
+- while(rtw_end_of_queue_search(phead, plist) == false)
++ while(phead != plist)
+ {
+ precvframe = LIST_CONTAINOR(plist, union recv_frame, u);
+
+ plist = get_next(plist);
+
+- //rtw_list_delete(&precvframe->u.hdr.list); // will do this in rtw_free_recvframe()
++ //list_del_init(&precvframe->u.hdr.list); // will do this in rtw_free_recvframe()
+
+ rtw_free_recvframe(precvframe, pfree_recv_queue);
+ }
+@@ -332,12 +322,12 @@ sint rtw_enqueue_recvbuf_to_head(struct
+ {
+ _irqL irqL;
+
+- _enter_critical_bh(&queue->lock, &irqL);
++ spin_lock_bh(&queue->lock);
+
+- rtw_list_delete(&precvbuf->list);
+- rtw_list_insert_head(&precvbuf->list, get_list_head(queue));
++ list_del_init(&precvbuf->list);
++ list_add(&precvbuf->list, get_list_head(queue));
+
+- _exit_critical_bh(&queue->lock, &irqL);
++ spin_unlock_bh(&queue->lock);
+
+ return _SUCCESS;
+ }
+@@ -345,12 +335,12 @@ sint rtw_enqueue_recvbuf_to_head(struct
+ sint rtw_enqueue_recvbuf(struct recv_buf *precvbuf, _queue *queue)
+ {
+ _irqL irqL;
+- _enter_critical_bh(&queue->lock, &irqL);
++ spin_lock_bh(&queue->lock);
+
+- rtw_list_delete(&precvbuf->list);
++ list_del_init(&precvbuf->list);
+
+- rtw_list_insert_tail(&precvbuf->list, get_list_head(queue));
+- _exit_critical_bh(&queue->lock, &irqL);
++ list_add_tail(&precvbuf->list, get_list_head(queue));
++ spin_unlock_bh(&queue->lock);
+ return _SUCCESS;
+
+ }
+@@ -361,9 +351,9 @@ struct recv_buf *rtw_dequeue_recvbuf (_q
+ struct recv_buf *precvbuf;
+ _list *plist, *phead;
+
+- _enter_critical_bh(&queue->lock, &irqL);
++ spin_lock_bh(&queue->lock);
+
+- if(_rtw_queue_empty(queue) == true)
++ if(list_empty(&queue->queue))
+ {
+ precvbuf = NULL;
+ }
+@@ -375,11 +365,11 @@ struct recv_buf *rtw_dequeue_recvbuf (_q
+
+ precvbuf = LIST_CONTAINOR(plist, struct recv_buf, list);
+
+- rtw_list_delete(&precvbuf->list);
++ list_del_init(&precvbuf->list);
+
+ }
+
+- _exit_critical_bh(&queue->lock, &irqL);
++ spin_unlock_bh(&queue->lock);
+
+ return precvbuf;
+
+@@ -597,12 +587,6 @@ _func_enter_;
+ DBG_COUNTER(padapter->rx_logs.core_rx_post_decrypt_aes);
+ res = rtw_aes_decrypt(padapter, (u8 * )precv_frame);
+ break;
+-#ifdef CONFIG_WAPI_SUPPORT
+- case _SMS4_:
+- DBG_COUNTER(padapter->rx_logs.core_rx_post_decrypt_wapi);
+- rtw_sms4_decrypt(padapter, (u8 * )precv_frame);
+- break;
+-#endif
+ default:
+ break;
+ }
+@@ -783,7 +767,6 @@ _func_exit_;
+ void process_pwrbit_data(_adapter *padapter, union recv_frame *precv_frame);
+ void process_pwrbit_data(_adapter *padapter, union recv_frame *precv_frame)
+ {
+-#ifdef CONFIG_AP_MODE
+ unsigned char pwrbit;
+ u8 *ptr = precv_frame->u.hdr.rx_data;
+ struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
+@@ -822,14 +805,11 @@ void process_pwrbit_data(_adapter *padap
+ }
+
+ }
+-
+-#endif
+ }
+
+ void process_wmmps_data(_adapter *padapter, union recv_frame *precv_frame);
+ void process_wmmps_data(_adapter *padapter, union recv_frame *precv_frame)
+ {
+-#ifdef CONFIG_AP_MODE
+ struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ struct sta_info *psta=NULL;
+@@ -882,12 +862,7 @@ void process_wmmps_data(_adapter *padapt
+ issue_qos_nulldata(padapter, psta->hwaddr, (u16)pattrib->priority, 0, 0);
+ }
+ }
+-
+ }
+-
+-
+-#endif
+-
+ }
+
+ void count_rx_stats(_adapter *padapter, union recv_frame *prframe, struct sta_info*sta);
+@@ -1320,7 +1295,6 @@ sint validate_recv_ctrl_frame(_adapter *
+ //only handle ps-poll
+ if(GetFrameSubType(pframe) == WIFI_PSPOLL)
+ {
+-#ifdef CONFIG_AP_MODE
+ u16 aid;
+ u8 wmmps_ac=0;
+
+@@ -1368,19 +1342,19 @@ sint validate_recv_ctrl_frame(_adapter *
+ struct xmit_frame *pxmitframe=NULL;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+
+- //_enter_critical_bh(&psta->sleep_q.lock, &irqL);
+- _enter_critical_bh(&pxmitpriv->lock, &irqL);
++ //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 ((rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist)) == false)
++ if (xmitframe_phead != xmitframe_plist)
+ {
+ pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list);
+
+ xmitframe_plist = get_next(xmitframe_plist);
+
+- rtw_list_delete(&pxmitframe->list);
++ list_del_init(&pxmitframe->list);
+
+ psta->sleepq_len--;
+
+@@ -1406,14 +1380,14 @@ sint validate_recv_ctrl_frame(_adapter *
+ update_beacon(padapter, _TIM_IE_, NULL, true);
+ }
+
+- //_exit_critical_bh(&psta->sleep_q.lock, &irqL);
+- _exit_critical_bh(&pxmitpriv->lock, &irqL);
++ //spin_unlock_bh(&psta->sleep_q.lock);
++ spin_unlock_bh(&pxmitpriv->lock);
+
+ }
+ else
+ {
+- //_exit_critical_bh(&psta->sleep_q.lock, &irqL);
+- _exit_critical_bh(&pxmitpriv->lock, &irqL);
++ //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))
+@@ -1439,7 +1413,6 @@ sint validate_recv_ctrl_frame(_adapter *
+ }
+ }
+ }
+-#endif //CONFIG_AP_MODE
+ }
+
+ return _FAIL;
+@@ -1640,7 +1613,6 @@ _func_exit_;
+ return ret;
+ }
+
+-#ifdef CONFIG_IEEE80211W
+ static sint validate_80211w_mgmt(_adapter *adapter, union recv_frame *precv_frame)
+ {
+ struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
+@@ -1695,7 +1667,7 @@ static sint validate_80211w_mgmt(_adapte
+ 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;
+- rtw_mfree(mgmt_DATA, data_len);
++ kfree(mgmt_DATA);
+ /*//print packet content after decryption
+ {
+ int pp;
+@@ -1759,7 +1731,6 @@ validate_80211w_fail:
+ return _FAIL;
+
+ }
+-#endif //CONFIG_IEEE80211W
+
+ static inline void dump_rx_packet(u8 *ptr)
+ {
+@@ -1788,14 +1759,6 @@ sint validate_recv_frame(_adapter *adapt
+ u8 *ptr = precv_frame->u.hdr.rx_data;
+ u8 ver =(unsigned char) (*ptr)&0x3 ;
+
+-#ifdef CONFIG_WAPI_SUPPORT
+- PRT_WAPI_T pWapiInfo = &adapter->wapiInfo;
+- struct recv_frame_hdr *phdr = &precv_frame->u.hdr;
+- u8 wai_pkt = 0;
+- u16 sc;
+- u8 external_len = 0;
+-#endif
+-
+ _func_enter_;
+
+ //add version chk
+@@ -1819,9 +1782,6 @@ _func_enter_;
+ pattrib->mdata = GetMData(ptr);
+ pattrib->privacy = GetPrivacy(ptr);
+ pattrib->order = GetOrder(ptr);
+-#ifdef CONFIG_WAPI_SUPPORT
+- sc = (pattrib->seq_num<<4) | pattrib->frag_num;
+-#endif
+ {
+ u8 bDumpRxPkt;
+ rtw_hal_get_def_var(adapter, HAL_DEF_DBG_DUMP_RXPKT, &(bDumpRxPkt));
+@@ -1837,15 +1797,13 @@ _func_enter_;
+ {
+ case WIFI_MGT_TYPE: //mgnt
+ DBG_COUNTER(adapter->rx_logs.core_rx_pre_mgmt);
+-#ifdef CONFIG_IEEE80211W
+ if(validate_80211w_mgmt(adapter, precv_frame) == _FAIL)
+ {
+ retval = _FAIL;
+ DBG_COUNTER(padapter->rx_logs.core_rx_pre_mgmt_err_80211w);
+ break;
+ }
+-#endif //CONFIG_IEEE80211W
+-
++
+ retval = validate_recv_mgnt_frame(adapter, precv_frame);
+ if (retval == _FAIL)
+ {
+@@ -1866,39 +1824,6 @@ _func_enter_;
+ break;
+ case WIFI_DATA_TYPE: //data
+ DBG_COUNTER(adapter->rx_logs.core_rx_pre_data);
+-#ifdef CONFIG_WAPI_SUPPORT
+- if(pattrib->qos)
+- external_len = 2;
+- else
+- external_len= 0;
+-
+- wai_pkt = rtw_wapi_is_wai_packet(adapter,ptr);
+-
+- phdr->bIsWaiPacket = wai_pkt;
+-
+- if(wai_pkt !=0){
+- if(sc != adapter->wapiInfo.wapiSeqnumAndFragNum)
+- {
+- adapter->wapiInfo.wapiSeqnumAndFragNum = sc;
+- }
+- else
+- {
+- retval = _FAIL;
+- DBG_COUNTER(adapter->rx_logs.core_rx_pre_data_wapi_seq_err);
+- break;
+- }
+- }
+- else{
+-
+- if(rtw_wapi_drop_for_key_absent(adapter,GetAddr2Ptr(ptr))){
+- retval=_FAIL;
+- WAPI_TRACE(WAPI_RX,"drop for key absent for rx \n");
+- DBG_COUNTER(adapter->rx_logs.core_rx_pre_data_wapi_key_err);
+- break;
+- }
+- }
+-
+-#endif
+
+ pattrib->qos = (subtype & BIT(7))? 1:0;
+ retval = validate_recv_data_frame(adapter, precv_frame);
+@@ -2080,7 +2005,7 @@ _func_enter_;
+ plist = get_next(phead);
+ prframe = LIST_CONTAINOR(plist, union recv_frame, u);
+ pfhdr=&prframe->u.hdr;
+- rtw_list_delete(&(prframe->u.list));
++ list_del_init(&(prframe->u.list));
+
+ if(curfragnum!=pfhdr->attrib.frag_num)
+ {
+@@ -2100,7 +2025,7 @@ _func_enter_;
+
+ data=get_recvframe_data(prframe);
+
+- while(rtw_end_of_queue_search(phead, plist) == false)
++ while(phead != plist)
+ {
+ pnextrframe = LIST_CONTAINOR(plist, union recv_frame , u);
+ pnfhdr=&pnextrframe->u.hdr;
+@@ -2202,7 +2127,7 @@ _func_enter_;
+ if(fragnum==0)
+ {
+ //the first fragment
+- if(_rtw_queue_empty(pdefrag_q) == false)
++ if(!list_empty(&pdefrag_q->queue))
+ {
+ //free current defrag_q
+ rtw_free_recvframe_queue(pdefrag_q, pfree_recv_queue);
+@@ -2214,7 +2139,7 @@ _func_enter_;
+
+ //spin_lock(&pdefrag_q->lock);
+ phead = get_list_head(pdefrag_q);
+- rtw_list_insert_tail(&pfhdr->list, phead);
++ 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));
+@@ -2240,7 +2165,7 @@ _func_enter_;
+ {
+ //spin_lock(&pdefrag_q->lock);
+ phead = get_list_head(pdefrag_q);
+- rtw_list_insert_tail(&pfhdr->list,phead);
++ list_add_tail(&pfhdr->list,phead);
+ //spin_unlock(&pdefrag_q->lock);
+
+ //call recvframe_defrag to defrag
+@@ -2445,14 +2370,14 @@ int enqueue_reorder_recvframe(struct rec
+
+ //DbgPrint("+enqueue_reorder_recvframe()\n");
+
+- //_enter_critical_ex(&ppending_recvframe_queue->lock, &irql);
++ //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(rtw_end_of_queue_search(phead, plist) == false)
++ while (phead != plist)
+ {
+ pnextrframe = LIST_CONTAINOR(plist, union recv_frame, u);
+ pnextattrib = &pnextrframe->u.hdr.attrib;
+@@ -2466,7 +2391,7 @@ int enqueue_reorder_recvframe(struct rec
+ //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));
+
+- //_exit_critical_ex(&ppending_recvframe_queue->lock, &irql);
++ //spin_unlock_irqrestore(&ppending_recvframe_queue->lock, irql);
+
+ return false;
+ }
+@@ -2480,15 +2405,15 @@ int enqueue_reorder_recvframe(struct rec
+ }
+
+
+- //_enter_critical_ex(&ppending_recvframe_queue->lock, &irql);
++ //spin_lock_irqsave(&ppending_recvframe_queue->lock, irql);
+ //spin_lock(&ppending_recvframe_queue->lock);
+
+- rtw_list_delete(&(prframe->u.hdr.list));
++ list_del_init(&(prframe->u.hdr.list));
+
+- rtw_list_insert_tail(&(prframe->u.hdr.list), plist);
++ list_add_tail(&(prframe->u.hdr.list), plist);
+
+ //spin_unlock(&ppending_recvframe_queue->lock);
+- //_exit_critical_ex(&ppending_recvframe_queue->lock, &irql);
++ //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));
+@@ -2528,7 +2453,7 @@ int recv_indicatepkts_in_order(_adapter
+
+ //DbgPrint("+recv_indicatepkts_in_order\n");
+
+- //_enter_critical_ex(&ppending_recvframe_queue->lock, &irql);
++ //spin_lock_irqsave(&ppending_recvframe_queue->lock, irql);
+ //spin_lock(&ppending_recvframe_queue->lock);
+
+ phead = get_list_head(ppending_recvframe_queue);
+@@ -2538,9 +2463,9 @@ int recv_indicatepkts_in_order(_adapter
+ if(bforced==true)
+ {
+ pdbgpriv->dbg_rx_ampdu_forced_indicate_count++;
+- if(rtw_is_list_empty(phead))
++ if(list_empty(phead))
+ {
+- // _exit_critical_ex(&ppending_recvframe_queue->lock, &irql);
++ // spin_unlock_irqrestore(&ppending_recvframe_queue->lock, irql);
+ //spin_unlock(&ppending_recvframe_queue->lock);
+ return true;
+ }
+@@ -2559,7 +2484,7 @@ int recv_indicatepkts_in_order(_adapter
+
+ // Prepare indication list and indication.
+ // Check if there is any packet need indicate.
+- while(!rtw_is_list_empty(phead))
++ while(!list_empty(phead))
+ {
+
+ prframe = LIST_CONTAINOR(plist, union recv_frame, u);
+@@ -2572,7 +2497,7 @@ int recv_indicatepkts_in_order(_adapter
+ preorder_ctrl->indicate_seq, pattrib->seq_num, pattrib->amsdu));
+
+ plist = get_next(plist);
+- rtw_list_delete(&(prframe->u.hdr.list));
++ list_del_init(&(prframe->u.hdr.list));
+
+ if(SN_EQUAL(preorder_ctrl->indicate_seq, pattrib->seq_num))
+ {
+@@ -2632,7 +2557,7 @@ int recv_indicatepkts_in_order(_adapter
+ }
+
+ //spin_unlock(&ppending_recvframe_queue->lock);
+- //_exit_critical_ex(&ppending_recvframe_queue->lock, &irql);
++ //spin_unlock_irqrestore(&ppending_recvframe_queue->lock, irql);
+
+ /*
+ //Release the indication lock and set to new indication step.
+@@ -2649,7 +2574,7 @@ int recv_indicatepkts_in_order(_adapter
+ //pTS->RxIndicateState = RXTS_INDICATE_IDLE;
+ }
+ */
+- //_exit_critical_ex(&ppending_recvframe_queue->lock, &irql);
++ //spin_unlock_irqrestore(&ppending_recvframe_queue->lock, irql);
+
+ //return true;
+ return bPktInBuf;
+@@ -2744,7 +2669,7 @@ int recv_indicatepkt_reorder(_adapter *p
+ }
+ }
+
+- _enter_critical_bh(&ppending_recvframe_queue->lock, &irql);
++ spin_lock_bh(&ppending_recvframe_queue->lock);
+
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_,
+ ("recv_indicatepkt_reorder: indicate=%d seq=%d\n",
+@@ -2757,7 +2682,7 @@ int recv_indicatepkt_reorder(_adapter *p
+ //pHTInfo->RxReorderDropCounter++;
+ //ReturnRFDList(Adapter, pRfd);
+ //RT_TRACE(COMP_RX_REORDER, DBG_TRACE, ("RxReorderIndicatePacket() ==> Packet Drop!!\n"));
+- //_exit_critical_ex(&ppending_recvframe_queue->lock, &irql);
++ //spin_unlock_irqrestore(&ppending_recvframe_queue->lock, irql);
+ //return _FAIL;
+
+ #ifdef DBG_RX_DROP_FRAME
+@@ -2771,7 +2696,7 @@ int recv_indicatepkt_reorder(_adapter *p
+ if(!enqueue_reorder_recvframe(preorder_ctrl, prframe))
+ {
+ //DbgPrint("recv_indicatepkt_reorder, enqueue_reorder_recvframe fail!\n");
+- //_exit_critical_ex(&ppending_recvframe_queue->lock, &irql);
++ //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", __FUNCTION__);
+@@ -2794,11 +2719,11 @@ int recv_indicatepkt_reorder(_adapter *p
+ if(recv_indicatepkts_in_order(padapter, preorder_ctrl, false)==true)
+ {
+ _set_timer(&preorder_ctrl->reordering_ctrl_timer, REORDER_WAIT_TIME);
+- _exit_critical_bh(&ppending_recvframe_queue->lock, &irql);
++ spin_unlock_bh(&ppending_recvframe_queue->lock);
+ }
+ else
+ {
+- _exit_critical_bh(&ppending_recvframe_queue->lock, &irql);
++ spin_unlock_bh(&ppending_recvframe_queue->lock);
+ _cancel_timer_ex(&preorder_ctrl->reordering_ctrl_timer);
+ }
+
+@@ -2806,7 +2731,7 @@ int recv_indicatepkt_reorder(_adapter *p
+
+ _err_exit:
+
+- _exit_critical_bh(&ppending_recvframe_queue->lock, &irql);
++ spin_unlock_bh(&ppending_recvframe_queue->lock);
+
+ return _FAIL;
+ }
+@@ -2827,14 +2752,14 @@ void rtw_reordering_ctrl_timeout_handler
+
+ //DBG_871X("+rtw_reordering_ctrl_timeout_handler()=>\n");
+
+- _enter_critical_bh(&ppending_recvframe_queue->lock, &irql);
++ 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);
+ }
+
+- _exit_critical_bh(&ppending_recvframe_queue->lock, &irql);
++ spin_unlock_bh(&ppending_recvframe_queue->lock);
+
+ }
+
+@@ -2934,9 +2859,6 @@ static int recv_func_posthandle(_adapter
+
+ DBG_COUNTER(padapter->rx_logs.core_rx_post);
+
+- // DATA FRAME
+- rtw_led_control(padapter, LED_CTL_RX);
+-
+ prframe = decryptor(padapter, prframe);
+ if (prframe == NULL) {
+ RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("decryptor: drop pkt\n"));
+@@ -2971,10 +2893,6 @@ static int recv_func_posthandle(_adapter
+
+ count_rx_stats(padapter, prframe, NULL);
+
+-#ifdef CONFIG_WAPI_SUPPORT
+- rtw_wapi_update_info(padapter, prframe);
+-#endif
+-
+ ret = process_recv_indicatepkts(padapter, prframe);
+ if (ret != _SUCCESS)
+ {
+diff -Nurp linux/3rdparty/rtl8723bs.old/core/rtw_rf.c linux/3rdparty/rtl8723bs/core/rtw_rf.c
+--- linux/3rdparty/rtl8723bs.old/core/rtw_rf.c 2015-05-10 14:36:05.676667990 +0300
++++ linux/3rdparty/rtl8723bs/core/rtw_rf.c 2015-05-07 17:46:55.000000000 +0300
+@@ -69,23 +69,3 @@ u32 rtw_ch2freq(u32 channel)
+
+ return freq;
+ }
+-
+-u32 rtw_freq2ch(u32 freq)
+-{
+- u8 i;
+- u32 ch = 0;
+-
+- for (i = 0; i < ch_freq_map_num; i++)
+- {
+- if (freq == ch_freq_map[i].frequency)
+- {
+- ch = ch_freq_map[i].channel;
+- break;
+- }
+- }
+- if (i == ch_freq_map_num)
+- ch = 1;
+-
+- return ch;
+-}
+-
+diff -Nurp linux/3rdparty/rtl8723bs.old/core/rtw_security.c linux/3rdparty/rtl8723bs/core/rtw_security.c
+--- linux/3rdparty/rtl8723bs.old/core/rtw_security.c 2015-05-10 14:36:05.677668002 +0300
++++ linux/3rdparty/rtl8723bs/core/rtw_security.c 2015-05-07 17:46:55.000000000 +0300
+@@ -35,11 +35,7 @@ static const char *_security_type_str[]
+
+ const char *security_type_str(u8 value)
+ {
+-#ifdef CONFIG_IEEE80211W
+ if (value <= _BIP_)
+-#else
+- if (value <= _WEP_WPA_MIXED_)
+-#endif
+ return _security_type_str[value];
+ return NULL;
+ }
+@@ -1259,11 +1255,9 @@ _func_enter_;
+ 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;
+-#ifdef CONFIG_IEEE80211W
+ //802.11w management frame should set management bit(4)
+ if(frtype == WIFI_MGT_TYPE)
+ mic_iv[1] |= BIT(4);
+-#endif //CONFIG_IEEE80211W
+ 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
+@@ -1295,14 +1289,13 @@ static void construct_mic_header1(
+ _func_enter_;
+ mic_header1[0] = (u8)((header_length - 2) / 256);
+ mic_header1[1] = (u8)((header_length - 2) % 256);
+-#ifdef CONFIG_IEEE80211W
++
+ //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
+-#endif //CONFIG_IEEE80211W
+ 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];
+@@ -1399,11 +1392,9 @@ _func_enter_;
+ ctr_preload[1] = mpdu[30] & 0x0f; /* QoC_Control */
+ if (qc_exists && !a4_exists)
+ ctr_preload[1] = mpdu[24] & 0x0f;
+-#ifdef CONFIG_IEEE80211W
+ //802.11w management frame should set management bit(4)
+ if(frtype == WIFI_MGT_TYPE)
+ ctr_preload[1] |= BIT(4);
+-#endif //CONFIG_IEEE80211W
+ 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
+@@ -2129,7 +2120,6 @@ exit:
+ return res;
+ }
+
+-#ifdef CONFIG_IEEE80211W
+ u32 rtw_BIP_verify(_adapter *padapter, u8 *precvframe)
+ {
+ struct rx_pkt_attrib *pattrib = &((union recv_frame *)precvframe)->u.hdr.attrib;
+@@ -2226,10 +2216,9 @@ u32 rtw_BIP_verify(_adapter *padapter, u
+ res = RTW_RX_HANDLED;
+ BIP_exit:
+
+- rtw_mfree(BIP_AAD, ori_len);
++ kfree(BIP_AAD);
+ return res;
+ }
+-#endif //CONFIG_IEEE80211W
+
+ /* AES tables*/
+ const u32 Te0[256] = {
+@@ -2509,7 +2498,7 @@ static void gf_mulx(u8 *pad)
+ static void aes_encrypt_deinit(void *ctx)
+ {
+ memset(ctx, 0, AES_PRIV_SIZE);
+- rtw_mfree(ctx, AES_PRIV_SIZE);
++ kfree(ctx);
+ }
+
+
+@@ -2604,30 +2593,6 @@ int omac1_aes_128(u8 *key, u8 *data, siz
+ return omac1_aes_128_vector(key, 1, &data, &data_len, mac);
+ }
+
+-void rtw_use_tkipkey_handler(RTW_TIMER_HDL_ARGS)
+-{
+- _adapter *padapter = (_adapter *)FunctionContext;
+-
+-_func_enter_;
+-
+- RT_TRACE(_module_rtl871x_security_c_,_drv_err_,("^^^rtw_use_tkipkey_handler ^^^\n"));
+-
+-/*
+- if(padapter->bDriverStopped ||padapter->bSurpriseRemoved){
+- RT_TRACE(_module_rtl871x_security_c_,_drv_err_,("^^^rtw_use_tkipkey_handler (padapter->bDriverStopped %d)(padapter->bSurpriseRemoved %d)^^^\n",padapter->bDriverStopped,padapter->bSurpriseRemoved));
+-
+- return;
+- }
+- */
+-
+- padapter->securitypriv.busetkipkey=true;
+-
+- RT_TRACE(_module_rtl871x_security_c_,_drv_err_,("^^^rtw_use_tkipkey_handler padapter->securitypriv.busetkipkey=%d^^^\n",padapter->securitypriv.busetkipkey));
+-
+-_func_exit_;
+-
+-}
+-
+ /* Restore HW wep key setting according to key_mask */
+ void rtw_sec_restore_wep_key(_adapter *adapter)
+ {
+diff -Nurp linux/3rdparty/rtl8723bs.old/core/rtw_sta_mgt.c linux/3rdparty/rtl8723bs/core/rtw_sta_mgt.c
+--- linux/3rdparty/rtl8723bs.old/core/rtw_sta_mgt.c 2015-05-10 14:36:05.678668013 +0300
++++ linux/3rdparty/rtl8723bs/core/rtw_sta_mgt.c 2015-05-07 17:46:55.000000000 +0300
+@@ -30,23 +30,21 @@ _func_enter_;
+ memset((u8 *)psta, 0, sizeof (struct sta_info));
+
+ spin_lock_init(&psta->lock);
+- _rtw_init_listhead(&psta->list);
+- _rtw_init_listhead(&psta->hash_list);
+- //_rtw_init_listhead(&psta->asoc_list);
+- //_rtw_init_listhead(&psta->sleep_list);
+- //_rtw_init_listhead(&psta->wakeup_list);
++ 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);
+-
+-#ifdef CONFIG_AP_MODE
+
+- _rtw_init_listhead(&psta->asoc_list);
++ INIT_LIST_HEAD(&psta->asoc_list);
+
+- _rtw_init_listhead(&psta->auth_list);
++ INIT_LIST_HEAD(&psta->auth_list);
+
+ psta->expire_to = 0;
+
+@@ -56,24 +54,17 @@ _func_enter_;
+
+ psta->bpairwise_key_installed = false;
+
+-
+-#ifdef CONFIG_NATIVEAP_MLME
+ 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;
+-#endif
+
+-#ifdef CONFIG_TX_MCAST2UNI
+ psta->under_exist_checking = 0;
+-#endif // CONFIG_TX_MCAST2UNI
+-
++
+ psta->keep_alive_trycnt = 0;
+
+-#endif // CONFIG_AP_MODE
+-
+ _func_exit_;
+
+ }
+@@ -85,7 +76,7 @@ u32 _rtw_init_sta_priv(struct sta_priv *
+
+ _func_enter_;
+
+- pstapriv->pallocated_stainfo_buf = rtw_zvmalloc (sizeof(struct sta_info) * NUM_STA+ 4);
++ pstapriv->pallocated_stainfo_buf = vzalloc (sizeof(struct sta_info) * NUM_STA+ 4);
+
+ if(!pstapriv->pallocated_stainfo_buf)
+ return _FAIL;
+@@ -109,22 +100,18 @@ _func_enter_;
+ {
+ _rtw_init_stainfo(psta);
+
+- _rtw_init_listhead(&(pstapriv->sta_hash[i]));
++ INIT_LIST_HEAD(&(pstapriv->sta_hash[i]));
+
+- rtw_list_insert_tail(&psta->list, get_list_head(&pstapriv->free_sta_queue));
++ list_add_tail(&psta->list, get_list_head(&pstapriv->free_sta_queue));
+
+ psta++;
+ }
+
+-
+-
+-#ifdef CONFIG_AP_MODE
+-
+ pstapriv->sta_dz_bitmap = 0;
+ pstapriv->tim_bitmap = 0;
+
+- _rtw_init_listhead(&pstapriv->asoc_list);
+- _rtw_init_listhead(&pstapriv->auth_list);
++ 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;
+@@ -136,9 +123,7 @@ _func_enter_;
+ //pstapriv->expire_to = 30;// 30*2 = 60 sec = 1 min, expire after no any traffic.
+ pstapriv->expire_to = 3; // 3*2 = 6 sec
+ pstapriv->max_num_sta = NUM_STA;
+-
+-#endif
+-
++
+ _func_exit_;
+
+ return _SUCCESS;
+@@ -164,8 +149,8 @@ inline struct sta_info *rtw_get_stainfo_
+ }
+
+ // this function is used to free the memory of lock || sema for all stainfos
+-void rtw_mfree_all_stainfo(struct sta_priv *pstapriv );
+-void rtw_mfree_all_stainfo(struct sta_priv *pstapriv )
++void kfree_all_stainfo(struct sta_priv *pstapriv );
++void kfree_all_stainfo(struct sta_priv *pstapriv )
+ {
+ _irqL irqL;
+ _list *plist, *phead;
+@@ -173,31 +158,29 @@ void rtw_mfree_all_stainfo(struct sta_pr
+
+ _func_enter_;
+
+- _enter_critical_bh(&pstapriv->sta_hash_lock, &irqL);
++ spin_lock_bh(&pstapriv->sta_hash_lock);
+
+ phead = get_list_head(&pstapriv->free_sta_queue);
+ plist = get_next(phead);
+
+- while ((rtw_end_of_queue_search(phead, plist)) == false)
++ while (phead != plist)
+ {
+ psta = LIST_CONTAINOR(plist, struct sta_info ,list);
+ plist = get_next(plist);
+ }
+
+- _exit_critical_bh(&pstapriv->sta_hash_lock, &irqL);
++ spin_unlock_bh(&pstapriv->sta_hash_lock);
+
+ _func_exit_;
+
+ }
+
+-void rtw_mfree_sta_priv_lock(struct sta_priv *pstapriv);
+-void rtw_mfree_sta_priv_lock(struct sta_priv *pstapriv)
++void kfree_sta_priv_lock(struct sta_priv *pstapriv);
++void kfree_sta_priv_lock(struct sta_priv *pstapriv)
+ {
+-#ifdef CONFIG_AP_MODE
+ struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
+-#endif
+
+- rtw_mfree_all_stainfo(pstapriv); //be done before free sta_hash_lock
++ kfree_all_stainfo(pstapriv); //be done before free sta_hash_lock
+ }
+
+ u32 _rtw_free_sta_priv(struct sta_priv *pstapriv)
+@@ -212,13 +195,13 @@ _func_enter_;
+ if(pstapriv){
+
+ /* delete all reordering_ctrl_timer */
+- _enter_critical_bh(&pstapriv->sta_hash_lock, &irqL);
++ spin_lock_bh(&pstapriv->sta_hash_lock);
+ for(index = 0; index < NUM_STA; index++)
+ {
+ phead = &(pstapriv->sta_hash[index]);
+ plist = get_next(phead);
+
+- while ((rtw_end_of_queue_search(phead, plist)) == false)
++ while (phead != plist)
+ {
+ int i;
+ psta = LIST_CONTAINOR(plist, struct sta_info ,hash_list);
+@@ -231,13 +214,13 @@ _func_enter_;
+ }
+ }
+ }
+- _exit_critical_bh(&pstapriv->sta_hash_lock, &irqL);
++ spin_unlock_bh(&pstapriv->sta_hash_lock);
+ /*===============================*/
+
+- rtw_mfree_sta_priv_lock(pstapriv);
++ kfree_sta_priv_lock(pstapriv);
+
+ if(pstapriv->pallocated_stainfo_buf) {
+- rtw_vmfree(pstapriv->pallocated_stainfo_buf, sizeof(struct sta_info)*NUM_STA+4);
++ vfree(pstapriv->pallocated_stainfo_buf);
+ }
+ }
+
+@@ -263,12 +246,12 @@ _func_enter_;
+
+ pfree_sta_queue = &pstapriv->free_sta_queue;
+
+- //_enter_critical_bh(&(pfree_sta_queue->lock), &irqL);
+- _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL2);
+- if (_rtw_queue_empty(pfree_sta_queue) == true)
++ //spin_lock_bh(&(pfree_sta_queue->lock));
++ spin_lock_bh(&(pstapriv->sta_hash_lock));
++ if (list_empty(&pfree_sta_queue->queue))
+ {
+- //_exit_critical_bh(&(pfree_sta_queue->lock), &irqL);
+- _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL2);
++ //spin_unlock_bh(&(pfree_sta_queue->lock));
++ spin_unlock_bh(&(pstapriv->sta_hash_lock));
+ psta = NULL;
+ return psta;
+ }
+@@ -276,9 +259,9 @@ _func_enter_;
+ {
+ psta = LIST_CONTAINOR(get_next(&pfree_sta_queue->queue), struct sta_info, list);
+
+- rtw_list_delete(&(psta->list));
++ list_del_init(&(psta->list));
+
+- //_exit_critical_bh(&(pfree_sta_queue->lock), &irqL);
++ //spin_unlock_bh(&(pfree_sta_queue->lock));
+
+ tmp_aid = psta->aid;
+
+@@ -299,13 +282,13 @@ _func_enter_;
+ }
+ phash_list = &(pstapriv->sta_hash[index]);
+
+- //_enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL2);
++ //spin_lock_bh(&(pstapriv->sta_hash_lock));
+
+- rtw_list_insert_tail(&psta->hash_list, phash_list);
++ list_add_tail(&psta->hash_list, phash_list);
+
+ pstapriv->asoc_sta_count ++ ;
+
+- //_exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL2);
++ //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.
+@@ -360,7 +343,7 @@ _func_enter_;
+
+ exit:
+
+- _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL2);
++ spin_unlock_bh(&(pstapriv->sta_hash_lock));
+
+ _func_exit_;
+
+@@ -389,63 +372,63 @@ _func_enter_;
+ goto exit;
+
+
+- _enter_critical_bh(&psta->lock, &irqL0);
++ spin_lock_bh(&psta->lock);
+ psta->state &= ~_FW_LINKED;
+- _exit_critical_bh(&psta->lock, &irqL0);
++ spin_unlock_bh(&psta->lock);
+
+ pfree_sta_queue = &pstapriv->free_sta_queue;
+
+
+ pstaxmitpriv = &psta->sta_xmitpriv;
+
+- //rtw_list_delete(&psta->sleep_list);
++ //list_del_init(&psta->sleep_list);
+
+- //rtw_list_delete(&psta->wakeup_list);
++ //list_del_init(&psta->wakeup_list);
+
+- _enter_critical_bh(&pxmitpriv->lock, &irqL0);
++ spin_lock_bh(&pxmitpriv->lock);
+
+ rtw_free_xmitframe_queue(pxmitpriv, &psta->sleep_q);
+ psta->sleepq_len = 0;
+
+ //vo
+- //_enter_critical_bh(&(pxmitpriv->vo_pending.lock), &irqL0);
++ //spin_lock_bh(&(pxmitpriv->vo_pending.lock));
+ rtw_free_xmitframe_queue( pxmitpriv, &pstaxmitpriv->vo_q.sta_pending);
+- rtw_list_delete(&(pstaxmitpriv->vo_q.tx_pending));
++ list_del_init(&(pstaxmitpriv->vo_q.tx_pending));
+ phwxmit = pxmitpriv->hwxmits;
+ phwxmit->accnt -= pstaxmitpriv->vo_q.qcnt;
+ pstaxmitpriv->vo_q.qcnt = 0;
+- //_exit_critical_bh(&(pxmitpriv->vo_pending.lock), &irqL0);
++ //spin_unlock_bh(&(pxmitpriv->vo_pending.lock));
+
+ //vi
+- //_enter_critical_bh(&(pxmitpriv->vi_pending.lock), &irqL0);
++ //spin_lock_bh(&(pxmitpriv->vi_pending.lock));
+ rtw_free_xmitframe_queue( pxmitpriv, &pstaxmitpriv->vi_q.sta_pending);
+- rtw_list_delete(&(pstaxmitpriv->vi_q.tx_pending));
++ list_del_init(&(pstaxmitpriv->vi_q.tx_pending));
+ phwxmit = pxmitpriv->hwxmits+1;
+ phwxmit->accnt -= pstaxmitpriv->vi_q.qcnt;
+ pstaxmitpriv->vi_q.qcnt = 0;
+- //_exit_critical_bh(&(pxmitpriv->vi_pending.lock), &irqL0);
++ //spin_unlock_bh(&(pxmitpriv->vi_pending.lock));
+
+ //be
+- //_enter_critical_bh(&(pxmitpriv->be_pending.lock), &irqL0);
++ //spin_lock_bh(&(pxmitpriv->be_pending.lock));
+ rtw_free_xmitframe_queue( pxmitpriv, &pstaxmitpriv->be_q.sta_pending);
+- rtw_list_delete(&(pstaxmitpriv->be_q.tx_pending));
++ list_del_init(&(pstaxmitpriv->be_q.tx_pending));
+ phwxmit = pxmitpriv->hwxmits+2;
+ phwxmit->accnt -= pstaxmitpriv->be_q.qcnt;
+ pstaxmitpriv->be_q.qcnt = 0;
+- //_exit_critical_bh(&(pxmitpriv->be_pending.lock), &irqL0);
++ //spin_unlock_bh(&(pxmitpriv->be_pending.lock));
+
+ //bk
+- //_enter_critical_bh(&(pxmitpriv->bk_pending.lock), &irqL0);
++ //spin_lock_bh(&(pxmitpriv->bk_pending.lock));
+ rtw_free_xmitframe_queue( pxmitpriv, &pstaxmitpriv->bk_q.sta_pending);
+- rtw_list_delete(&(pstaxmitpriv->bk_q.tx_pending));
++ list_del_init(&(pstaxmitpriv->bk_q.tx_pending));
+ phwxmit = pxmitpriv->hwxmits+3;
+ phwxmit->accnt -= pstaxmitpriv->bk_q.qcnt;
+ pstaxmitpriv->bk_q.qcnt = 0;
+- //_exit_critical_bh(&(pxmitpriv->bk_pending.lock), &irqL0);
++ //spin_unlock_bh(&(pxmitpriv->bk_pending.lock));
+
+- _exit_critical_bh(&pxmitpriv->lock, &irqL0);
++ spin_unlock_bh(&pxmitpriv->lock);
+
+- rtw_list_delete(&psta->hash_list);
++ 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 --;
+
+@@ -472,23 +455,23 @@ _func_enter_;
+
+ ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue;
+
+- _enter_critical_bh(&ppending_recvframe_queue->lock, &irqL);
++ spin_lock_bh(&ppending_recvframe_queue->lock);
+
+ phead = get_list_head(ppending_recvframe_queue);
+ plist = get_next(phead);
+
+- while(!rtw_is_list_empty(phead))
++ while(!list_empty(phead))
+ {
+ prframe = LIST_CONTAINOR(plist, union recv_frame, u);
+
+ plist = get_next(plist);
+
+- rtw_list_delete(&(prframe->u.hdr.list));
++ list_del_init(&(prframe->u.hdr.list));
+
+ rtw_free_recvframe(prframe, pfree_recv_queue);
+ }
+
+- _exit_critical_bh(&ppending_recvframe_queue->lock, &irqL);
++ spin_unlock_bh(&ppending_recvframe_queue->lock);
+
+ }
+
+@@ -499,19 +482,17 @@ _func_enter_;
+ //release mac id for non-bc/mc station,
+ rtw_release_macid(pstapriv->padapter, psta);
+
+-#ifdef CONFIG_AP_MODE
+-
+ /*
+- _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL0);
+- rtw_list_delete(&psta->asoc_list);
+- _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL0);
++ spin_lock_bh(&pstapriv->asoc_list_lock);
++ list_del_init(&psta->asoc_list);
++ spin_unlock_bh(&pstapriv->asoc_list_lock);
+ */
+- _enter_critical_bh(&pstapriv->auth_list_lock, &irqL0);
+- if (!rtw_is_list_empty(&psta->auth_list)) {
+- rtw_list_delete(&psta->auth_list);
++ spin_lock_bh(&pstapriv->auth_list_lock);
++ if (!list_empty(&psta->auth_list)) {
++ list_del_init(&psta->auth_list);
+ pstapriv->auth_list_cnt--;
+ }
+- _exit_critical_bh(&pstapriv->auth_list_lock, &irqL0);
++ spin_unlock_bh(&pstapriv->auth_list_lock);
+
+ psta->expire_to = 0;
+ psta->sleepq_ac_len = 0;
+@@ -525,30 +506,20 @@ _func_enter_;
+
+ psta->has_legacy_ac = 0;
+
+-#ifdef CONFIG_NATIVEAP_MLME
+-
+ pstapriv->sta_dz_bitmap &=~BIT(psta->aid);
+ pstapriv->tim_bitmap &=~BIT(psta->aid);
+
+- //rtw_indicate_sta_disassoc_event(padapter, psta);
+-
+ if ((psta->aid >0)&&(pstapriv->sta_aid[psta->aid - 1] == psta))
+ {
+ pstapriv->sta_aid[psta->aid - 1] = NULL;
+ psta->aid = 0;
+- }
+-
+-#endif // CONFIG_NATIVEAP_MLME
++ }
+
+-#ifdef CONFIG_TX_MCAST2UNI
+ psta->under_exist_checking = 0;
+-#endif // CONFIG_TX_MCAST2UNI
+-
+-#endif // CONFIG_AP_MODE
+
+- //_enter_critical_bh(&(pfree_sta_queue->lock), &irqL0);
+- rtw_list_insert_tail(&psta->list, get_list_head(pfree_sta_queue));
+- //_exit_critical_bh(&(pfree_sta_queue->lock), &irqL0);
++ //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:
+
+@@ -573,14 +544,14 @@ _func_enter_;
+ if(pstapriv->asoc_sta_count==1)
+ goto exit;
+
+- _enter_critical_bh(&pstapriv->sta_hash_lock, &irqL);
++ spin_lock_bh(&pstapriv->sta_hash_lock);
+
+ for(index=0; index< NUM_STA; index++)
+ {
+ phead = &(pstapriv->sta_hash[index]);
+ plist = get_next(phead);
+
+- while ((rtw_end_of_queue_search(phead, plist)) == false)
++ while (phead != plist)
+ {
+ psta = LIST_CONTAINOR(plist, struct sta_info ,hash_list);
+
+@@ -592,7 +563,7 @@ _func_enter_;
+ }
+ }
+
+- _exit_critical_bh(&pstapriv->sta_hash_lock, &irqL);
++ spin_unlock_bh(&pstapriv->sta_hash_lock);
+
+ exit:
+
+@@ -632,13 +603,13 @@ _func_enter_;
+
+ index = wifi_mac_hash(addr);
+
+- _enter_critical_bh(&pstapriv->sta_hash_lock, &irqL);
++ spin_lock_bh(&pstapriv->sta_hash_lock);
+
+ phead = &(pstapriv->sta_hash[index]);
+ plist = get_next(phead);
+
+
+- while ((rtw_end_of_queue_search(phead, plist)) == false)
++ while (phead != plist)
+ {
+
+ psta = LIST_CONTAINOR(plist, struct sta_info, hash_list);
+@@ -651,7 +622,7 @@ _func_enter_;
+ plist = get_next(plist);
+ }
+
+- _exit_critical_bh(&pstapriv->sta_hash_lock, &irqL);
++ spin_unlock_bh(&pstapriv->sta_hash_lock);
+ _func_exit_;
+ return psta;
+
+@@ -683,13 +654,13 @@ _func_enter_;
+
+ ptxservq= &(psta->sta_xmitpriv.be_q);
+
+-/*
+- _enter_critical(&pstapending->lock, &irqL0);
++/* DEADCODE
++ spin_lock_irqsave(&pstapending->lock, irqL0);
+
+ if (rtw_is_list_empty(&ptxservq->tx_pending))
+- rtw_list_insert_tail(&ptxservq->tx_pending, get_list_head(pstapending));
++ list_add_tail(&ptxservq->tx_pending, get_list_head(pstapending));
+
+- _exit_critical(&pstapending->lock, &irqL0);
++ spin_unlock_irqrestore(&pstapending->lock, irqL0);
+ */
+
+ exit:
+@@ -714,7 +685,6 @@ _func_exit_;
+ u8 rtw_access_ctrl(_adapter *padapter, u8 *mac_addr)
+ {
+ u8 res = true;
+-#ifdef CONFIG_AP_MODE
+ _irqL irqL;
+ _list *plist, *phead;
+ struct rtw_wlan_acl_node *paclnode;
+@@ -723,10 +693,10 @@ u8 rtw_access_ctrl(_adapter *padapter, u
+ struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
+ _queue *pacl_node_q =&pacl_list->acl_node_q;
+
+- _enter_critical_bh(&(pacl_node_q->lock), &irqL);
++ spin_lock_bh(&(pacl_node_q->lock));
+ phead = get_list_head(pacl_node_q);
+ plist = get_next(phead);
+- while ((rtw_end_of_queue_search(phead, plist)) == false)
++ while (phead != plist)
+ {
+ paclnode = LIST_CONTAINOR(plist, struct rtw_wlan_acl_node, list);
+ plist = get_next(plist);
+@@ -740,7 +710,7 @@ u8 rtw_access_ctrl(_adapter *padapter, u
+ }
+ }
+ }
+- _exit_critical_bh(&(pacl_node_q->lock), &irqL);
++ spin_unlock_bh(&(pacl_node_q->lock));
+
+
+ if(pacl_list->mode == 1)//accept unless in deny list
+@@ -755,10 +725,7 @@ u8 rtw_access_ctrl(_adapter *padapter, u
+ {
+ res = true;
+ }
+-
+-#endif
+
+ return res;
+-
+ }
+
+diff -Nurp linux/3rdparty/rtl8723bs.old/core/rtw_wapi.c linux/3rdparty/rtl8723bs/core/rtw_wapi.c
+--- linux/3rdparty/rtl8723bs.old/core/rtw_wapi.c 2015-05-10 14:36:05.678668013 +0300
++++ linux/3rdparty/rtl8723bs/core/rtw_wapi.c 1970-01-01 02:00:00.000000000 +0200
+@@ -1,1047 +0,0 @@
+-#ifdef CONFIG_WAPI_SUPPORT
+-
+-#include
+-#include
+-#include
+-#include
+-
+-
+-u32 wapi_debug_component =
+-// WAPI_INIT |
+-// WAPI_API |
+-// WAPI_TX |
+-// WAPI_RX |
+- WAPI_ERR ; //always open err flags on
+-
+-void WapiFreeAllStaInfo(_adapter *padapter)
+-{
+- PRT_WAPI_T pWapiInfo;
+- PRT_WAPI_STA_INFO pWapiStaInfo;
+- PRT_WAPI_BKID pWapiBkid;
+-
+- WAPI_TRACE(WAPI_INIT, "===========> %s\n", __FUNCTION__);
+- pWapiInfo = &padapter->wapiInfo;
+-
+- //Pust to Idle List
+- rtw_wapi_return_all_sta_info(padapter);
+-
+- //Sta Info List
+- while(!list_empty(&(pWapiInfo->wapiSTAIdleList)))
+- {
+- pWapiStaInfo = (PRT_WAPI_STA_INFO)list_entry(pWapiInfo->wapiSTAIdleList.next, RT_WAPI_STA_INFO, list);
+- list_del_init(&pWapiStaInfo->list);
+- }
+-
+- //BKID List
+- while(!list_empty(&(pWapiInfo->wapiBKIDIdleList)))
+- {
+- pWapiBkid = (PRT_WAPI_BKID)list_entry(pWapiInfo->wapiBKIDIdleList.next, RT_WAPI_BKID, list);
+- list_del_init(&pWapiBkid->list);
+- }
+- WAPI_TRACE(WAPI_INIT, "<=========== %s\n", __FUNCTION__);
+- return;
+-}
+-
+-void WapiSetIE(_adapter *padapter)
+-{
+- PRT_WAPI_T pWapiInfo = &(padapter->wapiInfo);
+- //PRT_WAPI_BKID pWapiBkid;
+- u16 protocolVer = 1;
+- u16 akmCnt = 1;
+- u16 suiteCnt = 1;
+- u16 capability = 0;
+- u8 OUI[3];
+-
+- OUI[0] = 0x00;
+- OUI[1] = 0x14;
+- OUI[2] = 0x72;
+-
+- pWapiInfo->wapiIELength = 0;
+-//protocol version
+- memcpy(pWapiInfo->wapiIE+pWapiInfo->wapiIELength, &protocolVer, 2);
+- pWapiInfo->wapiIELength +=2;
+-//akm
+- memcpy(pWapiInfo->wapiIE+pWapiInfo->wapiIELength, &akmCnt, 2);
+- pWapiInfo->wapiIELength +=2;
+-
+- if(pWapiInfo->bWapiPSK){
+- memcpy(pWapiInfo->wapiIE+pWapiInfo->wapiIELength,OUI, 3);
+- pWapiInfo->wapiIELength +=3;
+- pWapiInfo->wapiIE[pWapiInfo->wapiIELength] = 0x2;
+- pWapiInfo->wapiIELength +=1;
+- }else{
+- memcpy(pWapiInfo->wapiIE+pWapiInfo->wapiIELength,OUI, 3);
+- pWapiInfo->wapiIELength +=3;
+- pWapiInfo->wapiIE[pWapiInfo->wapiIELength] = 0x1;
+- pWapiInfo->wapiIELength +=1;
+- }
+-
+-//usk
+- memcpy(pWapiInfo->wapiIE+pWapiInfo->wapiIELength, &suiteCnt, 2);
+- pWapiInfo->wapiIELength +=2;
+- memcpy(pWapiInfo->wapiIE+pWapiInfo->wapiIELength,OUI, 3);
+- pWapiInfo->wapiIELength +=3;
+- pWapiInfo->wapiIE[pWapiInfo->wapiIELength] = 0x1;
+- pWapiInfo->wapiIELength +=1;
+-
+-//msk
+- memcpy(pWapiInfo->wapiIE+pWapiInfo->wapiIELength,OUI, 3);
+- pWapiInfo->wapiIELength +=3;
+- pWapiInfo->wapiIE[pWapiInfo->wapiIELength] = 0x1;
+- pWapiInfo->wapiIELength +=1;
+-
+-//Capbility
+- memcpy(pWapiInfo->wapiIE+pWapiInfo->wapiIELength, &capability, 2);
+- pWapiInfo->wapiIELength +=2;
+-}
+-
+-
+-/* PN1 > PN2, return 1,
+- * else return 0.
+- */
+-u32 WapiComparePN(u8 *PN1, u8 *PN2)
+-{
+- char i;
+-
+- if ((NULL == PN1) || (NULL == PN2))
+- return 1;
+-
+- // overflow case
+- if ((PN2[15] - PN1[15]) & 0x80)
+- return 1;
+-
+- for (i=16; i>0; i--)
+- {
+- if(PN1[i-1] == PN2[i-1])
+- continue;
+- else if(PN1[i-1] > PN2[i-1])
+- return 1;
+- else
+- return 0;
+- }
+-
+- return 0;
+-}
+-
+-u8
+-WapiGetEntryForCamWrite(_adapter *padapter,u8 *pMacAddr,u8 KID,bool IsMsk)
+-{
+- PRT_WAPI_T pWapiInfo=NULL;
+- //PRT_WAPI_CAM_ENTRY pEntry=NULL;
+- u8 i=0;
+- u8 ret = 0xff;
+-
+- WAPI_TRACE(WAPI_API, "===========> %s\n", __FUNCTION__);
+-
+- pWapiInfo = &padapter->wapiInfo;
+-
+- //exist?
+- for(i=0;iwapiCamEntry[i].IsUsed
+- && (!memcmp(pMacAddr, pWapiInfo->wapiCamEntry[i].PeerMacAddr, ETH_ALEN))
+- && pWapiInfo->wapiCamEntry[i].keyidx == KID
+- && pWapiInfo->wapiCamEntry[i].type == IsMsk)
+- {
+- ret = pWapiInfo->wapiCamEntry[i].entry_idx; //cover it
+- break;
+- }
+- }
+-
+- if(i == WAPI_CAM_ENTRY_NUM) //not found
+- {
+- for(i=0;iwapiCamEntry[i].IsUsed == 0)
+- {
+- pWapiInfo->wapiCamEntry[i].IsUsed = 1;
+- pWapiInfo->wapiCamEntry[i].type = IsMsk;
+- pWapiInfo->wapiCamEntry[i].keyidx = KID;
+- memcpy(pWapiInfo->wapiCamEntry[i].PeerMacAddr, pMacAddr,ETH_ALEN);
+- ret = pWapiInfo->wapiCamEntry[i].entry_idx;
+- break;
+- }
+- }
+- }
+-
+- WAPI_TRACE(WAPI_API, "<========== %s\n", __FUNCTION__);
+- return ret;
+-
+-/*
+- if(RTIsListEmpty(&pWapiInfo->wapiCamIdleList)){
+- RT_TRACE(COMP_SEC,DBG_LOUD,("No Entry for wapi!!!\n"));
+- return 0;
+- }
+-
+- pEntry = (PRT_WAPI_CAM_ENTRY)RTRemoveHeadList(&pWapiInfo->wapiCamIdleList);
+- RTInsertTailList(&pWapiInfo->wapiCamUsedList, &pEntry->list);
+-
+- RT_TRACE(COMP_SEC,DBG_LOUD,("<====WapiGetCamEntry(),Get Entry Idx:%d.but we just return 4 for test\n",pEntry->entry_idx));
+-
+- return pEntry->entry_idx;*/
+-}
+-
+-u8 WapiGetEntryForCamClear(_adapter *padapter,u8 *pPeerMac,u8 keyid,u8 IsMsk)
+-{
+- PRT_WAPI_T pWapiInfo=NULL;
+- u8 i=0;
+-
+- WAPI_TRACE(WAPI_API, "===========> %s\n", __FUNCTION__);
+-
+- pWapiInfo = &padapter->wapiInfo;
+-
+- for(i=0;iwapiCamEntry[i].IsUsed
+- && (!memcmp(pPeerMac, pWapiInfo->wapiCamEntry[i].PeerMacAddr, ETH_ALEN))
+- && pWapiInfo->wapiCamEntry[i].keyidx == keyid
+- && pWapiInfo->wapiCamEntry[i].type == IsMsk)
+- {
+- pWapiInfo->wapiCamEntry[i].IsUsed = 0;
+- pWapiInfo->wapiCamEntry[i].keyidx = 2;
+- memset(pWapiInfo->wapiCamEntry[i].PeerMacAddr,0,ETH_ALEN);
+-
+- WAPI_TRACE(WAPI_API, "<========== %s\n", __FUNCTION__);
+- return pWapiInfo->wapiCamEntry[i].entry_idx;
+- }
+- }
+-
+- WAPI_TRACE(WAPI_API,"<====WapiGetReturnCamEntry(), No this cam entry.\n");
+- return 0xff;
+-/*
+- if(RTIsListEmpty(&pWapiInfo->wapiCamUsedList)){
+- RT_TRACE(COMP_SEC,DBG_LOUD,("No Entry for wapi!!!\n"));
+- return false;
+- }
+-
+- pList = &pWapiInfo->wapiCamUsedList;
+- while(pList->Flink != &pWapiInfo->wapiCamUsedList)
+- {
+- pEntry = (PRT_WAPI_CAM_ENTRY)pList->Flink;
+- if(PlatformCompareMemory(pPeerMac,pEntry->PeerMacAddr, ETHER_ADDRLEN)== 0
+- && keyid == pEntry->keyidx)
+- {
+- RTRemoveEntryList(pList);
+- RTInsertHeadList(&pWapiInfo->wapiCamIdleList, pList);
+- return pEntry->entry_idx;
+- }
+- pList = pList->Flink;
+- }
+-
+- return 0;
+-*/
+-}
+-
+-void
+-WapiResetAllCamEntry(_adapter *padapter)
+-{
+- PRT_WAPI_T pWapiInfo;
+- int i;
+-
+- WAPI_TRACE(WAPI_API, "===========> %s\n", __FUNCTION__);
+-
+- pWapiInfo = &padapter->wapiInfo;
+-
+- for (i=0;iwapiCamEntry[i].PeerMacAddr, 0, ETH_ALEN);
+- pWapiInfo->wapiCamEntry[i].IsUsed = 0;
+- pWapiInfo->wapiCamEntry[i].keyidx = 2; //invalid
+- pWapiInfo->wapiCamEntry[i].entry_idx = 4+i*2;
+- }
+-
+- WAPI_TRACE(WAPI_API, "<========== %s\n", __FUNCTION__);
+-
+- return;
+-}
+-
+-u8 WapiWriteOneCamEntry(
+- _adapter *padapter,
+- u8 *pMacAddr,
+- u8 KeyId,
+- u8 EntryId,
+- u8 EncAlg,
+- u8 bGroupKey,
+- u8 *pKey
+-)
+-{
+- u8 retVal = 0;
+- u16 usConfig = 0;
+-
+- WAPI_TRACE(WAPI_API, "===========> %s\n", __FUNCTION__);
+-
+- if(EntryId >= 32)
+- {
+- WAPI_TRACE(WAPI_ERR, "<=== CamAddOneEntry(): ulKeyId exceed!\n");
+- return retVal;
+- }
+-
+- usConfig=usConfig|(0x01<<15)|((u16)(EncAlg)<<2)|(KeyId);
+-
+- if(EncAlg == _SMS4_ )
+- {
+- if(bGroupKey == 1)
+- usConfig |= (0x01<<6);
+- if((EntryId % 2)==1) // ==0 sec key; == 1mic key
+- usConfig |= (0x01<<5);
+- }
+-
+- write_cam(padapter, EntryId, usConfig, pMacAddr, pKey);
+-
+- WAPI_TRACE(WAPI_API, "===========> %s\n", __FUNCTION__);
+- return 1;
+-}
+-
+-void rtw_wapi_init(_adapter *padapter)
+-{
+- PRT_WAPI_T pWapiInfo;
+- int i;
+-
+- WAPI_TRACE(WAPI_INIT, "===========> %s\n", __FUNCTION__);
+- RT_ASSERT_RET(padapter);
+-
+- if (!padapter->WapiSupport)
+- {
+- WAPI_TRACE(WAPI_INIT, "<========== %s, WAPI not supported!\n", __FUNCTION__);
+- return;
+- }
+-
+- pWapiInfo = &padapter->wapiInfo;
+- pWapiInfo->bWapiEnable = false;
+-
+- //Init BKID List
+- INIT_LIST_HEAD(&pWapiInfo->wapiBKIDIdleList);
+- INIT_LIST_HEAD(&pWapiInfo->wapiBKIDStoreList);
+- for(i=0;iwapiBKID[i].list, &pWapiInfo->wapiBKIDIdleList);
+- }
+-
+- //Init STA List
+- INIT_LIST_HEAD(&pWapiInfo->wapiSTAIdleList);
+- INIT_LIST_HEAD(&pWapiInfo->wapiSTAUsedList);
+- for(i=0;iwapiSta[i].list, &pWapiInfo->wapiSTAIdleList);
+- }
+-
+- for (i=0;iwapiCamEntry[i].IsUsed = 0;
+- pWapiInfo->wapiCamEntry[i].keyidx = 2; //invalid
+- pWapiInfo->wapiCamEntry[i].entry_idx = 4+i*2;
+- }
+-
+- WAPI_TRACE(WAPI_INIT, "<========== %s\n", __FUNCTION__);
+-}
+-
+-void rtw_wapi_free(_adapter *padapter)
+-{
+- WAPI_TRACE(WAPI_INIT, "===========> %s\n", __FUNCTION__);
+- RT_ASSERT_RET(padapter);
+-
+- if (!padapter->WapiSupport)
+- {
+- WAPI_TRACE(WAPI_INIT, "<========== %s, WAPI not supported!\n", __FUNCTION__);
+- return;
+- }
+-
+- WapiFreeAllStaInfo(padapter);
+-
+- WAPI_TRACE(WAPI_INIT, "<========== %s\n", __FUNCTION__);
+-}
+-
+-void rtw_wapi_disable_tx(_adapter *padapter)
+-{
+- WAPI_TRACE(WAPI_INIT, "===========> %s\n", __FUNCTION__);
+- RT_ASSERT_RET(padapter);
+-
+- if (!padapter->WapiSupport)
+- {
+- WAPI_TRACE(WAPI_INIT, "<========== %s, WAPI not supported!\n", __FUNCTION__);
+- return;
+- }
+-
+- padapter->wapiInfo.wapiTxMsk.bTxEnable = false;
+- padapter->wapiInfo.wapiTxMsk.bSet = false;
+-
+- WAPI_TRACE(WAPI_INIT, "<========== %s\n", __FUNCTION__);
+-}
+-
+-u8 rtw_wapi_is_wai_packet(_adapter* padapter,u8 *pkt_data)
+-{
+- PRT_WAPI_T pWapiInfo = &(padapter->wapiInfo);
+- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+- struct security_priv *psecuritypriv = &padapter->securitypriv;
+- PRT_WAPI_STA_INFO pWapiSta = NULL;
+- u8 WaiPkt = 0, *pTaddr, bFind = false;
+- u8 Offset_TypeWAI = 0 ; // (mac header len + llc length)
+-
+- WAPI_TRACE(WAPI_TX|WAPI_RX, "===========> %s\n", __FUNCTION__);
+-
+- if ((!padapter->WapiSupport) || (!pWapiInfo->bWapiEnable))
+- {
+- WAPI_TRACE(WAPI_MLME, "<========== %s, WAPI not supported or not enabled!\n", __FUNCTION__);
+- return 0;
+- }
+-
+- Offset_TypeWAI = 24 + 6 ;
+-
+- //YJ,add,091103. Data frame may also have skb->data[30]=0x88 and skb->data[31]=0xb4.
+- if ((pkt_data[1]&0x40) !=0)
+- {
+- //DBG_871X("data is privacy \n");
+- return 0;
+- }
+-
+- pTaddr = GetAddr2Ptr(pkt_data);
+- if(list_empty(&pWapiInfo->wapiSTAUsedList)){
+- bFind = false;
+- }else{
+- list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list){
+- if (!memcmp(pTaddr, pWapiSta->PeerMacAddr, 6)) {
+- bFind = true;
+- break;
+- }
+- }
+- }
+-
+- WAPI_TRACE(WAPI_TX|WAPI_RX, "%s: bFind=%d pTaddr="MAC_FMT"\n", __FUNCTION__, bFind, MAC_ARG(pTaddr));
+-
+- if (pkt_data[0] == WIFI_QOS_DATA_TYPE)
+- {
+- Offset_TypeWAI += 2;
+- }
+-
+- // 88b4?
+- if( (pkt_data[Offset_TypeWAI]==0x88) && (pkt_data[Offset_TypeWAI+1]==0xb4) ){
+- WaiPkt = pkt_data[Offset_TypeWAI+5];
+-
+- psecuritypriv->hw_decrypted = true;
+- }else{
+- WAPI_TRACE(WAPI_TX|WAPI_RX, "%s(): non wai packet\n",__FUNCTION__);
+- }
+-
+- WAPI_TRACE(WAPI_TX|WAPI_RX, "%s(): Recvd WAI frame. IsWAIPkt(%d)\n",__FUNCTION__, WaiPkt);
+-
+- return WaiPkt;
+-}
+-
+-
+-void rtw_wapi_update_info(_adapter *padapter, union recv_frame *precv_frame)
+-{
+- PRT_WAPI_T pWapiInfo = &(padapter->wapiInfo);
+- struct recv_frame_hdr *precv_hdr;
+- u8 *ptr;
+- u8 *pTA;
+- u8 *pRecvPN;
+-
+-
+- WAPI_TRACE(WAPI_RX, "===========> %s\n", __FUNCTION__);
+-
+- if ((!padapter->WapiSupport) || (!pWapiInfo->bWapiEnable))
+- {
+- WAPI_TRACE(WAPI_RX, "<========== %s, WAPI not supported or not enabled!\n", __FUNCTION__);
+- return;
+- }
+-
+- precv_hdr = &precv_frame->u.hdr;
+- ptr = precv_hdr->rx_data;
+-
+- if (precv_hdr->attrib.qos == 1)
+- {
+- precv_hdr->UserPriority = GetTid(ptr);
+- }
+- else
+- {
+- precv_hdr->UserPriority = 0;
+- }
+-
+- pTA = GetAddr2Ptr(ptr);
+- memcpy((u8 *)precv_hdr->WapiSrcAddr, pTA, 6);
+- pRecvPN = ptr + precv_hdr->attrib.hdrlen + 2;
+- memcpy((u8 *)precv_hdr->WapiTempPN, pRecvPN, 16);
+-
+- WAPI_TRACE(WAPI_RX, "<========== %s\n", __FUNCTION__);
+-}
+-
+-/****************************************************************************
+-true-----------------Drop
+-false---------------- handle
+-add to support WAPI to N-mode
+-*****************************************************************************/
+-u8 rtw_wapi_check_for_drop(
+- _adapter *padapter,
+- union recv_frame *precv_frame
+-)
+-{
+- PRT_WAPI_T pWapiInfo = &(padapter->wapiInfo);
+- u8 *pLastRecvPN = NULL;
+- u8 bFind = false;
+- PRT_WAPI_STA_INFO pWapiSta = NULL;
+- u8 bDrop = false;
+- struct recv_frame_hdr *precv_hdr = &precv_frame->u.hdr;
+- u8 WapiAEPNInitialValueSrc[16] = {0x37,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C} ;
+- u8 WapiAEMultiCastPNInitialValueSrc[16] = {0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C} ;
+- u8 *ptr = precv_frame->u.hdr.rx_data;
+- int i;
+-
+- WAPI_TRACE(WAPI_RX, "===========> %s\n", __FUNCTION__);
+-
+- if ((!padapter->WapiSupport) || (!pWapiInfo->bWapiEnable))
+- {
+- WAPI_TRACE(WAPI_RX, "<========== %s, WAPI not supported or not enabled!\n", __FUNCTION__);
+- return false;
+- }
+-
+- if(precv_hdr->bIsWaiPacket !=0)
+- {
+- if(precv_hdr->bIsWaiPacket== 0x8)
+- {
+-
+- DBG_871X("rtw_wapi_check_for_drop: dump packet \n");
+- for(i=0;i<50;i++)
+- {
+- DBG_871X("%02X ",ptr[i]);
+- if((i+1) %8 ==0)
+- DBG_871X("\n");
+- }
+- DBG_871X("\n rtw_wapi_check_for_drop: dump packet \n");
+-
+- for(i=0;i<16;i++)
+- {
+- if(ptr[i+27] !=0)
+- break;
+- }
+-
+- if(i== 16)
+- {
+- WAPI_TRACE(WAPI_RX,"rtw_wapi_check_for_drop: drop with zero BKID \n");
+- return true;
+- }
+- else
+- {
+- return false;
+- }
+- }
+- else
+- return false;
+- }
+-
+- if(list_empty(&pWapiInfo->wapiSTAUsedList)){
+- bFind = false;
+- }else{
+- list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list) {
+- if (!memcmp(precv_hdr->WapiSrcAddr, pWapiSta->PeerMacAddr, ETH_ALEN)) {
+- bFind = true;
+- break;
+- }
+- }
+- }
+- WAPI_TRACE(WAPI_RX, "%s: bFind=%d prxb->WapiSrcAddr="MAC_FMT"\n", __FUNCTION__, bFind, MAC_ARG(precv_hdr->WapiSrcAddr));
+-
+- if(bFind)
+- {
+- if(IS_MCAST(precv_hdr->attrib.ra))
+- {
+- WAPI_TRACE(WAPI_RX,"rtw_wapi_check_for_drop: multicast case \n");
+- pLastRecvPN = pWapiSta->lastRxMulticastPN;
+- }
+- else
+- {
+- WAPI_TRACE(WAPI_RX,"rtw_wapi_check_for_drop: unicast case \n");
+- switch(precv_hdr->UserPriority)
+- {
+- case 0:
+- case 3:
+- pLastRecvPN = pWapiSta->lastRxUnicastPNBEQueue;
+- break;
+- case 1:
+- case 2:
+- pLastRecvPN = pWapiSta->lastRxUnicastPNBKQueue;
+- break;
+- case 4:
+- case 5:
+- pLastRecvPN = pWapiSta->lastRxUnicastPNVIQueue;
+- break;
+- case 6:
+- case 7:
+- pLastRecvPN = pWapiSta->lastRxUnicastPNVOQueue;
+- break;
+- default:
+- WAPI_TRACE(WAPI_ERR,"%s: Unknown TID \n",__FUNCTION__);
+- break;
+- }
+- }
+-
+- if(!WapiComparePN(precv_hdr->WapiTempPN,pLastRecvPN))
+- {
+- WAPI_TRACE(WAPI_RX,"%s: Equal PN!!\n",__FUNCTION__);
+- if(IS_MCAST(precv_hdr->attrib.ra))
+- memcpy(pLastRecvPN,WapiAEMultiCastPNInitialValueSrc,16);
+- else
+- memcpy(pLastRecvPN,WapiAEPNInitialValueSrc,16);
+- bDrop = true;
+- }
+- else
+- {
+- memcpy(pLastRecvPN,precv_hdr->WapiTempPN,16);
+- }
+- }
+-
+- WAPI_TRACE(WAPI_RX, "<========== %s\n", __FUNCTION__);
+- return bDrop;
+-}
+-
+-void rtw_build_probe_resp_wapi_ie(_adapter *padapter, unsigned char *pframe, struct pkt_attrib *pattrib)
+-{
+- PRT_WAPI_T pWapiInfo = &(padapter->wapiInfo);
+- u8 WapiIELength = 0;
+-
+- WAPI_TRACE(WAPI_MLME, "===========> %s\n", __FUNCTION__);
+-
+- if ((!padapter->WapiSupport) || (!pWapiInfo->bWapiEnable))
+- {
+- WAPI_TRACE(WAPI_MLME, "<========== %s, WAPI not supported!\n", __FUNCTION__);
+- return;
+- }
+-
+- WapiSetIE(padapter);
+- WapiIELength = pWapiInfo->wapiIELength;
+- pframe[0] = _WAPI_IE_;
+- pframe[1] = WapiIELength;
+- memcpy(pframe+2, pWapiInfo->wapiIE, WapiIELength);
+- pframe += WapiIELength+2;
+- pattrib->pktlen += WapiIELength+2;
+-
+- WAPI_TRACE(WAPI_MLME, "<========== %s\n", __FUNCTION__);
+-}
+-
+-void rtw_build_beacon_wapi_ie(_adapter *padapter, unsigned char *pframe, struct pkt_attrib *pattrib)
+-{
+- PRT_WAPI_T pWapiInfo = &(padapter->wapiInfo);
+- u8 WapiIELength = 0;
+- WAPI_TRACE(WAPI_MLME, "===========> %s\n", __FUNCTION__);
+-
+- if ((!padapter->WapiSupport) || (!pWapiInfo->bWapiEnable))
+- {
+- WAPI_TRACE(WAPI_MLME, "<========== %s, WAPI not supported!\n", __FUNCTION__);
+- return;
+- }
+-
+- WapiSetIE(padapter);
+- WapiIELength = pWapiInfo->wapiIELength;
+- pframe[0] = _WAPI_IE_;
+- pframe[1] = WapiIELength;
+- memcpy(pframe+2, pWapiInfo->wapiIE, WapiIELength);
+- pframe += WapiIELength+2;
+- pattrib->pktlen += WapiIELength+2;
+-
+- WAPI_TRACE(WAPI_MLME, "<========== %s\n", __FUNCTION__);
+-}
+-
+-void rtw_build_assoc_req_wapi_ie(_adapter *padapter, unsigned char *pframe, struct pkt_attrib *pattrib)
+-{
+- PRT_WAPI_BKID pWapiBKID;
+- u16 bkidNum;
+- PRT_WAPI_T pWapiInfo = &(padapter->wapiInfo);
+- u8 WapiIELength = 0;
+-
+- WAPI_TRACE(WAPI_MLME, "===========> %s\n", __FUNCTION__);
+-
+- if ((!padapter->WapiSupport) || (!pWapiInfo->bWapiEnable))
+- {
+- WAPI_TRACE(WAPI_MLME, "<========== %s, WAPI not supported!\n", __FUNCTION__);
+- return;
+- }
+-
+- WapiSetIE(padapter);
+- WapiIELength = pWapiInfo->wapiIELength;
+- bkidNum = 0;
+- if(!list_empty(&(pWapiInfo->wapiBKIDStoreList))){
+- list_for_each_entry(pWapiBKID, &pWapiInfo->wapiBKIDStoreList, list) {
+- bkidNum ++;
+- memcpy(pWapiInfo->wapiIE+WapiIELength+2, pWapiBKID->bkid,16);
+- WapiIELength += 16;
+- }
+- }
+- memcpy(pWapiInfo->wapiIE+WapiIELength, &bkidNum, 2);
+- WapiIELength += 2;
+-
+- pframe[0] = _WAPI_IE_;
+- pframe[1] = WapiIELength;
+- memcpy(pframe+2, pWapiInfo->wapiIE, WapiIELength);
+- pframe += WapiIELength+2;
+- pattrib->pktlen += WapiIELength+2;
+- WAPI_TRACE(WAPI_MLME, "<========== %s\n", __FUNCTION__);
+-}
+-
+-void rtw_wapi_on_assoc_ok(_adapter *padapter, PNDIS_802_11_VARIABLE_IEs pIE)
+-{
+- PRT_WAPI_T pWapiInfo = &(padapter->wapiInfo);
+- PRT_WAPI_STA_INFO pWapiSta;
+- u8 WapiAEPNInitialValueSrc[16] = {0x37,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C} ;
+- //u8 WapiASUEPNInitialValueSrc[16] = {0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C} ;
+- u8 WapiAEMultiCastPNInitialValueSrc[16] = {0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C} ;
+-
+- WAPI_TRACE(WAPI_MLME, "===========> %s\n", __FUNCTION__);
+-
+- if ((!padapter->WapiSupport) || (!pWapiInfo->bWapiEnable))
+- {
+- WAPI_TRACE(WAPI_MLME, "<========== %s, WAPI not supported or not enabled!\n", __FUNCTION__);
+- return;
+- }
+-
+- pWapiSta =(PRT_WAPI_STA_INFO)list_entry(pWapiInfo->wapiSTAIdleList.next, RT_WAPI_STA_INFO, list);
+- list_del_init(&pWapiSta->list);
+- list_add_tail(&pWapiSta->list, &pWapiInfo->wapiSTAUsedList);
+- memcpy(pWapiSta->PeerMacAddr,padapter->mlmeextpriv.mlmext_info.network.MacAddress,6);
+- memcpy(pWapiSta->lastRxMulticastPN, WapiAEMultiCastPNInitialValueSrc, 16);
+- memcpy(pWapiSta->lastRxUnicastPN, WapiAEPNInitialValueSrc, 16);
+-
+- //For chenk PN error with Qos Data after s3: add by ylb 20111114
+- memcpy(pWapiSta->lastRxUnicastPNBEQueue,WapiAEPNInitialValueSrc,16);
+- memcpy(pWapiSta->lastRxUnicastPNBKQueue,WapiAEPNInitialValueSrc,16);
+- memcpy(pWapiSta->lastRxUnicastPNVIQueue,WapiAEPNInitialValueSrc,16);
+- memcpy(pWapiSta->lastRxUnicastPNVOQueue,WapiAEPNInitialValueSrc,16);
+-
+- WAPI_TRACE(WAPI_MLME, "<========== %s\n", __FUNCTION__);
+-}
+-
+-
+-void rtw_wapi_return_one_sta_info(_adapter *padapter, u8 *MacAddr)
+-{
+- PRT_WAPI_T pWapiInfo;
+- PRT_WAPI_STA_INFO pWapiStaInfo = NULL;
+- PRT_WAPI_BKID pWapiBkid = NULL;
+- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+-
+- pWapiInfo = &padapter->wapiInfo;
+-
+- WAPI_TRACE(WAPI_API, "==========> %s\n", __FUNCTION__);
+-
+- if ((!padapter->WapiSupport) || (!pWapiInfo->bWapiEnable))
+- {
+- WAPI_TRACE(WAPI_MLME, "<========== %s, WAPI not supported or not enabled!\n", __FUNCTION__);
+- return;
+- }
+-
+- if(check_fwstate(pmlmepriv, WIFI_STATION_STATE))
+- {
+- while(!list_empty(&(pWapiInfo->wapiBKIDStoreList)))
+- {
+- pWapiBkid = (PRT_WAPI_BKID)list_entry(pWapiInfo->wapiBKIDStoreList.next, RT_WAPI_BKID, list);
+- list_del_init(&pWapiBkid->list);
+- memset(pWapiBkid->bkid,0,16);
+- list_add_tail(&pWapiBkid->list, &pWapiInfo->wapiBKIDIdleList);
+- }
+- }
+-
+-
+- WAPI_TRACE(WAPI_API, " %s: after clear bkid \n", __FUNCTION__);
+-
+-
+- //Remove STA info
+- if(list_empty(&(pWapiInfo->wapiSTAUsedList))){
+- WAPI_TRACE(WAPI_API, " %s: wapiSTAUsedList is null \n", __FUNCTION__);
+- return;
+- }else{
+- WAPI_TRACE(WAPI_API, " %s: wapiSTAUsedList is not null \n", __FUNCTION__);
+-
+- while(!list_empty(&(pWapiInfo->wapiSTAUsedList)))
+- {
+- pWapiStaInfo = (PRT_WAPI_STA_INFO)list_entry(pWapiInfo->wapiSTAUsedList.next, RT_WAPI_STA_INFO, list);
+-
+- DBG_871X("peer Addr %02x-%02x-%02x-%02x-%02x-%02x \n",pWapiStaInfo->PeerMacAddr[0],pWapiStaInfo->PeerMacAddr[1],pWapiStaInfo->PeerMacAddr[2],pWapiStaInfo->PeerMacAddr[3],pWapiStaInfo->PeerMacAddr[4],pWapiStaInfo->PeerMacAddr[5]);
+-
+- list_del_init(&pWapiStaInfo->list);
+- memset(pWapiStaInfo->PeerMacAddr,0,ETH_ALEN);
+- pWapiStaInfo->bSetkeyOk = 0;
+- list_add_tail(&pWapiStaInfo->list, &pWapiInfo->wapiSTAIdleList);
+- }
+-
+- }
+-
+- WAPI_TRACE(WAPI_API, "<========== %s\n", __FUNCTION__);
+- return;
+-}
+-
+-void rtw_wapi_return_all_sta_info(_adapter *padapter)
+-{
+- PRT_WAPI_T pWapiInfo;
+- PRT_WAPI_STA_INFO pWapiStaInfo;
+- PRT_WAPI_BKID pWapiBkid;
+- WAPI_TRACE(WAPI_API, "===========> %s\n", __FUNCTION__);
+-
+- pWapiInfo = &padapter->wapiInfo;
+-
+- if ((!padapter->WapiSupport) || (!pWapiInfo->bWapiEnable))
+- {
+- WAPI_TRACE(WAPI_MLME, "<========== %s, WAPI not supported or not enabled!\n", __FUNCTION__);
+- return;
+- }
+-
+- //Sta Info List
+- while(!list_empty(&(pWapiInfo->wapiSTAUsedList)))
+- {
+- pWapiStaInfo = (PRT_WAPI_STA_INFO)list_entry(pWapiInfo->wapiSTAUsedList.next, RT_WAPI_STA_INFO, list);
+- list_del_init(&pWapiStaInfo->list);
+- memset(pWapiStaInfo->PeerMacAddr,0,ETH_ALEN);
+- pWapiStaInfo->bSetkeyOk = 0;
+- list_add_tail(&pWapiStaInfo->list, &pWapiInfo->wapiSTAIdleList);
+- }
+-
+- //BKID List
+- while(!list_empty(&(pWapiInfo->wapiBKIDStoreList)))
+- {
+- pWapiBkid = (PRT_WAPI_BKID)list_entry(pWapiInfo->wapiBKIDStoreList.next, RT_WAPI_BKID, list);
+- list_del_init(&pWapiBkid->list);
+- memset(pWapiBkid->bkid,0,16);
+- list_add_tail(&pWapiBkid->list, &pWapiInfo->wapiBKIDIdleList);
+- }
+- WAPI_TRACE(WAPI_API, "<========== %s\n", __FUNCTION__);
+-}
+-
+-void rtw_wapi_clear_cam_entry(_adapter *padapter, u8 *pMacAddr)
+-{
+- u8 UcIndex = 0;
+-
+- WAPI_TRACE(WAPI_API, "===========> %s\n", __FUNCTION__);
+-
+- if ((!padapter->WapiSupport) || (!padapter->wapiInfo.bWapiEnable))
+- {
+- WAPI_TRACE(WAPI_MLME, "<========== %s, WAPI not supported or not enabled!\n", __FUNCTION__);
+- return;
+- }
+-
+- UcIndex = WapiGetEntryForCamClear(padapter, pMacAddr, 0, 0);
+- if(UcIndex != 0xff){
+- //CAM_mark_invalid(Adapter, UcIndex);
+- CAM_empty_entry(padapter, UcIndex);
+- }
+-
+- UcIndex = WapiGetEntryForCamClear(padapter, pMacAddr, 1, 0);
+- if(UcIndex != 0xff){
+- //CAM_mark_invalid(Adapter, UcIndex);
+- CAM_empty_entry(padapter, UcIndex);
+- }
+-
+- UcIndex = WapiGetEntryForCamClear(padapter, pMacAddr, 0, 1);
+- if(UcIndex != 0xff){
+- //CAM_mark_invalid(Adapter, UcIndex);
+- CAM_empty_entry(padapter, UcIndex);
+- }
+-
+- UcIndex = WapiGetEntryForCamClear(padapter, pMacAddr, 1, 1);
+- if(UcIndex != 0xff){
+- //CAM_mark_invalid(padapter, UcIndex);
+- CAM_empty_entry(padapter, UcIndex);
+- }
+-
+- WAPI_TRACE(WAPI_API, "<========== %s\n", __FUNCTION__);
+-}
+-
+-void rtw_wapi_clear_all_cam_entry(_adapter *padapter)
+-{
+- WAPI_TRACE(WAPI_API, "===========> %s\n", __FUNCTION__);
+-
+- if ((!padapter->WapiSupport) || (!padapter->wapiInfo.bWapiEnable))
+- {
+- WAPI_TRACE(WAPI_MLME, "<========== %s, WAPI not supported or not enabled!\n", __FUNCTION__);
+- return;
+- }
+-
+- invalidate_cam_all(padapter); // is this ok?
+- WapiResetAllCamEntry(padapter);
+-
+- WAPI_TRACE(WAPI_API, "===========> %s\n", __FUNCTION__);
+-}
+-
+-void rtw_wapi_set_key(_adapter *padapter, RT_WAPI_KEY *pWapiKey, RT_WAPI_STA_INFO *pWapiSta, u8 bGroupKey, u8 bUseDefaultKey)
+-{
+- PRT_WAPI_T pWapiInfo = &padapter->wapiInfo;
+- u8 *pMacAddr = pWapiSta->PeerMacAddr;
+- u32 EntryId = 0;
+- bool IsPairWise = false ;
+- u8 EncAlgo;
+-
+- WAPI_TRACE(WAPI_API, "===========> %s\n", __FUNCTION__);
+-
+- if ((!padapter->WapiSupport) || (!padapter->wapiInfo.bWapiEnable))
+- {
+- WAPI_TRACE(WAPI_API, "<========== %s, WAPI not supported or not enabled!\n", __FUNCTION__);
+- return;
+- }
+-
+- EncAlgo = _SMS4_;
+-
+- //For Tx bc/mc pkt,use defualt key entry
+- if(bUseDefaultKey)
+- {
+- // when WAPI update key, keyid will be 0 or 1 by turns.
+- if (pWapiKey->keyId == 0)
+- EntryId = 0;
+- else
+- EntryId = 2;
+- }
+- else
+- {
+- // tx/rx unicast pkt, or rx broadcast, find the key entry by peer's MacAddr
+- EntryId = WapiGetEntryForCamWrite(padapter,pMacAddr,pWapiKey->keyId,bGroupKey);
+- }
+-
+- if(EntryId == 0xff){
+- WAPI_TRACE(WAPI_API, "===>No entry for WAPI setkey! !!\n");
+- return;
+- }
+-
+- //EntryId is also used to diff Sec key and Mic key
+- //Sec Key
+- WapiWriteOneCamEntry(padapter,
+- pMacAddr,
+- pWapiKey->keyId, //keyid
+- EntryId, //entry
+- EncAlgo, //type
+- bGroupKey, //pairwise or group key
+- pWapiKey->dataKey);
+- //MIC key
+- WapiWriteOneCamEntry(padapter,
+- pMacAddr,
+- pWapiKey->keyId, //keyid
+- EntryId+1, //entry
+- EncAlgo, //type
+- bGroupKey, //pairwise or group key
+- pWapiKey->micKey);
+-
+- WAPI_TRACE(WAPI_API, "Set Wapi Key :KeyId:%d,EntryId:%d,PairwiseKey:%d.\n",pWapiKey->keyId,EntryId,!bGroupKey);
+- WAPI_TRACE(WAPI_API, "===========> %s\n", __FUNCTION__);
+-
+-}
+-
+-void rtw_wapi_get_iv(_adapter *padapter,u8 *pRA, u8*IV)
+-{
+- PWLAN_HEADER_WAPI_EXTENSION pWapiExt = NULL;
+- PRT_WAPI_T pWapiInfo = &padapter->wapiInfo;
+- bool bPNOverflow = false;
+- bool bFindMatchPeer = false;
+- PRT_WAPI_STA_INFO pWapiSta = NULL;
+-
+- pWapiExt = (PWLAN_HEADER_WAPI_EXTENSION)IV;
+-
+- WAPI_DATA(WAPI_RX,"wapi_get_iv: pra",pRA,6);
+-
+- if(IS_MCAST(pRA)){
+- if(!pWapiInfo->wapiTxMsk.bTxEnable){
+- WAPI_TRACE(WAPI_ERR,"%s: bTxEnable = 0!!\n",__FUNCTION__);
+- return;
+- }
+-
+- if(pWapiInfo->wapiTxMsk.keyId <= 1){
+- pWapiExt->KeyIdx = pWapiInfo->wapiTxMsk.keyId;
+- pWapiExt->Reserved = 0;
+- bPNOverflow = WapiIncreasePN(pWapiInfo->lastTxMulticastPN, 1);
+- memcpy(pWapiExt->PN, pWapiInfo->lastTxMulticastPN, 16);
+- }
+- }
+- else
+- {
+- if(list_empty(&pWapiInfo->wapiSTAUsedList)){
+- WAPI_TRACE(WAPI_RX,"rtw_wapi_get_iv: list is empty \n");
+- memset(IV,10,18);
+- return;
+- }
+- else{
+- list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list){
+- WAPI_DATA(WAPI_RX,"rtw_wapi_get_iv: peermacaddr ",pWapiSta->PeerMacAddr,6);
+- if (!memcmp((u8*)pWapiSta->PeerMacAddr, pRA, 6)) {
+- bFindMatchPeer = true;
+- break;
+- }
+- }
+-
+- WAPI_TRACE(WAPI_RX,"bFindMatchPeer: %d \n",bFindMatchPeer);
+- WAPI_DATA(WAPI_RX,"Addr",pRA,6);
+-
+- if (bFindMatchPeer){
+- if((!pWapiSta->wapiUskUpdate.bTxEnable) && (!pWapiSta->wapiUsk.bTxEnable))
+- return;
+-
+- if (pWapiSta->wapiUsk.keyId <= 1){
+- if(pWapiSta->wapiUskUpdate.bTxEnable)
+- pWapiExt->KeyIdx = pWapiSta->wapiUskUpdate.keyId;
+- else
+- pWapiExt->KeyIdx = pWapiSta->wapiUsk.keyId;
+-
+- pWapiExt->Reserved = 0;
+- bPNOverflow = WapiIncreasePN(pWapiSta->lastTxUnicastPN, 2);
+- memcpy(pWapiExt->PN, pWapiSta->lastTxUnicastPN, 16);
+-
+- }
+- }
+- }
+-
+- }
+-
+-}
+-
+-bool rtw_wapi_drop_for_key_absent(_adapter *padapter,u8 *pRA)
+-{
+- PRT_WAPI_T pWapiInfo = &padapter->wapiInfo;
+- bool bFindMatchPeer = false;
+- bool bDrop = false;
+- PRT_WAPI_STA_INFO pWapiSta = NULL;
+- struct security_priv *psecuritypriv = &padapter->securitypriv;
+-
+- WAPI_DATA(WAPI_RX,"rtw_wapi_drop_for_key_absent: ra ",pRA,6);
+-
+- if(psecuritypriv->dot11PrivacyAlgrthm == _SMS4_)
+- {
+- if ((!padapter->WapiSupport) || (!pWapiInfo->bWapiEnable))
+- return true;
+-
+- if(IS_MCAST(pRA)){
+- if(!pWapiInfo->wapiTxMsk.bTxEnable){
+- bDrop = true;
+- WAPI_TRACE(WAPI_RX,"rtw_wapi_drop_for_key_absent: multicast key is absent \n");
+- return bDrop;
+- }
+- }
+- else{
+- if(!list_empty(&pWapiInfo->wapiSTAUsedList)){
+- list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list){
+- WAPI_DATA(WAPI_RX,"rtw_wapi_drop_for_key_absent: pWapiSta->PeerMacAddr ",pWapiSta->PeerMacAddr,6);
+- if (!memcmp(pRA, pWapiSta->PeerMacAddr, 6)){
+- bFindMatchPeer = true;
+- break;
+- }
+- }
+- if (bFindMatchPeer) {
+- if (!pWapiSta->wapiUsk.bTxEnable){
+- bDrop = true;
+- WAPI_TRACE(WAPI_RX,"rtw_wapi_drop_for_key_absent: unicast key is absent \n");
+- return bDrop;
+- }
+- }
+- else{
+- bDrop = true;
+- WAPI_TRACE(WAPI_RX,"rtw_wapi_drop_for_key_absent: no peer find \n");
+- return bDrop;
+- }
+-
+- }
+- else{
+- bDrop = true;
+- WAPI_TRACE(WAPI_RX,"rtw_wapi_drop_for_key_absent: no sta exist \n");
+- return bDrop;
+- }
+- }
+- }
+- else
+- {
+- return bDrop;
+- }
+-
+- return bDrop;
+-}
+-
+-#endif
+diff -Nurp linux/3rdparty/rtl8723bs.old/core/rtw_wapi_sms4.c linux/3rdparty/rtl8723bs/core/rtw_wapi_sms4.c
+--- linux/3rdparty/rtl8723bs.old/core/rtw_wapi_sms4.c 2015-05-10 14:36:05.678668013 +0300
++++ linux/3rdparty/rtl8723bs/core/rtw_wapi_sms4.c 1970-01-01 02:00:00.000000000 +0200
+@@ -1,713 +0,0 @@
+-#ifdef CONFIG_WAPI_SUPPORT
+-
+-#include
+-#include
+-#include
+-#include
+-
+-
+-#ifdef CONFIG_WAPI_SW_SMS4
+-
+-#define WAPI_LITTLE_ENDIAN
+-//#define BIG_ENDIAN
+-#define ENCRYPT 0
+-#define DECRYPT 1
+-
+-
+-/**********************************************************
+- **********************************************************/
+-const u8 Sbox[256] = {
+-0xd6,0x90,0xe9,0xfe,0xcc,0xe1,0x3d,0xb7,0x16,0xb6,0x14,0xc2,0x28,0xfb,0x2c,0x05,
+-0x2b,0x67,0x9a,0x76,0x2a,0xbe,0x04,0xc3,0xaa,0x44,0x13,0x26,0x49,0x86,0x06,0x99,
+-0x9c,0x42,0x50,0xf4,0x91,0xef,0x98,0x7a,0x33,0x54,0x0b,0x43,0xed,0xcf,0xac,0x62,
+-0xe4,0xb3,0x1c,0xa9,0xc9,0x08,0xe8,0x95,0x80,0xdf,0x94,0xfa,0x75,0x8f,0x3f,0xa6,
+-0x47,0x07,0xa7,0xfc,0xf3,0x73,0x17,0xba,0x83,0x59,0x3c,0x19,0xe6,0x85,0x4f,0xa8,
+-0x68,0x6b,0x81,0xb2,0x71,0x64,0xda,0x8b,0xf8,0xeb,0x0f,0x4b,0x70,0x56,0x9d,0x35,
+-0x1e,0x24,0x0e,0x5e,0x63,0x58,0xd1,0xa2,0x25,0x22,0x7c,0x3b,0x01,0x21,0x78,0x87,
+-0xd4,0x00,0x46,0x57,0x9f,0xd3,0x27,0x52,0x4c,0x36,0x02,0xe7,0xa0,0xc4,0xc8,0x9e,
+-0xea,0xbf,0x8a,0xd2,0x40,0xc7,0x38,0xb5,0xa3,0xf7,0xf2,0xce,0xf9,0x61,0x15,0xa1,
+-0xe0,0xae,0x5d,0xa4,0x9b,0x34,0x1a,0x55,0xad,0x93,0x32,0x30,0xf5,0x8c,0xb1,0xe3,
+-0x1d,0xf6,0xe2,0x2e,0x82,0x66,0xca,0x60,0xc0,0x29,0x23,0xab,0x0d,0x53,0x4e,0x6f,
+-0xd5,0xdb,0x37,0x45,0xde,0xfd,0x8e,0x2f,0x03,0xff,0x6a,0x72,0x6d,0x6c,0x5b,0x51,
+-0x8d,0x1b,0xaf,0x92,0xbb,0xdd,0xbc,0x7f,0x11,0xd9,0x5c,0x41,0x1f,0x10,0x5a,0xd8,
+-0x0a,0xc1,0x31,0x88,0xa5,0xcd,0x7b,0xbd,0x2d,0x74,0xd0,0x12,0xb8,0xe5,0xb4,0xb0,
+-0x89,0x69,0x97,0x4a,0x0c,0x96,0x77,0x7e,0x65,0xb9,0xf1,0x09,0xc5,0x6e,0xc6,0x84,
+-0x18,0xf0,0x7d,0xec,0x3a,0xdc,0x4d,0x20,0x79,0xee,0x5f,0x3e,0xd7,0xcb,0x39,0x48
+-};
+-
+-const u32 CK[32] = {
+- 0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269,
+- 0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9,
+- 0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249,
+- 0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9,
+- 0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229,
+- 0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299,
+- 0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209,
+- 0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279 };
+-
+-#define Rotl(_x, _y) (((_x) << (_y)) | ((_x) >> (32 - (_y))))
+-
+-#define ByteSub(_A) (Sbox[(_A) >> 24 & 0xFF] << 24 | \
+- Sbox[(_A) >> 16 & 0xFF] << 16 | \
+- Sbox[(_A) >> 8 & 0xFF] << 8 | \
+- Sbox[(_A) & 0xFF])
+-
+-#define L1(_B) ((_B) ^ Rotl(_B, 2) ^ Rotl(_B, 10) ^ Rotl(_B, 18) ^ Rotl(_B, 24))
+-#define L2(_B) ((_B) ^ Rotl(_B, 13) ^ Rotl(_B, 23))
+-
+-static void
+-xor_block(void *dst, void *src1, void *src2)
+-/* 128-bit xor: *dst = *src1 xor *src2. Pointers must be 32-bit aligned */
+-{
+- ((u32 *)dst)[0] = ((u32 *)src1)[0] ^ ((u32 *)src2)[0];
+- ((u32 *)dst)[1] = ((u32 *)src1)[1] ^ ((u32 *)src2)[1];
+- ((u32 *)dst)[2] = ((u32 *)src1)[2] ^ ((u32 *)src2)[2];
+- ((u32 *)dst)[3] = ((u32 *)src1)[3] ^ ((u32 *)src2)[3];
+-}
+-
+-
+-void SMS4Crypt(u8 *Input, u8 *Output, u32 *rk)
+-{
+- u32 r, mid, x0, x1, x2, x3, *p;
+- p = (u32 *)Input;
+- x0 = p[0];
+- x1 = p[1];
+- x2 = p[2];
+- x3 = p[3];
+-#ifdef WAPI_LITTLE_ENDIAN
+- x0 = Rotl(x0, 16); x0 = ((x0 & 0x00FF00FF) << 8) | ((x0 & 0xFF00FF00) >> 8);
+- x1 = Rotl(x1, 16); x1 = ((x1 & 0x00FF00FF) << 8) | ((x1 & 0xFF00FF00) >> 8);
+- x2 = Rotl(x2, 16); x2 = ((x2 & 0x00FF00FF) << 8) | ((x2 & 0xFF00FF00) >> 8);
+- x3 = Rotl(x3, 16); x3 = ((x3 & 0x00FF00FF) << 8) | ((x3 & 0xFF00FF00) >> 8);
+-#endif
+- for (r = 0; r < 32; r += 4)
+- {
+- mid = x1 ^ x2 ^ x3 ^ rk[r + 0];
+- mid = ByteSub(mid);
+- x0 ^= L1(mid);
+- mid = x2 ^ x3 ^ x0 ^ rk[r + 1];
+- mid = ByteSub(mid);
+- x1 ^= L1(mid);
+- mid = x3 ^ x0 ^ x1 ^ rk[r + 2];
+- mid = ByteSub(mid);
+- x2 ^= L1(mid);
+- mid = x0 ^ x1 ^ x2 ^ rk[r + 3];
+- mid = ByteSub(mid);
+- x3 ^= L1(mid);
+- }
+-#ifdef WAPI_LITTLE_ENDIAN
+- x0 = Rotl(x0, 16); x0 = ((x0 & 0x00FF00FF) << 8) | ((x0 & 0xFF00FF00) >> 8);
+- x1 = Rotl(x1, 16); x1 = ((x1 & 0x00FF00FF) << 8) | ((x1 & 0xFF00FF00) >> 8);
+- x2 = Rotl(x2, 16); x2 = ((x2 & 0x00FF00FF) << 8) | ((x2 & 0xFF00FF00) >> 8);
+- x3 = Rotl(x3, 16); x3 = ((x3 & 0x00FF00FF) << 8) | ((x3 & 0xFF00FF00) >> 8);
+-#endif
+- p = (u32 *)Output;
+- p[0] = x3;
+- p[1] = x2;
+- p[2] = x1;
+- p[3] = x0;
+-}
+-
+-
+-
+-void SMS4KeyExt(u8 *Key, u32 *rk, u32 CryptFlag)
+-{
+- u32 r, mid, x0, x1, x2, x3, *p;
+-
+- p = (u32 *)Key;
+- x0 = p[0];
+- x1 = p[1];
+- x2 = p[2];
+- x3 = p[3];
+-#ifdef WAPI_LITTLE_ENDIAN
+- x0 = Rotl(x0, 16); x0 = ((x0 & 0xFF00FF) << 8) | ((x0 & 0xFF00FF00) >> 8);
+- x1 = Rotl(x1, 16); x1 = ((x1 & 0xFF00FF) << 8) | ((x1 & 0xFF00FF00) >> 8);
+- x2 = Rotl(x2, 16); x2 = ((x2 & 0xFF00FF) << 8) | ((x2 & 0xFF00FF00) >> 8);
+- x3 = Rotl(x3, 16); x3 = ((x3 & 0xFF00FF) << 8) | ((x3 & 0xFF00FF00) >> 8);
+-#endif
+-
+- x0 ^= 0xa3b1bac6;
+- x1 ^= 0x56aa3350;
+- x2 ^= 0x677d9197;
+- x3 ^= 0xb27022dc;
+- for (r = 0; r < 32; r += 4)
+- {
+- mid = x1 ^ x2 ^ x3 ^ CK[r + 0];
+- mid = ByteSub(mid);
+- rk[r + 0] = x0 ^= L2(mid);
+- mid = x2 ^ x3 ^ x0 ^ CK[r + 1];
+- mid = ByteSub(mid);
+- rk[r + 1] = x1 ^= L2(mid);
+- mid = x3 ^ x0 ^ x1 ^ CK[r + 2];
+- mid = ByteSub(mid);
+- rk[r + 2] = x2 ^= L2(mid);
+- mid = x0 ^ x1 ^ x2 ^ CK[r + 3];
+- mid = ByteSub(mid);
+- rk[r + 3] = x3 ^= L2(mid);
+- }
+- if (CryptFlag == DECRYPT)
+- {
+- for (r = 0; r < 16; r++)
+- mid = rk[r], rk[r] = rk[31 - r], rk[31 - r] = mid;
+- }
+-}
+-
+-
+-void WapiSMS4Cryption(u8 *Key, u8 *IV, u8 *Input, u16 InputLength,
+- u8 *Output, u16 *OutputLength, u32 CryptFlag)
+-{
+- u32 blockNum,i,j, rk[32];
+- u16 remainder;
+- u8 blockIn[16],blockOut[16], tempIV[16], k;
+-
+- *OutputLength = 0;
+- remainder = InputLength & 0x0F;
+- blockNum = InputLength >> 4;
+- if(remainder !=0)
+- blockNum++;
+- else
+- remainder = 16;
+-
+- for(k=0;k<16;k++)
+- tempIV[k] = IV[15-k];
+-
+- memcpy(blockIn, tempIV, 16);
+-
+- SMS4KeyExt((u8 *)Key, rk,CryptFlag);
+-
+- for(i=0; i> 4;
+-
+- for(k=0;k<16;k++)
+- tempIV[k] = IV[15-k];
+-
+- memcpy(BlockIn, tempIV, 16);
+-
+- SMS4KeyExt((u8 *)Key, rk, ENCRYPT);
+-
+- SMS4Crypt((u8 *)BlockIn, BlockOut, rk);
+-
+- for(i=0; i> 4;
+-
+- for(i=0; i %s\n", __FUNCTION__);
+- switch(UserPriority)
+- {
+- case 0:
+- case 3:
+- memcpy(PNOut,pWapiStaInfo->lastRxUnicastPNBEQueue,16);
+- break;
+- case 1:
+- case 2:
+- memcpy(PNOut,pWapiStaInfo->lastRxUnicastPNBKQueue,16);
+- break;
+- case 4:
+- case 5:
+- memcpy(PNOut,pWapiStaInfo->lastRxUnicastPNVIQueue,16);
+- break;
+- case 6:
+- case 7:
+- memcpy(PNOut,pWapiStaInfo->lastRxUnicastPNVOQueue,16);
+- break;
+- default:
+- WAPI_TRACE(WAPI_ERR, "%s: Unknown TID \n", __FUNCTION__);
+- break;
+- }
+- WAPI_TRACE(WAPI_RX, "<=========== %s\n", __FUNCTION__);
+-}
+-
+-
+-void WapiSetLastRxUnicastPNForQoSData(
+- u8 UserPriority,
+- u8 *PNIn,
+- PRT_WAPI_STA_INFO pWapiStaInfo
+-)
+-{
+- WAPI_TRACE(WAPI_RX, "===========> %s\n", __FUNCTION__);
+- switch(UserPriority)
+- {
+- case 0:
+- case 3:
+- memcpy(pWapiStaInfo->lastRxUnicastPNBEQueue,PNIn,16);
+- break;
+- case 1:
+- case 2:
+- memcpy(pWapiStaInfo->lastRxUnicastPNBKQueue,PNIn,16);
+- break;
+- case 4:
+- case 5:
+- memcpy(pWapiStaInfo->lastRxUnicastPNVIQueue,PNIn,16);
+- break;
+- case 6:
+- case 7:
+- memcpy(pWapiStaInfo->lastRxUnicastPNVOQueue,PNIn,16);
+- break;
+- default:
+- WAPI_TRACE(WAPI_ERR, "%s: Unknown TID \n", __FUNCTION__);
+- break;
+- }
+- WAPI_TRACE(WAPI_RX, "<=========== %s\n", __FUNCTION__);
+-}
+-
+-// WAPI SW Enc: must have done Coalesce!
+-void SecSWSMS4Encryption(
+- _adapter *padapter,
+- u8 * pxmitframe
+- )
+-{
+- PRT_WAPI_T pWapiInfo = &padapter->wapiInfo;
+- PRT_WAPI_STA_INFO pWapiSta = NULL;
+- u8 *pframe = ((struct xmit_frame*)pxmitframe)->buf_addr + TXDESC_SIZE;
+- struct pkt_attrib *pattrib = &((struct xmit_frame*)pxmitframe)->attrib;
+-
+- u8 *SecPtr = NULL, *pRA, *pMicKey = NULL, *pDataKey = NULL, *pIV = NULL;
+- u8 IVOffset, DataOffset, bFindMatchPeer = false, KeyIdx = 0, MicBuffer[16];
+- u16 OutputLength;
+-
+- WAPI_TRACE(WAPI_TX, "=========>%s\n", __FUNCTION__);
+-
+- WAPI_TRACE(WAPI_TX,"hdrlen: %d \n",pattrib->hdrlen);
+-
+- return;
+-
+- DataOffset = pattrib->hdrlen + pattrib->iv_len;
+-
+- pRA = pframe + 4;
+-
+-
+- if( IS_MCAST(pRA) ){
+- KeyIdx = pWapiInfo->wapiTxMsk.keyId;
+- pIV = pWapiInfo->lastTxMulticastPN;
+- pMicKey = pWapiInfo->wapiTxMsk.micKey;
+- pDataKey = pWapiInfo->wapiTxMsk.dataKey;
+- }else{
+- if (!list_empty(&(pWapiInfo->wapiSTAUsedList))){
+- list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list) {
+- if (!memcmp(pWapiSta->PeerMacAddr, pRA, 6)){
+- bFindMatchPeer = true;
+- break;
+- }
+- }
+-
+- if (bFindMatchPeer){
+- if (pWapiSta->wapiUskUpdate.bTxEnable){
+- KeyIdx = pWapiSta->wapiUskUpdate.keyId;
+- WAPI_TRACE(WAPI_TX, "%s(): Use update USK!! KeyIdx=%d\n", __FUNCTION__, KeyIdx);
+- pIV = pWapiSta->lastTxUnicastPN;
+- pMicKey = pWapiSta->wapiUskUpdate.micKey;
+- pDataKey = pWapiSta->wapiUskUpdate.dataKey;
+- }else{
+- KeyIdx = pWapiSta->wapiUsk.keyId;
+- WAPI_TRACE(WAPI_TX, "%s(): Use USK!! KeyIdx=%d\n", __FUNCTION__, KeyIdx);
+- pIV = pWapiSta->lastTxUnicastPN;
+- pMicKey = pWapiSta->wapiUsk.micKey;
+- pDataKey = pWapiSta->wapiUsk.dataKey;
+- }
+- }else{
+- WAPI_TRACE(WAPI_ERR,"%s: Can not find Peer Sta!!\n",__FUNCTION__);
+- return;
+- }
+- }else{
+- WAPI_TRACE(WAPI_ERR,"%s: wapiSTAUsedList is empty!!\n",__FUNCTION__);
+- return;
+- }
+- }
+-
+- SecPtr = pframe;
+-
+- WAPI_DATA(WAPI_TX, "Encryption - MIC", MicBuffer, padapter->wapiInfo.extra_postfix_len);
+-
+- memcpy(pframe+pattrib->hdrlen+pattrib->iv_len+pattrib->pktlen-pattrib->icv_len,
+- (u8 *)MicBuffer,
+- padapter->wapiInfo.extra_postfix_len
+- );
+-
+-
+- WapiSMS4Encryption(pDataKey, pIV, (SecPtr+DataOffset),pattrib->pktlen+pattrib->icv_len, (SecPtr+DataOffset), &OutputLength);
+-
+- WAPI_DATA(WAPI_TX, "Encryption - After SMS4 encryption",pframe,pattrib->hdrlen+pattrib->iv_len+pattrib->pktlen);
+-
+- WAPI_TRACE(WAPI_TX, "<=========%s\n", __FUNCTION__);
+-}
+-
+-u8 SecSWSMS4Decryption(
+- _adapter *padapter,
+- u8 *precv_frame,
+- struct recv_priv *precv_priv
+- )
+-{
+- PRT_WAPI_T pWapiInfo = &padapter->wapiInfo;
+- struct recv_frame_hdr *precv_hdr;
+- PRT_WAPI_STA_INFO pWapiSta = NULL;
+- u8 IVOffset, DataOffset, bFindMatchPeer = false, bUseUpdatedKey = false;
+- u8 KeyIdx, MicBuffer[16], lastRxPNforQoS[16];
+- u8 *pRA, *pTA, *pMicKey, *pDataKey, *pLastRxPN, *pRecvPN, *pSecData, *pRecvMic, *pos;
+- u8 TID = 0;
+- u16 OutputLength, DataLen;
+- u8 bQosData;
+- struct sk_buff * pskb;
+-
+- WAPI_TRACE(WAPI_RX, "=========>%s\n", __FUNCTION__);
+-
+- return 0;
+-
+- precv_hdr = &((union recv_frame*)precv_frame)->u.hdr;
+- pskb = (struct sk_buff *)(precv_hdr->rx_data);
+- precv_hdr->bWapiCheckPNInDecrypt = false;
+- WAPI_TRACE(WAPI_RX, "=========>%s: check PN %d\n", __FUNCTION__,precv_hdr->bWapiCheckPNInDecrypt);
+- WAPI_DATA(WAPI_RX, "Decryption - Before decryption", pskb->data, pskb->len);
+-
+- IVOffset = sMacHdrLng;
+- bQosData = GetFrameType(pskb->data) == WIFI_QOS_DATA_TYPE;
+- if (bQosData){
+- IVOffset += 2;
+- }
+-
+- //if(GetHTC())
+- // IVOffset += 4;
+-
+- //IVOffset += SNAP_SIZE + sizeof(u16);
+-
+- DataOffset = IVOffset + padapter->wapiInfo.extra_prefix_len;
+-
+- pRA = pskb->data + 4;
+- pTA = pskb->data + 10;
+- KeyIdx = *(pskb->data + IVOffset);
+- pRecvPN = pskb->data + IVOffset + 2;
+- pSecData = pskb->data + DataOffset;
+- DataLen = pskb->len - DataOffset;
+- pRecvMic = pskb->data + pskb->len - padapter->wapiInfo.extra_postfix_len;
+- TID = GetTid(pskb->data);
+-
+- if (!list_empty(&(pWapiInfo->wapiSTAUsedList))){
+- list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list) {
+- if (!memcmp(pWapiSta->PeerMacAddr, pTA, 6)){
+- bFindMatchPeer = true;
+- break;
+- }
+- }
+- }
+-
+- if (!bFindMatchPeer){
+- WAPI_TRACE(WAPI_ERR, "%s: Can not find Peer Sta "MAC_FMT" for Key Info!!!\n", __FUNCTION__, MAC_ARG(pTA));
+- return false;
+- }
+-
+- if( IS_MCAST(pRA) ){
+- WAPI_TRACE(WAPI_RX, "%s: Multicast decryption !!!\n", __FUNCTION__);
+- if (pWapiSta->wapiMsk.keyId == KeyIdx && pWapiSta->wapiMsk.bSet){
+- pLastRxPN = pWapiSta->lastRxMulticastPN;
+- if (!WapiComparePN(pRecvPN, pLastRxPN)){
+- WAPI_TRACE(WAPI_ERR, "%s: MSK PN is not larger than last, Dropped!!!\n", __FUNCTION__);
+- WAPI_DATA(WAPI_ERR, "pRecvPN:", pRecvPN, 16);
+- WAPI_DATA(WAPI_ERR, "pLastRxPN:", pLastRxPN, 16);
+- return false;
+- }
+-
+- memcpy(pLastRxPN, pRecvPN, 16);
+- pMicKey = pWapiSta->wapiMsk.micKey;
+- pDataKey = pWapiSta->wapiMsk.dataKey;
+- }else if (pWapiSta->wapiMskUpdate.keyId == KeyIdx && pWapiSta->wapiMskUpdate.bSet){
+- WAPI_TRACE(WAPI_RX, "%s: Use Updated MSK for Decryption !!!\n", __FUNCTION__);
+- bUseUpdatedKey = true;
+- memcpy(pWapiSta->lastRxMulticastPN, pRecvPN, 16);
+- pMicKey = pWapiSta->wapiMskUpdate.micKey;
+- pDataKey = pWapiSta->wapiMskUpdate.dataKey;
+- }else{
+- WAPI_TRACE(WAPI_ERR, "%s: Can not find MSK with matched KeyIdx(%d), Dropped !!!\n", __FUNCTION__,KeyIdx);
+- return false;
+- }
+- }
+- else{
+- WAPI_TRACE(WAPI_RX, "%s: Unicast decryption !!!\n", __FUNCTION__);
+- if (pWapiSta->wapiUsk.keyId == KeyIdx && pWapiSta->wapiUsk.bSet){
+- WAPI_TRACE(WAPI_RX, "%s: Use USK for Decryption!!!\n", __FUNCTION__);
+- if(precv_hdr->bWapiCheckPNInDecrypt){
+- if(GetFrameType(pskb->data) == WIFI_QOS_DATA_TYPE){
+- WapiGetLastRxUnicastPNForQoSData(TID, pWapiSta, lastRxPNforQoS);
+- pLastRxPN = lastRxPNforQoS;
+- }else{
+- pLastRxPN = pWapiSta->lastRxUnicastPN;
+- }
+- if (!WapiComparePN(pRecvPN, pLastRxPN)){
+- return false;
+- }
+- if(bQosData){
+- WapiSetLastRxUnicastPNForQoSData(TID, pRecvPN, pWapiSta);
+- }else{
+- memcpy(pWapiSta->lastRxUnicastPN, pRecvPN, 16);
+- }
+- }else{
+- memcpy(precv_hdr->WapiTempPN,pRecvPN,16);
+- }
+-
+- if (check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE))
+- {
+- if ((pRecvPN[0] & 0x1) == 0){
+- WAPI_TRACE(WAPI_ERR, "%s: Rx USK PN is not odd when Infra STA mode, Dropped !!!\n", __FUNCTION__);
+- return false;
+- }
+- }
+-
+- pMicKey = pWapiSta->wapiUsk.micKey;
+- pDataKey = pWapiSta->wapiUsk.dataKey;
+- }
+- else if (pWapiSta->wapiUskUpdate.keyId == KeyIdx && pWapiSta->wapiUskUpdate.bSet ){
+- WAPI_TRACE(WAPI_RX, "%s: Use Updated USK for Decryption!!!\n", __FUNCTION__);
+- if(pWapiSta->bAuthenticatorInUpdata)
+- bUseUpdatedKey = true;
+- else
+- bUseUpdatedKey = false;
+-
+- if(bQosData){
+- WapiSetLastRxUnicastPNForQoSData(TID, pRecvPN, pWapiSta);
+- }else{
+- memcpy(pWapiSta->lastRxUnicastPN, pRecvPN, 16);
+- }
+- pMicKey = pWapiSta->wapiUskUpdate.micKey;
+- pDataKey = pWapiSta->wapiUskUpdate.dataKey;
+- }else{
+- WAPI_TRACE(WAPI_ERR, "%s: No valid USK!!!KeyIdx=%d pWapiSta->wapiUsk.keyId=%d pWapiSta->wapiUskUpdate.keyId=%d\n", __FUNCTION__, KeyIdx, pWapiSta->wapiUsk.keyId, pWapiSta->wapiUskUpdate.keyId);
+- //dump_buf(pskb->data,pskb->len);
+- return false;
+- }
+- }
+-
+- WAPI_DATA(WAPI_RX, "Decryption - DataKey", pDataKey, 16);
+- WAPI_DATA(WAPI_RX, "Decryption - IV", pRecvPN, 16);
+- WapiSMS4Decryption(pDataKey, pRecvPN, pSecData, DataLen, pSecData, &OutputLength);
+-
+- if (OutputLength != DataLen)
+- WAPI_TRACE(WAPI_ERR, "%s: Output Length Error!!!!\n", __FUNCTION__);
+-
+- WAPI_DATA(WAPI_RX, "Decryption - After decryption", pskb->data, pskb->len);
+-
+- DataLen -= padapter->wapiInfo.extra_postfix_len;
+-
+- WAPI_DATA(WAPI_RX, "Decryption - MIC received", pRecvMic, SMS4_MIC_LEN);
+- WAPI_DATA(WAPI_RX, "Decryption - MIC calculated", MicBuffer, SMS4_MIC_LEN);
+-
+- if (!memcmp(MicBuffer, pRecvMic, padapter->wapiInfo.extra_postfix_len)){
+- WAPI_TRACE(WAPI_RX, "%s: Check MIC OK!!\n", __FUNCTION__);
+- if (bUseUpdatedKey){
+- // delete the old key
+- if ( IS_MCAST(pRA) ){
+- WAPI_TRACE(WAPI_API, "%s(): AE use new update MSK!!\n", __FUNCTION__);
+- pWapiSta->wapiMsk.keyId = pWapiSta->wapiMskUpdate.keyId;
+- memcpy(pWapiSta->wapiMsk.dataKey, pWapiSta->wapiMskUpdate.dataKey, 16);
+- memcpy(pWapiSta->wapiMsk.micKey, pWapiSta->wapiMskUpdate.micKey, 16);
+- pWapiSta->wapiMskUpdate.bTxEnable = pWapiSta->wapiMskUpdate.bSet = false;
+- }else{
+- WAPI_TRACE(WAPI_API, "%s(): AE use new update USK!!\n", __FUNCTION__);
+- pWapiSta->wapiUsk.keyId = pWapiSta->wapiUskUpdate.keyId;
+- memcpy(pWapiSta->wapiUsk.dataKey, pWapiSta->wapiUskUpdate.dataKey, 16);
+- memcpy(pWapiSta->wapiUsk.micKey, pWapiSta->wapiUskUpdate.micKey, 16);
+- pWapiSta->wapiUskUpdate.bTxEnable = pWapiSta->wapiUskUpdate.bSet = false;
+- }
+- }
+- }else{
+- WAPI_TRACE(WAPI_ERR, "%s: Check MIC Error, Dropped !!!!\n", __FUNCTION__);
+- return false;
+- }
+-
+- pos = pskb->data;
+- memmove(pos+padapter->wapiInfo.extra_prefix_len, pos, IVOffset);
+- skb_pull(pskb, padapter->wapiInfo.extra_prefix_len);
+-
+- WAPI_TRACE(WAPI_RX, "<=========%s\n", __FUNCTION__);
+-
+- return true;
+-}
+-
+-u32 rtw_sms4_encrypt(_adapter *padapter, u8 *pxmitframe)
+-{
+-
+- u8 *pframe;
+- u32 res = _SUCCESS;
+-
+- WAPI_TRACE(WAPI_TX, "=========>%s\n", __FUNCTION__);
+-
+- if ((!padapter->WapiSupport) || (!padapter->wapiInfo.bWapiEnable))
+- {
+- WAPI_TRACE(WAPI_TX, "<========== %s, WAPI not supported or enabled!\n", __FUNCTION__);
+- return _FAIL;
+- }
+-
+- if(((struct xmit_frame*)pxmitframe)->buf_addr==NULL)
+- return _FAIL;
+-
+- pframe = ((struct xmit_frame*)pxmitframe)->buf_addr + TXDESC_OFFSET;
+-
+- SecSWSMS4Encryption(padapter, pxmitframe);
+-
+- WAPI_TRACE(WAPI_TX, "<=========%s\n", __FUNCTION__);
+- return res;
+-}
+-
+-u32 rtw_sms4_decrypt(_adapter *padapter, u8 *precvframe)
+-{
+- u8 *pframe;
+- u32 res = _SUCCESS;
+-
+- WAPI_TRACE(WAPI_RX, "=========>%s\n", __FUNCTION__);
+-
+- if ((!padapter->WapiSupport) || (!padapter->wapiInfo.bWapiEnable))
+- {
+- WAPI_TRACE(WAPI_RX, "<========== %s, WAPI not supported or enabled!\n", __FUNCTION__);
+- return _FAIL;
+- }
+-
+-
+- //drop packet when hw decrypt fail
+- //return tempraily
+- return _FAIL;
+-
+- //pframe=(unsigned char *)((union recv_frame*)precvframe)->u.hdr.rx_data;
+-
+- if (false == SecSWSMS4Decryption(padapter, precvframe, &padapter->recvpriv))
+- {
+- WAPI_TRACE(WAPI_ERR, "%s():SMS4 decrypt frame error\n",__FUNCTION__);
+- return _FAIL;
+- }
+-
+- WAPI_TRACE(WAPI_RX, "<=========%s\n", __FUNCTION__);
+- return res;
+-}
+-
+-#else
+-
+-u32 rtw_sms4_encrypt(_adapter *padapter, u8 *pxmitframe)
+-{
+- WAPI_TRACE(WAPI_TX, "=========>Dummy %s\n", __FUNCTION__);
+- WAPI_TRACE(WAPI_TX, "<=========Dummy %s\n", __FUNCTION__);
+- return _SUCCESS;
+-}
+-
+-u32 rtw_sms4_decrypt(_adapter *padapter, u8 *precvframe)
+-{
+- WAPI_TRACE(WAPI_RX, "=========>Dummy %s\n", __FUNCTION__);
+- WAPI_TRACE(WAPI_RX, "<=========Dummy %s\n", __FUNCTION__);
+- return _SUCCESS;
+-}
+-
+-#endif
+-
+-#endif
+diff -Nurp linux/3rdparty/rtl8723bs.old/core/rtw_wlan_util.c linux/3rdparty/rtl8723bs/core/rtw_wlan_util.c
+--- linux/3rdparty/rtl8723bs.old/core/rtw_wlan_util.c 2015-05-10 14:36:05.680668035 +0300
++++ linux/3rdparty/rtl8723bs/core/rtw_wlan_util.c 2015-05-07 17:46:55.000000000 +0300
+@@ -101,41 +101,6 @@ int cckratesonly_included(unsigned char
+ return true;
+ }
+
+-u8 networktype_to_raid(_adapter *adapter,struct sta_info *psta)
+-{
+- unsigned char raid;
+- switch(psta->wireless_mode)
+- {
+- case WIRELESS_11B:
+- raid = RATR_INX_WIRELESS_B;
+- break;
+- case WIRELESS_11A:
+- case WIRELESS_11G:
+- raid = RATR_INX_WIRELESS_G;
+- break;
+- case WIRELESS_11BG:
+- raid = RATR_INX_WIRELESS_GB;
+- break;
+- case WIRELESS_11_24N:
+- case WIRELESS_11_5N:
+- raid = RATR_INX_WIRELESS_N;
+- break;
+- case WIRELESS_11A_5N:
+- case WIRELESS_11G_24N:
+- raid = RATR_INX_WIRELESS_NG;
+- break;
+- case WIRELESS_11BG_24N:
+- raid = RATR_INX_WIRELESS_NGB;
+- break;
+- default:
+- raid = RATR_INX_WIRELESS_GB;
+- break;
+-
+- }
+- return raid;
+-
+-}
+-
+ u8 networktype_to_raid_ex(_adapter *adapter, struct sta_info *psta)
+ {
+ struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
+@@ -199,46 +164,6 @@ u8 networktype_to_raid_ex(_adapter *adap
+
+ }
+
+-u8 judge_network_type(_adapter *padapter, unsigned char *rate, int ratelen)
+-{
+- u8 network_type = 0;
+- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
+-
+-
+- 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->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;
+- }
+- }
+-
+- return network_type;
+-}
+-
+ unsigned char ratetbl_val_2wifirate(unsigned char rate);
+ unsigned char ratetbl_val_2wifirate(unsigned char rate)
+ {
+@@ -522,59 +447,6 @@ inline void rtw_set_oper_choffset(_adapt
+ adapter_to_dvobj(adapter)->oper_ch_offset = offset;
+ }
+
+-u8 rtw_get_offset_by_ch(u8 channel)
+-{
+- u8 offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+-
+- if(channel>=1 && channel<=4)
+- {
+- offset = HAL_PRIME_CHNL_OFFSET_LOWER;
+- }
+- else if(channel>=5 && channel<=14)
+- {
+- offset = HAL_PRIME_CHNL_OFFSET_UPPER;
+- }
+- else
+- {
+- switch(channel)
+- {
+- case 36:
+- case 44:
+- case 52:
+- case 60:
+- case 100:
+- case 108:
+- case 116:
+- case 124:
+- case 132:
+- case 149:
+- case 157:
+- offset = HAL_PRIME_CHNL_OFFSET_LOWER;
+- break;
+- case 40:
+- case 48:
+- case 56:
+- case 64:
+- case 104:
+- case 112:
+- case 120:
+- case 128:
+- case 136:
+- case 153:
+- case 161:
+- offset = HAL_PRIME_CHNL_OFFSET_UPPER;
+- break;
+- default:
+- offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+- break;
+- }
+-
+- }
+-
+- return offset;
+-
+-}
+-
+ u8 rtw_get_center_ch(u8 channel, u8 chnl_bw, u8 chnl_offset)
+ {
+ u8 center_ch = channel;
+@@ -607,11 +479,6 @@ u8 rtw_get_center_ch(u8 channel, u8 chnl
+ return center_ch;
+ }
+
+-inline u32 rtw_get_on_oper_ch_time(_adapter *adapter)
+-{
+- return adapter_to_dvobj(adapter)->on_oper_ch_time;
+-}
+-
+ inline unsigned long rtw_get_on_cur_ch_time(_adapter *adapter)
+ {
+ if (adapter->mlmeextpriv.cur_channel == adapter_to_dvobj(adapter)->oper_channel)
+@@ -624,29 +491,15 @@ void SelectChannel(_adapter *padapter, u
+ {
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+
+- _enter_critical_mutex(&(adapter_to_dvobj(padapter)->setch_mutex), NULL);
++ 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);
+
+- _exit_critical_mutex(&(adapter_to_dvobj(padapter)->setch_mutex), NULL);
+-}
+-
+-void SetBWMode(_adapter *padapter, unsigned short bwmode, unsigned char channel_offset)
+-{
+- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+-
+- _enter_critical_mutex(&(adapter_to_dvobj(padapter)->setbw_mutex), NULL);
+-
+- //saved bw info
+- rtw_set_oper_bw(padapter, bwmode);
+- rtw_set_oper_choffset(padapter, channel_offset);
+-
+- rtw_hal_set_bwmode(padapter, (CHANNEL_WIDTH)bwmode, channel_offset);
+-
+- _exit_critical_mutex(&(adapter_to_dvobj(padapter)->setbw_mutex), NULL);
++ mutex_unlock(&(adapter_to_dvobj(padapter)->setch_mutex));
+ }
+
+ void set_channel_bwmode(_adapter *padapter, unsigned char channel, unsigned char channel_offset, unsigned short bwmode)
+@@ -672,7 +525,8 @@ void set_channel_bwmode(_adapter *padapt
+ }
+
+ //set Channel
+- _enter_critical_mutex(&(adapter_to_dvobj(padapter)->setch_mutex), NULL);
++ if (mutex_lock_interruptible(&(adapter_to_dvobj(padapter)->setch_mutex)))
++ return;
+
+ //saved channel/bw info
+ rtw_set_oper_ch(padapter, channel);
+@@ -681,23 +535,7 @@ void set_channel_bwmode(_adapter *padapt
+
+ rtw_hal_set_chnl_bw(padapter, center_ch, bwmode, channel_offset, chnl_offset80); // set center channel
+
+- _exit_critical_mutex(&(adapter_to_dvobj(padapter)->setch_mutex), NULL);
+-}
+-
+-int get_bsstype(unsigned short capability)
+-{
+- if (capability & BIT(0))
+- {
+- return WIFI_FW_AP_STATE;
+- }
+- else if (capability & BIT(1))
+- {
+- return WIFI_FW_ADHOC_STATE;
+- }
+- else
+- {
+- return 0;
+- }
++ mutex_unlock(&(adapter_to_dvobj(padapter)->setch_mutex));
+ }
+
+ __inline u8 *get_my_bssid(WLAN_BSSID_EX *pnetwork)
+@@ -784,14 +622,6 @@ unsigned int decide_wait_for_beacon_time
+ }
+ }
+
+-void CAM_empty_entry(
+- PADAPTER Adapter,
+- u8 ucIndex
+-)
+-{
+- rtw_hal_set_hwreg(Adapter, HW_VAR_CAM_EMPTY_ENTRY, (u8 *)(&ucIndex));
+-}
+-
+ void invalidate_cam_all(_adapter *padapter)
+ {
+ struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
+@@ -800,10 +630,10 @@ void invalidate_cam_all(_adapter *padapt
+
+ rtw_hal_set_hwreg(padapter, HW_VAR_CAM_INVALID_ALL, NULL);
+
+- _enter_critical_bh(&cam_ctl->lock, &irqL);
++ spin_lock_bh(&cam_ctl->lock);
+ cam_ctl->bitmap = 0;
+ memset(dvobj->cam_cache, 0, sizeof(struct cam_entry_cache)*TOTAL_CAM_ENTRY);
+- _exit_critical_bh(&cam_ctl->lock, &irqL);
++ spin_unlock_bh(&cam_ctl->lock);
+ }
+
+ static u32 _ReadCAM(_adapter *padapter ,u32 addr)
+@@ -875,12 +705,8 @@ void _clear_cam_entry(_adapter *padapter
+
+ inline void write_cam(_adapter *adapter, u8 id, u16 ctrl, u8 *mac, u8 *key)
+ {
+-#ifdef CONFIG_WRITE_CACHE_ONLY
+- write_cam_cache(adapter, id ,ctrl, mac, key);
+-#else
+ _write_cam(adapter, id, ctrl, mac, key);
+ write_cam_cache(adapter, id ,ctrl, mac, key);
+-#endif
+ }
+
+ inline void clear_cam_entry(_adapter *adapter, u8 id)
+@@ -896,9 +722,9 @@ inline void write_cam_from_cache(_adapte
+ _irqL irqL;
+ struct cam_entry_cache cache;
+
+- _enter_critical_bh(&cam_ctl->lock, &irqL);
++ spin_lock_bh(&cam_ctl->lock);
+ memcpy(&cache, &dvobj->cam_cache[id], sizeof(struct cam_entry_cache));
+- _exit_critical_bh(&cam_ctl->lock, &irqL);
++ spin_unlock_bh(&cam_ctl->lock);
+
+ _write_cam(adapter, id, cache.ctrl, cache.mac, cache.key);
+ }
+@@ -909,13 +735,13 @@ void write_cam_cache(_adapter *adapter,
+ struct cam_ctl_t *cam_ctl = &dvobj->cam_ctl;
+ _irqL irqL;
+
+- _enter_critical_bh(&cam_ctl->lock, &irqL);
++ 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);
+
+- _exit_critical_bh(&cam_ctl->lock, &irqL);
++ spin_unlock_bh(&cam_ctl->lock);
+ }
+
+ void clear_cam_cache(_adapter *adapter, u8 id)
+@@ -924,54 +750,11 @@ void clear_cam_cache(_adapter *adapter,
+ struct cam_ctl_t *cam_ctl = &dvobj->cam_ctl;
+ _irqL irqL;
+
+- _enter_critical_bh(&cam_ctl->lock, &irqL);
++ spin_lock_bh(&cam_ctl->lock);
+
+ memset(&(dvobj->cam_cache[id]), 0, sizeof(struct cam_entry_cache));
+
+- _exit_critical_bh(&cam_ctl->lock, &irqL);
+-}
+-
+-s16 rtw_get_camid(_adapter *adapter, struct sta_info *sta, s16 kid)
+-{
+- u8 macid;
+- s16 camid;
+-
+- //cam_entry:
+- //0~3 for default key
+-
+- //for concurrent mode (ap+sta, sta+sta):
+- //default key is disable, using sw encrypt/decrypt
+- //camid 0, 1, 2, 3 is default entry for default key/group key
+- //macid = 1 is for bc/mc stainfo, no mapping to camid
+- //macid = 0 mapping to camid 4
+- //for macid >=2, camid = macid+3;
+-
+- if (sta) {
+- struct mlme_ext_info *mlmeinfo = &adapter->mlmeextpriv.mlmext_info;
+- macid = sta->mac_id;
+-
+- if((mlmeinfo->state&0x03) == WIFI_FW_AP_STATE) {
+- if((macid == 1) || (macid>(NUM_STA-4))){
+- DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" failed, mac_id=%d\n", FUNC_ADPT_ARG(adapter), macid);
+- camid = -1;
+- goto exit;
+- }
+- }
+-
+- if(macid==0)
+- camid = 4;
+- else if(macid >=2)
+- camid = macid + 3;
+- else
+- camid = 4;
+- }
+- else {
+- /* default key is disabled */
+- camid = -1;
+- }
+-
+-exit:
+- return (s16)camid;
++ spin_unlock_bh(&cam_ctl->lock);
+ }
+
+ static bool _rtw_camid_is_gk(_adapter *adapter, u8 cam_id)
+@@ -1026,9 +809,9 @@ s16 rtw_camid_search(_adapter *adapter,
+ _irqL irqL;
+ s16 cam_id = -1;
+
+- _enter_critical_bh(&cam_ctl->lock, &irqL);
++ spin_lock_bh(&cam_ctl->lock);
+ cam_id = _rtw_camid_search(adapter, addr, kid);
+- _exit_critical_bh(&cam_ctl->lock, &irqL);
++ spin_unlock_bh(&cam_ctl->lock);
+
+ return cam_id;
+ }
+@@ -1039,75 +822,70 @@ s16 rtw_camid_alloc(_adapter *adapter, s
+ struct cam_ctl_t *cam_ctl = &dvobj->cam_ctl;
+ _irqL irqL;
+ s16 cam_id = -1;
++ struct mlme_ext_info *mlmeinfo;
+
+- _enter_critical_bh(&cam_ctl->lock, &irqL);
++ spin_lock_bh(&cam_ctl->lock);
+
+-#ifdef DYNAMIC_CAMID_ALLOC
+- {
+- struct mlme_ext_info *mlmeinfo = &adapter->mlmeextpriv.mlmext_info;
++ 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;
++ 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;
+ }
+- 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);
+- }
++ cam_id = kid;
++ }
++ else {
++ int i;
++ u8 *addr = sta?sta->hwaddr:NULL;
+
+- if ((i = _rtw_camid_search(adapter, addr, kid)) >= 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);
++ 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;
+ }
+
+- for (i=4;ibitmap & BIT(i)))
+- break;
++ addr = get_bssid(&adapter->mlmepriv);
++ }
+
+- 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"
++ if ((i = _rtw_camid_search(adapter, addr, kid)) >= 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);
+- rtw_warn_on(1);
+- goto bitmap_handle;
+- }
++ goto bitmap_handle;
++ }
++
++ for (i=4;ibitmap & BIT(i)))
++ break;
+
+- cam_id = i;
++ 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;
+ }
+-#else
+- cam_id = rtw_get_camid(adapter, sta, kid);
+-#endif /* DYNAMIC_CAMID_ALLOC */
+
+ bitmap_handle:
+ if (cam_id >= 0)
+ cam_ctl->bitmap |= BIT(cam_id);
+
+- _exit_critical_bh(&cam_ctl->lock, &irqL);
++ spin_unlock_bh(&cam_ctl->lock);
+
+ return cam_id;
+ }
+@@ -1118,12 +896,12 @@ void rtw_camid_free(_adapter *adapter, u
+ struct cam_ctl_t *cam_ctl = &dvobj->cam_ctl;
+ _irqL irqL;
+
+- _enter_critical_bh(&cam_ctl->lock, &irqL);
++ spin_lock_bh(&cam_ctl->lock);
+
+ if (cam_id < TOTAL_CAM_ENTRY)
+ cam_ctl->bitmap &= ~(BIT(cam_id));
+
+- _exit_critical_bh(&cam_ctl->lock, &irqL);
++ spin_unlock_bh(&cam_ctl->lock);
+ }
+
+ int allocate_fw_sta_entry(_adapter *padapter)
+@@ -1153,9 +931,7 @@ void flush_all_cam_entry(_adapter *padap
+
+ invalidate_cam_all(padapter);
+ /* clear default key related key search setting */
+- #ifdef DYNAMIC_CAMID_ALLOC
+ rtw_hal_set_hwreg(padapter, HW_VAR_SEC_DK_CFG, (u8*)false);
+- #endif
+
+ memset((u8 *)(pmlmeinfo->FW_sta_info), 0, sizeof(pmlmeinfo->FW_sta_info));
+
+@@ -1221,8 +997,7 @@ void WMMOnAssocRsp(_adapter *padapter)
+
+ acm_mask = 0;
+
+- if (IsSupported5G(pmlmeext->cur_wireless_mode) ||
+- (pmlmeext->cur_wireless_mode & WIRELESS_11_24N) )
++ if (pmlmeext->cur_wireless_mode & WIRELESS_11_24N)
+ aSifsTime = 16;
+ else
+ aSifsTime = 10;
+@@ -1916,11 +1691,11 @@ int rtw_check_bcn_info(ADAPTER *Adapter,
+ }
+ }
+
+- rtw_mfree((u8 *)bssid, sizeof(WLAN_BSSID_EX));
++ kfree((u8 *)bssid);
+ return _SUCCESS;
+
+ _mismatch:
+- rtw_mfree((u8 *)bssid, sizeof(WLAN_BSSID_EX));
++ kfree((u8 *)bssid);
+
+ if (pmlmepriv->NumOfBcnInfoChkFail == 0)
+ {
+@@ -2030,190 +1805,6 @@ unsigned int is_ap_in_tkip(_adapter *pad
+
+ }
+
+-unsigned int should_forbid_n_rate(_adapter * padapter)
+-{
+- u32 i;
+- PNDIS_802_11_VARIABLE_IEs pIE;
+- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+- WLAN_BSSID_EX *cur_network = &pmlmepriv->cur_network.network;
+-
+- if (rtw_get_capability((WLAN_BSSID_EX *)cur_network) & WLAN_CAPABILITY_PRIVACY)
+- {
+- for (i = sizeof(NDIS_802_11_FIXED_IEs); i < cur_network->IELength;)
+- {
+- pIE = (PNDIS_802_11_VARIABLE_IEs)(cur_network->IEs + i);
+-
+- switch (pIE->ElementID)
+- {
+- case _VENDOR_SPECIFIC_IE_:
+- if (!memcmp(pIE->data, RTW_WPA_OUI, 4) &&
+- ((!memcmp((pIE->data + 12), WPA_CIPHER_SUITE_CCMP, 4)) ||
+- (!memcmp((pIE->data + 16), WPA_CIPHER_SUITE_CCMP, 4))))
+- return false;
+- break;
+-
+- case _RSN_IE_2_:
+- if ((!memcmp((pIE->data + 8), RSN_CIPHER_SUITE_CCMP, 4)) ||
+- (!memcmp((pIE->data + 12), RSN_CIPHER_SUITE_CCMP, 4)))
+- return false;
+-
+- default:
+- break;
+- }
+-
+- i += (pIE->Length + 2);
+- }
+-
+- return true;
+- }
+- else
+- {
+- return false;
+- }
+-
+-}
+-
+-
+-unsigned int is_ap_in_wep(_adapter *padapter)
+-{
+- u32 i;
+- PNDIS_802_11_VARIABLE_IEs pIE;
+- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
+- WLAN_BSSID_EX *cur_network = &(pmlmeinfo->network);
+-
+- if (rtw_get_capability((WLAN_BSSID_EX *)cur_network) & WLAN_CAPABILITY_PRIVACY)
+- {
+- for (i = sizeof(NDIS_802_11_FIXED_IEs); i < pmlmeinfo->network.IELength;)
+- {
+- pIE = (PNDIS_802_11_VARIABLE_IEs)(pmlmeinfo->network.IEs + i);
+-
+- switch (pIE->ElementID)
+- {
+- case _VENDOR_SPECIFIC_IE_:
+- if (!memcmp(pIE->data, RTW_WPA_OUI, 4))
+- return false;
+- break;
+-
+- case _RSN_IE_2_:
+- return false;
+-
+- default:
+- break;
+- }
+-
+- i += (pIE->Length + 2);
+- }
+-
+- return true;
+- }
+- else
+- {
+- return false;
+- }
+-
+-}
+-
+-int wifirate2_ratetbl_inx(unsigned char rate);
+-int wifirate2_ratetbl_inx(unsigned char rate)
+-{
+- int inx = 0;
+- rate = rate & 0x7f;
+-
+- switch (rate)
+- {
+- case 54*2:
+- inx = 11;
+- break;
+-
+- case 48*2:
+- inx = 10;
+- break;
+-
+- case 36*2:
+- inx = 9;
+- break;
+-
+- case 24*2:
+- inx = 8;
+- break;
+-
+- case 18*2:
+- inx = 7;
+- break;
+-
+- case 12*2:
+- inx = 6;
+- break;
+-
+- case 9*2:
+- inx = 5;
+- break;
+-
+- case 6*2:
+- inx = 4;
+- break;
+-
+- case 11*2:
+- inx = 3;
+- break;
+- case 11:
+- inx = 2;
+- break;
+-
+- case 2*2:
+- inx = 1;
+- break;
+-
+- case 1*2:
+- inx = 0;
+- break;
+-
+- }
+- return inx;
+-}
+-
+-unsigned int update_basic_rate(unsigned char *ptn, unsigned int ptn_sz)
+-{
+- unsigned int i, num_of_rate;
+- unsigned int mask = 0;
+-
+- num_of_rate = (ptn_sz > NumRates)? NumRates: ptn_sz;
+-
+- for (i = 0; i < num_of_rate; i++)
+- {
+- if ((*(ptn + i)) & 0x80)
+- {
+- mask |= 0x1 << wifirate2_ratetbl_inx(*(ptn + i));
+- }
+- }
+- return mask;
+-}
+-
+-unsigned int update_supported_rate(unsigned char *ptn, unsigned int ptn_sz)
+-{
+- unsigned int i, num_of_rate;
+- unsigned int mask = 0;
+-
+- num_of_rate = (ptn_sz > NumRates)? NumRates: ptn_sz;
+-
+- for (i = 0; i < num_of_rate; i++)
+- {
+- mask |= 0x1 << wifirate2_ratetbl_inx(*(ptn + i));
+- }
+-
+- return mask;
+-}
+-
+-unsigned int update_MCS_rate(struct HT_caps_element *pHT_caps)
+-{
+- unsigned int mask = 0;
+-
+- mask = ((pHT_caps->u.HT_cap_element.MCS_rate[0] << 12) | (pHT_caps->u.HT_cap_element.MCS_rate[1] << 20));
+-
+- return mask;
+-}
+-
+ int support_short_GI(_adapter *padapter, struct HT_caps_element *pHT_caps, u8 bwmode)
+ {
+ unsigned char bit_offset;
+@@ -2252,24 +1843,6 @@ unsigned char get_highest_rate_idx(u32 m
+ return rate_idx;
+ }
+
+-unsigned char get_highest_mcs_rate(struct HT_caps_element *pHT_caps);
+-unsigned char get_highest_mcs_rate(struct HT_caps_element *pHT_caps)
+-{
+- int i, mcs_rate;
+-
+- mcs_rate = (pHT_caps->u.HT_cap_element.MCS_rate[0] | (pHT_caps->u.HT_cap_element.MCS_rate[1] << 8));
+-
+- for (i = 15; i >= 0; i--)
+- {
+- if (mcs_rate & (0x1 << i))
+- {
+- break;
+- }
+- }
+-
+- return i;
+-}
+-
+ void Update_RA_Entry(_adapter *padapter, struct sta_info *psta)
+ {
+ rtw_hal_update_ra_mask(psta, 0);
+@@ -2287,38 +1860,6 @@ void set_sta_rate(_adapter *padapter, st
+ enable_rate_adaptive(padapter, psta);
+ }
+
+-// Update RRSR and Rate for USERATE
+-void update_tx_basic_rate(_adapter *padapter, u8 wirelessmode)
+-{
+- NDIS_802_11_RATES_EX supported_rates;
+- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+-#ifdef CONFIG_INTEL_WIDI
+- if (padapter->mlmepriv.widi_state != INTEL_WIDI_STATE_NONE)
+- return;
+-#endif //CONFIG_INTEL_WIDI
+-
+- memset(supported_rates, 0, NDIS_802_11_LENGTH_RATES_EX);
+-
+- //clear B mod if current channel is in 5G band, avoid tx cck rate in 5G band.
+- if(pmlmeext->cur_channel > 14)
+- wirelessmode &= ~(WIRELESS_11B);
+-
+- if ((wirelessmode & WIRELESS_11B) && (wirelessmode == WIRELESS_11B)) {
+- memcpy(supported_rates, rtw_basic_rate_cck, 4);
+- } else if (wirelessmode & WIRELESS_11B) {
+- memcpy(supported_rates, rtw_basic_rate_mix, 7);
+- } else {
+- memcpy(supported_rates, rtw_basic_rate_ofdm, 3);
+- }
+-
+- if (wirelessmode & WIRELESS_11B)
+- update_mgnt_tx_rate(padapter, IEEE80211_CCK_RATE_1MB);
+- else
+- update_mgnt_tx_rate(padapter, IEEE80211_OFDM_RATE_6MB);
+-
+- rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, supported_rates);
+-}
+-
+ unsigned char check_assoc_AP(u8 *pframe, uint len)
+ {
+ unsigned int i;
+@@ -2338,7 +1879,7 @@ unsigned char check_assoc_AP(u8 *pframe,
+ }
+ else if ((!memcmp(pIE->data, BROADCOM_OUI1, 3))
+ || (!memcmp(pIE->data, BROADCOM_OUI2, 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;
+@@ -2797,7 +2338,7 @@ void rtw_alloc_macid(_adapter *padapter,
+ return;
+ }
+
+- _enter_critical_bh(&pdvobj->lock, &irqL);
++ spin_lock_bh(&pdvobj->lock);
+ for(i=0; imacid[i] == false)
+@@ -2806,7 +2347,7 @@ void rtw_alloc_macid(_adapter *padapter,
+ break;
+ }
+ }
+- _exit_critical_bh(&pdvobj->lock, &irqL);
++ spin_unlock_bh(&pdvobj->lock);
+
+ if( i > (NUM_STA-1))
+ {
+@@ -2837,7 +2378,7 @@ void rtw_release_macid(_adapter *padapte
+ return;
+ }
+
+- _enter_critical_bh(&pdvobj->lock, &irqL);
++ spin_lock_bh(&pdvobj->lock);
+ if(psta->mac_idmac_id !=1 )
+ {
+ if(pdvobj->macid[psta->mac_id] == true)
+@@ -2848,7 +2389,7 @@ void rtw_release_macid(_adapter *padapte
+ }
+
+ }
+- _exit_critical_bh(&pdvobj->lock, &irqL);
++ spin_unlock_bh(&pdvobj->lock);
+
+ }
+ //For 8188E RA
+@@ -2858,7 +2399,7 @@ u8 rtw_search_max_mac_id(_adapter *padap
+ struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter);
+ int i;
+ _irqL irqL;
+- _enter_critical_bh(&pdvobj->lock, &irqL);
++ spin_lock_bh(&pdvobj->lock);
+ for(i=(NUM_STA-1); i>=0 ; i--)
+ {
+ if(pdvobj->macid[i] == true)
+@@ -2867,7 +2408,7 @@ u8 rtw_search_max_mac_id(_adapter *padap
+ }
+ }
+ max_mac_id = i;
+- _exit_critical_bh(&pdvobj->lock, &irqL);
++ spin_unlock_bh(&pdvobj->lock);
+
+ return max_mac_id;
+
+@@ -2892,93 +2433,6 @@ _adapter *dvobj_get_port0_adapter(struct
+ return port0_iface;
+ }
+
+-/*
+- * Description:
+- * rtw_check_invalid_mac_address:
+- * This is only used for checking mac address valid or not.
+- *
+- * Input:
+- * adapter: mac_address pointer.
+- *
+- * Output:
+- * true: The mac address is invalid.
+- * false: The mac address is valid.
+- *
+- * Auther: Isaac.Li
+- */
+-u8 rtw_check_invalid_mac_address(u8 *mac_addr) {
+- u8 null_mac_addr[ETH_ALEN] = {0, 0, 0, 0, 0, 0};
+- u8 multi_mac_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+- u8 res = false;
+-
+- if (!memcmp(mac_addr, null_mac_addr, ETH_ALEN)) {
+- res = true;
+- goto func_exit;
+- }
+-
+- if (!memcmp(mac_addr, multi_mac_addr, ETH_ALEN)) {
+- res = true;
+- goto func_exit;
+- }
+-
+- if (mac_addr[0] & BIT0) {
+- res = true;
+- goto func_exit;
+- }
+-
+- if (mac_addr[0] & BIT1) {
+- res = true;
+- goto func_exit;
+- }
+-
+-func_exit:
+- return res;
+-}
+-
+-/*
+- * Description:
+- * dump_TX_FIFO: This is only used to dump TX_FIFO for debug WoW mode offload
+- * contant.
+- *
+- * Input:
+- * adapter: adapter pointer.
+- * page_num: The max. page number that user want to dump.
+- * page_size: page size of each page. eg. 128 bytes, 256 bytes.
+- */
+-void dump_TX_FIFO(_adapter* padapter, u8 page_num, u16 page_size){
+-
+- int i;
+- u8 val = 0;
+- u8 base = 0;
+- u32 addr = 0;
+- u32 count = (page_size / 8);
+-
+- if (page_num <= 0) {
+- DBG_871X("!!%s: incorrect input page_num paramter!\n", __func__);
+- return;
+- }
+-
+- if (page_size < 128 || page_size > 256) {
+- DBG_871X("!!%s: incorrect input page_size paramter!\n", __func__);
+- return;
+- }
+-
+- DBG_871X("+%s+\n", __func__);
+- val = rtw_read8(padapter, 0x106);
+- rtw_write8(padapter, 0x106, 0x69);
+- DBG_871X("0x106: 0x%02x\n", val);
+- base = rtw_read8(padapter, 0x209);
+- DBG_871X("0x209: 0x%02x\n", base);
+-
+- addr = ((base) * page_size)/8;
+- for (i = 0 ; i < page_num * count ; i+=2) {
+- rtw_write32(padapter, 0x140, addr + i);
+- printk(" %08x %08x ", rtw_read32(padapter, 0x144), rtw_read32(padapter, 0x148));
+- rtw_write32(padapter, 0x140, addr + i + 1);
+- printk(" %08x %08x \n", rtw_read32(padapter, 0x144), rtw_read32(padapter, 0x148));
+- }
+-}
+-
+ #ifdef CONFIG_GPIO_API
+ int rtw_get_gpio(struct net_device *netdev, int gpio_num)
+ {
+@@ -3165,334 +2619,5 @@ void rtw_set_sec_pn(PADAPTER padapter)
+ #define CIPHER_NONE "NONE"
+ #define CIPHER_WPA_PSK "WPA-PSK"
+ #define CIPHER_WPA_EAP "WPA-EAP IEEE8021X"
+-/*
+- * SSIDs list parsing from cscan tlv list
+- */
+-int rtw_parse_ssid_list_tlv(char** list_str, pno_ssid_t* ssid,
+- int max, int *bytes_left) {
+- char* str;
+-
+- int idx = 0;
+-
+- if ((list_str == NULL) || (*list_str == NULL) || (*bytes_left < 0)) {
+- DBG_871X("%s error paramters\n", __func__);
+- return -1;
+- }
+-
+- str = *list_str;
+- while (*bytes_left > 0) {
+-
+- if (str[0] != CSCAN_TLV_TYPE_SSID_IE) {
+- *list_str = str;
+- DBG_871X("nssid=%d left_parse=%d %d\n", idx, *bytes_left, str[0]);
+- return idx;
+- }
+-
+- /* Get proper CSCAN_TLV_TYPE_SSID_IE */
+- *bytes_left -= 1;
+- str += 1;
+-
+- if (str[0] == 0) {
+- /* Broadcast SSID */
+- ssid[idx].SSID_len = 0;
+- memset((char*)ssid[idx].SSID, 0x0, WLAN_SSID_MAXLEN);
+- *bytes_left -= 1;
+- str += 1;
+-
+- DBG_871X("BROADCAST SCAN left=%d\n", *bytes_left);
+- }
+- else if (str[0] <= WLAN_SSID_MAXLEN) {
+- /* Get proper SSID size */
+- ssid[idx].SSID_len = str[0];
+- *bytes_left -= 1;
+- str += 1;
+-
+- /* Get SSID */
+- if (ssid[idx].SSID_len > *bytes_left) {
+- DBG_871X("%s out of memory range len=%d but left=%d\n",
+- __func__, ssid[idx].SSID_len, *bytes_left);
+- return -1;
+- }
+-
+- memcpy((char*)ssid[idx].SSID, str, ssid[idx].SSID_len);
+-
+- *bytes_left -= ssid[idx].SSID_len;
+- str += ssid[idx].SSID_len;
+-
+- DBG_871X("%s :size=%d left=%d\n",
+- (char*)ssid[idx].SSID, ssid[idx].SSID_len, *bytes_left);
+- }
+- else {
+- DBG_871X("### SSID size more that %d\n", str[0]);
+- return -1;
+- }
+-
+- if (idx++ > max) {
+- DBG_871X("%s number of SSIDs more that %d\n", __func__, idx);
+- return -1;
+- }
+- }
+-
+- *list_str = str;
+- return idx;
+-}
+-
+-int rtw_parse_cipher_list(struct pno_nlo_info *nlo_info, char* list_str) {
+-
+- char *pch, *pnext, *pend;
+- u8 key_len = 0, index = 0;
+-
+- pch = list_str;
+-
+- if (nlo_info == NULL || list_str == NULL) {
+- DBG_871X("%s error paramters\n", __func__);
+- return -1;
+- }
+-
+- while (strlen(pch) != 0) {
+- pnext = strstr(pch, "key_mgmt=");
+- if (pnext != NULL) {
+- pch = pnext + strlen(CIPHER_IE);
+- pend = strstr(pch, "}");
+- if (strncmp(pch, CIPHER_NONE,
+- strlen(CIPHER_NONE)) == 0) {
+- nlo_info->ssid_cipher_info[index] = 0x00;
+- } else if (strncmp(pch, CIPHER_WPA_PSK,
+- strlen(CIPHER_WPA_PSK)) == 0) {
+- nlo_info->ssid_cipher_info[index] = 0x66;
+- } else if (strncmp(pch, CIPHER_WPA_EAP,
+- strlen(CIPHER_WPA_EAP)) == 0) {
+- nlo_info->ssid_cipher_info[index] = 0x01;
+- }
+- index ++;
+- pch = pend + 1;
+- } else {
+- break;
+- }
+- }
+- return 0;
+-}
+-
+-int rtw_dev_nlo_info_set(struct pno_nlo_info *nlo_info, pno_ssid_t* ssid,
+- int num, int pno_time, int pno_repeat, int pno_freq_expo_max) {
+-
+- int i = 0;
+- struct file *fp;
+- mm_segment_t fs;
+- loff_t pos = 0;
+- u8 *source = NULL;
+- long len = 0;
+-
+- DBG_871X("+%s+\n", __func__);
+-
+- nlo_info->fast_scan_period = pno_time;
+- nlo_info->ssid_num = num & BIT_LEN_MASK_32(8);
+- nlo_info->slow_scan_period = (pno_time * 2);
+- nlo_info->fast_scan_iterations = 5;
+-
+- //TODO: channel list and probe index is all empty.
+- for (i = 0 ; i < num ; i++) {
+- nlo_info->ssid_length[i]
+- = ssid[i].SSID_len;
+- }
+-
+- /* cipher array */
+- fp = filp_open("/data/misc/wifi/wpa_supplicant.conf", O_RDONLY, 0644);
+- if (IS_ERR(fp)) {
+- DBG_871X("Error, wpa_supplicant.conf doesn't exist.\n");
+- DBG_871X("Error, cipher array using default value.\n");
+- return 0;
+- }
+-
+- len = i_size_read(fp->f_path.dentry->d_inode);
+- if (len < 0 || len > 2048) {
+- DBG_871X("Error, file size is bigger than 2048.\n");
+- DBG_871X("Error, cipher array using default value.\n");
+- return 0;
+- }
+-
+- fs = get_fs();
+- set_fs(KERNEL_DS);
+-
+- source = rtw_zmalloc(2048);
+-
+- if (source != NULL) {
+- len = vfs_read(fp, source, len, &pos);
+- rtw_parse_cipher_list(nlo_info, source);
+- rtw_mfree(source, 2048);
+- }
+-
+- set_fs(fs);
+- filp_close(fp, NULL);
+-
+- DBG_871X("-%s-\n", __func__);
+- return 0;
+-}
+-
+-int rtw_dev_ssid_list_set(struct pno_ssid_list *pno_ssid_list,
+- pno_ssid_t* ssid, u8 num) {
+-
+- int i = 0;
+- if(num > MAX_PNO_LIST_COUNT)
+- num = MAX_PNO_LIST_COUNT;
+-
+- for (i = 0 ; i < num ; i++) {
+- memcpy(&pno_ssid_list->node[i].SSID,
+- ssid[i].SSID, ssid[i].SSID_len);
+- }
+- return 0;
+-}
+-
+-int rtw_dev_scan_info_set(_adapter *padapter, pno_ssid_t* ssid,
+- unsigned char ch, unsigned char ch_offset, unsigned short bw_mode) {
+-
+- struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(padapter);
+- struct pno_scan_info *scan_info = pwrctl->pscan_info;
+- int i;
+-
+- scan_info->channel_num = MAX_SCAN_LIST_COUNT;
+- scan_info->orig_ch = ch;
+- scan_info->orig_bw = bw_mode;
+- scan_info->orig_40_offset = ch_offset;
+-
+- for(i = 0 ; i < scan_info->channel_num ; i++) {
+- if (i < 11)
+- scan_info->ssid_channel_info[i].active = 1;
+- else
+- scan_info->ssid_channel_info[i].active = 0;
+-
+- scan_info->ssid_channel_info[i].timeout = 100;
+-
+- scan_info->ssid_channel_info[i].tx_power =
+- PHY_GetTxPowerIndex(padapter, 0, 0x02, bw_mode, i+1);
+-
+- scan_info->ssid_channel_info[i].channel = i+1;
+- }
+
+- DBG_871X("%s, channel_num: %d, orig_ch: %d, orig_bw: %d orig_40_offset: %d\n",
+- __func__, scan_info->channel_num, scan_info->orig_ch,
+- scan_info->orig_bw, scan_info->orig_40_offset);
+- return 0;
+-}
+-
+-int rtw_dev_pno_set(struct net_device *net, pno_ssid_t* ssid, int num,
+- int pno_time, int pno_repeat, int pno_freq_expo_max) {
+-
+- _adapter *padapter = (_adapter *)rtw_netdev_priv(net);
+- struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(padapter);
+- struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+-
+- int ret = -1;
+-
+- if (num == 0) {
+- DBG_871X("%s, nssid is zero, no need to setup pno ssid list\n", __func__);
+- return 0;
+- }
+-
+- if (pwrctl == NULL) {
+- DBG_871X("%s, ERROR: pwrctl is NULL\n", __func__);
+- return -1;
+- } else {
+- pwrctl->pnlo_info =
+- (pno_nlo_info_t*)rtw_zmalloc(sizeof(pno_nlo_info_t));
+- pwrctl->pno_ssid_list =
+- (pno_ssid_list_t*)rtw_zmalloc(sizeof(pno_ssid_list_t));
+- pwrctl->pscan_info =
+- (pno_scan_info_t*)rtw_zmalloc(sizeof(pno_scan_info_t));
+- }
+-
+- if (pwrctl->pnlo_info == NULL ||
+- pwrctl->pscan_info == NULL ||
+- pwrctl->pno_ssid_list == NULL){
+- DBG_871X("%s, ERROR: alloc nlo_info, ssid_list, scan_info fail\n", __func__);
+- goto failing;
+- }
+-
+- pwrctl->pno_in_resume = false;
+-
+- pwrctl->pno_inited = true;
+- /* NLO Info */
+- ret = rtw_dev_nlo_info_set(pwrctl->pnlo_info, ssid, num,
+- pno_time, pno_repeat, pno_freq_expo_max);
+-
+- /* SSID Info */
+- ret = rtw_dev_ssid_list_set(pwrctl->pno_ssid_list, ssid, num);
+-
+- /* SCAN Info */
+- ret = rtw_dev_scan_info_set(padapter, ssid, pmlmeext->cur_channel,
+- pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
+-
+- DBG_871X("+%s num: %d, pno_time: %d, pno_repeat:%d, pno_freq_expo_max:%d+\n",
+- __func__, num, pno_time, pno_repeat, pno_freq_expo_max);
+-
+- return 0;
+-
+-failing:
+- if (pwrctl->pnlo_info) {
+- rtw_mfree(pwrctl->pnlo_info, sizeof(pno_nlo_info_t));
+- pwrctl->pnlo_info = NULL;
+- }
+- if (pwrctl->pno_ssid_list) {
+- rtw_mfree(pwrctl->pno_ssid_list, sizeof(pno_ssid_list_t));
+- pwrctl->pno_ssid_list = NULL;
+- }
+- if (pwrctl->pscan_info) {
+- rtw_mfree(pwrctl->pscan_info, sizeof(pno_scan_info_t));
+- pwrctl->pscan_info = NULL;
+- }
+-
+- return -1;
+-}
+-
+-#ifdef CONFIG_PNO_SET_DEBUG
+-void rtw_dev_pno_debug(struct net_device *net) {
+- _adapter *padapter = (_adapter *)rtw_netdev_priv(net);
+- struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(padapter);
+- int i = 0, j = 0;
+-
+- DBG_871X("*******NLO_INFO********\n");
+- DBG_871X("ssid_num: %d\n", pwrctl->pnlo_info->ssid_num);
+- DBG_871X("fast_scan_iterations: %d\n",
+- pwrctl->pnlo_info->fast_scan_iterations);
+- DBG_871X("fast_scan_period: %d\n", pwrctl->pnlo_info->fast_scan_period);
+- DBG_871X("slow_scan_period: %d\n", pwrctl->pnlo_info->slow_scan_period);
+- DBG_871X("ssid_length: ");
+- for (i = 0 ; i < MAX_PNO_LIST_COUNT ; i++) {
+- printk("%d, ", pwrctl->pnlo_info->ssid_length[i]);
+- }
+- DBG_871X("\n");
+-
+- DBG_871X("cipher_info: ");
+- for (i = 0 ; i < MAX_PNO_LIST_COUNT ; i++) {
+- DBG_871X("%d, ", pwrctl->pnlo_info->ssid_cipher_info[i]);
+- }
+- DBG_871X("\n");
+-
+- DBG_871X("channel_info: ");
+- for (i = 0 ; i < MAX_PNO_LIST_COUNT ; i++) {
+- DBG_871X("%d, ", pwrctl->pnlo_info->ssid_channel_info[i]);
+- }
+- DBG_871X("\n");
+-
+- DBG_871X("******SSID_LISD******\n");
+- for (i = 0 ; i < MAX_PNO_LIST_COUNT ; i++) {
+- DBG_871X("[%d]SSID: %s \n", i,
+- pwrctl->pno_ssid_list->node[i].SSID);
+- }
+-
+- DBG_871X("******SCAN_INFO******\n");
+- DBG_871X("ch_num: %d\n", pwrctl->pscan_info->channel_num);
+- DBG_871X("orig_ch: %d\n", pwrctl->pscan_info->orig_ch);
+- DBG_871X("orig bw: %d\n", pwrctl->pscan_info->orig_bw);
+- DBG_871X("orig 40 offset: %d\n", pwrctl->pscan_info->orig_40_offset);
+- for(i = 0 ; i < MAX_SCAN_LIST_COUNT ; i++) {
+- DBG_871X("[%02d] avtive:%d, timeout:%d, tx_power:%d, ch:%02d\n",
+- i, pwrctl->pscan_info->ssid_channel_info[i].active,
+- pwrctl->pscan_info->ssid_channel_info[i].timeout,
+- pwrctl->pscan_info->ssid_channel_info[i].tx_power,
+- pwrctl->pscan_info->ssid_channel_info[i].channel);
+- }
+- DBG_871X("*****************\n");
+-}
+-#endif //CONFIG_PNO_SET_DEBUG
+ #endif //CONFIG_PNO_SUPPORT
+diff -Nurp linux/3rdparty/rtl8723bs.old/core/rtw_xmit.c linux/3rdparty/rtl8723bs/core/rtw_xmit.c
+--- linux/3rdparty/rtl8723bs.old/core/rtw_xmit.c 2015-05-10 14:36:05.681668046 +0300
++++ linux/3rdparty/rtl8723bs/core/rtw_xmit.c 2015-05-07 17:46:55.000000000 +0300
+@@ -27,7 +27,7 @@ static u8 RFC1042_OUI[P80211_OUI_LEN] =
+ static void _init_txservq(struct tx_servq *ptxservq)
+ {
+ _func_enter_;
+- _rtw_init_listhead(&ptxservq->tx_pending);
++ INIT_LIST_HEAD(&ptxservq->tx_pending);
+ _rtw_init_queue(&ptxservq->sta_pending);
+ ptxservq->qcnt = 0;
+ _func_exit_;
+@@ -50,8 +50,8 @@ _func_enter_;
+ _init_txservq(&psta_xmitpriv->bk_q);
+ _init_txservq(&psta_xmitpriv->vi_q);
+ _init_txservq(&psta_xmitpriv->vo_q);
+- _rtw_init_listhead(&psta_xmitpriv->legacy_dz);
+- _rtw_init_listhead(&psta_xmitpriv->apsd);
++ INIT_LIST_HEAD(&psta_xmitpriv->legacy_dz);
++ INIT_LIST_HEAD(&psta_xmitpriv->apsd);
+
+ _func_exit_;
+
+@@ -66,7 +66,7 @@ s32 _rtw_init_xmit_priv(struct xmit_priv
+
+ _func_enter_;
+
+- // We don't need to memset padapter->XXX to zero, because adapter is allocated by rtw_zvmalloc().
++ // 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);
+@@ -100,7 +100,7 @@ _func_enter_;
+ Please also apply free_txobj to link_up all the xmit_frames...
+ */
+
+- pxmitpriv->pallocated_frame_buf = rtw_zvmalloc(NR_XMITFRAME * sizeof(struct xmit_frame) + 4);
++ pxmitpriv->pallocated_frame_buf = vzalloc(NR_XMITFRAME * sizeof(struct xmit_frame) + 4);
+
+ if (pxmitpriv->pallocated_frame_buf == NULL){
+ pxmitpriv->pxmit_frame_buf =NULL;
+@@ -116,7 +116,7 @@ _func_enter_;
+
+ for (i = 0; i < NR_XMITFRAME; i++)
+ {
+- _rtw_init_listhead(&(pxframe->list));
++ INIT_LIST_HEAD(&(pxframe->list));
+
+ pxframe->padapter = padapter;
+ pxframe->frame_tag = NULL_FRAMETAG;
+@@ -126,7 +126,7 @@ _func_enter_;
+ pxframe->buf_addr = NULL;
+ pxframe->pxmitbuf = NULL;
+
+- rtw_list_insert_tail(&(pxframe->list), &(pxmitpriv->free_xmit_queue.queue));
++ list_add_tail(&(pxframe->list), &(pxmitpriv->free_xmit_queue.queue));
+
+ pxframe++;
+ }
+@@ -140,7 +140,7 @@ _func_enter_;
+ _rtw_init_queue(&pxmitpriv->free_xmitbuf_queue);
+ _rtw_init_queue(&pxmitpriv->pending_xmitbuf_queue);
+
+- pxmitpriv->pallocated_xmitbuf = rtw_zvmalloc(NR_XMITBUFF * sizeof(struct xmit_buf) + 4);
++ 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"));
+@@ -156,7 +156,7 @@ _func_enter_;
+
+ for (i = 0; i < NR_XMITBUFF; i++)
+ {
+- _rtw_init_listhead(&pxmitbuf->list);
++ INIT_LIST_HEAD(&pxmitbuf->list);
+
+ pxmitbuf->priv_data = NULL;
+ pxmitbuf->padapter = padapter;
+@@ -178,7 +178,7 @@ _func_enter_;
+
+ pxmitbuf->flags = XMIT_VO_QUEUE;
+
+- rtw_list_insert_tail(&pxmitbuf->list, &(pxmitpriv->free_xmitbuf_queue.queue));
++ list_add_tail(&pxmitbuf->list, &(pxmitpriv->free_xmitbuf_queue.queue));
+ #ifdef DBG_XMIT_BUF
+ pxmitbuf->no=i;
+ #endif
+@@ -192,7 +192,7 @@ _func_enter_;
+ /* init xframe_ext queue, the same count as extbuf */
+ _rtw_init_queue(&pxmitpriv->free_xframe_ext_queue);
+
+- pxmitpriv->xframe_ext_alloc_addr = rtw_zvmalloc(NR_XMIT_EXTBUFF * sizeof(struct xmit_frame) + 4);
++ 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;
+@@ -204,7 +204,7 @@ _func_enter_;
+ pxframe = (struct xmit_frame*)pxmitpriv->xframe_ext;
+
+ for (i = 0; i < NR_XMIT_EXTBUFF; i++) {
+- _rtw_init_listhead(&(pxframe->list));
++ INIT_LIST_HEAD(&(pxframe->list));
+
+ pxframe->padapter = padapter;
+ pxframe->frame_tag = NULL_FRAMETAG;
+@@ -216,7 +216,7 @@ _func_enter_;
+
+ pxframe->ext_tag = 1;
+
+- rtw_list_insert_tail(&(pxframe->list), &(pxmitpriv->free_xframe_ext_queue.queue));
++ list_add_tail(&(pxframe->list), &(pxmitpriv->free_xframe_ext_queue.queue));
+
+ pxframe++;
+ }
+@@ -225,7 +225,7 @@ _func_enter_;
+ // Init xmit extension buff
+ _rtw_init_queue(&pxmitpriv->free_xmit_extbuf_queue);
+
+- pxmitpriv->pallocated_xmit_extbuf = rtw_zvmalloc(NR_XMIT_EXTBUFF * sizeof(struct xmit_buf) + 4);
++ 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"));
+@@ -239,7 +239,7 @@ _func_enter_;
+
+ for (i = 0; i < NR_XMIT_EXTBUFF; i++)
+ {
+- _rtw_init_listhead(&pxmitbuf->list);
++ INIT_LIST_HEAD(&pxmitbuf->list);
+
+ pxmitbuf->priv_data = NULL;
+ pxmitbuf->padapter = padapter;
+@@ -255,7 +255,7 @@ _func_enter_;
+ pxmitbuf->len = 0;
+ pxmitbuf->pdata = pxmitbuf->ptail = pxmitbuf->phead;
+
+- rtw_list_insert_tail(&pxmitbuf->list, &(pxmitpriv->free_xmit_extbuf_queue.queue));
++ list_add_tail(&pxmitbuf->list, &(pxmitpriv->free_xmit_extbuf_queue.queue));
+ #ifdef DBG_XMIT_BUF_EXT
+ pxmitbuf->no=i;
+ #endif
+@@ -268,7 +268,7 @@ _func_enter_;
+ for (i = 0; ipcmd_xmitbuf[i];
+ if (pxmitbuf) {
+- _rtw_init_listhead(&pxmitbuf->list);
++ INIT_LIST_HEAD(&pxmitbuf->list);
+
+ pxmitbuf->priv_data = NULL;
+ pxmitbuf->padapter = padapter;
+@@ -337,12 +337,12 @@ void _rtw_free_xmit_priv (struct xmit_pr
+ }
+
+ if(pxmitpriv->pallocated_frame_buf) {
+- rtw_vmfree(pxmitpriv->pallocated_frame_buf, NR_XMITFRAME * sizeof(struct xmit_frame) + 4);
++ vfree(pxmitpriv->pallocated_frame_buf);
+ }
+
+
+ if(pxmitpriv->pallocated_xmitbuf) {
+- rtw_vmfree(pxmitpriv->pallocated_xmitbuf, NR_XMITBUFF * sizeof(struct xmit_buf) + 4);
++ vfree(pxmitpriv->pallocated_xmitbuf);
+ }
+
+ /* free xframe_ext queue, the same count as extbuf */
+@@ -353,7 +353,7 @@ void _rtw_free_xmit_priv (struct xmit_pr
+ }
+ }
+ if (pxmitpriv->xframe_ext_alloc_addr)
+- rtw_vmfree(pxmitpriv->xframe_ext_alloc_addr, NR_XMIT_EXTBUFF * sizeof(struct xmit_frame) + 4);
++ vfree(pxmitpriv->xframe_ext_alloc_addr);
+
+ // free xmit extension buff
+ pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmit_extbuf;
+@@ -365,7 +365,7 @@ void _rtw_free_xmit_priv (struct xmit_pr
+ }
+
+ if(pxmitpriv->pallocated_xmit_extbuf) {
+- rtw_vmfree(pxmitpriv->pallocated_xmit_extbuf, NR_XMIT_EXTBUFF * sizeof(struct xmit_buf) + 4);
++ vfree(pxmitpriv->pallocated_xmit_extbuf);
+ }
+
+ for (i=0; iencrypt, bmcast);
+
+-#ifdef CONFIG_WAPI_SUPPORT
+- if(pattrib->ether_type == 0x88B4)
+- pattrib->encrypt=_NO_PRIVACY_;
+-#endif
+-
+ switch(psecuritypriv->dot11AuthAlgrthm)
+ {
+ case dot11AuthAlgrthm_Open:
+@@ -691,13 +686,6 @@ static s32 update_attrib_sec_info(_adapt
+
+ break;
+
+-#ifdef CONFIG_WAPI_SUPPORT
+- case _SMS4_:
+- pattrib->iv_len = 18;
+- pattrib->icv_len = 16;
+- rtw_wapi_get_iv(padapter,pattrib->ra,pattrib->iv);
+- break;
+-#endif
+ default:
+ pattrib->iv_len = 0;
+ pattrib->icv_len = 0;
+@@ -723,11 +711,6 @@ static s32 update_attrib_sec_info(_adapt
+ RT_TRACE(_module_rtl871x_xmit_c_,_drv_info_,("update_attrib: bswenc=false\n"));
+ }
+
+-#ifdef CONFIG_WAPI_SUPPORT
+- if(pattrib->encrypt == _SMS4_)
+- pattrib->bswenc = false;
+-#endif
+-
+ exit:
+
+ return res;
+@@ -898,15 +881,11 @@ static s32 update_attrib(_adapter *padap
+ }
+
+ // If EAPOL , ARP , OR DHCP packet, driver must be in active mode.
+-#ifdef CONFIG_WAPI_SUPPORT
+- if ( (pattrib->ether_type == 0x88B4) || (pattrib->ether_type == 0x0806) || (pattrib->ether_type == 0x888e) || (pattrib->dhcp_pkt == 1) )
+-#else //!CONFIG_WAPI_SUPPORT
+ if (pattrib->icmp_pkt==1)
+ {
+ rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_LEAVE, 1);
+ }
+ else if(pattrib->dhcp_pkt==1)
+-#endif
+ {
+ DBG_COUNTER(padapter->tx_logs.core_tx_upd_attrib_active);
+ rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_SPECIAL_PACKET, 1);
+@@ -1178,10 +1157,6 @@ _func_enter_;
+ case _AES_:
+ rtw_aes_encrypt(padapter, (u8 * )pxmitframe);
+ break;
+-#ifdef CONFIG_WAPI_SUPPORT
+- case _SMS4_:
+- rtw_sms4_encrypt(padapter, (u8 * )pxmitframe);
+-#endif
+ default:
+ break;
+ }
+@@ -1385,70 +1360,10 @@ s32 rtw_txframes_pending(_adapter *padap
+ {
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+
+- return ((_rtw_queue_empty(&pxmitpriv->be_pending) == false) ||
+- (_rtw_queue_empty(&pxmitpriv->bk_pending) == false) ||
+- (_rtw_queue_empty(&pxmitpriv->vi_pending) == false) ||
+- (_rtw_queue_empty(&pxmitpriv->vo_pending) == false));
+-}
+-
+-s32 rtw_txframes_sta_ac_pending(_adapter *padapter, struct pkt_attrib *pattrib)
+-{
+- struct sta_info *psta;
+- struct tx_servq *ptxservq;
+- int priority = pattrib->priority;
+-/*
+- if(pattrib->psta)
+- {
+- psta = pattrib->psta;
+- }
+- else
+- {
+- DBG_871X("%s, call rtw_get_stainfo()\n", __func__);
+- psta=rtw_get_stainfo(&padapter->stapriv ,&pattrib->ra[0]);
+- }
+-*/
+- 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 0;
+- }
+-
+- if(psta==NULL)
+- {
+- DBG_871X("%s, psta==NUL\n", __func__);
+- return 0;
+- }
+-
+- if(!(psta->state &_FW_LINKED))
+- {
+- DBG_871X("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, psta->state);
+- return 0;
+- }
+-
+- switch(priority)
+- {
+- case 1:
+- case 2:
+- ptxservq = &(psta->sta_xmitpriv.bk_q);
+- break;
+- case 4:
+- case 5:
+- ptxservq = &(psta->sta_xmitpriv.vi_q);
+- break;
+- case 6:
+- case 7:
+- ptxservq = &(psta->sta_xmitpriv.vo_q);
+- break;
+- case 0:
+- case 3:
+- default:
+- ptxservq = &(psta->sta_xmitpriv.be_q);
+- break;
+-
+- }
+-
+- return ptxservq->qcnt;
++ 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)));
+ }
+
+ /*
+@@ -1594,11 +1509,6 @@ _func_enter_;
+ else
+ AES_IV(pattrib->iv, psta->dot11txpn, 0);
+ break;
+-#ifdef CONFIG_WAPI_SUPPORT
+- case _SMS4_:
+- rtw_wapi_get_iv(padapter,pattrib->ra,pattrib->iv);
+- break;
+-#endif
+ }
+ }
+ */
+@@ -1683,7 +1593,6 @@ _func_exit_;
+ return res;
+ }
+
+-#ifdef CONFIG_IEEE80211W
+ //broadcast or multicast management pkt use BIP, unicast management pkt use CCMP encryption
+ s32 rtw_mgmt_xmitframe_coalesce(_adapter *padapter, _pkt *pkt, struct xmit_frame *pxmitframe)
+ {
+@@ -1719,7 +1628,7 @@ _func_enter_;
+ if(BIP_AAD == NULL)
+ return _FAIL;
+
+- _enter_critical_bh(&padapter->security_key_mutex, &irqL);
++ spin_lock_bh(&padapter->security_key_mutex);
+
+ //only support station mode
+ if(!check_fwstate(pmlmepriv, WIFI_STATION_STATE) || !check_fwstate(pmlmepriv, _FW_LINKED))
+@@ -1907,19 +1816,18 @@ _func_enter_;
+ }
+
+ xmitframe_coalesce_success:
+- _exit_critical_bh(&padapter->security_key_mutex, &irqL);
+- rtw_mfree(BIP_AAD, ori_len);
++ spin_unlock_bh(&padapter->security_key_mutex);
++ kfree(BIP_AAD);
+ _func_exit_;
+ return _SUCCESS;
+
+ xmitframe_coalesce_fail:
+- _exit_critical_bh(&padapter->security_key_mutex, &irqL);
+- rtw_mfree(BIP_AAD, ori_len);
++ spin_unlock_bh(&padapter->security_key_mutex);
++ kfree(BIP_AAD);
+ _func_exit_;
+
+ return _FAIL;
+ }
+-#endif //CONFIG_IEEE80211W
+
+ /* Logical Link Control(LLC) SubNetwork Attachment Point(SNAP) header
+ * IEEE LLC/SNAP header contains 8 octets
+@@ -2103,9 +2011,9 @@ struct xmit_buf *rtw_alloc_xmitbuf_ext(s
+
+ _func_enter_;
+
+- _enter_critical(&pfree_queue->lock, &irqL);
++ spin_lock_irqsave(&pfree_queue->lock, irqL);
+
+- if(_rtw_queue_empty(pfree_queue) == true) {
++ if(list_empty(&pfree_queue->queue)) {
+ pxmitbuf = NULL;
+ } else {
+
+@@ -2115,7 +2023,7 @@ _func_enter_;
+
+ pxmitbuf = LIST_CONTAINOR(plist, struct xmit_buf, list);
+
+- rtw_list_delete(&(pxmitbuf->list));
++ list_del_init(&(pxmitbuf->list));
+ }
+
+ if (pxmitbuf != NULL)
+@@ -2139,7 +2047,7 @@ _func_enter_;
+
+ }
+
+- _exit_critical(&pfree_queue->lock, &irqL);
++ spin_unlock_irqrestore(&pfree_queue->lock, irqL);
+
+ _func_exit_;
+
+@@ -2158,17 +2066,17 @@ _func_enter_;
+ return _FAIL;
+ }
+
+- _enter_critical(&pfree_queue->lock, &irqL);
++ spin_lock_irqsave(&pfree_queue->lock, irqL);
+
+- rtw_list_delete(&pxmitbuf->list);
++ list_del_init(&pxmitbuf->list);
+
+- rtw_list_insert_tail(&(pxmitbuf->list), get_list_head(pfree_queue));
++ 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
+
+- _exit_critical(&pfree_queue->lock, &irqL);
++ spin_unlock_irqrestore(&pfree_queue->lock, irqL);
+
+ _func_exit_;
+
+@@ -2186,9 +2094,9 @@ _func_enter_;
+
+ //DBG_871X("+rtw_alloc_xmitbuf\n");
+
+- _enter_critical(&pfree_xmitbuf_queue->lock, &irqL);
++ spin_lock_irqsave(&pfree_xmitbuf_queue->lock, irqL);
+
+- if(_rtw_queue_empty(pfree_xmitbuf_queue) == true) {
++ if(list_empty(&pfree_xmitbuf_queue->queue)) {
+ pxmitbuf = NULL;
+ } else {
+
+@@ -2198,7 +2106,7 @@ _func_enter_;
+
+ pxmitbuf = LIST_CONTAINOR(plist, struct xmit_buf, list);
+
+- rtw_list_delete(&(pxmitbuf->list));
++ list_del_init(&(pxmitbuf->list));
+ }
+
+ if (pxmitbuf != NULL)
+@@ -2228,7 +2136,7 @@ _func_enter_;
+ }
+ #endif
+
+- _exit_critical(&pfree_xmitbuf_queue->lock, &irqL);
++ spin_unlock_irqrestore(&pfree_xmitbuf_queue->lock, irqL);
+
+ _func_exit_;
+
+@@ -2261,18 +2169,18 @@ _func_enter_;
+ }
+ else
+ {
+- _enter_critical(&pfree_xmitbuf_queue->lock, &irqL);
++ spin_lock_irqsave(&pfree_xmitbuf_queue->lock, irqL);
+
+- rtw_list_delete(&pxmitbuf->list);
++ list_del_init(&pxmitbuf->list);
+
+- rtw_list_insert_tail(&(pxmitbuf->list), get_list_head(pfree_xmitbuf_queue));
++ 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
+- _exit_critical(&pfree_xmitbuf_queue->lock, &irqL);
++ spin_unlock_irqrestore(&pfree_xmitbuf_queue->lock, irqL);
+ }
+
+ _func_exit_;
+@@ -2324,9 +2232,9 @@ struct xmit_frame *rtw_alloc_xmitframe(s
+
+ _func_enter_;
+
+- _enter_critical_bh(&pfree_xmit_queue->lock, &irqL);
++ spin_lock_bh(&pfree_xmit_queue->lock);
+
+- if (_rtw_queue_empty(pfree_xmit_queue) == true) {
++ 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 {
+@@ -2336,12 +2244,12 @@ _func_enter_;
+
+ pxframe = LIST_CONTAINOR(plist, struct xmit_frame, list);
+
+- rtw_list_delete(&(pxframe->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));
+ }
+
+- _exit_critical_bh(&pfree_xmit_queue->lock, &irqL);
++ spin_unlock_bh(&pfree_xmit_queue->lock);
+
+ rtw_init_xmitframe(pxframe);
+
+@@ -2359,9 +2267,9 @@ struct xmit_frame *rtw_alloc_xmitframe_e
+
+ _func_enter_;
+
+- _enter_critical_bh(&queue->lock, &irqL);
++ spin_lock_bh(&queue->lock);
+
+- if (_rtw_queue_empty(queue) == true) {
++ 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 {
+@@ -2369,12 +2277,12 @@ _func_enter_;
+ plist = get_next(phead);
+ pxframe = LIST_CONTAINOR(plist, struct xmit_frame, list);
+
+- rtw_list_delete(&(pxframe->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));
+ }
+
+- _exit_critical_bh(&queue->lock, &irqL);
++ spin_unlock_bh(&queue->lock);
+
+ rtw_init_xmitframe(pxframe);
+
+@@ -2433,7 +2341,7 @@ _func_enter_;
+
+ if (pxmitframe->alloc_addr) {
+ DBG_871X("################## %s with alloc_addr ##################\n", __func__);
+- rtw_mfree(pxmitframe->alloc_addr, sizeof(struct xmit_frame) + 4);
++ kfree(pxmitframe->alloc_addr);
+ goto check_pkt_complete;
+ }
+
+@@ -2444,10 +2352,10 @@ _func_enter_;
+ else
+ {}
+
+- _enter_critical_bh(&queue->lock, &irqL);
++ spin_lock_bh(&queue->lock);
+
+- rtw_list_delete(&pxmitframe->list);
+- rtw_list_insert_tail(&pxmitframe->list, get_list_head(queue));
++ 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));
+@@ -2457,7 +2365,7 @@ _func_enter_;
+ } else {
+ }
+
+- _exit_critical_bh(&queue->lock, &irqL);
++ spin_unlock_bh(&queue->lock);
+
+ check_pkt_complete:
+
+@@ -2479,12 +2387,12 @@ void rtw_free_xmitframe_queue(struct xmi
+
+ _func_enter_;
+
+- _enter_critical_bh(&(pframequeue->lock), &irqL);
++ spin_lock_bh(&(pframequeue->lock));
+
+ phead = get_list_head(pframequeue);
+ plist = get_next(phead);
+
+- while (rtw_end_of_queue_search(phead, plist) == false)
++ while (phead != plist)
+ {
+
+ pxmitframe = LIST_CONTAINOR(plist, struct xmit_frame, list);
+@@ -2494,7 +2402,7 @@ _func_enter_;
+ rtw_free_xmitframe(pxmitpriv,pxmitframe);
+
+ }
+- _exit_critical_bh(&(pframequeue->lock), &irqL);
++ spin_unlock_bh(&(pframequeue->lock));
+
+ _func_exit_;
+ }
+@@ -2513,111 +2421,6 @@ s32 rtw_xmitframe_enqueue(_adapter *pada
+ return _SUCCESS;
+ }
+
+-static struct xmit_frame *dequeue_one_xmitframe(struct xmit_priv *pxmitpriv, struct hw_xmit *phwxmit, struct tx_servq *ptxservq, _queue *pframe_queue)
+-{
+- _list *xmitframe_plist, *xmitframe_phead;
+- struct xmit_frame *pxmitframe=NULL;
+-
+- xmitframe_phead = get_list_head(pframe_queue);
+- xmitframe_plist = get_next(xmitframe_phead);
+-
+- while ((rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist)) == false)
+- {
+- pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list);
+-
+- xmitframe_plist = get_next(xmitframe_plist);
+-
+- rtw_list_delete(&pxmitframe->list);
+-
+- ptxservq->qcnt--;
+-
+- //rtw_list_insert_tail(&pxmitframe->list, &phwxmit->pending);
+-
+- //ptxservq->qcnt--;
+-
+- break;
+-
+- pxmitframe = NULL;
+-
+- }
+-
+- return pxmitframe;
+-}
+-
+-struct xmit_frame* rtw_dequeue_xframe(struct xmit_priv *pxmitpriv, struct hw_xmit *phwxmit_i, sint entry)
+-{
+- _irqL irqL0;
+- _list *sta_plist, *sta_phead;
+- struct hw_xmit *phwxmit;
+- struct tx_servq *ptxservq = NULL;
+- _queue *pframe_queue = NULL;
+- struct xmit_frame *pxmitframe = NULL;
+- _adapter *padapter = pxmitpriv->adapter;
+- struct registry_priv *pregpriv = &padapter->registrypriv;
+- int i, inx[4];
+-
+-_func_enter_;
+-
+- inx[0] = 0; inx[1] = 1; inx[2] = 2; inx[3] = 3;
+-
+- if(pregpriv->wifi_spec==1)
+- {
+- int j, tmp, acirp_cnt[4];
+-
+- for(j=0; j<4; j++)
+- inx[j] = pxmitpriv->wmm_para_seq[j];
+- }
+-
+- _enter_critical_bh(&pxmitpriv->lock, &irqL0);
+-
+- for(i = 0; i < entry; i++)
+- {
+- phwxmit = phwxmit_i + inx[i];
+-
+- //_enter_critical_ex(&phwxmit->sta_queue->lock, &irqL0);
+-
+- sta_phead = get_list_head(phwxmit->sta_queue);
+- sta_plist = get_next(sta_phead);
+-
+- while ((rtw_end_of_queue_search(sta_phead, sta_plist)) == false)
+- {
+-
+- ptxservq= LIST_CONTAINOR(sta_plist, struct tx_servq, tx_pending);
+-
+- pframe_queue = &ptxservq->sta_pending;
+-
+- pxmitframe = dequeue_one_xmitframe(pxmitpriv, phwxmit, ptxservq, pframe_queue);
+-
+- if(pxmitframe)
+- {
+- phwxmit->accnt--;
+-
+- //Remove sta node when there is no pending packets.
+- if(_rtw_queue_empty(pframe_queue)) //must be done after get_next and before break
+- rtw_list_delete(&ptxservq->tx_pending);
+-
+- //_exit_critical_ex(&phwxmit->sta_queue->lock, &irqL0);
+-
+- goto exit;
+- }
+-
+- sta_plist = get_next(sta_plist);
+-
+- }
+-
+- //_exit_critical_ex(&phwxmit->sta_queue->lock, &irqL0);
+-
+- }
+-
+-exit:
+-
+- _exit_critical_bh(&pxmitpriv->lock, &irqL0);
+-
+-_func_exit_;
+-
+- return pxmitframe;
+-}
+-
+ struct tx_servq *rtw_get_sta_pending(_adapter *padapter, struct sta_info *psta, sint up, u8 *ac)
+ {
+ struct tx_servq *ptxservq=NULL;
+@@ -2715,21 +2518,21 @@ _func_enter_;
+
+ ptxservq = rtw_get_sta_pending(padapter, psta, pattrib->priority, (u8 *)(&ac_index));
+
+- //_enter_critical(&pstapending->lock, &irqL0);
++ //spin_lock_irqsave(&pstapending->lock, irqL0);
+
+- if (rtw_is_list_empty(&ptxservq->tx_pending)) {
+- rtw_list_insert_tail(&ptxservq->tx_pending, get_list_head(phwxmits[ac_index].sta_queue));
++ if (list_empty(&ptxservq->tx_pending)) {
++ list_add_tail(&ptxservq->tx_pending, get_list_head(phwxmits[ac_index].sta_queue));
+ }
+
+- //_enter_critical(&ptxservq->sta_pending.lock, &irqL1);
++ //spin_lock_irqsave(&ptxservq->sta_pending.lock, irqL1);
+
+- rtw_list_insert_tail(&pxmitframe->list, get_list_head(&ptxservq->sta_pending));
++ list_add_tail(&pxmitframe->list, get_list_head(&ptxservq->sta_pending));
+ ptxservq->qcnt++;
+ phwxmits[ac_index].accnt++;
+
+- //_exit_critical(&ptxservq->sta_pending.lock, &irqL1);
++ //spin_unlock_irqrestore(&ptxservq->sta_pending.lock, irqL1);
+
+- //_exit_critical(&pstapending->lock, &irqL0);
++ //spin_unlock_irqrestore(&pstapending->lock, irqL0);
+
+ exit:
+
+@@ -2815,7 +2618,7 @@ void rtw_free_hwxmits(_adapter *padapter
+
+ hwxmits = pxmitpriv->hwxmits;
+ if(hwxmits)
+- rtw_mfree((u8 *)hwxmits, (sizeof (struct hw_xmit) * pxmitpriv->hwxmit_entry));
++ kfree((u8 *)hwxmits);
+ }
+
+ void rtw_init_hwxmits(struct hw_xmit *phwxmit, sint entry)
+@@ -2825,7 +2628,7 @@ _func_enter_;
+ for(i = 0; i < entry; i++, phwxmit++)
+ {
+ //spin_lock_init(&phwxmit->xmit_lock);
+- //_rtw_init_listhead(&phwxmit->pending);
++ //INIT_LIST_HEAD(&phwxmit->pending);
+ //phwxmit->txcmdcnt = 0;
+ phwxmit->accnt = 0;
+ }
+@@ -2894,9 +2697,8 @@ s32 rtw_xmit(_adapter *padapter, _pkt **
+ {
+ static unsigned long start = 0;
+ static u32 drop_cnt = 0;
+-#ifdef CONFIG_AP_MODE
+ _irqL irqL0;
+-#endif
++
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct xmit_frame *pxmitframe = NULL;
+
+@@ -2925,16 +2727,6 @@ s32 rtw_xmit(_adapter *padapter, _pkt **
+
+ res = update_attrib(padapter, *ppkt, &pxmitframe->attrib);
+
+-#ifdef CONFIG_WAPI_SUPPORT
+- if(pxmitframe->attrib.ether_type != 0x88B4)
+- {
+- if(rtw_wapi_drop_for_key_absent(padapter, pxmitframe->attrib.ra))
+- {
+- WAPI_TRACE(WAPI_RX,"drop for key absend when tx \n");
+- res = _FAIL;
+- }
+- }
+-#endif
+ if (res == _FAIL) {
+ RT_TRACE(_module_xmit_osdep_c_, _drv_err_, ("rtw_xmit: update attrib fail\n"));
+ #ifdef DBG_TX_DROP_FRAME
+@@ -2945,20 +2737,16 @@ s32 rtw_xmit(_adapter *padapter, _pkt **
+ }
+ pxmitframe->pkt = *ppkt;
+
+- rtw_led_control(padapter, LED_CTL_TX);
+-
+ do_queue_select(padapter, &pxmitframe->attrib);
+
+-#ifdef CONFIG_AP_MODE
+- _enter_critical_bh(&pxmitpriv->lock, &irqL0);
++ spin_lock_bh(&pxmitpriv->lock);
+ if(xmitframe_enqueue_for_sleeping_sta(padapter, pxmitframe) == true)
+ {
+- _exit_critical_bh(&pxmitpriv->lock, &irqL0);
++ spin_unlock_bh(&pxmitpriv->lock);
+ DBG_COUNTER(padapter->tx_logs.core_tx_ap_enqueue);
+ return 1;
+ }
+- _exit_critical_bh(&pxmitpriv->lock, &irqL0);
+-#endif
++ spin_unlock_bh(&pxmitpriv->lock);
+
+ //pre_xmitframe
+ if (rtw_hal_xmit(padapter, pxmitframe) == false)
+@@ -2983,9 +2771,6 @@ inline bool xmitframe_hiq_filter(struct
+
+ if (attrib->ether_type == 0x0806
+ || attrib->ether_type == 0x888e
+- #ifdef CONFIG_WAPI_SUPPORT
+- || attrib->ether_type == 0x88B4
+- #endif
+ || attrib->dhcp_pkt
+ ) {
+ DBG_871X(FUNC_ADPT_FMT" ether_type:0x%04x%s\n", FUNC_ADPT_ARG(xmitframe->padapter)
+@@ -3005,8 +2790,6 @@ inline bool xmitframe_hiq_filter(struct
+ return allow;
+ }
+
+-#if defined(CONFIG_AP_MODE)
+-
+ sint xmitframe_enqueue_for_sleeping_sta(_adapter *padapter, struct xmit_frame *pxmitframe)
+ {
+ _irqL irqL;
+@@ -3071,17 +2854,17 @@ sint xmitframe_enqueue_for_sleeping_sta(
+
+ if(bmcst)
+ {
+- _enter_critical_bh(&psta->sleep_q.lock, &irqL);
++ spin_lock_bh(&psta->sleep_q.lock);
+
+ if(pstapriv->sta_dz_bitmap)//if anyone sta is in ps mode
+ {
+ //pattrib->qsel = 0x11;//HIQ
+
+- rtw_list_delete(&pxmitframe->list);
++ list_del_init(&pxmitframe->list);
+
+- //_enter_critical_bh(&psta->sleep_q.lock, &irqL);
++ //spin_lock_bh(&psta->sleep_q.lock);
+
+- rtw_list_insert_tail(&pxmitframe->list, get_list_head(&psta->sleep_q));
++ list_add_tail(&pxmitframe->list, get_list_head(&psta->sleep_q));
+
+ psta->sleepq_len++;
+
+@@ -3099,7 +2882,7 @@ sint xmitframe_enqueue_for_sleeping_sta(
+ chk_bmc_sleepq_cmd(padapter);
+ }
+
+- //_exit_critical_bh(&psta->sleep_q.lock, &irqL);
++ //spin_unlock_bh(&psta->sleep_q.lock);
+
+ ret = true;
+
+@@ -3107,14 +2890,14 @@ sint xmitframe_enqueue_for_sleeping_sta(
+
+ }
+
+- _exit_critical_bh(&psta->sleep_q.lock, &irqL);
++ spin_unlock_bh(&psta->sleep_q.lock);
+
+ return ret;
+
+ }
+
+
+- _enter_critical_bh(&psta->sleep_q.lock, &irqL);
++ spin_lock_bh(&psta->sleep_q.lock);
+
+ if(psta->state&WIFI_SLEEP_STATE)
+ {
+@@ -3122,11 +2905,11 @@ sint xmitframe_enqueue_for_sleeping_sta(
+
+ if(pstapriv->sta_dz_bitmap&BIT(psta->aid))
+ {
+- rtw_list_delete(&pxmitframe->list);
++ list_del_init(&pxmitframe->list);
+
+- //_enter_critical_bh(&psta->sleep_q.lock, &irqL);
++ //spin_lock_bh(&psta->sleep_q.lock);
+
+- rtw_list_insert_tail(&pxmitframe->list, get_list_head(&psta->sleep_q));
++ list_add_tail(&pxmitframe->list, get_list_head(&psta->sleep_q));
+
+ psta->sleepq_len++;
+
+@@ -3171,7 +2954,7 @@ sint xmitframe_enqueue_for_sleeping_sta(
+ }
+ }
+
+- //_exit_critical_bh(&psta->sleep_q.lock, &irqL);
++ //spin_unlock_bh(&psta->sleep_q.lock);
+
+ //if(psta->sleepq_len > (NR_XMITFRAME>>3))
+ //{
+@@ -3185,7 +2968,7 @@ sint xmitframe_enqueue_for_sleeping_sta(
+
+ }
+
+- _exit_critical_bh(&psta->sleep_q.lock, &irqL);
++ spin_unlock_bh(&psta->sleep_q.lock);
+
+ return ret;
+
+@@ -3204,7 +2987,7 @@ static void dequeue_xmitframes_to_sleepi
+ phead = get_list_head(pframequeue);
+ plist = get_next(phead);
+
+- while (rtw_end_of_queue_search(phead, plist) == false)
++ while (phead != plist)
+ {
+ pxmitframe = LIST_CONTAINOR(plist, struct xmit_frame, list);
+
+@@ -3246,7 +3029,7 @@ void stop_sta_xmit(_adapter *padapter, s
+ psta_bmc = rtw_get_bcmc_stainfo(padapter);
+
+
+- _enter_critical_bh(&pxmitpriv->lock, &irqL0);
++ spin_lock_bh(&pxmitpriv->lock);
+
+ psta->state |= WIFI_SLEEP_STATE;
+
+@@ -3255,26 +3038,26 @@ void stop_sta_xmit(_adapter *padapter, s
+
+
+ dequeue_xmitframes_to_sleeping_queue(padapter, psta, &pstaxmitpriv->vo_q.sta_pending);
+- rtw_list_delete(&(pstaxmitpriv->vo_q.tx_pending));
++ list_del_init(&(pstaxmitpriv->vo_q.tx_pending));
+
+
+ dequeue_xmitframes_to_sleeping_queue(padapter, psta, &pstaxmitpriv->vi_q.sta_pending);
+- rtw_list_delete(&(pstaxmitpriv->vi_q.tx_pending));
++ list_del_init(&(pstaxmitpriv->vi_q.tx_pending));
+
+
+ dequeue_xmitframes_to_sleeping_queue(padapter, psta, &pstaxmitpriv->be_q.sta_pending);
+- rtw_list_delete(&(pstaxmitpriv->be_q.tx_pending));
++ list_del_init(&(pstaxmitpriv->be_q.tx_pending));
+
+
+ dequeue_xmitframes_to_sleeping_queue(padapter, psta, &pstaxmitpriv->bk_q.sta_pending);
+- rtw_list_delete(&(pstaxmitpriv->bk_q.tx_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);
+- rtw_list_delete(&(pstaxmitpriv->be_q.tx_pending));
++ list_del_init(&(pstaxmitpriv->be_q.tx_pending));
+
+- _exit_critical_bh(&pxmitpriv->lock, &irqL0);
++ spin_unlock_bh(&pxmitpriv->lock);
+ }
+
+ void wakeup_sta_to_xmit(_adapter *padapter, struct sta_info *psta)
+@@ -3290,19 +3073,19 @@ void wakeup_sta_to_xmit(_adapter *padapt
+ psta_bmc = rtw_get_bcmc_stainfo(padapter);
+
+
+- //_enter_critical_bh(&psta->sleep_q.lock, &irqL);
+- _enter_critical_bh(&pxmitpriv->lock, &irqL);
++ //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 ((rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist)) == false)
++ while (xmitframe_phead != xmitframe_plist)
+ {
+ pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list);
+
+ xmitframe_plist = get_next(xmitframe_plist);
+
+- rtw_list_delete(&pxmitframe->list);
++ list_del_init(&pxmitframe->list);
+
+ switch(pxmitframe->attrib.priority)
+ {
+@@ -3349,12 +3132,12 @@ void wakeup_sta_to_xmit(_adapter *padapt
+ pxmitframe->attrib.triggered = 1;
+
+ /*
+- _exit_critical_bh(&psta->sleep_q.lock, &irqL);
++ spin_unlock_bh(&psta->sleep_q.lock);
+ if(rtw_hal_xmit(padapter, pxmitframe) == true)
+ {
+ rtw_os_xmit_complete(padapter, pxmitframe);
+ }
+- _enter_critical_bh(&psta->sleep_q.lock, &irqL);
++ spin_lock_bh(&psta->sleep_q.lock);
+ */
+ rtw_hal_xmitframe_enqueue(padapter, pxmitframe);
+
+@@ -3394,13 +3177,13 @@ void wakeup_sta_to_xmit(_adapter *padapt
+ xmitframe_phead = get_list_head(&psta_bmc->sleep_q);
+ xmitframe_plist = get_next(xmitframe_phead);
+
+- while ((rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist)) == false)
++ while (xmitframe_phead != xmitframe_plist)
+ {
+ pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list);
+
+ xmitframe_plist = get_next(xmitframe_plist);
+
+- rtw_list_delete(&pxmitframe->list);
++ list_del_init(&pxmitframe->list);
+
+ psta_bmc->sleepq_len--;
+ if(psta_bmc->sleepq_len>0)
+@@ -3411,12 +3194,12 @@ void wakeup_sta_to_xmit(_adapter *padapt
+
+ pxmitframe->attrib.triggered = 1;
+ /*
+- _exit_critical_bh(&psta_bmc->sleep_q.lock, &irqL);
++ spin_unlock_bh(&psta_bmc->sleep_q.lock);
+ if(rtw_hal_xmit(padapter, pxmitframe) == true)
+ {
+ rtw_os_xmit_complete(padapter, pxmitframe);
+ }
+- _enter_critical_bh(&psta_bmc->sleep_q.lock, &irqL);
++ spin_lock_bh(&psta_bmc->sleep_q.lock);
+
+ */
+ rtw_hal_xmitframe_enqueue(padapter, pxmitframe);
+@@ -3439,8 +3222,8 @@ void wakeup_sta_to_xmit(_adapter *padapt
+
+ _exit:
+
+- //_exit_critical_bh(&psta_bmc->sleep_q.lock, &irqL);
+- _exit_critical_bh(&pxmitpriv->lock, &irqL);
++ //spin_unlock_bh(&psta_bmc->sleep_q.lock);
++ spin_unlock_bh(&pxmitpriv->lock);
+
+ if(update_mask)
+ {
+@@ -3461,13 +3244,13 @@ void xmit_delivery_enabled_frames(_adapt
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+
+
+- //_enter_critical_bh(&psta->sleep_q.lock, &irqL);
+- _enter_critical_bh(&pxmitpriv->lock, &irqL);
++ //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 ((rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist)) == false)
++ while (xmitframe_phead != xmitframe_plist)
+ {
+ pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list);
+
+@@ -3497,7 +3280,7 @@ void xmit_delivery_enabled_frames(_adapt
+ if(!wmmps_ac)
+ continue;
+
+- rtw_list_delete(&pxmitframe->list);
++ list_del_init(&pxmitframe->list);
+
+ psta->sleepq_len--;
+ psta->sleepq_ac_len--;
+@@ -3529,14 +3312,12 @@ void xmit_delivery_enabled_frames(_adapt
+
+ }
+
+- //_exit_critical_bh(&psta->sleep_q.lock, &irqL);
+- _exit_critical_bh(&pxmitpriv->lock, &irqL);
++ //spin_unlock_bh(&psta->sleep_q.lock);
++ spin_unlock_bh(&pxmitpriv->lock);
+
+ return;
+ }
+
+-#endif
+-
+ void enqueue_pending_xmitbuf(
+ struct xmit_priv *pxmitpriv,
+ struct xmit_buf *pxmitbuf)
+@@ -3547,10 +3328,10 @@ void enqueue_pending_xmitbuf(
+
+ pqueue = &pxmitpriv->pending_xmitbuf_queue;
+
+- _enter_critical_bh(&pqueue->lock, &irql);
+- rtw_list_delete(&pxmitbuf->list);
+- rtw_list_insert_tail(&pxmitbuf->list, get_list_head(pqueue));
+- _exit_critical_bh(&pqueue->lock, &irql);
++ 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));
+ }
+@@ -3565,10 +3346,10 @@ void enqueue_pending_xmitbuf_to_head(
+
+ pqueue = &pxmitpriv->pending_xmitbuf_queue;
+
+- _enter_critical_bh(&pqueue->lock, &irql);
+- rtw_list_delete(&pxmitbuf->list);
+- rtw_list_insert_head(&pxmitbuf->list, get_list_head(pqueue));
+- _exit_critical_bh(&pqueue->lock, &irql);
++ 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(
+@@ -3582,19 +3363,19 @@ struct xmit_buf* dequeue_pending_xmitbuf
+ pxmitbuf = NULL;
+ pqueue = &pxmitpriv->pending_xmitbuf_queue;
+
+- _enter_critical_bh(&pqueue->lock, &irql);
++ spin_lock_bh(&pqueue->lock);
+
+- if (_rtw_queue_empty(pqueue) == false)
++ if (!list_empty(&pqueue->queue))
+ {
+ _list *plist, *phead;
+
+ phead = get_list_head(pqueue);
+ plist = get_next(phead);
+ pxmitbuf = LIST_CONTAINOR(plist, struct xmit_buf, list);
+- rtw_list_delete(&pxmitbuf->list);
++ list_del_init(&pxmitbuf->list);
+ }
+
+- _exit_critical_bh(&pqueue->lock, &irql);
++ spin_unlock_bh(&pqueue->lock);
+
+ return pxmitbuf;
+ }
+@@ -3610,9 +3391,9 @@ struct xmit_buf* dequeue_pending_xmitbuf
+ pxmitbuf = NULL;
+ pqueue = &pxmitpriv->pending_xmitbuf_queue;
+
+- _enter_critical_bh(&pqueue->lock, &irql);
++ spin_lock_bh(&pqueue->lock);
+
+- if (_rtw_queue_empty(pqueue) == false)
++ if (!list_empty(&pqueue->queue))
+ {
+ _list *plist, *phead;
+ u8 type;
+@@ -3631,14 +3412,14 @@ struct xmit_buf* dequeue_pending_xmitbuf
+ (type == WIFI_DATA_NULL) ||
+ (type == WIFI_QOS_DATA_NULL))
+ {
+- rtw_list_delete(&pxmitbuf->list);
++ list_del_init(&pxmitbuf->list);
+ break;
+ }
+ pxmitbuf = NULL;
+ } while (1);
+ }
+
+- _exit_critical_bh(&pqueue->lock, &irql);
++ spin_unlock_bh(&pqueue->lock);
+
+ return pxmitbuf;
+ }
+@@ -3652,12 +3433,12 @@ sint check_pending_xmitbuf(
+
+ pqueue = &pxmitpriv->pending_xmitbuf_queue;
+
+- _enter_critical_bh(&pqueue->lock, &irql);
++ spin_lock_bh(&pqueue->lock);
+
+- if(_rtw_queue_empty(pqueue) == false)
++ if(!list_empty(&pqueue->queue))
+ ret = true;
+
+- _exit_critical_bh(&pqueue->lock, &irql);
++ spin_unlock_bh(&pqueue->lock);
+
+ return ret;
+ }
+diff -Nurp linux/3rdparty/rtl8723bs.old/hal/HalBtc8723b1Ant.c linux/3rdparty/rtl8723bs/hal/HalBtc8723b1Ant.c
+--- linux/3rdparty/rtl8723bs.old/hal/HalBtc8723b1Ant.c 2015-05-10 14:36:05.684668079 +0300
++++ linux/3rdparty/rtl8723bs/hal/HalBtc8723b1Ant.c 2015-05-07 17:46:55.000000000 +0300
+@@ -3606,32 +3606,6 @@ EXhalbtc8723b1ant_BtInfoNotify(
+ }
+
+ void
+-EXhalbtc8723b1ant_RfStatusNotify(
+- IN PBTC_COEXIST pBtCoexist,
+- IN u1Byte type
+- )
+-{
+- BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], RF Status notify\n"));
+-
+- if(BTC_RF_ON == type)
+- {
+- BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], RF is turned ON!!\n"));
+- pBtCoexist->bStopCoexDm = false;
+- }
+- else if(BTC_RF_OFF == type)
+- {
+- BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], RF is turned OFF!!\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);
+- pBtCoexist->bStopCoexDm = true;
+- }
+-}
+-
+-void
+ EXhalbtc8723b1ant_HaltNotify(
+ IN PBTC_COEXIST pBtCoexist
+ )
+@@ -3681,19 +3655,6 @@ EXhalbtc8723b1ant_PnpNotify(
+ }
+
+ void
+-EXhalbtc8723b1ant_CoexDmReset(
+- IN PBTC_COEXIST pBtCoexist
+- )
+-{
+- BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], *****************Coex DM Reset*****************\n"));
+-
+- halbtc8723b1ant_InitHwConfig(pBtCoexist, false, false);
+- //pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x1, 0xfffff, 0x0);
+- //pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x2, 0xfffff, 0x0);
+- halbtc8723b1ant_InitCoexDm(pBtCoexist);
+-}
+-
+-void
+ EXhalbtc8723b1ant_Periodical(
+ IN PBTC_COEXIST pBtCoexist
+ )
+diff -Nurp linux/3rdparty/rtl8723bs.old/hal/HalBtc8723b1Ant.h linux/3rdparty/rtl8723bs/hal/HalBtc8723b1Ant.h
+--- linux/3rdparty/rtl8723bs.old/hal/HalBtc8723b1Ant.h 2015-05-10 14:36:05.684668079 +0300
++++ linux/3rdparty/rtl8723bs/hal/HalBtc8723b1Ant.h 2015-05-07 17:46:55.000000000 +0300
+@@ -213,11 +213,6 @@ EXhalbtc8723b1ant_BtInfoNotify(
+ IN u1Byte length
+ );
+ void
+-EXhalbtc8723b1ant_RfStatusNotify(
+- IN PBTC_COEXIST pBtCoexist,
+- IN u1Byte type
+- );
+-void
+ EXhalbtc8723b1ant_HaltNotify(
+ IN PBTC_COEXIST pBtCoexist
+ );
+@@ -227,10 +222,6 @@ EXhalbtc8723b1ant_PnpNotify(
+ IN u1Byte pnpState
+ );
+ void
+-EXhalbtc8723b1ant_CoexDmReset(
+- IN PBTC_COEXIST pBtCoexist
+- );
+-void
+ EXhalbtc8723b1ant_Periodical(
+ IN PBTC_COEXIST pBtCoexist
+ );
+diff -Nurp linux/3rdparty/rtl8723bs.old/hal/hal_btcoex.c linux/3rdparty/rtl8723bs/hal/hal_btcoex.c
+--- linux/3rdparty/rtl8723bs.old/hal/hal_btcoex.c 2015-05-10 14:36:05.687668113 +0300
++++ linux/3rdparty/rtl8723bs/hal/hal_btcoex.c 2015-05-07 17:46:55.000000000 +0300
+@@ -108,7 +108,7 @@ static void DBG_BT_INFO_INIT(PBTCDBGINFO
+ void DBG_BT_INFO(u8 *dbgmsg)
+ {
+ PBTCDBGINFO pinfo;
+- u32 msglen, buflen;
++ u32 msglen;
+ u8 *pbuf;
+
+
+@@ -218,7 +218,6 @@ static void halbtcoutsrc_LeaveLowPower(P
+ {
+ PADAPTER padapter;
+ PHAL_DATA_TYPE pHalData;
+- struct pwrctrl_priv *pwrctrl;
+ s32 ready;
+ unsigned long stime;
+ unsigned long utime;
+@@ -227,7 +226,6 @@ static void halbtcoutsrc_LeaveLowPower(P
+
+ padapter = pBtCoexist->Adapter;
+ pHalData = GET_HAL_DATA(padapter);
+- pwrctrl = adapter_to_pwrctl(padapter);
+ ready = _FAIL;
+ #ifdef LPS_RPWM_WAIT_MS
+ timeout = LPS_RPWM_WAIT_MS;
+@@ -373,7 +371,6 @@ static u32 halbtcoutsrc_GetWifiLinkStatu
+
+
+ padapter = pBtCoexist->Adapter;
+- retVal = 0;
+ portConnectedStatus = 0;
+ numOfConnectedPort = 0;
+
+@@ -391,10 +388,6 @@ static u32 halbtcoutsrc_GetWifiLinkStatu
+
+ static u32 halbtcoutsrc_GetBtPatchVer(PBTC_COEXIST pBtCoexist)
+ {
+- u16 btRealFwVer = 0x0;
+- u8 btFwVer = 0x0;
+- u8 cnt = 0;
+-
+ return pBtCoexist->btInfo.btRealFwVer;
+ }
+
+@@ -417,8 +410,6 @@ static u8 halbtcoutsrc_GetWifiScanAPNum(
+ struct mlme_ext_priv *pmlmeext;
+ static u8 scan_AP_num = 0;
+
+-
+- pmlmepriv = &padapter->mlmepriv;
+ pmlmeext = &padapter->mlmeextpriv;
+
+ if (GLBtcWiFiInScanState == false) {
+@@ -437,7 +428,6 @@ static u8 halbtcoutsrc_Get(void *pBtcCon
+ PADAPTER padapter;
+ PHAL_DATA_TYPE pHalData;
+ struct mlme_ext_priv *mlmeext;
+- u8 bSoftApExist, bVwifiExist;
+ u8 *pu8;
+ s32 *pS4Tmp;
+ u32 *pU4Tmp;
+@@ -452,8 +442,6 @@ static u8 halbtcoutsrc_Get(void *pBtcCon
+ padapter = pBtCoexist->Adapter;
+ pHalData = GET_HAL_DATA(padapter);
+ mlmeext = &padapter->mlmeextpriv;
+- bSoftApExist = false;
+- bVwifiExist = false;
+ pu8 = (u8*)pOutBuf;
+ pS4Tmp = (s32*)pOutBuf;
+ pU4Tmp = (u32*)pOutBuf;
+@@ -1011,7 +999,6 @@ static void halbtcoutsrc_DisplayDbgMsg(v
+ static u8 EXhalbtcoutsrc_BindBtCoexWithAdapter(void *padapter)
+ {
+ PBTC_COEXIST pBtCoexist=&GLBtCoexist;
+- u1Byte antNum=2, chipType;
+
+ if(pBtCoexist->bBinded)
+ return false;
+@@ -1307,20 +1294,6 @@ void EXhalbtcoutsrc_BtInfoNotify(PBTC_CO
+ // halbtcoutsrc_NormalLowPower(pBtCoexist);
+ }
+
+-void
+-EXhalbtcoutsrc_RfStatusNotify(
+- IN PBTC_COEXIST pBtCoexist,
+- IN u1Byte type
+- )
+-{
+- if(!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist))
+- return;
+- pBtCoexist->statistics.cntRfStatusNotify++;
+-
+- if(pBtCoexist->boardInfo.btdmAntNum == 1)
+- EXhalbtc8723b1ant_RfStatusNotify(pBtCoexist, type);
+-}
+-
+ void EXhalbtcoutsrc_HaltNotify(PBTC_COEXIST pBtCoexist)
+ {
+ if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist))
+@@ -1334,18 +1307,6 @@ void EXhalbtcoutsrc_HaltNotify(PBTC_COEX
+ pBtCoexist->bBinded = false;
+ }
+
+-static void EXhalbtcoutsrc_SwitchBtTRxMask(PBTC_COEXIST pBtCoexist)
+-{
+- if (pBtCoexist->boardInfo.btdmAntNum == 2)
+- {
+- halbtcoutsrc_SetBtReg(pBtCoexist, 0, 0x3c, 0x01); //BT goto standby while GNT_BT 1-->0
+- }
+- else if (pBtCoexist->boardInfo.btdmAntNum == 1)
+- {
+- halbtcoutsrc_SetBtReg(pBtCoexist, 0, 0x3c, 0x15); //BT goto standby while GNT_BT 1-->0
+- }
+-}
+-
+ void EXhalbtcoutsrc_PnpNotify(PBTC_COEXIST pBtCoexist, u8 pnpState)
+ {
+ if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist))
+@@ -1362,27 +1323,6 @@ void EXhalbtcoutsrc_PnpNotify(PBTC_COEXI
+ EXhalbtc8723b2ant_PnpNotify(pBtCoexist,pnpState);
+ }
+
+-void EXhalbtcoutsrc_CoexDmSwitch(PBTC_COEXIST pBtCoexist)
+-{
+- if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist))
+- return;
+- pBtCoexist->statistics.cntCoexDmSwitch++;
+-
+- halbtcoutsrc_LeaveLowPower(pBtCoexist);
+-
+- if (pBtCoexist->boardInfo.btdmAntNum == 1)
+- {
+- pBtCoexist->bStopCoexDm = true;
+- EXhalbtc8723b1ant_CoexDmReset(pBtCoexist);
+- EXhalbtcoutsrc_SetAntNum(BT_COEX_ANT_TYPE_DETECTED, 2);
+- EXhalbtc8723b2ant_InitHwConfig(pBtCoexist, false);
+- EXhalbtc8723b2ant_InitCoexDm(pBtCoexist);
+- pBtCoexist->bStopCoexDm = false;
+- }
+-
+- halbtcoutsrc_NormalLowPower(pBtCoexist);
+-}
+-
+ void EXhalbtcoutsrc_Periodical(PBTC_COEXIST pBtCoexist)
+ {
+ if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist))
+@@ -1401,51 +1341,6 @@ void EXhalbtcoutsrc_Periodical(PBTC_COEX
+ // halbtcoutsrc_NormalLowPower(pBtCoexist);
+ }
+
+-void EXhalbtcoutsrc_DbgControl(PBTC_COEXIST pBtCoexist, u8 opCode, u8 opLen, u8 *pData)
+-{
+- if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist))
+- return;
+-
+- pBtCoexist->statistics.cntDbgCtrl++;
+-
+- // This function doesn't be called yet,
+- // default no need to leave low power to avoid deadlock
+-// halbtcoutsrc_LeaveLowPower(pBtCoexist);
+-
+-// halbtcoutsrc_NormalLowPower(pBtCoexist);
+-}
+-
+-void EXhalbtcoutsrc_UpdateMinBtRssi(s8 btRssi)
+-{
+- PBTC_COEXIST pBtCoexist = &GLBtCoexist;
+-
+- if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist))
+- return;
+-
+- pBtCoexist->stackInfo.minBtRssi = btRssi;
+-}
+-
+-void EXhalbtcoutsrc_SetHciVersion(u16 hciVersion)
+-{
+- PBTC_COEXIST pBtCoexist = &GLBtCoexist;
+-
+- if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist))
+- return;
+-
+- pBtCoexist->stackInfo.hciVersion = hciVersion;
+-}
+-
+-void EXhalbtcoutsrc_SetBtPatchVersion(u16 btHciVersion, u16 btPatchVersion)
+-{
+- PBTC_COEXIST pBtCoexist = &GLBtCoexist;
+-
+- if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist))
+- return;
+-
+- pBtCoexist->btInfo.btRealFwVer = btPatchVersion;
+- pBtCoexist->btInfo.btHciVer = btHciVersion;
+-}
+-
+ void EXhalbtcoutsrc_SetChipType(u8 chipType)
+ {
+ GLBtCoexist.boardInfo.btChipType = BTC_CHIP_RTL8723B;
+@@ -1546,15 +1441,6 @@ void hal_btcoex_SetChipType(PADAPTER pad
+ EXhalbtcoutsrc_SetChipType(chipType);
+ }
+
+-u8 hal_btcoex_GetChipType(PADAPTER padapter)
+-{
+- PHAL_DATA_TYPE pHalData;
+-
+-
+- pHalData = GET_HAL_DATA(padapter);
+- return pHalData->bt_coexist.btChipType;
+-}
+-
+ void hal_btcoex_SetPgAntNum(PADAPTER padapter, u8 antNum)
+ {
+ PHAL_DATA_TYPE pHalData;
+@@ -1566,16 +1452,6 @@ void hal_btcoex_SetPgAntNum(PADAPTER pad
+ EXhalbtcoutsrc_SetAntNum(BT_COEX_ANT_TYPE_PG, antNum);
+ }
+
+-u8 hal_btcoex_GetPgAntNum(PADAPTER padapter)
+-{
+- PHAL_DATA_TYPE pHalData;
+-
+-
+- pHalData = GET_HAL_DATA(padapter);
+-
+- return pHalData->bt_coexist.btTotalAntNum;
+-}
+-
+ void hal_btcoex_SetSingleAntPath(PADAPTER padapter, u8 singleAntPath)
+ {
+ EXhalbtcoutsrc_SetSingleAntPath(singleAntPath);
+@@ -1666,11 +1542,6 @@ void hal_btcoex_HaltNotify(PADAPTER pada
+ EXhalbtcoutsrc_HaltNotify(&GLBtCoexist);
+ }
+
+-void hal_btcoex_SwitchBtTRxMask(PADAPTER padapter)
+-{
+- EXhalbtcoutsrc_SwitchBtTRxMask(&GLBtCoexist);
+-}
+-
+ void hal_btcoex_Hanlder(PADAPTER padapter)
+ {
+ EXhalbtcoutsrc_Periodical(&GLBtCoexist);
+@@ -1681,27 +1552,11 @@ s32 hal_btcoex_IsBTCoexCtrlAMPDUSize(PAD
+ return (s32)GLBtCoexist.btInfo.bBtCtrlAggBufSize;
+ }
+
+-u32 hal_btcoex_GetAMPDUSize(PADAPTER padapter)
+-{
+- return (u32)GLBtCoexist.btInfo.aggBufSize;
+-}
+-
+ void hal_btcoex_SetManualControl(PADAPTER padapter, u8 bmanual)
+ {
+ GLBtCoexist.bManualControl = bmanual;
+ }
+
+-u8 hal_btcoex_1Ant(PADAPTER padapter)
+-{
+- if (hal_btcoex_IsBtExist(padapter) == false)
+- return false;
+-
+- if (GLBtCoexist.boardInfo.btdmAntNum == 1)
+- return true;
+-
+- return false;
+-}
+-
+ u8 hal_btcoex_IsBtControlLps(PADAPTER padapter)
+ {
+ if (hal_btcoex_IsBtExist(padapter) == false)
+@@ -1796,7 +1651,6 @@ u32 hal_btcoex_GetDBG(PADAPTER padapter,
+ if ((NULL == pStrBuf) || (0 == bufSize))
+ return 0;
+
+- count = 0;
+ pstr = pStrBuf;
+ leftSize = bufSize;
+ // DBG_871X(FUNC_ADPT_FMT ": bufsize=%d\n", FUNC_ADPT_ARG(padapter), bufSize);
+@@ -1828,13 +1682,13 @@ u32 hal_btcoex_GetDBG(PADAPTER padapter,
+ pstr += count;
+ leftSize -= count;
+ count = rtw_sprintf(pstr, leftSize, "\tbit[0]=%d for INTF_INIT\n",
+- GLBtcDbgType[BTC_MSG_INTERFACE]&INTF_INIT?1:0);
++ (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);
++ (GLBtcDbgType[BTC_MSG_INTERFACE]&INTF_NOTIFY)?1:0);
+ if ((count < 0) || (count >= leftSize))
+ goto exit;
+ pstr += count;
+@@ -1846,61 +1700,61 @@ u32 hal_btcoex_GetDBG(PADAPTER padapter,
+ 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);
++ (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);
++ (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);
++ (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);
++ (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);
++ (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);
++ (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);
++ (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);
++ (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);
++ (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);
++ (GLBtcDbgType[BTC_MSG_ALGORITHM]&ALGO_TRACE_SW_EXEC)?1:0);
+ if ((count < 0) || (count >= leftSize))
+ goto exit;
+ pstr += count;
+@@ -1912,22 +1766,3 @@ exit:
+
+ return count;
+ }
+-
+-u8 hal_btcoex_IncreaseScanDeviceNum(PADAPTER padapter)
+-{
+- if (!hal_btcoex_IsBtExist(padapter))
+- return false;
+-
+- if (GLBtCoexist.btInfo.bIncreaseScanDevNum)
+- return true;
+-
+- return false;
+-}
+-
+-u8 hal_btcoex_IsBtLinkExist(PADAPTER padapter)
+-{
+- if (GLBtCoexist.btLinkInfo.bBtLinkExist)
+- return true;
+-
+- return false;
+-}
+diff -Nurp linux/3rdparty/rtl8723bs.old/hal/HalBtcOutSrc.h linux/3rdparty/rtl8723bs/hal/HalBtcOutSrc.h
+--- linux/3rdparty/rtl8723bs.old/hal/HalBtcOutSrc.h 2015-05-10 14:36:05.687668113 +0300
++++ linux/3rdparty/rtl8723bs/hal/HalBtcOutSrc.h 2015-05-07 17:46:55.000000000 +0300
+@@ -659,11 +659,6 @@ EXhalbtcoutsrc_BtInfoNotify(
+ IN u1Byte length
+ );
+ void
+-EXhalbtcoutsrc_RfStatusNotify(
+- IN PBTC_COEXIST pBtCoexist,
+- IN u1Byte type
+- );
+-void
+ EXhalbtcoutsrc_HaltNotify(
+ IN PBTC_COEXIST pBtCoexist
+ );
+@@ -673,34 +668,10 @@ EXhalbtcoutsrc_PnpNotify(
+ IN u1Byte pnpState
+ );
+ void
+-EXhalbtcoutsrc_CoexDmSwitch(
+- IN PBTC_COEXIST pBtCoexist
+- );
+-void
+ EXhalbtcoutsrc_Periodical(
+ IN PBTC_COEXIST pBtCoexist
+ );
+ void
+-EXhalbtcoutsrc_DbgControl(
+- IN PBTC_COEXIST pBtCoexist,
+- IN u1Byte opCode,
+- IN u1Byte opLen,
+- IN pu1Byte pData
+- );
+-void
+-EXhalbtcoutsrc_SetHciVersion(
+- IN u2Byte hciVersion
+- );
+-void
+-EXhalbtcoutsrc_SetBtPatchVersion(
+- IN u2Byte btHciVersion,
+- IN u2Byte btPatchVersion
+- );
+-void
+-EXhalbtcoutsrc_UpdateMinBtRssi(
+- IN s8 btRssi
+- );
+-void
+ EXhalbtcoutsrc_SetChipType(
+ IN u1Byte chipType
+ );
+diff -Nurp linux/3rdparty/rtl8723bs.old/hal/hal_com.c linux/3rdparty/rtl8723bs/hal/hal_com.c
+--- linux/3rdparty/rtl8723bs.old/hal/hal_com.c 2015-05-10 14:36:05.688668124 +0300
++++ linux/3rdparty/rtl8723bs/hal/hal_com.c 2015-05-07 17:46:55.000000000 +0300
+@@ -29,7 +29,7 @@ u8 rtw_hal_data_init(_adapter *padapter)
+ if(is_primary_adapter(padapter)) //if(padapter->isprimary)
+ {
+ padapter->hal_data_sz = sizeof(HAL_DATA_TYPE);
+- padapter->HalData = rtw_zvmalloc(padapter->hal_data_sz);
++ padapter->HalData = vzalloc(padapter->hal_data_sz);
+ if(padapter->HalData == NULL){
+ DBG_8192C("cant not alloc memory for HAL DATA \n");
+ return _FAIL;
+@@ -47,7 +47,7 @@ void rtw_hal_data_deinit(_adapter *padap
+ #ifdef CONFIG_LOAD_PHY_PARA_FROM_FILE
+ phy_free_filebuf(padapter);
+ #endif
+- rtw_vmfree(padapter->HalData, padapter->hal_data_sz);
++ vfree(padapter->HalData);
+ padapter->HalData = NULL;
+ padapter->hal_data_sz = 0;
+ }
+@@ -165,10 +165,8 @@ HAL_IsLegalChannel(
+ bool bLegalChannel = true;
+
+ if (Channel > 14) {
+- if(IsSupported5G(Adapter->registrypriv.wireless_mode) == false) {
+- bLegalChannel = false;
+- DBG_871X("Channel > 14 but wireless_mode do not support 5G\n");
+- }
++ bLegalChannel = false;
++ DBG_871X("Channel > 14 but wireless_mode do not support 5G\n");
+ } else if ((Channel <= 14) && (Channel >=1)){
+ if(IsSupported24G(Adapter->registrypriv.wireless_mode) == false) {
+ bLegalChannel = false;
+@@ -577,20 +575,6 @@ void c2h_evt_clear(_adapter *adapter)
+ rtw_write8(adapter, REG_C2HEVT_CLEAR, C2H_EVT_HOST_CLOSE);
+ }
+
+-s32 c2h_evt_read(_adapter *adapter, u8 *buf)
+-{
+- s32 ret = _FAIL;
+- struct c2h_evt_hdr *c2h_evt;
+- int i;
+- u8 trigger;
+-
+- if (buf == NULL)
+- goto exit;
+-
+-exit:
+- return ret;
+-}
+-
+ /*
+ * C2H event format:
+ * Field TRIGGER CMD_LEN CONTENT CMD_SEQ CMD_ID
+@@ -725,14 +709,10 @@ _func_enter_;
+ break;
+ case HW_VAR_SEC_CFG:
+ {
+- #if defined(DYNAMIC_CAMID_ALLOC)
+ u16 reg_scr;
+
+ reg_scr = rtw_read16(adapter, REG_SECCFG);
+ rtw_write16(adapter, REG_SECCFG, reg_scr|SCR_CHK_KEYID|SCR_RxDecEnable|SCR_TxEncEnable);
+- #else
+- rtw_write8(adapter, REG_SECCFG, *((u8*)val));
+- #endif
+ }
+ break;
+ case HW_VAR_SEC_DK_CFG:
+@@ -1019,10 +999,10 @@ void SetHalODMVar(
+ }
+ else{
+ DBG_8192C("### Clean STA_(%d) info ###\n",psta->mac_id);
+- //_enter_critical_bh(&pHalData->odm_stainfo_lock, &irqL);
++ //spin_lock_bh(&pHalData->odm_stainfo_lock);
+ ODM_CmnInfoPtrArrayHook(podmpriv, ODM_CMNINFO_STA_STATUS,psta->mac_id,NULL);
+
+- //_exit_critical_bh(&pHalData->odm_stainfo_lock, &irqL);
++ //spin_unlock_bh(&pHalData->odm_stainfo_lock);
+ }
+ }
+ break;
+diff -Nurp linux/3rdparty/rtl8723bs.old/hal/hal_com_phycfg.c linux/3rdparty/rtl8723bs/hal/hal_com_phycfg.c
+--- linux/3rdparty/rtl8723bs.old/hal/hal_com_phycfg.c 2015-05-10 14:36:05.690668146 +0300
++++ linux/3rdparty/rtl8723bs/hal/hal_com_phycfg.c 2015-05-07 17:46:55.000000000 +0300
+@@ -22,50 +22,6 @@
+ #include
+ #include
+
+-
+-//
+-// Description:
+-// Map Tx power index into dBm according to
+-// current HW model, for example, RF and PA, and
+-// current wireless mode.
+-// By Bruce, 2008-01-29.
+-//
+-s32
+-phy_TxPwrIdxToDbm(
+- IN PADAPTER Adapter,
+- IN WIRELESS_MODE WirelessMode,
+- IN u8 TxPwrIdx
+- )
+-{
+- s32 Offset = 0;
+- s32 PwrOutDbm = 0;
+-
+- //
+- // Tested by MP, we found that CCK Index 0 equals to -7dbm, OFDM legacy equals to -8dbm.
+- // Note:
+- // The mapping may be different by different NICs. Do not use this formula for what needs accurate result.
+- // By Bruce, 2008-01-29.
+- //
+- switch(WirelessMode)
+- {
+- case WIRELESS_MODE_B:
+- Offset = -7;
+- break;
+-
+- case WIRELESS_MODE_G:
+- case WIRELESS_MODE_N_24G:
+- Offset = -8;
+- break;
+-
+- default: //for MacOSX compiler warning
+- break;
+- }
+-
+- PwrOutDbm = TxPwrIdx / 2 + Offset; // Discard the decimal part.
+-
+- return PwrOutDbm;
+-}
+-
+ u8
+ PHY_GetTxPowerByRateBase(
+ IN PADAPTER Adapter,
+@@ -272,7 +228,7 @@ phy_StoreTxPowerByRateBase(
+ IN PADAPTER pAdapter
+ )
+ {
+- u8 path = 0, base = 0, index = 0;
++ u8 path, base;
+
+ //DBG_871X( "===>%s\n", __FUNCTION__ );
+
+@@ -399,9 +355,8 @@ PHY_GetRateValuesOfTxPowerByRate(
+ )
+ {
+ HAL_DATA_TYPE *pHalData = GET_HAL_DATA( pAdapter );
+- PDM_ODM_T pDM_Odm = &pHalData->odmpriv;
+- u8 index = 0, i = 0;
+-
++ u8 i = 0;
++
+ switch ( RegAddr )
+ {
+ case rTxAGC_A_Rate18_06:
+@@ -875,7 +830,7 @@ PHY_InitTxPowerByRate(
+ )
+ {
+ HAL_DATA_TYPE *pHalData = GET_HAL_DATA(pAdapter);
+- u8 band = 0, rfPath = 0, TxNum = 0, rate = 0, i = 0, j = 0;
++ u8 band, rfPath, TxNum, rate;
+
+ for ( band = BAND_ON_2_4G; band <= BAND_ON_5G; ++band )
+ for ( rfPath = 0; rfPath < TX_PWR_BY_RATE_NUM_RF; ++rfPath )
+@@ -921,10 +876,8 @@ phy_ConvertTxPowerByRateInDbmToRelativeV
+ IN PADAPTER pAdapter
+ )
+ {
+- HAL_DATA_TYPE *pHalData = GET_HAL_DATA( pAdapter );
+ u8 base = 0, i = 0, value = 0,
+- band = 0, path = 0, txNum = 0, index = 0,
+- startIndex = 0, endIndex = 0;
++ band = 0, path = 0, txNum = 0;
+ u8 cckRates[4] = {MGN_1M, MGN_2M, MGN_5_5M, MGN_11M},
+ ofdmRates[8] = {MGN_6M, MGN_9M, MGN_12M, MGN_18M, MGN_24M, MGN_36M, MGN_48M, MGN_54M},
+ mcs0_7Rates[8] = {MGN_MCS0, MGN_MCS1, MGN_MCS2, MGN_MCS3, MGN_MCS4, MGN_MCS5, MGN_MCS6, MGN_MCS7},
+@@ -1024,8 +977,6 @@ PHY_TxPowerByRateConfiguration(
+ IN PADAPTER pAdapter
+ )
+ {
+- HAL_DATA_TYPE *pHalData = GET_HAL_DATA( pAdapter);
+-
+ phy_StoreTxPowerByRateBase( pAdapter );
+ phy_ConvertTxPowerByRateInDbmToRelativeValues( pAdapter );
+ }
+@@ -1166,7 +1117,6 @@ PHY_GetTxPowerIndexBase(
+ )
+ {
+ PHAL_DATA_TYPE pHalData = GET_HAL_DATA(pAdapter);
+- PDM_ODM_T pDM_Odm = &pHalData->odmpriv;
+ u8 i = 0; //default set to 1S
+ u8 txPower = 0;
+ u8 chnlIdx = (Channel-1);
+@@ -1475,7 +1425,7 @@ PHY_GetTxPowerByRate(
+ )
+ {
+ HAL_DATA_TYPE *pHalData = GET_HAL_DATA( pAdapter );
+- s8 value = 0, limit = 0;
++ s8 value = 0;
+ u8 rateIndex = PHY_GetRateIndexOfTxPowerByRate( Rate );
+
+ if ( ( pAdapter->registrypriv.RegEnableTxPowerByRate == 2 && pHalData->EEPROMRegulatory == 2 ) ||
+@@ -1925,10 +1875,8 @@ PHY_ConvertTxPowerLimitToPowerIndex(
+ )
+ {
+ HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);
+- u8 BW40PwrBasedBm2_4G = 0x2E, BW40PwrBasedBm5G = 0x2E;
++ u8 BW40PwrBasedBm2_4G = 0x2E;
+ u8 regulation, bw, channel, rateSection;
+- u8 baseIndex2_4G;
+- u8 baseIndex5G;
+ s8 tempValue = 0, tempPwrLmt = 0;
+ u8 rfPath = 0;
+
+@@ -2121,11 +2069,7 @@ PHY_GetTxPowerIndex(
+ IN u8 Channel
+ )
+ {
+- u8 txPower = 0x3E;
+-
+- txPower = PHY_GetTxPowerIndex_8723B(pAdapter, RFPath, Rate, BandWidth, Channel);
+-
+- return txPower;
++ return PHY_GetTxPowerIndex_8723B(pAdapter, RFPath, Rate, BandWidth, Channel);
+ }
+
+ void
+@@ -2340,7 +2284,7 @@ phy_ConfigMACWithParaFile(
+ if (rlen > 0)
+ {
+ rtStatus = _SUCCESS;
+- pHalData->mac_reg = rtw_zvmalloc(rlen);
++ pHalData->mac_reg = vzalloc(rlen);
+ if(pHalData->mac_reg) {
+ memcpy(pHalData->mac_reg, pHalData->para_file_buf, rlen);
+ pHalData->mac_reg_len = rlen;
+@@ -2439,7 +2383,7 @@ phy_ConfigBBWithParaFile(
+ if (rlen > 0)
+ {
+ rtStatus = _SUCCESS;
+- pBuf = rtw_zvmalloc(rlen);
++ pBuf = vzalloc(rlen);
+ if(pBuf) {
+ memcpy(pBuf, pHalData->para_file_buf, rlen);
+ *pBufLen = rlen;
+@@ -2888,7 +2832,7 @@ phy_ConfigBBWithPgParaFile(
+ if (rlen > 0)
+ {
+ rtStatus = _SUCCESS;
+- pHalData->bb_phy_reg_pg = rtw_zvmalloc(rlen);
++ pHalData->bb_phy_reg_pg = vzalloc(rlen);
+ if(pHalData->bb_phy_reg_pg) {
+ memcpy(pHalData->bb_phy_reg_pg, pHalData->para_file_buf, rlen);
+ pHalData->bb_phy_reg_pg_len = rlen;
+@@ -2968,7 +2912,7 @@ PHY_ConfigRFWithParaFile(
+ if (rlen > 0)
+ {
+ rtStatus = _SUCCESS;
+- pBuf = rtw_zvmalloc(rlen);
++ pBuf = vzalloc(rlen);
+ if(pBuf) {
+ memcpy(pBuf, pHalData->para_file_buf, rlen);
+ *pBufLen = rlen;
+@@ -3242,7 +3186,7 @@ PHY_ConfigRFWithTxPwrTrackParaFile(
+ if (rlen > 0)
+ {
+ rtStatus = _SUCCESS;
+- pHalData->rf_tx_pwr_track = rtw_zvmalloc(rlen);
++ pHalData->rf_tx_pwr_track = vzalloc(rlen);
+ if(pHalData->rf_tx_pwr_track) {
+ memcpy(pHalData->rf_tx_pwr_track, pHalData->para_file_buf, rlen);
+ pHalData->rf_tx_pwr_track_len = rlen;
+@@ -3591,7 +3535,7 @@ PHY_ConfigRFWithPowerLimitTableParaFile(
+ if (rlen > 0)
+ {
+ rtStatus = _SUCCESS;
+- pHalData->rf_tx_pwr_lmt = rtw_zvmalloc(rlen);
++ pHalData->rf_tx_pwr_lmt = vzalloc(rlen);
+ if(pHalData->rf_tx_pwr_lmt) {
+ memcpy(pHalData->rf_tx_pwr_lmt, pHalData->para_file_buf, rlen);
+ pHalData->rf_tx_pwr_lmt_len = rlen;
+@@ -3631,23 +3575,23 @@ void phy_free_filebuf(_adapter *padapter
+ HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
+
+ if(pHalData->mac_reg)
+- rtw_vmfree(pHalData->mac_reg, pHalData->mac_reg_len);
++ vfree(pHalData->mac_reg);
+ if(pHalData->bb_phy_reg)
+- rtw_vmfree(pHalData->bb_phy_reg, pHalData->bb_phy_reg_len);
++ vfree(pHalData->bb_phy_reg);
+ if(pHalData->bb_agc_tab)
+- rtw_vmfree(pHalData->bb_agc_tab, pHalData->bb_agc_tab_len);
++ vfree(pHalData->bb_agc_tab);
+ if(pHalData->bb_phy_reg_pg)
+- rtw_vmfree(pHalData->bb_phy_reg_pg, pHalData->bb_phy_reg_pg_len);
++ vfree(pHalData->bb_phy_reg_pg);
+ if(pHalData->bb_phy_reg_mp)
+- rtw_vmfree(pHalData->bb_phy_reg_mp, pHalData->bb_phy_reg_mp_len);
++ vfree(pHalData->bb_phy_reg_mp);
+ if(pHalData->rf_radio_a)
+- rtw_vmfree(pHalData->rf_radio_a, pHalData->rf_radio_a_len);
++ vfree(pHalData->rf_radio_a);
+ if(pHalData->rf_radio_b)
+- rtw_vmfree(pHalData->rf_radio_b, pHalData->rf_radio_b_len);
++ vfree(pHalData->rf_radio_b);
+ if(pHalData->rf_tx_pwr_track)
+- rtw_vmfree(pHalData->rf_tx_pwr_track, pHalData->rf_tx_pwr_track_len);
++ vfree(pHalData->rf_tx_pwr_track);
+ if(pHalData->rf_tx_pwr_lmt)
+- rtw_vmfree(pHalData->rf_tx_pwr_lmt, pHalData->rf_tx_pwr_lmt_len);
++ vfree(pHalData->rf_tx_pwr_lmt);
+
+ }
+
+diff -Nurp linux/3rdparty/rtl8723bs.old/hal/HalHWImg8723B_BB.c linux/3rdparty/rtl8723bs/hal/HalHWImg8723B_BB.c
+--- linux/3rdparty/rtl8723bs.old/hal/HalHWImg8723B_BB.c 2015-05-10 14:36:05.690668146 +0300
++++ linux/3rdparty/rtl8723bs/hal/HalHWImg8723B_BB.c 2015-05-07 17:46:55.000000000 +0300
+@@ -313,12 +313,6 @@ ODM_ReadAndConfig_MP_8723B_AGC_TAB(
+ }
+ }
+
+-u4Byte
+-ODM_GetVersion_MP_8723B_AGC_TAB(void)
+-{
+- return 11;
+-}
+-
+ /******************************************************************************
+ * PHY_REG.TXT
+ ******************************************************************************/
+@@ -588,12 +582,6 @@ ODM_ReadAndConfig_MP_8723B_PHY_REG(
+ }
+ }
+
+-u4Byte
+-ODM_GetVersion_MP_8723B_PHY_REG(void)
+-{
+- return 11;
+-}
+-
+ /******************************************************************************
+ * PHY_REG_PG.TXT
+ ******************************************************************************/
+diff -Nurp linux/3rdparty/rtl8723bs.old/hal/HalHWImg8723B_BB.h linux/3rdparty/rtl8723bs/hal/HalHWImg8723B_BB.h
+--- linux/3rdparty/rtl8723bs.old/hal/HalHWImg8723B_BB.h 2015-05-10 14:36:05.690668146 +0300
++++ linux/3rdparty/rtl8723bs/hal/HalHWImg8723B_BB.h 2015-05-07 17:46:55.000000000 +0300
+@@ -30,7 +30,6 @@ void
+ ODM_ReadAndConfig_MP_8723B_AGC_TAB( // TC: Test Chip, MP: MP Chip
+ IN PDM_ODM_T pDM_Odm
+ );
+-u4Byte ODM_GetVersion_MP_8723B_AGC_TAB(void);
+
+ /******************************************************************************
+ * PHY_REG.TXT
+@@ -40,7 +39,6 @@ void
+ ODM_ReadAndConfig_MP_8723B_PHY_REG( // TC: Test Chip, MP: MP Chip
+ IN PDM_ODM_T pDM_Odm
+ );
+-u4Byte ODM_GetVersion_MP_8723B_PHY_REG(void);
+
+ /******************************************************************************
+ * PHY_REG_PG.TXT
+diff -Nurp linux/3rdparty/rtl8723bs.old/hal/HalHWImg8723B_MAC.c linux/3rdparty/rtl8723bs/hal/HalHWImg8723B_MAC.c
+--- linux/3rdparty/rtl8723bs.old/hal/HalHWImg8723B_MAC.c 2015-05-10 14:36:05.699668247 +0300
++++ linux/3rdparty/rtl8723bs/hal/HalHWImg8723B_MAC.c 2015-05-07 17:46:55.000000000 +0300
+@@ -284,9 +284,3 @@ ODM_ReadAndConfig_MP_8723B_MAC_REG(
+ }
+ }
+ }
+-
+-u4Byte
+-ODM_GetVersion_MP_8723B_MAC_REG(void)
+-{
+- return 11;
+-}
+diff -Nurp linux/3rdparty/rtl8723bs.old/hal/HalHWImg8723B_MAC.h linux/3rdparty/rtl8723bs/hal/HalHWImg8723B_MAC.h
+--- linux/3rdparty/rtl8723bs.old/hal/HalHWImg8723B_MAC.h 2015-05-10 14:36:05.699668247 +0300
++++ linux/3rdparty/rtl8723bs/hal/HalHWImg8723B_MAC.h 2015-05-07 17:46:55.000000000 +0300
+@@ -30,6 +30,4 @@ void
+ ODM_ReadAndConfig_MP_8723B_MAC_REG( // TC: Test Chip, MP: MP Chip
+ IN PDM_ODM_T pDM_Odm
+ );
+-u4Byte ODM_GetVersion_MP_8723B_MAC_REG(void);
+-
+ #endif
+diff -Nurp linux/3rdparty/rtl8723bs.old/hal/HalHWImg8723B_RF.c linux/3rdparty/rtl8723bs/hal/HalHWImg8723B_RF.c
+--- linux/3rdparty/rtl8723bs.old/hal/HalHWImg8723B_RF.c 2015-05-10 14:36:05.700668257 +0300
++++ linux/3rdparty/rtl8723bs/hal/HalHWImg8723B_RF.c 2015-05-07 17:46:55.000000000 +0300
+@@ -306,34 +306,6 @@ ODM_ReadAndConfig_MP_8723B_RadioA(
+ }
+ }
+
+-u4Byte
+-ODM_GetVersion_MP_8723B_RadioA(void)
+-{
+- return 11;
+-}
+-
+-/******************************************************************************
+-* TxPowerTrack_AP.TXT
+-******************************************************************************/
+-
+-void
+-ODM_ReadAndConfig_MP_8723B_TxPowerTrack_AP(
+- IN PDM_ODM_T pDM_Odm
+- )
+-{
+-}
+-
+-/******************************************************************************
+-* TxPowerTrack_PCIE.TXT
+-******************************************************************************/
+-
+-void
+-ODM_ReadAndConfig_MP_8723B_TxPowerTrack_PCIE(
+- IN PDM_ODM_T pDM_Odm
+- )
+-{
+-}
+-
+ /******************************************************************************
+ * TxPowerTrack_SDIO.TXT
+ ******************************************************************************/
+@@ -394,17 +366,6 @@ ODM_ReadAndConfig_MP_8723B_TxPowerTrack_
+ }
+
+ /******************************************************************************
+-* TxPowerTrack_USB.TXT
+-******************************************************************************/
+-
+-void
+-ODM_ReadAndConfig_MP_8723B_TxPowerTrack_USB(
+- IN PDM_ODM_T pDM_Odm
+- )
+-{
+-}
+-
+-/******************************************************************************
+ * TXPWR_LMT.TXT
+ ******************************************************************************/
+
+diff -Nurp linux/3rdparty/rtl8723bs.old/hal/HalHWImg8723B_RF.h linux/3rdparty/rtl8723bs/hal/HalHWImg8723B_RF.h
+--- linux/3rdparty/rtl8723bs.old/hal/HalHWImg8723B_RF.h 2015-05-10 14:36:05.700668257 +0300
++++ linux/3rdparty/rtl8723bs/hal/HalHWImg8723B_RF.h 2015-05-07 17:46:55.000000000 +0300
+@@ -30,27 +30,6 @@ void
+ ODM_ReadAndConfig_MP_8723B_RadioA( // TC: Test Chip, MP: MP Chip
+ IN PDM_ODM_T pDM_Odm
+ );
+-u4Byte ODM_GetVersion_MP_8723B_RadioA(void);
+-
+-/******************************************************************************
+-* TxPowerTrack_AP.TXT
+-******************************************************************************/
+-
+-void
+-ODM_ReadAndConfig_MP_8723B_TxPowerTrack_AP( // TC: Test Chip, MP: MP Chip
+- IN PDM_ODM_T pDM_Odm
+-);
+-u4Byte ODM_GetVersion_MP_8723B_TxPowerTrack_AP(void);
+-
+-/******************************************************************************
+-* TxPowerTrack_PCIE.TXT
+-******************************************************************************/
+-
+-void
+-ODM_ReadAndConfig_MP_8723B_TxPowerTrack_PCIE( // TC: Test Chip, MP: MP Chip
+- IN PDM_ODM_T pDM_Odm
+-);
+-u4Byte ODM_GetVersion_MP_8723B_TxPowerTrack_PCIE(void);
+
+ /******************************************************************************
+ * TxPowerTrack_SDIO.TXT
+@@ -63,16 +42,6 @@ ODM_ReadAndConfig_MP_8723B_TxPowerTrack_
+ u4Byte ODM_GetVersion_MP_8723B_TxPowerTrack_SDIO(void);
+
+ /******************************************************************************
+-* TxPowerTrack_USB.TXT
+-******************************************************************************/
+-
+-void
+-ODM_ReadAndConfig_MP_8723B_TxPowerTrack_USB( // TC: Test Chip, MP: MP Chip
+- IN PDM_ODM_T pDM_Odm
+-);
+-u4Byte ODM_GetVersion_MP_8723B_TxPowerTrack_USB(void);
+-
+-/******************************************************************************
+ * TXPWR_LMT.TXT
+ ******************************************************************************/
+
+diff -Nurp linux/3rdparty/rtl8723bs.old/hal/hal_intf.c linux/3rdparty/rtl8723bs/hal/hal_intf.c
+--- linux/3rdparty/rtl8723bs.old/hal/hal_intf.c 2015-05-10 14:36:05.700668257 +0300
++++ linux/3rdparty/rtl8723bs/hal/hal_intf.c 2015-05-07 17:46:55.000000000 +0300
+@@ -69,29 +69,6 @@ void rtw_hal_dm_deinit(_adapter *padapte
+ if(padapter->HalFunc.dm_deinit)
+ padapter->HalFunc.dm_deinit(padapter);
+ }
+-void rtw_hal_sw_led_init(_adapter *padapter)
+-{
+- if(padapter->HalFunc.InitSwLeds)
+- padapter->HalFunc.InitSwLeds(padapter);
+-}
+-
+-void rtw_hal_sw_led_deinit(_adapter *padapter)
+-{
+- if(padapter->HalFunc.DeInitSwLeds)
+- padapter->HalFunc.DeInitSwLeds(padapter);
+-}
+-
+-u32 rtw_hal_power_on(_adapter *padapter)
+-{
+- if(padapter->HalFunc.hal_power_on)
+- return padapter->HalFunc.hal_power_on(padapter);
+- return _FAIL;
+-}
+-void rtw_hal_power_off(_adapter *padapter)
+-{
+- if(padapter->HalFunc.hal_power_off)
+- padapter->HalFunc.hal_power_off(padapter);
+-}
+
+ static void rtw_hal_init_opmode(_adapter *padapter)
+ {
+@@ -136,8 +113,6 @@ uint rtw_hal_init(_adapter *padapter)
+ for (i = 0; iiface_nums; i++)
+ rtw_sec_restore_wep_key(dvobj->padapters[i]);
+
+- rtw_led_control(padapter, LED_CTL_POWER_ON);
+-
+ init_hw_mlme_ext(padapter);
+
+ rtw_bb_rf_gain_offset(padapter);
+@@ -164,7 +139,6 @@ _func_enter_;
+ status = padapter->HalFunc.hal_deinit(padapter);
+
+ if(status == _SUCCESS){
+- rtw_led_control(padapter, LED_CTL_POWER_OFF);
+ for (i = 0; iiface_nums; i++) {
+ padapter = dvobj->padapters[i];
+ padapter->hw_init_completed = false;
+@@ -261,41 +235,6 @@ void rtw_hal_clear_interrupt(_adapter *p
+ }
+ #endif
+
+-u32 rtw_hal_inirp_init(_adapter *padapter)
+-{
+- u32 rst = _FAIL;
+- if(padapter->HalFunc.inirp_init)
+- rst = padapter->HalFunc.inirp_init(padapter);
+- else
+- DBG_871X(" %s HalFunc.inirp_init is NULL!!!\n",__FUNCTION__);
+- return rst;
+-}
+-
+-u32 rtw_hal_inirp_deinit(_adapter *padapter)
+-{
+-
+- if(padapter->HalFunc.inirp_deinit)
+- return padapter->HalFunc.inirp_deinit(padapter);
+-
+- return _FAIL;
+-
+-}
+-
+-void rtw_hal_irp_reset(_adapter *padapter)
+-{
+- if(padapter->HalFunc.irp_reset)
+- padapter->HalFunc.irp_reset(padapter);
+- else
+- DBG_871X("%s: HalFunc.rtw_hal_irp_reset is NULL!\n", __FUNCTION__);
+-}
+-
+-u8 rtw_hal_intf_ps_func(_adapter *padapter,HAL_INTF_PS_FUNC efunc_id, u8* val)
+-{
+- if(padapter->HalFunc.interface_ps_func)
+- return padapter->HalFunc.interface_ps_func(padapter,efunc_id,val);
+- return _FAIL;
+-}
+-
+ s32 rtw_hal_xmitframe_enqueue(_adapter *padapter, struct xmit_frame *pxmitframe)
+ {
+ if(padapter->HalFunc.hal_xmitframe_enqueue)
+@@ -325,7 +264,6 @@ s32 rtw_hal_mgnt_xmit(_adapter *padapter
+ //pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+ //memcpy(pmgntframe->attrib.ra, pwlanhdr->addr1, ETH_ALEN);
+
+-#ifdef CONFIG_IEEE80211W
+ if(padapter->securitypriv.binstallBIPkey == true)
+ {
+ if(IS_MCAST(pmgntframe->attrib.ra))
+@@ -340,8 +278,7 @@ s32 rtw_hal_mgnt_xmit(_adapter *padapter
+ }
+ rtw_mgmt_xmitframe_coalesce(padapter, pmgntframe->pkt, pmgntframe);
+ }
+-#endif //CONFIG_IEEE80211W
+-
++
+ if(padapter->HalFunc.mgnt_xmit)
+ ret = padapter->HalFunc.mgnt_xmit(padapter, pmgntframe);
+ return ret;
+@@ -441,19 +378,6 @@ void rtw_hal_write_rfreg(_adapter *padap
+ padapter->HalFunc.write_rfreg(padapter, eRFPath, RegAddr, BitMask, Data);
+ }
+
+-s32 rtw_hal_interrupt_handler(_adapter *padapter)
+-{
+- if(padapter->HalFunc.interrupt_handler)
+- return padapter->HalFunc.interrupt_handler(padapter);
+- return _FAIL;
+-}
+-
+-void rtw_hal_set_bwmode(_adapter *padapter, CHANNEL_WIDTH Bandwidth, u8 Offset)
+-{
+- if(padapter->HalFunc.set_bwmode_handler)
+- padapter->HalFunc.set_bwmode_handler(padapter, Bandwidth, Offset);
+-}
+-
+ void rtw_hal_set_chan(_adapter *padapter, u8 channel)
+ {
+ if(padapter->HalFunc.set_channel_handler)
+@@ -466,18 +390,6 @@ void rtw_hal_set_chnl_bw(_adapter *padap
+ padapter->HalFunc.set_chnl_bw_handler(padapter, channel, Bandwidth, Offset40, Offset80);
+ }
+
+-void rtw_hal_set_tx_power_level(_adapter *padapter, u8 channel)
+-{
+- if(padapter->HalFunc.set_tx_power_level_handler)
+- padapter->HalFunc.set_tx_power_level_handler(padapter, channel);
+-}
+-
+-void rtw_hal_get_tx_power_level(_adapter *padapter, s32 *powerlevel)
+-{
+- if(padapter->HalFunc.get_tx_power_level_handler)
+- padapter->HalFunc.get_tx_power_level_handler(padapter, powerlevel);
+-}
+-
+ void rtw_hal_dm_watchdog(_adapter *padapter)
+ {
+ if(padapter->HalFunc.hal_dm_watchdog)
+diff -Nurp linux/3rdparty/rtl8723bs.old/hal/hal_phy.c linux/3rdparty/rtl8723bs/hal/hal_phy.c
+--- linux/3rdparty/rtl8723bs.old/hal/hal_phy.c 2015-05-10 14:36:05.700668257 +0300
++++ linux/3rdparty/rtl8723bs/hal/hal_phy.c 1970-01-01 02:00:00.000000000 +0200
+@@ -1,285 +0,0 @@
+-/******************************************************************************
+- *
+- * 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.
+- *
+- * 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.,
+- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+- *
+- *
+- ******************************************************************************/
+-#define _HAL_PHY_C_
+-
+-#include
+-
+-//================================================================================
+-// Constant.
+-//================================================================================
+-// 2008/11/20 MH For Debug only, RF
+-static RF_SHADOW_T RF_Shadow[RF6052_MAX_PATH][RF6052_MAX_REG];
+-
+-/**
+-* Function: PHY_CalculateBitShift
+-*
+-* OverView: Get shifted position of the BitMask
+-*
+-* Input:
+-* u4Byte BitMask,
+-*
+-* Output: none
+-* Return: u4Byte Return the shift bit bit position of the mask
+-*/
+-u32
+-PHY_CalculateBitShift(
+- u32 BitMask
+- )
+-{
+- u32 i;
+-
+- for(i=0; i<=31; i++)
+- {
+- if ( ((BitMask>>i) & 0x1 ) == 1)
+- break;
+- }
+-
+- return (i);
+-}
+-
+-
+-//
+-// ==> RF shadow Operation API Code Section!!!
+-//
+-/*-----------------------------------------------------------------------------
+- * Function: PHY_RFShadowRead
+- * PHY_RFShadowWrite
+- * PHY_RFShadowCompare
+- * PHY_RFShadowRecorver
+- * PHY_RFShadowCompareAll
+- * PHY_RFShadowRecorverAll
+- * PHY_RFShadowCompareFlagSet
+- * PHY_RFShadowRecorverFlagSet
+- *
+- * Overview: When we set RF register, we must write shadow at first.
+- * When we are running, we must compare shadow abd locate error addr.
+- * Decide to recorver or not.
+- *
+- * Input: NONE
+- *
+- * Output: NONE
+- *
+- * Return: NONE
+- *
+- * Revised History:
+- * When Who Remark
+- * 11/20/2008 MHC Create Version 0.
+- *
+- *---------------------------------------------------------------------------*/
+-u32
+-PHY_RFShadowRead(
+- IN PADAPTER Adapter,
+- IN u8 eRFPath,
+- IN u32 Offset)
+-{
+- return RF_Shadow[eRFPath][Offset].Value;
+-
+-} /* PHY_RFShadowRead */
+-
+-
+-void
+-PHY_RFShadowWrite(
+- IN PADAPTER Adapter,
+- IN u8 eRFPath,
+- IN u32 Offset,
+- IN u32 Data)
+-{
+- RF_Shadow[eRFPath][Offset].Value = (Data & bRFRegOffsetMask);
+- RF_Shadow[eRFPath][Offset].Driver_Write = true;
+-
+-} /* PHY_RFShadowWrite */
+-
+-
+-bool
+-PHY_RFShadowCompare(
+- IN PADAPTER Adapter,
+- IN u8 eRFPath,
+- IN u32 Offset)
+-{
+- u32 reg;
+- // Check if we need to check the register
+- if (RF_Shadow[eRFPath][Offset].Compare == true)
+- {
+- reg = rtw_hal_read_rfreg(Adapter, eRFPath, Offset, bRFRegOffsetMask);
+- // Compare shadow and real rf register for 20bits!!
+- if (RF_Shadow[eRFPath][Offset].Value != reg)
+- {
+- // Locate error position.
+- RF_Shadow[eRFPath][Offset].ErrorOrNot = true;
+- //RT_TRACE(COMP_INIT, DBG_LOUD,
+- //("PHY_RFShadowCompare RF-%d Addr%02lx Err = %05lx\n",
+- //eRFPath, Offset, reg));
+- }
+- return RF_Shadow[eRFPath][Offset].ErrorOrNot ;
+- }
+- return false;
+-} /* PHY_RFShadowCompare */
+-
+-
+-void
+-PHY_RFShadowRecorver(
+- IN PADAPTER Adapter,
+- IN u8 eRFPath,
+- IN u32 Offset)
+-{
+- // Check if the address is error
+- if (RF_Shadow[eRFPath][Offset].ErrorOrNot == true)
+- {
+- // Check if we need to recorver the register.
+- if (RF_Shadow[eRFPath][Offset].Recorver == true)
+- {
+- rtw_hal_write_rfreg(Adapter, eRFPath, Offset, bRFRegOffsetMask,
+- RF_Shadow[eRFPath][Offset].Value);
+- //RT_TRACE(COMP_INIT, DBG_LOUD,
+- //("PHY_RFShadowRecorver RF-%d Addr%02lx=%05lx",
+- //eRFPath, Offset, RF_Shadow[eRFPath][Offset].Value));
+- }
+- }
+-
+-} /* PHY_RFShadowRecorver */
+-
+-
+-void
+-PHY_RFShadowCompareAll(
+- IN PADAPTER Adapter)
+-{
+- u8 eRFPath = 0 ;
+- u32 Offset = 0, maxReg= GET_RF6052_REAL_MAX_REG(Adapter);
+-
+- for (eRFPath = 0; eRFPath < RF6052_MAX_PATH; eRFPath++)
+- {
+- for (Offset = 0; Offset < maxReg; Offset++)
+- {
+- PHY_RFShadowCompare(Adapter, eRFPath, Offset);
+- }
+- }
+-
+-} /* PHY_RFShadowCompareAll */
+-
+-
+-void
+-PHY_RFShadowRecorverAll(
+- IN PADAPTER Adapter)
+-{
+- u8 eRFPath =0;
+- u32 Offset = 0, maxReg= GET_RF6052_REAL_MAX_REG(Adapter);
+-
+- for (eRFPath = 0; eRFPath < RF6052_MAX_PATH; eRFPath++)
+- {
+- for (Offset = 0; Offset < maxReg; Offset++)
+- {
+- PHY_RFShadowRecorver(Adapter, eRFPath, Offset);
+- }
+- }
+-
+-} /* PHY_RFShadowRecorverAll */
+-
+-
+-void
+-PHY_RFShadowCompareFlagSet(
+- IN PADAPTER Adapter,
+- IN u8 eRFPath,
+- IN u32 Offset,
+- IN u8 Type)
+-{
+- // Set True or False!!!
+- RF_Shadow[eRFPath][Offset].Compare = Type;
+-
+-} /* PHY_RFShadowCompareFlagSet */
+-
+-
+-void
+-PHY_RFShadowRecorverFlagSet(
+- IN PADAPTER Adapter,
+- IN u8 eRFPath,
+- IN u32 Offset,
+- IN u8 Type)
+-{
+- // Set True or False!!!
+- RF_Shadow[eRFPath][Offset].Recorver= Type;
+-
+-} /* PHY_RFShadowRecorverFlagSet */
+-
+-
+-void
+-PHY_RFShadowCompareFlagSetAll(
+- IN PADAPTER Adapter)
+-{
+- u8 eRFPath = 0;
+- u32 Offset = 0, maxReg= GET_RF6052_REAL_MAX_REG(Adapter);
+-
+- for (eRFPath = 0; eRFPath < RF6052_MAX_PATH; eRFPath++)
+- {
+- for (Offset = 0; Offset < maxReg; Offset++)
+- {
+- // 2008/11/20 MH For S3S4 test, we only check reg 26/27 now!!!!
+- if (Offset != 0x26 && Offset != 0x27)
+- PHY_RFShadowCompareFlagSet(Adapter, eRFPath, Offset, false);
+- else
+- PHY_RFShadowCompareFlagSet(Adapter, eRFPath, Offset, true);
+- }
+- }
+-
+-} /* PHY_RFShadowCompareFlagSetAll */
+-
+-
+-void
+-PHY_RFShadowRecorverFlagSetAll(
+- IN PADAPTER Adapter)
+-{
+- u8 eRFPath = 0;
+- u32 Offset = 0, maxReg= GET_RF6052_REAL_MAX_REG(Adapter);
+-
+- for (eRFPath = 0; eRFPath < RF6052_MAX_PATH; eRFPath++)
+- {
+- for (Offset = 0; Offset < maxReg; Offset++)
+- {
+- // 2008/11/20 MH For S3S4 test, we only check reg 26/27 now!!!!
+- if (Offset != 0x26 && Offset != 0x27)
+- PHY_RFShadowRecorverFlagSet(Adapter, eRFPath, Offset, false);
+- else
+- PHY_RFShadowRecorverFlagSet(Adapter, eRFPath, Offset, true);
+- }
+- }
+-
+-} /* PHY_RFShadowCompareFlagSetAll */
+-
+-void
+-PHY_RFShadowRefresh(
+- IN PADAPTER Adapter)
+-{
+- u8 eRFPath = 0;
+- u32 Offset = 0, maxReg= GET_RF6052_REAL_MAX_REG(Adapter);
+-
+- for (eRFPath = 0; eRFPath < RF6052_MAX_PATH; eRFPath++)
+- {
+- for (Offset = 0; Offset < maxReg; Offset++)
+- {
+- RF_Shadow[eRFPath][Offset].Value = 0;
+- RF_Shadow[eRFPath][Offset].Compare = false;
+- RF_Shadow[eRFPath][Offset].Recorver = false;
+- RF_Shadow[eRFPath][Offset].ErrorOrNot = false;
+- RF_Shadow[eRFPath][Offset].Driver_Write = false;
+- }
+- }
+-
+-} /* PHY_RFShadowRead */
+-
+-
+diff -Nurp linux/3rdparty/rtl8723bs.old/hal/HalPhyRf_8723B.c linux/3rdparty/rtl8723bs/hal/HalPhyRf_8723B.c
+--- linux/3rdparty/rtl8723bs.old/hal/HalPhyRf_8723B.c 2015-05-10 14:36:05.702668280 +0300
++++ linux/3rdparty/rtl8723bs/hal/HalPhyRf_8723B.c 2015-05-07 17:46:55.000000000 +0300
+@@ -88,24 +88,24 @@ static void setIqkMatrix_8723B(
+ case ODM_RF_PATH_A:
+ //wirte new elements A, C, D to regC80 and regC94, element B is always 0
+ value32 = (ele_D<<22)|((ele_C&0x3F)<<16)|ele_A;
+- ODM_SetBBReg(pDM_Odm, rOFDM0_XATxIQImbalance, bMaskDWord, value32);
++ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_XATxIQImbalance, bMaskDWord, value32);
+
+ value32 = (ele_C&0x000003C0)>>6;
+- ODM_SetBBReg(pDM_Odm, rOFDM0_XCTxAFE, bMaskH4Bits, value32);
++ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_XCTxAFE, bMaskH4Bits, value32);
+
+ value32 = ((IqkResult_X * ele_D)>>7)&0x01;
+- ODM_SetBBReg(pDM_Odm, rOFDM0_ECCAThreshold, BIT24, value32);
++ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, BIT24, value32);
+ break;
+ case ODM_RF_PATH_B:
+ //wirte new elements A, C, D to regC88 and regC9C, element B is always 0
+ value32=(ele_D<<22)|((ele_C&0x3F)<<16) |ele_A;
+- ODM_SetBBReg(pDM_Odm, rOFDM0_XBTxIQImbalance, bMaskDWord, value32);
++ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_XBTxIQImbalance, bMaskDWord, value32);
+
+ value32 = (ele_C&0x000003C0)>>6;
+- ODM_SetBBReg(pDM_Odm, rOFDM0_XDTxAFE, bMaskH4Bits, value32);
++ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_XDTxAFE, bMaskH4Bits, value32);
+
+ value32 = ((IqkResult_X * ele_D)>>7)&0x01;
+- ODM_SetBBReg(pDM_Odm, rOFDM0_ECCAThreshold, BIT28, value32);
++ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, BIT28, value32);
+
+ break;
+ default:
+@@ -117,15 +117,15 @@ static void setIqkMatrix_8723B(
+ switch (RFPath)
+ {
+ case ODM_RF_PATH_A:
+- ODM_SetBBReg(pDM_Odm, rOFDM0_XATxIQImbalance, bMaskDWord, OFDMSwingTable_New[OFDM_index]);
+- ODM_SetBBReg(pDM_Odm, rOFDM0_XCTxAFE, bMaskH4Bits, 0x00);
+- ODM_SetBBReg(pDM_Odm, rOFDM0_ECCAThreshold, BIT24, 0x00);
++ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_XATxIQImbalance, bMaskDWord, OFDMSwingTable_New[OFDM_index]);
++ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_XCTxAFE, bMaskH4Bits, 0x00);
++ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, BIT24, 0x00);
+ break;
+
+ case ODM_RF_PATH_B:
+- ODM_SetBBReg(pDM_Odm, rOFDM0_XBTxIQImbalance, bMaskDWord, OFDMSwingTable_New[OFDM_index]);
+- ODM_SetBBReg(pDM_Odm, rOFDM0_XDTxAFE, bMaskH4Bits, 0x00);
+- ODM_SetBBReg(pDM_Odm, rOFDM0_ECCAThreshold, BIT28, 0x00);
++ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_XBTxIQImbalance, bMaskDWord, OFDMSwingTable_New[OFDM_index]);
++ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_XDTxAFE, bMaskH4Bits, 0x00);
++ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, BIT28, 0x00);
+ break;
+
+ default:
+@@ -146,25 +146,25 @@ setCCKFilterCoefficient(
+ {
+ if(!pDM_Odm->RFCalibrateInfo.bCCKinCH14)
+ {
+- ODM_Write1Byte(pDM_Odm, 0xa22, CCKSwingTable_Ch1_Ch13_New[CCKSwingIndex][0]);
+- ODM_Write1Byte(pDM_Odm, 0xa23, CCKSwingTable_Ch1_Ch13_New[CCKSwingIndex][1]);
+- ODM_Write1Byte(pDM_Odm, 0xa24, CCKSwingTable_Ch1_Ch13_New[CCKSwingIndex][2]);
+- ODM_Write1Byte(pDM_Odm, 0xa25, CCKSwingTable_Ch1_Ch13_New[CCKSwingIndex][3]);
+- ODM_Write1Byte(pDM_Odm, 0xa26, CCKSwingTable_Ch1_Ch13_New[CCKSwingIndex][4]);
+- ODM_Write1Byte(pDM_Odm, 0xa27, CCKSwingTable_Ch1_Ch13_New[CCKSwingIndex][5]);
+- ODM_Write1Byte(pDM_Odm, 0xa28, CCKSwingTable_Ch1_Ch13_New[CCKSwingIndex][6]);
+- ODM_Write1Byte(pDM_Odm, 0xa29, CCKSwingTable_Ch1_Ch13_New[CCKSwingIndex][7]);
++ rtw_write8(pDM_Odm->Adapter, 0xa22, CCKSwingTable_Ch1_Ch13_New[CCKSwingIndex][0]);
++ rtw_write8(pDM_Odm->Adapter, 0xa23, CCKSwingTable_Ch1_Ch13_New[CCKSwingIndex][1]);
++ rtw_write8(pDM_Odm->Adapter, 0xa24, CCKSwingTable_Ch1_Ch13_New[CCKSwingIndex][2]);
++ rtw_write8(pDM_Odm->Adapter, 0xa25, CCKSwingTable_Ch1_Ch13_New[CCKSwingIndex][3]);
++ rtw_write8(pDM_Odm->Adapter, 0xa26, CCKSwingTable_Ch1_Ch13_New[CCKSwingIndex][4]);
++ rtw_write8(pDM_Odm->Adapter, 0xa27, CCKSwingTable_Ch1_Ch13_New[CCKSwingIndex][5]);
++ rtw_write8(pDM_Odm->Adapter, 0xa28, CCKSwingTable_Ch1_Ch13_New[CCKSwingIndex][6]);
++ rtw_write8(pDM_Odm->Adapter, 0xa29, CCKSwingTable_Ch1_Ch13_New[CCKSwingIndex][7]);
+ }
+ else
+ {
+- ODM_Write1Byte(pDM_Odm, 0xa22, CCKSwingTable_Ch14_New[CCKSwingIndex][0]);
+- ODM_Write1Byte(pDM_Odm, 0xa23, CCKSwingTable_Ch14_New[CCKSwingIndex][1]);
+- ODM_Write1Byte(pDM_Odm, 0xa24, CCKSwingTable_Ch14_New[CCKSwingIndex][2]);
+- ODM_Write1Byte(pDM_Odm, 0xa25, CCKSwingTable_Ch14_New[CCKSwingIndex][3]);
+- ODM_Write1Byte(pDM_Odm, 0xa26, CCKSwingTable_Ch14_New[CCKSwingIndex][4]);
+- ODM_Write1Byte(pDM_Odm, 0xa27, CCKSwingTable_Ch14_New[CCKSwingIndex][5]);
+- ODM_Write1Byte(pDM_Odm, 0xa28, CCKSwingTable_Ch14_New[CCKSwingIndex][6]);
+- ODM_Write1Byte(pDM_Odm, 0xa29, CCKSwingTable_Ch14_New[CCKSwingIndex][7]);
++ rtw_write8(pDM_Odm->Adapter, 0xa22, CCKSwingTable_Ch14_New[CCKSwingIndex][0]);
++ rtw_write8(pDM_Odm->Adapter, 0xa23, CCKSwingTable_Ch14_New[CCKSwingIndex][1]);
++ rtw_write8(pDM_Odm->Adapter, 0xa24, CCKSwingTable_Ch14_New[CCKSwingIndex][2]);
++ rtw_write8(pDM_Odm->Adapter, 0xa25, CCKSwingTable_Ch14_New[CCKSwingIndex][3]);
++ rtw_write8(pDM_Odm->Adapter, 0xa26, CCKSwingTable_Ch14_New[CCKSwingIndex][4]);
++ rtw_write8(pDM_Odm->Adapter, 0xa27, CCKSwingTable_Ch14_New[CCKSwingIndex][5]);
++ rtw_write8(pDM_Odm->Adapter, 0xa28, CCKSwingTable_Ch14_New[CCKSwingIndex][6]);
++ rtw_write8(pDM_Odm->Adapter, 0xa29, CCKSwingTable_Ch14_New[CCKSwingIndex][7]);
+ }
+ }
+
+@@ -487,60 +487,60 @@ phy_PathA_IQK_8723B(
+ PDM_ODM_T pDM_Odm = &pHalData->odmpriv;
+
+ // Save RF Path
+- Path_SEL_BB = ODM_GetBBReg(pDM_Odm, 0x948, bMaskDWord);
++ Path_SEL_BB = PHY_QueryBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord);
+
+ ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Path A IQK!\n"));
+
+ //leave IQK mode
+- ODM_SetBBReg(pDM_Odm, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
++ PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
+
+ // enable path A PA in TXIQK mode
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, RF_WE_LUT, 0x80000, 0x1);
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x18000 );
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0003f );
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xc7f87 );
++ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_WE_LUT, 0x80000, 0x1);
++ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x18000 );
++ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0003f );
++ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xc7f87 );
+ // disable path B PA in TXIQK mode
+-// ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, 0xed, bRFRegOffsetMask, 0x00020 );
+-// ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, 0x43, bRFRegOffsetMask, 0x40ec1 );
++// PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0xed, bRFRegOffsetMask, 0x00020 );
++// PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0x43, bRFRegOffsetMask, 0x40ec1 );
+
+ //1 Tx IQK
+ //IQK setting
+- ODM_SetBBReg(pDM_Odm, rTx_IQK, bMaskDWord, 0x01007c00);
+- ODM_SetBBReg(pDM_Odm, rRx_IQK, bMaskDWord, 0x01004800);
++ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK, bMaskDWord, 0x01007c00);
++ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK, bMaskDWord, 0x01004800);
+ //path-A IQK setting
+ // ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Path-A IQK setting!\n"));
+- ODM_SetBBReg(pDM_Odm, rTx_IQK_Tone_A, bMaskDWord, 0x18008c1c);
+- ODM_SetBBReg(pDM_Odm, rRx_IQK_Tone_A, bMaskDWord, 0x38008c1c);
+- ODM_SetBBReg(pDM_Odm, rTx_IQK_Tone_B, bMaskDWord, 0x38008c1c);
+- ODM_SetBBReg(pDM_Odm, rRx_IQK_Tone_B, bMaskDWord, 0x38008c1c);
+-// ODM_SetBBReg(pDM_Odm, rTx_IQK_PI_A, bMaskDWord, 0x8214010a);
+- ODM_SetBBReg(pDM_Odm, rTx_IQK_PI_A, bMaskDWord, 0x821303ea);
+- ODM_SetBBReg(pDM_Odm, rRx_IQK_PI_A, bMaskDWord, 0x28110000);
+- ODM_SetBBReg(pDM_Odm, rTx_IQK_PI_B, bMaskDWord, 0x82110000);
+- ODM_SetBBReg(pDM_Odm, rRx_IQK_PI_B, bMaskDWord, 0x28110000);
++ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_Tone_A, bMaskDWord, 0x18008c1c);
++ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_Tone_A, bMaskDWord, 0x38008c1c);
++ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_Tone_B, bMaskDWord, 0x38008c1c);
++ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_Tone_B, bMaskDWord, 0x38008c1c);
++// PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_PI_A, bMaskDWord, 0x8214010a);
++ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_PI_A, bMaskDWord, 0x821303ea);
++ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_PI_A, bMaskDWord, 0x28110000);
++ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_PI_B, bMaskDWord, 0x82110000);
++ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_PI_B, bMaskDWord, 0x28110000);
+
+ //LO calibration setting
+ // ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("LO calibration setting!\n"));
+- ODM_SetBBReg(pDM_Odm, rIQK_AGC_Rsp, bMaskDWord, 0x00462911);
++ PHY_SetBBReg(pDM_Odm->Adapter, rIQK_AGC_Rsp, bMaskDWord, 0x00462911);
+
+ //enter IQK mode
+- ODM_SetBBReg(pDM_Odm, rFPGA0_IQK, bMaskH3Bytes, 0x808000);
++ PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x808000);
+
+ //Ant switch
+ if (configPathB || (RF_Path == 0))
+ // wifi switch to S1
+- ODM_SetBBReg(pDM_Odm, 0x948, bMaskDWord, 0x00000000);
++ PHY_SetBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord, 0x00000000);
+ else
+ // wifi switch to S0
+- ODM_SetBBReg(pDM_Odm, 0x948, bMaskDWord, 0x00000280);
++ PHY_SetBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord, 0x00000280);
+
+ //GNT_BT = 0
+- ODM_SetBBReg(pDM_Odm, 0x764, bMaskDWord, 0x00000800);
++ PHY_SetBBReg(pDM_Odm->Adapter, 0x764, bMaskDWord, 0x00000800);
+
+ //One shot, path A LOK & IQK
+ // ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("One shot, path A LOK & IQK!\n"));
+- ODM_SetBBReg(pDM_Odm, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
+- ODM_SetBBReg(pDM_Odm, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
++ PHY_SetBBReg(pDM_Odm->Adapter, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
++ PHY_SetBBReg(pDM_Odm->Adapter, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
+
+ // delay x ms
+ // ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Delay %d ms for One shot, path A LOK & IQK.\n", IQK_DELAY_TIME_8723B));
+@@ -548,23 +548,23 @@ phy_PathA_IQK_8723B(
+ mdelay(IQK_DELAY_TIME_8723B);
+
+ //restore Ant Path
+- ODM_SetBBReg(pDM_Odm, 0x948, bMaskDWord,Path_SEL_BB);
++ PHY_SetBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord,Path_SEL_BB);
+ //GNT_BT = 1
+- ODM_SetBBReg(pDM_Odm, 0x764, bMaskDWord, 0x00001800);
++ PHY_SetBBReg(pDM_Odm->Adapter, 0x764, bMaskDWord, 0x00001800);
+
+ //leave IQK mode
+- ODM_SetBBReg(pDM_Odm, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
++ PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
+
+
+ // Check failed
+- regEAC = ODM_GetBBReg(pDM_Odm, rRx_Power_After_IQK_A_2, bMaskDWord);
+- regE94 = ODM_GetBBReg(pDM_Odm, rTx_Power_Before_IQK_A, bMaskDWord);
+- regE9C= ODM_GetBBReg(pDM_Odm, rTx_Power_After_IQK_A, bMaskDWord);
++ regEAC = PHY_QueryBBReg(pDM_Odm->Adapter, rRx_Power_After_IQK_A_2, bMaskDWord);
++ regE94 = PHY_QueryBBReg(pDM_Odm->Adapter, rTx_Power_Before_IQK_A, bMaskDWord);
++ regE9C= PHY_QueryBBReg(pDM_Odm->Adapter, rTx_Power_After_IQK_A, bMaskDWord);
+ ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xeac = 0x%x\n", regEAC));
+ ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xe94 = 0x%x, 0xe9c = 0x%x\n", regE94, regE9C));
+ //monitor image power before & after IQK
+ ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xe90(before IQK)= 0x%x, 0xe98(afer IQK) = 0x%x\n",
+- ODM_GetBBReg(pDM_Odm, 0xe90, bMaskDWord), ODM_GetBBReg(pDM_Odm, 0xe98, bMaskDWord)));
++ PHY_QueryBBReg(pDM_Odm->Adapter, 0xe90, bMaskDWord), PHY_QueryBBReg(pDM_Odm->Adapter, 0xe98, bMaskDWord)));
+
+
+ //Allen 20131125
+@@ -601,61 +601,61 @@ phy_PathA_RxIQK8723B(
+ // ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Path A Rx IQK!\n"));
+
+ // Save RF Path
+- Path_SEL_BB = ODM_GetBBReg(pDM_Odm, 0x948, bMaskDWord);
++ Path_SEL_BB = PHY_QueryBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord);
+
+ //leave IQK mode
+- ODM_SetBBReg(pDM_Odm, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
++ PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
+
+ ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Path A RX IQK:Get TXIMR setting\n"));
+ //1 Get TXIMR setting
+ //modify RXIQK mode table
+ // ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Path-A Rx IQK modify RXIQK mode table!\n"));
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, RF_WE_LUT, 0x80000, 0x1);
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x18000);
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0001f);
++ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_WE_LUT, 0x80000, 0x1);
++ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x18000);
++ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0001f);
+ //LNA2 off, PA on for Dcut
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xf7fb7);
+-// ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, RF_WE_LUT, 0x80000, 0x0);
+- ODM_SetBBReg(pDM_Odm, rFPGA0_IQK, bMaskH3Bytes, 0x808000);
++ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xf7fb7);
++// PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_WE_LUT, 0x80000, 0x0);
++ PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x808000);
+
+ //IQK setting
+- ODM_SetBBReg(pDM_Odm, rTx_IQK, bMaskDWord, 0x01007c00);
+- ODM_SetBBReg(pDM_Odm, rRx_IQK, bMaskDWord, 0x01004800);
++ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK, bMaskDWord, 0x01007c00);
++ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK, bMaskDWord, 0x01004800);
+
+ //path-A IQK setting
+- ODM_SetBBReg(pDM_Odm, rTx_IQK_Tone_A, bMaskDWord, 0x18008c1c);
+- ODM_SetBBReg(pDM_Odm, rRx_IQK_Tone_A, bMaskDWord, 0x38008c1c);
+- ODM_SetBBReg(pDM_Odm, rTx_IQK_Tone_B, bMaskDWord, 0x38008c1c);
+- ODM_SetBBReg(pDM_Odm, rRx_IQK_Tone_B, bMaskDWord, 0x38008c1c);
+-
+-// ODM_SetBBReg(pDM_Odm, rTx_IQK_PI_A, bMaskDWord, 0x82160c1f);
+- ODM_SetBBReg(pDM_Odm, rTx_IQK_PI_A, bMaskDWord, 0x82130ff0);
+- ODM_SetBBReg(pDM_Odm, rRx_IQK_PI_A, bMaskDWord, 0x28110000);
+- ODM_SetBBReg(pDM_Odm, rTx_IQK_PI_B, bMaskDWord, 0x82110000);
+- ODM_SetBBReg(pDM_Odm, rRx_IQK_PI_B, bMaskDWord, 0x28110000);
++ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_Tone_A, bMaskDWord, 0x18008c1c);
++ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_Tone_A, bMaskDWord, 0x38008c1c);
++ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_Tone_B, bMaskDWord, 0x38008c1c);
++ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_Tone_B, bMaskDWord, 0x38008c1c);
++
++// PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_PI_A, bMaskDWord, 0x82160c1f);
++ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_PI_A, bMaskDWord, 0x82130ff0);
++ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_PI_A, bMaskDWord, 0x28110000);
++ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_PI_B, bMaskDWord, 0x82110000);
++ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_PI_B, bMaskDWord, 0x28110000);
+
+ //LO calibration setting
+ // ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("LO calibration setting!\n"));
+- ODM_SetBBReg(pDM_Odm, rIQK_AGC_Rsp, bMaskDWord, 0x0046a911);
++ PHY_SetBBReg(pDM_Odm->Adapter, rIQK_AGC_Rsp, bMaskDWord, 0x0046a911);
+
+ //enter IQK mode
+- ODM_SetBBReg(pDM_Odm, rFPGA0_IQK, bMaskH3Bytes, 0x808000);
++ PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x808000);
+
+ //Ant switch
+ if (configPathB || (RF_Path == 0))
+ // wifi switch to S1
+- ODM_SetBBReg(pDM_Odm, 0x948, bMaskDWord, 0x00000000);
++ PHY_SetBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord, 0x00000000);
+ else
+ // wifi switch to S0
+- ODM_SetBBReg(pDM_Odm, 0x948, bMaskDWord, 0x00000280);
++ PHY_SetBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord, 0x00000280);
+
+ //GNT_BT = 0
+- ODM_SetBBReg(pDM_Odm, 0x764, bMaskDWord, 0x00000800);
++ PHY_SetBBReg(pDM_Odm->Adapter, 0x764, bMaskDWord, 0x00000800);
+
+ //One shot, path A LOK & IQK
+ // ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("One shot, path A LOK & IQK!\n"));
+- ODM_SetBBReg(pDM_Odm, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
+- ODM_SetBBReg(pDM_Odm, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
++ PHY_SetBBReg(pDM_Odm->Adapter, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
++ PHY_SetBBReg(pDM_Odm->Adapter, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
+
+ // delay x ms
+ // ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Delay %d ms for One shot, path A LOK & IQK.\n", IQK_DELAY_TIME_8723B));
+@@ -663,22 +663,22 @@ phy_PathA_RxIQK8723B(
+ mdelay(IQK_DELAY_TIME_8723B);
+
+ //restore Ant Path
+- ODM_SetBBReg(pDM_Odm, 0x948, bMaskDWord,Path_SEL_BB);
++ PHY_SetBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord,Path_SEL_BB);
+ //GNT_BT = 1
+- ODM_SetBBReg(pDM_Odm, 0x764, bMaskDWord, 0x00001800);
++ PHY_SetBBReg(pDM_Odm->Adapter, 0x764, bMaskDWord, 0x00001800);
+
+ //leave IQK mode
+- ODM_SetBBReg(pDM_Odm, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
++ PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
+
+ // Check failed
+- regEAC = ODM_GetBBReg(pDM_Odm, rRx_Power_After_IQK_A_2, bMaskDWord);
+- regE94 = ODM_GetBBReg(pDM_Odm, rTx_Power_Before_IQK_A, bMaskDWord);
+- regE9C= ODM_GetBBReg(pDM_Odm, rTx_Power_After_IQK_A, bMaskDWord);
++ regEAC = PHY_QueryBBReg(pDM_Odm->Adapter, rRx_Power_After_IQK_A_2, bMaskDWord);
++ regE94 = PHY_QueryBBReg(pDM_Odm->Adapter, rTx_Power_Before_IQK_A, bMaskDWord);
++ regE9C= PHY_QueryBBReg(pDM_Odm->Adapter, rTx_Power_After_IQK_A, bMaskDWord);
+ ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xeac = 0x%x\n", regEAC));
+ ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xe94 = 0x%x, 0xe9c = 0x%x\n", regE94, regE9C));
+ //monitor image power before & after IQK
+ ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xe90(before IQK)= 0x%x, 0xe98(afer IQK) = 0x%x\n",
+- ODM_GetBBReg(pDM_Odm, 0xe90, bMaskDWord), ODM_GetBBReg(pDM_Odm, 0xe98, bMaskDWord)));
++ PHY_QueryBBReg(pDM_Odm->Adapter, 0xe90, bMaskDWord), PHY_QueryBBReg(pDM_Odm->Adapter, 0xe98, bMaskDWord)));
+
+ //Allen 20131125
+ tmp=(regE9C & 0x03FF0000)>>16;
+@@ -698,8 +698,8 @@ phy_PathA_RxIQK8723B(
+
+
+ u4tmp = 0x80007C00 | (regE94&0x3FF0000) | ((regE9C&0x3FF0000) >> 16);
+- ODM_SetBBReg(pDM_Odm, rTx_IQK, bMaskDWord, u4tmp);
+- ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xe40 = 0x%x u4tmp = 0x%x \n", ODM_GetBBReg(pDM_Odm, rTx_IQK, bMaskDWord), u4tmp));
++ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK, bMaskDWord, u4tmp);
++ ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xe40 = 0x%x u4tmp = 0x%x \n", PHY_QueryBBReg(pDM_Odm->Adapter, rTx_IQK, bMaskDWord), u4tmp));
+
+
+ //1 RX IQK
+@@ -707,56 +707,56 @@ phy_PathA_RxIQK8723B(
+
+ //modify RXIQK mode table
+ // ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Path-A Rx IQK modify RXIQK mode table 2!\n"));
+- ODM_SetBBReg(pDM_Odm, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, RF_WE_LUT, 0x80000, 0x1);
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x18000 );
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0001f );
++ PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
++ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_WE_LUT, 0x80000, 0x1);
++ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x18000 );
++ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0001f );
+ //LAN2 on, PA off for Dcut
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xf7d77 );
+-// ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, RF_WE_LUT, 0x80000, 0x0);
++ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xf7d77 );
++// PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_WE_LUT, 0x80000, 0x0);
+
+ //PA, PAD setting
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, 0xdf, bRFRegOffsetMask, 0xf80 );
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, 0x55, bRFRegOffsetMask, 0x4021f );
++ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0xdf, bRFRegOffsetMask, 0xf80 );
++ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0x55, bRFRegOffsetMask, 0x4021f );
+
+
+ //IQK setting
+- ODM_SetBBReg(pDM_Odm, rRx_IQK, bMaskDWord, 0x01004800);
++ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK, bMaskDWord, 0x01004800);
+
+ //path-A IQK setting
+- ODM_SetBBReg(pDM_Odm, rTx_IQK_Tone_A, bMaskDWord, 0x38008c1c);
+- ODM_SetBBReg(pDM_Odm, rRx_IQK_Tone_A, bMaskDWord, 0x18008c1c);
+- ODM_SetBBReg(pDM_Odm, rTx_IQK_Tone_B, bMaskDWord, 0x38008c1c);
+- ODM_SetBBReg(pDM_Odm, rRx_IQK_Tone_B, bMaskDWord, 0x38008c1c);
+-
+- ODM_SetBBReg(pDM_Odm, rTx_IQK_PI_A, bMaskDWord, 0x82110000);
+-// ODM_SetBBReg(pDM_Odm, rRx_IQK_PI_A, bMaskDWord, 0x281604c2);
+- ODM_SetBBReg(pDM_Odm, rRx_IQK_PI_A, bMaskDWord, 0x2813001f);
+- ODM_SetBBReg(pDM_Odm, rTx_IQK_PI_B, bMaskDWord, 0x82110000);
+- ODM_SetBBReg(pDM_Odm, rRx_IQK_PI_B, bMaskDWord, 0x28110000);
++ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_Tone_A, bMaskDWord, 0x38008c1c);
++ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_Tone_A, bMaskDWord, 0x18008c1c);
++ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_Tone_B, bMaskDWord, 0x38008c1c);
++ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_Tone_B, bMaskDWord, 0x38008c1c);
++
++ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_PI_A, bMaskDWord, 0x82110000);
++// PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_PI_A, bMaskDWord, 0x281604c2);
++ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_PI_A, bMaskDWord, 0x2813001f);
++ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_PI_B, bMaskDWord, 0x82110000);
++ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_PI_B, bMaskDWord, 0x28110000);
+
+ //LO calibration setting
+ // ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("LO calibration setting!\n"));
+- ODM_SetBBReg(pDM_Odm, rIQK_AGC_Rsp, bMaskDWord, 0x0046a8d1);
++ PHY_SetBBReg(pDM_Odm->Adapter, rIQK_AGC_Rsp, bMaskDWord, 0x0046a8d1);
+
+ //enter IQK mode
+- ODM_SetBBReg(pDM_Odm, rFPGA0_IQK, bMaskH3Bytes, 0x808000);
++ PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x808000);
+
+ //Ant switch
+ if (configPathB || (RF_Path == 0))
+ // wifi switch to S1
+- ODM_SetBBReg(pDM_Odm, 0x948, bMaskDWord, 0x00000000);
++ PHY_SetBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord, 0x00000000);
+ else
+ // wifi switch to S0
+- ODM_SetBBReg(pDM_Odm, 0x948, bMaskDWord, 0x00000280);
++ PHY_SetBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord, 0x00000280);
+
+ //GNT_BT = 0
+- ODM_SetBBReg(pDM_Odm, 0x764, bMaskDWord, 0x00000800);
++ PHY_SetBBReg(pDM_Odm->Adapter, 0x764, bMaskDWord, 0x00000800);
+
+ //One shot, path A LOK & IQK
+ // ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("One shot, path A LOK & IQK!\n"));
+- ODM_SetBBReg(pDM_Odm, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
+- ODM_SetBBReg(pDM_Odm, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
++ PHY_SetBBReg(pDM_Odm->Adapter, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
++ PHY_SetBBReg(pDM_Odm->Adapter, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
+
+ // delay x ms
+ // ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Delay %d ms for One shot, path A LOK & IQK.\n", IQK_DELAY_TIME_88E));
+@@ -764,26 +764,26 @@ phy_PathA_RxIQK8723B(
+ mdelay(IQK_DELAY_TIME_8723B);
+
+ //restore Ant Path
+- ODM_SetBBReg(pDM_Odm, 0x948, bMaskDWord,Path_SEL_BB);
++ PHY_SetBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord,Path_SEL_BB);
+ //GNT_BT = 1
+- ODM_SetBBReg(pDM_Odm, 0x764, bMaskDWord, 0x00001800);
++ PHY_SetBBReg(pDM_Odm->Adapter, 0x764, bMaskDWord, 0x00001800);
+
+ //leave IQK mode
+- ODM_SetBBReg(pDM_Odm, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
++ PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
+
+ // Check failed
+- regEAC = ODM_GetBBReg(pDM_Odm, rRx_Power_After_IQK_A_2, bMaskDWord);
+- regEA4= ODM_GetBBReg(pDM_Odm, rRx_Power_Before_IQK_A_2, bMaskDWord);
++ regEAC = PHY_QueryBBReg(pDM_Odm->Adapter, rRx_Power_After_IQK_A_2, bMaskDWord);
++ regEA4= PHY_QueryBBReg(pDM_Odm->Adapter, rRx_Power_Before_IQK_A_2, bMaskDWord);
+ ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xeac = 0x%x\n", regEAC));
+ ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xea4 = 0x%x, 0xeac = 0x%x\n", regEA4, regEAC));
+ //monitor image power before & after IQK
+ ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xea0(before IQK)= 0x%x, 0xea8(afer IQK) = 0x%x\n",
+- ODM_GetBBReg(pDM_Odm, 0xea0, bMaskDWord), ODM_GetBBReg(pDM_Odm, 0xea8, bMaskDWord)));
++ PHY_QueryBBReg(pDM_Odm->Adapter, 0xea0, bMaskDWord), PHY_QueryBBReg(pDM_Odm->Adapter, 0xea8, bMaskDWord)));
+
+ // PA/PAD controlled by 0x0
+ //leave IQK mode
+- ODM_SetBBReg(pDM_Odm, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, 0xdf, bRFRegOffsetMask, 0x780 );
++ PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
++ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0xdf, bRFRegOffsetMask, 0x780 );
+
+ //Allen 20131125
+ tmp=(regEAC & 0x03FF0000)>>16;
+@@ -819,57 +819,57 @@ phy_PathB_IQK_8723B(
+ ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Path B IQK!\n"));
+
+ // Save RF Path
+- Path_SEL_BB = ODM_GetBBReg(pDM_Odm, 0x948, bMaskDWord);
++ Path_SEL_BB = PHY_QueryBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord);
+
+ //leave IQK mode
+- ODM_SetBBReg(pDM_Odm, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
++ PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
+
+ // in TXIQK mode
+-// ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, RF_WE_LUT, 0x80000, 0x1 );
+-// ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x20000 );
+-// ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0003f );
+-// ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xc7f87 );
++// PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_WE_LUT, 0x80000, 0x1 );
++// PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x20000 );
++// PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0003f );
++// PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xc7f87 );
+ // enable path B PA in TXIQK mode
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, 0xed, 0x20, 0x1);
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, 0x43, bRFRegOffsetMask, 0x30fc1);
++ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0xed, 0x20, 0x1);
++ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0x43, bRFRegOffsetMask, 0x30fc1);
+
+
+
+ //1 Tx IQK
+ //IQK setting
+- ODM_SetBBReg(pDM_Odm, rTx_IQK, bMaskDWord, 0x01007c00);
+- ODM_SetBBReg(pDM_Odm, rRx_IQK, bMaskDWord, 0x01004800);
++ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK, bMaskDWord, 0x01007c00);
++ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK, bMaskDWord, 0x01004800);
+ //path-A IQK setting
+ // ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Path-B IQK setting!\n"));
+- ODM_SetBBReg(pDM_Odm, rTx_IQK_Tone_A, bMaskDWord, 0x18008c1c);
+- ODM_SetBBReg(pDM_Odm, rRx_IQK_Tone_A, bMaskDWord, 0x38008c1c);
+- ODM_SetBBReg(pDM_Odm, rTx_IQK_Tone_B, bMaskDWord, 0x38008c1c);
+- ODM_SetBBReg(pDM_Odm, rRx_IQK_Tone_B, bMaskDWord, 0x38008c1c);
+-
+-// ODM_SetBBReg(pDM_Odm, rTx_IQK_PI_A, bMaskDWord, 0x82140114);
+- ODM_SetBBReg(pDM_Odm, rTx_IQK_PI_A, bMaskDWord, 0x821303ea);
+- ODM_SetBBReg(pDM_Odm, rRx_IQK_PI_A, bMaskDWord, 0x28110000);
+- ODM_SetBBReg(pDM_Odm, rTx_IQK_PI_B, bMaskDWord, 0x82110000);
+- ODM_SetBBReg(pDM_Odm, rRx_IQK_PI_B, bMaskDWord, 0x28110000);
++ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_Tone_A, bMaskDWord, 0x18008c1c);
++ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_Tone_A, bMaskDWord, 0x38008c1c);
++ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_Tone_B, bMaskDWord, 0x38008c1c);
++ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_Tone_B, bMaskDWord, 0x38008c1c);
++
++// PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_PI_A, bMaskDWord, 0x82140114);
++ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_PI_A, bMaskDWord, 0x821303ea);
++ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_PI_A, bMaskDWord, 0x28110000);
++ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_PI_B, bMaskDWord, 0x82110000);
++ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_PI_B, bMaskDWord, 0x28110000);
+
+ //LO calibration setting
+ // ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("LO calibration setting!\n"));
+- ODM_SetBBReg(pDM_Odm, rIQK_AGC_Rsp, bMaskDWord, 0x00462911);
++ PHY_SetBBReg(pDM_Odm->Adapter, rIQK_AGC_Rsp, bMaskDWord, 0x00462911);
+
+ //enter IQK mode
+- ODM_SetBBReg(pDM_Odm, rFPGA0_IQK, bMaskH3Bytes, 0x808000);
++ PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x808000);
+
+ //switch to path B
+- ODM_SetBBReg(pDM_Odm, 0x948, bMaskDWord, 0x00000280);
+-// ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, 0xb0, bRFRegOffsetMask, 0xeffe0);
++ PHY_SetBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord, 0x00000280);
++// PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0xb0, bRFRegOffsetMask, 0xeffe0);
+
+ //GNT_BT = 0
+- ODM_SetBBReg(pDM_Odm, 0x764, bMaskDWord, 0x00000800);
++ PHY_SetBBReg(pDM_Odm->Adapter, 0x764, bMaskDWord, 0x00000800);
+
+ //One shot, path B LOK & IQK
+ // ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("One shot, path B LOK & IQK!\n"));
+- ODM_SetBBReg(pDM_Odm, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
+- ODM_SetBBReg(pDM_Odm, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
++ PHY_SetBBReg(pDM_Odm->Adapter, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
++ PHY_SetBBReg(pDM_Odm->Adapter, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
+
+ // delay x ms
+ // ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Delay %d ms for One shot, path B LOK & IQK.\n", IQK_DELAY_TIME_88E));
+@@ -877,25 +877,25 @@ phy_PathB_IQK_8723B(
+ mdelay(IQK_DELAY_TIME_8723B);
+
+ //restore Ant Path
+- ODM_SetBBReg(pDM_Odm, 0x948, bMaskDWord,Path_SEL_BB);
++ PHY_SetBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord,Path_SEL_BB);
+ //GNT_BT = 1
+- ODM_SetBBReg(pDM_Odm, 0x764, bMaskDWord, 0x00001800);
++ PHY_SetBBReg(pDM_Odm->Adapter, 0x764, bMaskDWord, 0x00001800);
+
+ //leave IQK mode
+- ODM_SetBBReg(pDM_Odm, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
++ PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
+
+-// ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0x948 = 0x%x\n", ODM_GetBBReg(pDM_Odm, 0x948, bMaskDWord)));
++// ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0x948 = 0x%x\n", PHY_QueryBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord)));
+
+
+ // Check failed
+- regEAC = ODM_GetBBReg(pDM_Odm, rRx_Power_After_IQK_A_2, bMaskDWord);
+- regE94 = ODM_GetBBReg(pDM_Odm, rTx_Power_Before_IQK_A, bMaskDWord);
+- regE9C= ODM_GetBBReg(pDM_Odm, rTx_Power_After_IQK_A, bMaskDWord);
++ regEAC = PHY_QueryBBReg(pDM_Odm->Adapter, rRx_Power_After_IQK_A_2, bMaskDWord);
++ regE94 = PHY_QueryBBReg(pDM_Odm->Adapter, rTx_Power_Before_IQK_A, bMaskDWord);
++ regE9C= PHY_QueryBBReg(pDM_Odm->Adapter, rTx_Power_After_IQK_A, bMaskDWord);
+ ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xeac = 0x%x\n", regEAC));
+ ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xe94 = 0x%x, 0xe9c = 0x%x\n", regE94, regE9C));
+ //monitor image power before & after IQK
+ ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xe90(before IQK)= 0x%x, 0xe98(afer IQK) = 0x%x\n",
+- ODM_GetBBReg(pDM_Odm, 0xe90, bMaskDWord), ODM_GetBBReg(pDM_Odm, 0xe98, bMaskDWord)));
++ PHY_QueryBBReg(pDM_Odm->Adapter, 0xe90, bMaskDWord), PHY_QueryBBReg(pDM_Odm->Adapter, 0xe98, bMaskDWord)));
+
+ //Allen 20131125
+ tmp=(regE9C & 0x03FF0000)>>16;
+@@ -929,61 +929,61 @@ phy_PathB_RxIQK8723B(
+ // ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Path B Rx IQK!\n"));
+
+ // Save RF Path
+- Path_SEL_BB = ODM_GetBBReg(pDM_Odm, 0x948, bMaskDWord);
++ Path_SEL_BB = PHY_QueryBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord);
+ //leave IQK mode
+- ODM_SetBBReg(pDM_Odm, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
++ PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
+
+ //switch to path B
+- ODM_SetBBReg(pDM_Odm, 0x948, bMaskDWord, 0x00000280);
++ PHY_SetBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord, 0x00000280);
+
+ //1 Get TXIMR setting
+ ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Path B RX IQK:Get TXIMR setting!\n"));
+ //modify RXIQK mode table
+ // ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Path-A Rx IQK modify RXIQK mode table!\n"));
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, RF_WE_LUT, 0x80000, 0x1 );
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x18000 );
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0001f );
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xf7fb7 );
++ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_WE_LUT, 0x80000, 0x1 );
++ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x18000 );
++ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0001f );
++ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xf7fb7 );
+ //open PA S1 & SMIXER
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, 0xed, 0x20, 0x1 );
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, 0x43, bRFRegOffsetMask, 0x30fcd );
++ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0xed, 0x20, 0x1 );
++ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0x43, bRFRegOffsetMask, 0x30fcd );
+
+
+ //IQK setting
+- ODM_SetBBReg(pDM_Odm, rTx_IQK, bMaskDWord, 0x01007c00);
+- ODM_SetBBReg(pDM_Odm, rRx_IQK, bMaskDWord, 0x01004800);
++ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK, bMaskDWord, 0x01007c00);
++ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK, bMaskDWord, 0x01004800);
+
+
+ //path-B IQK setting
+- ODM_SetBBReg(pDM_Odm, rTx_IQK_Tone_A, bMaskDWord, 0x18008c1c);
+- ODM_SetBBReg(pDM_Odm, rRx_IQK_Tone_A, bMaskDWord, 0x38008c1c);
+- ODM_SetBBReg(pDM_Odm, rTx_IQK_Tone_B, bMaskDWord, 0x38008c1c);
+- ODM_SetBBReg(pDM_Odm, rRx_IQK_Tone_B, bMaskDWord, 0x38008c1c);
+-
+-// ODM_SetBBReg(pDM_Odm, rTx_IQK_PI_A, bMaskDWord, 0x82160c1f );
+- ODM_SetBBReg(pDM_Odm, rTx_IQK_PI_A, bMaskDWord, 0x82130ff0);
+- ODM_SetBBReg(pDM_Odm, rRx_IQK_PI_A, bMaskDWord, 0x28110000);
+- ODM_SetBBReg(pDM_Odm, rTx_IQK_PI_B, bMaskDWord, 0x82110000);
+- ODM_SetBBReg(pDM_Odm, rRx_IQK_PI_B, bMaskDWord, 0x28110000);
++ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_Tone_A, bMaskDWord, 0x18008c1c);
++ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_Tone_A, bMaskDWord, 0x38008c1c);
++ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_Tone_B, bMaskDWord, 0x38008c1c);
++ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_Tone_B, bMaskDWord, 0x38008c1c);
++
++// PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_PI_A, bMaskDWord, 0x82160c1f );
++ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_PI_A, bMaskDWord, 0x82130ff0);
++ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_PI_A, bMaskDWord, 0x28110000);
++ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_PI_B, bMaskDWord, 0x82110000);
++ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_PI_B, bMaskDWord, 0x28110000);
+
+ //LO calibration setting
+ // ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("LO calibration setting!\n"));
+- ODM_SetBBReg(pDM_Odm, rIQK_AGC_Rsp, bMaskDWord, 0x0046a911);
++ PHY_SetBBReg(pDM_Odm->Adapter, rIQK_AGC_Rsp, bMaskDWord, 0x0046a911);
+
+ //enter IQK mode
+- ODM_SetBBReg(pDM_Odm, rFPGA0_IQK, bMaskH3Bytes, 0x808000);
++ PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x808000);
+
+ //switch to path B
+- ODM_SetBBReg(pDM_Odm, 0x948, bMaskDWord, 0x00000280);
+-// ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, 0xb0, bRFRegOffsetMask, 0xeffe0);
++ PHY_SetBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord, 0x00000280);
++// PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0xb0, bRFRegOffsetMask, 0xeffe0);
+
+ //GNT_BT = 0
+- ODM_SetBBReg(pDM_Odm, 0x764, bMaskDWord, 0x00000800);
++ PHY_SetBBReg(pDM_Odm->Adapter, 0x764, bMaskDWord, 0x00000800);
+
+ //One shot, path B TXIQK @ RXIQK
+ // ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("One shot, path B LOK & IQK!\n"));
+- ODM_SetBBReg(pDM_Odm, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
+- ODM_SetBBReg(pDM_Odm, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
++ PHY_SetBBReg(pDM_Odm->Adapter, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
++ PHY_SetBBReg(pDM_Odm->Adapter, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
+
+
+ // delay x ms
+@@ -992,22 +992,22 @@ phy_PathB_RxIQK8723B(
+ mdelay(IQK_DELAY_TIME_8723B);
+
+ //restore Ant Path
+- ODM_SetBBReg(pDM_Odm, 0x948, bMaskDWord,Path_SEL_BB);
++ PHY_SetBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord,Path_SEL_BB);
+ //GNT_BT = 1
+- ODM_SetBBReg(pDM_Odm, 0x764, bMaskDWord, 0x00001800);
++ PHY_SetBBReg(pDM_Odm->Adapter, 0x764, bMaskDWord, 0x00001800);
+
+ //leave IQK mode
+- ODM_SetBBReg(pDM_Odm, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
++ PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
+
+ // Check failed
+- regEAC = ODM_GetBBReg(pDM_Odm, rRx_Power_After_IQK_A_2, bMaskDWord);
+- regE94 = ODM_GetBBReg(pDM_Odm, rTx_Power_Before_IQK_A, bMaskDWord);
+- regE9C= ODM_GetBBReg(pDM_Odm, rTx_Power_After_IQK_A, bMaskDWord);
++ regEAC = PHY_QueryBBReg(pDM_Odm->Adapter, rRx_Power_After_IQK_A_2, bMaskDWord);
++ regE94 = PHY_QueryBBReg(pDM_Odm->Adapter, rTx_Power_Before_IQK_A, bMaskDWord);
++ regE9C= PHY_QueryBBReg(pDM_Odm->Adapter, rTx_Power_After_IQK_A, bMaskDWord);
+ ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xeac = 0x%x\n", regEAC));
+ ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xe94 = 0x%x, 0xe9c = 0x%x\n", regE94, regE9C));
+ //monitor image power before & after IQK
+ ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xe90(before IQK)= 0x%x, 0xe98(afer IQK) = 0x%x\n",
+- ODM_GetBBReg(pDM_Odm, 0xe90, bMaskDWord), ODM_GetBBReg(pDM_Odm, 0xe98, bMaskDWord)));
++ PHY_QueryBBReg(pDM_Odm->Adapter, 0xe90, bMaskDWord), PHY_QueryBBReg(pDM_Odm->Adapter, 0xe98, bMaskDWord)));
+
+ //Allen 20131125
+ tmp=(regE9C & 0x03FF0000)>>16;
+@@ -1029,8 +1029,8 @@ phy_PathB_RxIQK8723B(
+
+
+ u4tmp = 0x80007C00 | (regE94&0x3FF0000) | ((regE9C&0x3FF0000) >> 16);
+- ODM_SetBBReg(pDM_Odm, rTx_IQK, bMaskDWord, u4tmp);
+- ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xe40 = 0x%x u4tmp = 0x%x \n", ODM_GetBBReg(pDM_Odm, rTx_IQK, bMaskDWord), u4tmp));
++ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK, bMaskDWord, u4tmp);
++ ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xe40 = 0x%x u4tmp = 0x%x \n", PHY_QueryBBReg(pDM_Odm->Adapter, rTx_IQK, bMaskDWord), u4tmp));
+
+
+ //1 RX IQK
+@@ -1038,56 +1038,56 @@ phy_PathB_RxIQK8723B(
+
+ //modify RXIQK mode table
+ //<20121009, Kordan> RF Mode = 3
+- ODM_SetBBReg(pDM_Odm, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, RF_WE_LUT, 0x80000, 0x1);
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x18000);
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0001f);
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xf7d77);
+-// ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, RF_WE_LUT, 0x80000, 0x0);
++ PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
++ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_WE_LUT, 0x80000, 0x1);
++ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x18000);
++ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0001f);
++ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xf7d77);
++// PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_WE_LUT, 0x80000, 0x0);
+
+ //open PA S1 & close SMIXER
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, 0xed, 0x20, 0x1);
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, 0x43, bRFRegOffsetMask, 0x30ebd);
++ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0xed, 0x20, 0x1);
++ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0x43, bRFRegOffsetMask, 0x30ebd);
+
+ //PA, PAD setting
+-// ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, 0xdf, bRFRegOffsetMask, 0xf80);
+-// ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, 0x56, bRFRegOffsetMask, 0x51000);
++// PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0xdf, bRFRegOffsetMask, 0xf80);
++// PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0x56, bRFRegOffsetMask, 0x51000);
+
+
+
+ //IQK setting
+- ODM_SetBBReg(pDM_Odm, rRx_IQK, bMaskDWord, 0x01004800);
++ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK, bMaskDWord, 0x01004800);
+
+ //path-B IQK setting
+- ODM_SetBBReg(pDM_Odm, rTx_IQK_Tone_A, bMaskDWord, 0x38008c1c);
+- ODM_SetBBReg(pDM_Odm, rRx_IQK_Tone_A, bMaskDWord, 0x18008c1c);
+- ODM_SetBBReg(pDM_Odm, rTx_IQK_Tone_B, bMaskDWord, 0x38008c1c);
+- ODM_SetBBReg(pDM_Odm, rRx_IQK_Tone_B, bMaskDWord, 0x38008c1c);
+-
+- ODM_SetBBReg(pDM_Odm, rTx_IQK_PI_A, bMaskDWord, 0x82110000);
+-// ODM_SetBBReg(pDM_Odm, rRx_IQK_PI_A, bMaskDWord, 0x281604c2);
+- ODM_SetBBReg(pDM_Odm, rRx_IQK_PI_A, bMaskDWord, 0x2813001f);
+- ODM_SetBBReg(pDM_Odm, rTx_IQK_PI_B, bMaskDWord, 0x82110000);
+- ODM_SetBBReg(pDM_Odm, rRx_IQK_PI_B, bMaskDWord, 0x28110000);
++ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_Tone_A, bMaskDWord, 0x38008c1c);
++ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_Tone_A, bMaskDWord, 0x18008c1c);
++ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_Tone_B, bMaskDWord, 0x38008c1c);
++ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_Tone_B, bMaskDWord, 0x38008c1c);
++
++ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_PI_A, bMaskDWord, 0x82110000);
++// PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_PI_A, bMaskDWord, 0x281604c2);
++ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_PI_A, bMaskDWord, 0x2813001f);
++ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_PI_B, bMaskDWord, 0x82110000);
++ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_PI_B, bMaskDWord, 0x28110000);
+
+ //LO calibration setting
+ // ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("LO calibration setting!\n"));
+- ODM_SetBBReg(pDM_Odm, rIQK_AGC_Rsp, bMaskDWord, 0x0046a8d1);
++ PHY_SetBBReg(pDM_Odm->Adapter, rIQK_AGC_Rsp, bMaskDWord, 0x0046a8d1);
+
+ //enter IQK mode
+- ODM_SetBBReg(pDM_Odm, rFPGA0_IQK, bMaskH3Bytes, 0x808000);
++ PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x808000);
+
+ //switch to path B
+- ODM_SetBBReg(pDM_Odm, 0x948, bMaskDWord, 0x00000280);
+-// ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, 0xb0, bRFRegOffsetMask, 0xeffe0);
++ PHY_SetBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord, 0x00000280);
++// PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0xb0, bRFRegOffsetMask, 0xeffe0);
+
+ //GNT_BT = 0
+- ODM_SetBBReg(pDM_Odm, 0x764, bMaskDWord, 0x00000800);
++ PHY_SetBBReg(pDM_Odm->Adapter, 0x764, bMaskDWord, 0x00000800);
+
+ //One shot, path B LOK & IQK
+ // ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("One shot, path B LOK & IQK!\n"));
+- ODM_SetBBReg(pDM_Odm, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
+- ODM_SetBBReg(pDM_Odm, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
++ PHY_SetBBReg(pDM_Odm->Adapter, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
++ PHY_SetBBReg(pDM_Odm->Adapter, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
+
+ // delay x ms
+ // ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Delay %d ms for One shot, path A LOK & IQK.\n", IQK_DELAY_TIME_88E));
+@@ -1095,27 +1095,27 @@ phy_PathB_RxIQK8723B(
+ mdelay(IQK_DELAY_TIME_8723B);
+
+ //restore Ant Path
+- ODM_SetBBReg(pDM_Odm, 0x948, bMaskDWord,Path_SEL_BB);
++ PHY_SetBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord,Path_SEL_BB);
+ //GNT_BT = 1
+- ODM_SetBBReg(pDM_Odm, 0x764, bMaskDWord, 0x00001800);
++ PHY_SetBBReg(pDM_Odm->Adapter, 0x764, bMaskDWord, 0x00001800);
+
+ //leave IQK mode
+- ODM_SetBBReg(pDM_Odm, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
++ PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
+
+ // Check failed
+- regEAC = ODM_GetBBReg(pDM_Odm, rRx_Power_After_IQK_A_2, bMaskDWord);
+- regEA4= ODM_GetBBReg(pDM_Odm, rRx_Power_Before_IQK_A_2, bMaskDWord);;
++ regEAC = PHY_QueryBBReg(pDM_Odm->Adapter, rRx_Power_After_IQK_A_2, bMaskDWord);
++ regEA4= PHY_QueryBBReg(pDM_Odm->Adapter, rRx_Power_Before_IQK_A_2, bMaskDWord);;
+
+ ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xeac = 0x%x\n", regEAC));
+ ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xea4 = 0x%x, 0xeac = 0x%x\n", regEA4, regEAC));
+ //monitor image power before & after IQK
+ ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xea0(before IQK)= 0x%x, 0xea8(afer IQK) = 0x%x\n",
+- ODM_GetBBReg(pDM_Odm, 0xea0, bMaskDWord), ODM_GetBBReg(pDM_Odm, 0xea8, bMaskDWord)));
++ PHY_QueryBBReg(pDM_Odm->Adapter, 0xea0, bMaskDWord), PHY_QueryBBReg(pDM_Odm->Adapter, 0xea8, bMaskDWord)));
+
+ // PA/PAD controlled by 0x0
+ //leave IQK mode
+-// ODM_SetBBReg(pDM_Odm, rFPGA0_IQK, 0xffffff00, 0x00000000);
+-// ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_B, 0xdf, bRFRegOffsetMask, 0x180 );
++// PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, 0xffffff00, 0x00000000);
++// PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_B, 0xdf, bRFRegOffsetMask, 0x180 );
+
+
+
+@@ -1165,16 +1165,16 @@ _PHY_PathAFillIQKMatrix8723B(
+
+ else if(bIQKOK)
+ {
+- Oldval_0 = (ODM_GetBBReg(pDM_Odm, rOFDM0_XATxIQImbalance, bMaskDWord) >> 22) & 0x3FF;
++ Oldval_0 = (PHY_QueryBBReg(pDM_Odm->Adapter, rOFDM0_XATxIQImbalance, bMaskDWord) >> 22) & 0x3FF;
+
+ X = result[final_candidate][0];
+ if ((X & 0x00000200) != 0)
+ X = X | 0xFFFFFC00;
+ TX0_A = (X * Oldval_0) >> 8;
+ ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("X = 0x%x, TX0_A = 0x%x, Oldval_0 0x%x\n", X, TX0_A, Oldval_0));
+- ODM_SetBBReg(pDM_Odm, rOFDM0_XATxIQImbalance, 0x3FF, TX0_A);
++ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_XATxIQImbalance, 0x3FF, TX0_A);
+
+- ODM_SetBBReg(pDM_Odm, rOFDM0_ECCAThreshold, BIT(31), ((X* Oldval_0>>7) & 0x1));
++ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, BIT(31), ((X* Oldval_0>>7) & 0x1));
+
+ Y = result[final_candidate][1];
+ if ((Y & 0x00000200) != 0)
+@@ -1183,17 +1183,17 @@ _PHY_PathAFillIQKMatrix8723B(
+ //2 Tx IQC
+ TX0_C = (Y * Oldval_0) >> 8;
+ ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Y = 0x%x, TX = 0x%x\n", Y, TX0_C));
+- ODM_SetBBReg(pDM_Odm, rOFDM0_XCTxAFE, 0xF0000000, ((TX0_C&0x3C0)>>6));
++ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_XCTxAFE, 0xF0000000, ((TX0_C&0x3C0)>>6));
+ pRFCalibrateInfo->TxIQC_8723B[PATH_S1][IDX_0xC94][KEY] = rOFDM0_XCTxAFE;
+- pRFCalibrateInfo->TxIQC_8723B[PATH_S1][IDX_0xC94][VAL] = ODM_GetBBReg(pDM_Odm, rOFDM0_XCTxAFE, bMaskDWord);
++ pRFCalibrateInfo->TxIQC_8723B[PATH_S1][IDX_0xC94][VAL] = PHY_QueryBBReg(pDM_Odm->Adapter, rOFDM0_XCTxAFE, bMaskDWord);
+
+- ODM_SetBBReg(pDM_Odm, rOFDM0_XATxIQImbalance, 0x003F0000, (TX0_C&0x3F));
++ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_XATxIQImbalance, 0x003F0000, (TX0_C&0x3F));
+ pRFCalibrateInfo->TxIQC_8723B[PATH_S1][IDX_0xC80][KEY] = rOFDM0_XATxIQImbalance;
+- pRFCalibrateInfo->TxIQC_8723B[PATH_S1][IDX_0xC80][VAL] = ODM_GetBBReg(pDM_Odm, rOFDM0_XATxIQImbalance, bMaskDWord);
++ pRFCalibrateInfo->TxIQC_8723B[PATH_S1][IDX_0xC80][VAL] = PHY_QueryBBReg(pDM_Odm->Adapter, rOFDM0_XATxIQImbalance, bMaskDWord);
+
+- ODM_SetBBReg(pDM_Odm, rOFDM0_ECCAThreshold, BIT(29), ((Y* Oldval_0>>7) & 0x1));
++ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, BIT(29), ((Y* Oldval_0>>7) & 0x1));
+ pRFCalibrateInfo->TxIQC_8723B[PATH_S1][IDX_0xC4C][KEY] = rOFDM0_ECCAThreshold;
+- pRFCalibrateInfo->TxIQC_8723B[PATH_S1][IDX_0xC4C][VAL] = ODM_GetBBReg(pDM_Odm, rOFDM0_ECCAThreshold, bMaskDWord);
++ pRFCalibrateInfo->TxIQC_8723B[PATH_S1][IDX_0xC4C][VAL] = PHY_QueryBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, bMaskDWord);
+
+ if(bTxOnly)
+ {
+@@ -1201,9 +1201,9 @@ _PHY_PathAFillIQKMatrix8723B(
+
+ // <20130226, Kordan> Saving RxIQC, otherwise not initialized.
+ pRFCalibrateInfo->RxIQC_8723B[PATH_S1][IDX_0xCA0][KEY] = rOFDM0_RxIQExtAnta;
+- pRFCalibrateInfo->RxIQC_8723B[PATH_S1][IDX_0xCA0][VAL] = 0xfffffff & ODM_GetBBReg(pDM_Odm, rOFDM0_RxIQExtAnta, bMaskDWord);
++ pRFCalibrateInfo->RxIQC_8723B[PATH_S1][IDX_0xCA0][VAL] = 0xfffffff & PHY_QueryBBReg(pDM_Odm->Adapter, rOFDM0_RxIQExtAnta, bMaskDWord);
+ pRFCalibrateInfo->RxIQC_8723B[PATH_S1][IDX_0xC14][KEY] = rOFDM0_XARxIQImbalance;
+-// pRFCalibrateInfo->RxIQC_8723B[PATH_S1][IDX_0xC14][VAL] = ODM_GetBBReg(pDM_Odm, rOFDM0_XARxIQImbalance, bMaskDWord);
++// pRFCalibrateInfo->RxIQC_8723B[PATH_S1][IDX_0xC14][VAL] = PHY_QueryBBReg(pDM_Odm->Adapter, rOFDM0_XARxIQImbalance, bMaskDWord);
+ pRFCalibrateInfo->RxIQC_8723B[PATH_S1][IDX_0xC14][VAL] = 0x40000100;
+ return;
+ }
+@@ -1211,16 +1211,16 @@ _PHY_PathAFillIQKMatrix8723B(
+ reg = result[final_candidate][2];
+
+ //2 Rx IQC
+- ODM_SetBBReg(pDM_Odm, rOFDM0_XARxIQImbalance, 0x3FF, reg);
++ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_XARxIQImbalance, 0x3FF, reg);
+ reg = result[final_candidate][3] & 0x3F;
+- ODM_SetBBReg(pDM_Odm, rOFDM0_XARxIQImbalance, 0xFC00, reg);
++ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_XARxIQImbalance, 0xFC00, reg);
+ pRFCalibrateInfo->RxIQC_8723B[PATH_S1][IDX_0xC14][KEY] = rOFDM0_XARxIQImbalance;
+- pRFCalibrateInfo->RxIQC_8723B[PATH_S1][IDX_0xC14][VAL] = ODM_GetBBReg(pDM_Odm, rOFDM0_XARxIQImbalance, bMaskDWord);
++ pRFCalibrateInfo->RxIQC_8723B[PATH_S1][IDX_0xC14][VAL] = PHY_QueryBBReg(pDM_Odm->Adapter, rOFDM0_XARxIQImbalance, bMaskDWord);
+
+ reg = (result[final_candidate][3] >> 6) & 0xF;
+- ODM_SetBBReg(pDM_Odm, rOFDM0_RxIQExtAnta, 0xF0000000, reg);
++ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_RxIQExtAnta, 0xF0000000, reg);
+ pRFCalibrateInfo->RxIQC_8723B[PATH_S1][IDX_0xCA0][KEY] = rOFDM0_RxIQExtAnta;
+- pRFCalibrateInfo->RxIQC_8723B[PATH_S1][IDX_0xCA0][VAL] = ODM_GetBBReg(pDM_Odm, rOFDM0_RxIQExtAnta, bMaskDWord);
++ pRFCalibrateInfo->RxIQC_8723B[PATH_S1][IDX_0xCA0][VAL] = PHY_QueryBBReg(pDM_Odm->Adapter, rOFDM0_RxIQExtAnta, bMaskDWord);
+
+ }
+ }
+@@ -1248,7 +1248,7 @@ _PHY_PathBFillIQKMatrix8723B(
+
+ else if(bIQKOK)
+ {
+- Oldval_1 = (ODM_GetBBReg(pDM_Odm, rOFDM0_XBTxIQImbalance, bMaskDWord) >> 22) & 0x3FF;
++ Oldval_1 = (PHY_QueryBBReg(pDM_Odm->Adapter, rOFDM0_XBTxIQImbalance, bMaskDWord) >> 22) & 0x3FF;
+
+ X = result[final_candidate][4];
+ if ((X & 0x00000200) != 0)
+@@ -1256,9 +1256,9 @@ _PHY_PathBFillIQKMatrix8723B(
+ TX1_A = (X * Oldval_1) >> 8;
+ ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("X = 0x%x, TX1_A = 0x%x\n", X, TX1_A));
+
+- ODM_SetBBReg(pDM_Odm, rOFDM0_XBTxIQImbalance, 0x3FF, TX1_A);
++ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_XBTxIQImbalance, 0x3FF, TX1_A);
+
+- ODM_SetBBReg(pDM_Odm, rOFDM0_ECCAThreshold, BIT(27), ((X* Oldval_1>>7) & 0x1));
++ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, BIT(27), ((X* Oldval_1>>7) & 0x1));
+
+ Y = result[final_candidate][5];
+ if ((Y & 0x00000200) != 0)
+@@ -1268,43 +1268,43 @@ _PHY_PathBFillIQKMatrix8723B(
+ ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Y = 0x%x, TX1_C = 0x%x\n", Y, TX1_C));
+
+ //2 Tx IQC
+- ODM_SetBBReg(pDM_Odm, rOFDM0_XDTxAFE, 0xF0000000, ((TX1_C&0x3C0)>>6));
++ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_XDTxAFE, 0xF0000000, ((TX1_C&0x3C0)>>6));
+ // pRFCalibrateInfo->TxIQC_8723B[PATH_S0][IDX_0xC9C][KEY] = rOFDM0_XDTxAFE;
+-// pRFCalibrateInfo->TxIQC_8723B[PATH_S0][IDX_0xC9C][VAL] = ODM_GetBBReg(pDM_Odm, rOFDM0_XDTxAFE, bMaskDWord);
++// pRFCalibrateInfo->TxIQC_8723B[PATH_S0][IDX_0xC9C][VAL] = PHY_QueryBBReg(pDM_Odm->Adapter, rOFDM0_XDTxAFE, bMaskDWord);
+ pRFCalibrateInfo->TxIQC_8723B[PATH_S0][IDX_0xC94][KEY] = rOFDM0_XCTxAFE;
+- pRFCalibrateInfo->TxIQC_8723B[PATH_S0][IDX_0xC94][VAL] = ODM_GetBBReg(pDM_Odm, rOFDM0_XDTxAFE, bMaskDWord);
++ pRFCalibrateInfo->TxIQC_8723B[PATH_S0][IDX_0xC94][VAL] = PHY_QueryBBReg(pDM_Odm->Adapter, rOFDM0_XDTxAFE, bMaskDWord);
+
+- ODM_SetBBReg(pDM_Odm, rOFDM0_XBTxIQImbalance, 0x003F0000, (TX1_C&0x3F));
++ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_XBTxIQImbalance, 0x003F0000, (TX1_C&0x3F));
+ pRFCalibrateInfo->TxIQC_8723B[PATH_S0][IDX_0xC80][KEY] = rOFDM0_XATxIQImbalance;
+- pRFCalibrateInfo->TxIQC_8723B[PATH_S0][IDX_0xC80][VAL] = ODM_GetBBReg(pDM_Odm, rOFDM0_XBTxIQImbalance, bMaskDWord);
++ pRFCalibrateInfo->TxIQC_8723B[PATH_S0][IDX_0xC80][VAL] = PHY_QueryBBReg(pDM_Odm->Adapter, rOFDM0_XBTxIQImbalance, bMaskDWord);
+
+- ODM_SetBBReg(pDM_Odm, rOFDM0_ECCAThreshold, BIT(25), ((Y* Oldval_1>>7) & 0x1));
++ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, BIT(25), ((Y* Oldval_1>>7) & 0x1));
+ pRFCalibrateInfo->TxIQC_8723B[PATH_S0][IDX_0xC4C][KEY] = rOFDM0_ECCAThreshold;
+- pRFCalibrateInfo->TxIQC_8723B[PATH_S0][IDX_0xC4C][VAL] = ODM_GetBBReg(pDM_Odm, rOFDM0_ECCAThreshold, bMaskDWord);
++ pRFCalibrateInfo->TxIQC_8723B[PATH_S0][IDX_0xC4C][VAL] = PHY_QueryBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, bMaskDWord);
+
+ if(bTxOnly) {
+ ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("_PHY_PathBFillIQKMatrix8723B only Tx OK\n"));
+
+ pRFCalibrateInfo->RxIQC_8723B[PATH_S0][IDX_0xC14][KEY] = rOFDM0_XARxIQImbalance;
+-// pRFCalibrateInfo->RxIQC_8723B[PATH_S0][IDX_0xC14][VAL] = ODM_GetBBReg(pDM_Odm, rOFDM0_XARxIQImbalance, bMaskDWord);
++// pRFCalibrateInfo->RxIQC_8723B[PATH_S0][IDX_0xC14][VAL] = PHY_QueryBBReg(pDM_Odm->Adapter, rOFDM0_XARxIQImbalance, bMaskDWord);
+ pRFCalibrateInfo->RxIQC_8723B[PATH_S0][IDX_0xC14][VAL] = 0x40000100;
+ pRFCalibrateInfo->RxIQC_8723B[PATH_S0][IDX_0xCA0][KEY] = rOFDM0_RxIQExtAnta;
+- pRFCalibrateInfo->RxIQC_8723B[PATH_S0][IDX_0xCA0][VAL] = 0x0fffffff & ODM_GetBBReg(pDM_Odm, rOFDM0_RxIQExtAnta, bMaskDWord);
++ pRFCalibrateInfo->RxIQC_8723B[PATH_S0][IDX_0xCA0][VAL] = 0x0fffffff & PHY_QueryBBReg(pDM_Odm->Adapter, rOFDM0_RxIQExtAnta, bMaskDWord);
+ return;
+ }
+
+ //2 Rx IQC
+ reg = result[final_candidate][6];
+- ODM_SetBBReg(pDM_Odm, rOFDM0_XBRxIQImbalance, 0x3FF, reg);
++ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_XBRxIQImbalance, 0x3FF, reg);
+ reg = result[final_candidate][7] & 0x3F;
+- ODM_SetBBReg(pDM_Odm, rOFDM0_XBRxIQImbalance, 0xFC00, reg);
++ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_XBRxIQImbalance, 0xFC00, reg);
+ pRFCalibrateInfo->RxIQC_8723B[PATH_S0][IDX_0xC14][KEY] = rOFDM0_XARxIQImbalance;
+- pRFCalibrateInfo->RxIQC_8723B[PATH_S0][IDX_0xC14][VAL] = ODM_GetBBReg(pDM_Odm, rOFDM0_XBRxIQImbalance, bMaskDWord);
++ pRFCalibrateInfo->RxIQC_8723B[PATH_S0][IDX_0xC14][VAL] = PHY_QueryBBReg(pDM_Odm->Adapter, rOFDM0_XBRxIQImbalance, bMaskDWord);
+
+ reg = (result[final_candidate][7] >> 6) & 0xF;
+-// ODM_SetBBReg(pDM_Odm, rOFDM0_AGCRSSITable, 0x0000F000, reg);
++// PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_AGCRSSITable, 0x0000F000, reg);
+ pRFCalibrateInfo->RxIQC_8723B[PATH_S0][IDX_0xCA0][KEY] = rOFDM0_RxIQExtAnta;
+- pRFCalibrateInfo->RxIQC_8723B[PATH_S0][IDX_0xCA0][VAL] = (reg << 28)|(ODM_GetBBReg(pDM_Odm,rOFDM0_RxIQExtAnta, bMaskDWord)& 0x0fffffff);
++ pRFCalibrateInfo->RxIQC_8723B[PATH_S0][IDX_0xCA0][VAL] = (reg << 28)|(PHY_QueryBBReg(pDM_Odm->Adapter,rOFDM0_RxIQExtAnta, bMaskDWord)& 0x0fffffff);
+ }
+ }
+
+@@ -1328,22 +1328,22 @@ ODM_SetIQCbyRFpath(
+ if(RFpath) //S1: RFpath = 0, S0:RFpath = 1
+ {
+ //S0 TX IQC
+- ODM_SetBBReg(pDM_Odm, pRFCalibrateInfo->TxIQC_8723B[PATH_S0][IDX_0xC94][KEY], bMaskDWord, pRFCalibrateInfo->TxIQC_8723B[PATH_S0][IDX_0xC94][VAL]);
+- ODM_SetBBReg(pDM_Odm, pRFCalibrateInfo->TxIQC_8723B[PATH_S0][IDX_0xC80][KEY], bMaskDWord, pRFCalibrateInfo->TxIQC_8723B[PATH_S0][IDX_0xC80][VAL]);
+- ODM_SetBBReg(pDM_Odm, pRFCalibrateInfo->TxIQC_8723B[PATH_S0][IDX_0xC4C][KEY], bMaskDWord, pRFCalibrateInfo->TxIQC_8723B[PATH_S0][IDX_0xC4C][VAL]);
++ PHY_SetBBReg(pDM_Odm->Adapter, pRFCalibrateInfo->TxIQC_8723B[PATH_S0][IDX_0xC94][KEY], bMaskDWord, pRFCalibrateInfo->TxIQC_8723B[PATH_S0][IDX_0xC94][VAL]);
++ PHY_SetBBReg(pDM_Odm->Adapter, pRFCalibrateInfo->TxIQC_8723B[PATH_S0][IDX_0xC80][KEY], bMaskDWord, pRFCalibrateInfo->TxIQC_8723B[PATH_S0][IDX_0xC80][VAL]);
++ PHY_SetBBReg(pDM_Odm->Adapter, pRFCalibrateInfo->TxIQC_8723B[PATH_S0][IDX_0xC4C][KEY], bMaskDWord, pRFCalibrateInfo->TxIQC_8723B[PATH_S0][IDX_0xC4C][VAL]);
+ //S0 RX IQC
+- ODM_SetBBReg(pDM_Odm, pRFCalibrateInfo->RxIQC_8723B[PATH_S0][IDX_0xC14][KEY], bMaskDWord, pRFCalibrateInfo->RxIQC_8723B[PATH_S0][IDX_0xC14][VAL]);
+- ODM_SetBBReg(pDM_Odm, pRFCalibrateInfo->RxIQC_8723B[PATH_S0][IDX_0xCA0][KEY], bMaskDWord, pRFCalibrateInfo->RxIQC_8723B[PATH_S0][IDX_0xCA0][VAL]);
++ PHY_SetBBReg(pDM_Odm->Adapter, pRFCalibrateInfo->RxIQC_8723B[PATH_S0][IDX_0xC14][KEY], bMaskDWord, pRFCalibrateInfo->RxIQC_8723B[PATH_S0][IDX_0xC14][VAL]);
++ PHY_SetBBReg(pDM_Odm->Adapter, pRFCalibrateInfo->RxIQC_8723B[PATH_S0][IDX_0xCA0][KEY], bMaskDWord, pRFCalibrateInfo->RxIQC_8723B[PATH_S0][IDX_0xCA0][VAL]);
+ }
+ else
+ {
+ //S1 TX IQC
+- ODM_SetBBReg(pDM_Odm, pRFCalibrateInfo->TxIQC_8723B[PATH_S1][IDX_0xC94][KEY], bMaskDWord, pRFCalibrateInfo->TxIQC_8723B[PATH_S1][IDX_0xC94][VAL]);
+- ODM_SetBBReg(pDM_Odm, pRFCalibrateInfo->TxIQC_8723B[PATH_S1][IDX_0xC80][KEY], bMaskDWord, pRFCalibrateInfo->TxIQC_8723B[PATH_S1][IDX_0xC80][VAL]);
+- ODM_SetBBReg(pDM_Odm, pRFCalibrateInfo->TxIQC_8723B[PATH_S1][IDX_0xC4C][KEY], bMaskDWord, pRFCalibrateInfo->TxIQC_8723B[PATH_S1][IDX_0xC4C][VAL]);
++ PHY_SetBBReg(pDM_Odm->Adapter, pRFCalibrateInfo->TxIQC_8723B[PATH_S1][IDX_0xC94][KEY], bMaskDWord, pRFCalibrateInfo->TxIQC_8723B[PATH_S1][IDX_0xC94][VAL]);
++ PHY_SetBBReg(pDM_Odm->Adapter, pRFCalibrateInfo->TxIQC_8723B[PATH_S1][IDX_0xC80][KEY], bMaskDWord, pRFCalibrateInfo->TxIQC_8723B[PATH_S1][IDX_0xC80][VAL]);
++ PHY_SetBBReg(pDM_Odm->Adapter, pRFCalibrateInfo->TxIQC_8723B[PATH_S1][IDX_0xC4C][KEY], bMaskDWord, pRFCalibrateInfo->TxIQC_8723B[PATH_S1][IDX_0xC4C][VAL]);
+ //S1 RX IQC
+- ODM_SetBBReg(pDM_Odm, pRFCalibrateInfo->RxIQC_8723B[PATH_S1][IDX_0xC14][KEY], bMaskDWord, pRFCalibrateInfo->RxIQC_8723B[PATH_S1][IDX_0xC14][VAL]);
+- ODM_SetBBReg(pDM_Odm, pRFCalibrateInfo->RxIQC_8723B[PATH_S1][IDX_0xCA0][KEY], bMaskDWord, pRFCalibrateInfo->RxIQC_8723B[PATH_S1][IDX_0xCA0][VAL]);
++ PHY_SetBBReg(pDM_Odm->Adapter, pRFCalibrateInfo->RxIQC_8723B[PATH_S1][IDX_0xC14][KEY], bMaskDWord, pRFCalibrateInfo->RxIQC_8723B[PATH_S1][IDX_0xC14][VAL]);
++ PHY_SetBBReg(pDM_Odm->Adapter, pRFCalibrateInfo->RxIQC_8723B[PATH_S1][IDX_0xCA0][KEY], bMaskDWord, pRFCalibrateInfo->RxIQC_8723B[PATH_S1][IDX_0xCA0][VAL]);
+ }
+ }
+ }
+@@ -1396,7 +1396,7 @@ _PHY_SaveADDARegisters8723B(
+
+ ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Save ADDA parameters.\n"));
+ for( i = 0 ; i < RegisterNum ; i++){
+- ADDABackup[i] = ODM_GetBBReg(pDM_Odm, ADDAReg[i], bMaskDWord);
++ ADDABackup[i] = PHY_QueryBBReg(pDM_Odm->Adapter, ADDAReg[i], bMaskDWord);
+ }
+ }
+
+@@ -1414,9 +1414,9 @@ _PHY_SaveMACRegisters8723B(
+
+ ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Save MAC parameters.\n"));
+ for( i = 0 ; i < (IQK_MAC_REG_NUM - 1); i++){
+- MACBackup[i] = ODM_Read1Byte(pDM_Odm, MACReg[i]);
++ MACBackup[i] = rtw_read8(pDM_Odm->Adapter, MACReg[i]);
+ }
+- MACBackup[i] = ODM_Read4Byte(pDM_Odm, MACReg[i]);
++ MACBackup[i] = rtw_read32(pDM_Odm->Adapter, MACReg[i]);
+
+ }
+
+@@ -1436,7 +1436,7 @@ _PHY_ReloadADDARegisters8723B(
+ ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Reload ADDA power saving parameters !\n"));
+ for(i = 0 ; i < RegiesterNum; i++)
+ {
+- ODM_SetBBReg(pDM_Odm, ADDAReg[i], bMaskDWord, ADDABackup[i]);
++ PHY_SetBBReg(pDM_Odm->Adapter, ADDAReg[i], bMaskDWord, ADDABackup[i]);
+ }
+ }
+
+@@ -1453,9 +1453,9 @@ _PHY_ReloadMACRegisters8723B(
+
+ ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Reload MAC parameters !\n"));
+ for(i = 0 ; i < (IQK_MAC_REG_NUM - 1); i++){
+- ODM_Write1Byte(pDM_Odm, MACReg[i], (u1Byte)MACBackup[i]);
++ rtw_write8(pAdapter, MACReg[i], (u1Byte)MACBackup[i]);
+ }
+- ODM_Write4Byte(pDM_Odm, MACReg[i], MACBackup[i]);
++ rtw_write32(pAdapter, MACReg[i], MACBackup[i]);
+ }
+
+
+@@ -1477,14 +1477,14 @@ _PHY_PathADDAOn8723B(
+ pathOn = isPathAOn ? 0x01c00014 : 0x01c00014;
+ if(false == is2T){
+ pathOn = 0x01c00014;
+- ODM_SetBBReg(pDM_Odm, ADDAReg[0], bMaskDWord, 0x01c00014);
++ PHY_SetBBReg(pDM_Odm->Adapter, ADDAReg[0], bMaskDWord, 0x01c00014);
+ }
+ else{
+- ODM_SetBBReg(pDM_Odm,ADDAReg[0], bMaskDWord, pathOn);
++ PHY_SetBBReg(pDM_Odm->Adapter,ADDAReg[0], bMaskDWord, pathOn);
+ }
+
+ for( i = 1 ; i < IQK_ADDA_REG_NUM ; i++){
+- ODM_SetBBReg(pDM_Odm,ADDAReg[i], bMaskDWord, pathOn);
++ PHY_SetBBReg(pDM_Odm->Adapter,ADDAReg[i], bMaskDWord, pathOn);
+ }
+
+ }
+@@ -1502,12 +1502,12 @@ _PHY_MACSettingCalibration8723B(
+
+ ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("MAC settings for Calibration.\n"));
+
+- ODM_Write1Byte(pDM_Odm, MACReg[i], 0x3F);
++ rtw_write8(pDM_Odm->Adapter, MACReg[i], 0x3F);
+
+ for(i = 1 ; i < (IQK_MAC_REG_NUM - 1); i++){
+- ODM_Write1Byte(pDM_Odm, MACReg[i], (u1Byte)(MACBackup[i]&(~BIT3)));
++ rtw_write8(pDM_Odm->Adapter, MACReg[i], (u1Byte)(MACBackup[i]&(~BIT3)));
+ }
+- ODM_Write1Byte(pDM_Odm, MACReg[i], (u1Byte)(MACBackup[i]&(~BIT5)));
++ rtw_write8(pDM_Odm->Adapter, MACReg[i], (u1Byte)(MACBackup[i]&(~BIT5)));
+
+ }
+
+@@ -1642,8 +1642,8 @@ phy_IQCalibrate_8723B(
+
+ u4Byte i;
+ u1Byte PathAOK, PathBOK;
+- u1Byte tmp0xc50 = (u1Byte)ODM_GetBBReg(pDM_Odm, 0xC50, bMaskByte0);
+- u1Byte tmp0xc58 = (u1Byte)ODM_GetBBReg(pDM_Odm, 0xC58, bMaskByte0);
++ u1Byte tmp0xc50 = (u1Byte)PHY_QueryBBReg(pDM_Odm->Adapter, 0xC50, bMaskByte0);
++ u1Byte tmp0xc58 = (u1Byte)PHY_QueryBBReg(pDM_Odm->Adapter, 0xC58, bMaskByte0);
+ u4Byte ADDA_REG[IQK_ADDA_REG_NUM] = {
+ rFPGA0_XCD_SwitchControl, rBlue_Tooth,
+ rRx_Wait_CCA, rTx_CCK_RFON,
+@@ -1677,7 +1677,7 @@ phy_IQCalibrate_8723B(
+
+ if(t==0)
+ {
+-// bbvalue = ODM_GetBBReg(pDM_Odm, rFPGA0_RFMOD, bMaskDWord);
++// bbvalue = PHY_QueryBBReg(pDM_Odm->Adapter, rFPGA0_RFMOD, bMaskDWord);
+ // RT_DISP(FINIT, INIT_IQK, ("phy_IQCalibrate_8188E()==>0x%08x\n",bbvalue));
+
+ ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("IQ Calibration for %s for %d times\n", (is2T ? "2T2R" : "1T1R"), t));
+@@ -1694,41 +1694,41 @@ phy_IQCalibrate_8723B(
+ //no serial mode
+
+ //save RF path for 8723B
+-// Path_SEL_BB = ODM_GetBBReg(pDM_Odm, 0x948, bMaskDWord);
+-// Path_SEL_RF = ODM_GetRFReg(pDM_Odm, ODM_RF_PATH_A, 0xb0, 0xfffff);
++// Path_SEL_BB = PHY_QueryBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord);
++// Path_SEL_RF = PHY_QueryRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0xb0, 0xfffff);
+
+ //MAC settings
+ _PHY_MACSettingCalibration8723B(pAdapter, IQK_MAC_REG, pDM_Odm->RFCalibrateInfo.IQK_MAC_backup);
+
+ //BB setting
+- //ODM_SetBBReg(pDM_Odm, rFPGA0_RFMOD, BIT24, 0x00);
+- ODM_SetBBReg(pDM_Odm, rCCK0_AFESetting, 0x0f000000, 0xf);
+- ODM_SetBBReg(pDM_Odm, rOFDM0_TRxPathEnable, bMaskDWord, 0x03a05600);
+- ODM_SetBBReg(pDM_Odm, rOFDM0_TRMuxPar, bMaskDWord, 0x000800e4);
+- ODM_SetBBReg(pDM_Odm, rFPGA0_XCD_RFInterfaceSW, bMaskDWord, 0x22204000);
++ //PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_RFMOD, BIT24, 0x00);
++ PHY_SetBBReg(pDM_Odm->Adapter, rCCK0_AFESetting, 0x0f000000, 0xf);
++ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_TRxPathEnable, bMaskDWord, 0x03a05600);
++ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_TRMuxPar, bMaskDWord, 0x000800e4);
++ PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_XCD_RFInterfaceSW, bMaskDWord, 0x22204000);
+
+
+-// ODM_SetBBReg(pDM_Odm, rFPGA0_XAB_RFInterfaceSW, BIT10, 0x01);
+-// ODM_SetBBReg(pDM_Odm, rFPGA0_XAB_RFInterfaceSW, BIT26, 0x01);
+-// ODM_SetBBReg(pDM_Odm, rFPGA0_XA_RFInterfaceOE, BIT10, 0x00);
+-// ODM_SetBBReg(pDM_Odm, rFPGA0_XB_RFInterfaceOE, BIT10, 0x00);
++// PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_XAB_RFInterfaceSW, BIT10, 0x01);
++// PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_XAB_RFInterfaceSW, BIT26, 0x01);
++// PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_XA_RFInterfaceOE, BIT10, 0x00);
++// PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_XB_RFInterfaceOE, BIT10, 0x00);
+
+
+ //RX IQ calibration setting for 8723B D cut large current issue when leaving IPS
+
+- ODM_SetBBReg(pDM_Odm, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, RF_WE_LUT, 0x80000, 0x1);
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x30000);
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0001f);
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xf7fb7);
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, 0xed, 0x20, 0x1);
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, 0x43, bRFRegOffsetMask, 0x60fbd);
++ PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
++ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_WE_LUT, 0x80000, 0x1);
++ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x30000);
++ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0001f);
++ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xf7fb7);
++ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0xed, 0x20, 0x1);
++ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0x43, bRFRegOffsetMask, 0x60fbd);
+ /*
+ //LOK RF setting
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, 0xed, 0x2, 0x1);
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, 0xef, 0x2, 0x1);
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, 0x56, bRFRegOffsetMask, 0x00032);
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, 0x76, bRFRegOffsetMask, 0x00032);
++ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0xed, 0x2, 0x1);
++ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0xef, 0x2, 0x1);
++ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0x56, bRFRegOffsetMask, 0x00032);
++ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0x76, bRFRegOffsetMask, 0x00032);
+ */
+
+
+@@ -1738,12 +1738,12 @@ phy_IQCalibrate_8723B(
+ // if(PathAOK == 0x03){
+ if(PathAOK == 0x01){
+ // Path A Tx IQK Success
+- ODM_SetBBReg(pDM_Odm, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
+- pDM_Odm->RFCalibrateInfo.TxLOK[ODM_RF_PATH_A] = ODM_GetRFReg(pDM_Odm, ODM_RF_PATH_A, 0x8, bRFRegOffsetMask);
++ PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
++ pDM_Odm->RFCalibrateInfo.TxLOK[ODM_RF_PATH_A] = PHY_QueryRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0x8, bRFRegOffsetMask);
+
+ ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Path A Tx IQK Success!!\n"));
+- result[t][0] = (ODM_GetBBReg(pDM_Odm, rTx_Power_Before_IQK_A, bMaskDWord)&0x3FF0000)>>16;
+- result[t][1] = (ODM_GetBBReg(pDM_Odm, rTx_Power_After_IQK_A, bMaskDWord)&0x3FF0000)>>16;
++ result[t][0] = (PHY_QueryBBReg(pDM_Odm->Adapter, rTx_Power_Before_IQK_A, bMaskDWord)&0x3FF0000)>>16;
++ result[t][1] = (PHY_QueryBBReg(pDM_Odm->Adapter, rTx_Power_After_IQK_A, bMaskDWord)&0x3FF0000)>>16;
+ break;
+ }
+ }
+@@ -1753,10 +1753,10 @@ phy_IQCalibrate_8723B(
+ PathAOK = phy_PathA_RxIQK8723B(pAdapter, is2T, RF_Path);
+ if(PathAOK == 0x03){
+ ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Path A Rx IQK Success!!\n"));
+-// result[t][0] = (ODM_GetBBReg(pDM_Odm, rTx_Power_Before_IQK_A, bMaskDWord)&0x3FF0000)>>16;
+-// result[t][1] = (ODM_GetBBReg(pDM_Odm, rTx_Power_After_IQK_A, bMaskDWord)&0x3FF0000)>>16;
+- result[t][2] = (ODM_GetBBReg(pDM_Odm, rRx_Power_Before_IQK_A_2, bMaskDWord)&0x3FF0000)>>16;
+- result[t][3] = (ODM_GetBBReg(pDM_Odm, rRx_Power_After_IQK_A_2, bMaskDWord)&0x3FF0000)>>16;
++// result[t][0] = (PHY_QueryBBReg(pDM_Odm->Adapter, rTx_Power_Before_IQK_A, bMaskDWord)&0x3FF0000)>>16;
++// result[t][1] = (PHY_QueryBBReg(pDM_Odm->Adapter, rTx_Power_After_IQK_A, bMaskDWord)&0x3FF0000)>>16;
++ result[t][2] = (PHY_QueryBBReg(pDM_Odm->Adapter, rRx_Power_Before_IQK_A_2, bMaskDWord)&0x3FF0000)>>16;
++ result[t][3] = (PHY_QueryBBReg(pDM_Odm->Adapter, rRx_Power_After_IQK_A_2, bMaskDWord)&0x3FF0000)>>16;
+ break;
+ }
+ else
+@@ -1778,12 +1778,12 @@ phy_IQCalibrate_8723B(
+ // if(PathBOK == 0x03){
+ if(PathBOK == 0x01){
+ // Path B Tx IQK Success
+- ODM_SetBBReg(pDM_Odm, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
+- pDM_Odm->RFCalibrateInfo.TxLOK[ODM_RF_PATH_B] = ODM_GetRFReg(pDM_Odm, ODM_RF_PATH_B, 0x8, bRFRegOffsetMask);
++ PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
++ pDM_Odm->RFCalibrateInfo.TxLOK[ODM_RF_PATH_B] = PHY_QueryRFReg(pDM_Odm->Adapter, ODM_RF_PATH_B, 0x8, bRFRegOffsetMask);
+
+ ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Path B Tx IQK Success!!\n"));
+- result[t][4] = (ODM_GetBBReg(pDM_Odm, rTx_Power_Before_IQK_A, bMaskDWord)&0x3FF0000)>>16;
+- result[t][5] = (ODM_GetBBReg(pDM_Odm, rTx_Power_After_IQK_A, bMaskDWord)&0x3FF0000)>>16;
++ result[t][4] = (PHY_QueryBBReg(pDM_Odm->Adapter, rTx_Power_Before_IQK_A, bMaskDWord)&0x3FF0000)>>16;
++ result[t][5] = (PHY_QueryBBReg(pDM_Odm->Adapter, rTx_Power_After_IQK_A, bMaskDWord)&0x3FF0000)>>16;
+ break;
+ }
+ }
+@@ -1793,10 +1793,10 @@ for(i = 0 ; i < retryCount ; i++){
+ PathBOK = phy_PathB_RxIQK8723B(pAdapter, is2T);
+ if(PathBOK == 0x03){
+ ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Path B Rx IQK Success!!\n"));
+-// result[t][0] = (ODM_GetBBReg(pDM_Odm, rTx_Power_Before_IQK_A, bMaskDWord)&0x3FF0000)>>16;
+-// result[t][1] = (ODM_GetBBReg(pDM_Odm, rTx_Power_After_IQK_A, bMaskDWord)&0x3FF0000)>>16;
+- result[t][6] = (ODM_GetBBReg(pDM_Odm, rRx_Power_Before_IQK_A_2, bMaskDWord)&0x3FF0000)>>16;
+- result[t][7] = (ODM_GetBBReg(pDM_Odm, rRx_Power_After_IQK_A_2, bMaskDWord)&0x3FF0000)>>16;
++// result[t][0] = (PHY_QueryBBReg(pDM_Odm->Adapter, rTx_Power_Before_IQK_A, bMaskDWord)&0x3FF0000)>>16;
++// result[t][1] = (PHY_QueryBBReg(pDM_Odm->Adapter, rTx_Power_After_IQK_A, bMaskDWord)&0x3FF0000)>>16;
++ result[t][6] = (PHY_QueryBBReg(pDM_Odm->Adapter, rRx_Power_Before_IQK_A_2, bMaskDWord)&0x3FF0000)>>16;
++ result[t][7] = (PHY_QueryBBReg(pDM_Odm->Adapter, rRx_Power_After_IQK_A_2, bMaskDWord)&0x3FF0000)>>16;
+ break;
+ }
+ else
+@@ -1813,7 +1813,7 @@ for(i = 0 ; i < retryCount ; i++){
+
+ //Back to BB mode, load original value
+ ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("IQK:Back to BB mode, load original value!\n"));
+- ODM_SetBBReg(pDM_Odm, rFPGA0_IQK, bMaskH3Bytes, 0);
++ PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_IQK, bMaskH3Bytes, 0);
+
+ if(t!=0)
+ {
+@@ -1826,21 +1826,21 @@ for(i = 0 ; i < retryCount ; i++){
+ _PHY_ReloadADDARegisters8723B(pAdapter, IQK_BB_REG_92C, pDM_Odm->RFCalibrateInfo.IQK_BB_backup, IQK_BB_REG_NUM);
+
+ //Reload RF path
+-// ODM_SetBBReg(pDM_Odm, 0x948, bMaskDWord, Path_SEL_BB);
+-// ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, 0xb0, 0xfffff, Path_SEL_RF);
++// PHY_SetBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord, Path_SEL_BB);
++// PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0xb0, 0xfffff, Path_SEL_RF);
+
+ //Allen initial gain 0xc50
+ // Restore RX initial gain
+- ODM_SetBBReg(pDM_Odm, 0xc50, bMaskByte0, 0x50);
+- ODM_SetBBReg(pDM_Odm, 0xc50, bMaskByte0, tmp0xc50);
++ PHY_SetBBReg(pDM_Odm->Adapter, 0xc50, bMaskByte0, 0x50);
++ PHY_SetBBReg(pDM_Odm->Adapter, 0xc50, bMaskByte0, tmp0xc50);
+ if(is2T){
+- ODM_SetBBReg(pDM_Odm, 0xc58, bMaskByte0, 0x50);
+- ODM_SetBBReg(pDM_Odm, 0xc58, bMaskByte0, tmp0xc58);
++ PHY_SetBBReg(pDM_Odm->Adapter, 0xc58, bMaskByte0, 0x50);
++ PHY_SetBBReg(pDM_Odm->Adapter, 0xc58, bMaskByte0, tmp0xc58);
+ }
+
+ //load 0xe30 IQC default value
+- ODM_SetBBReg(pDM_Odm, rTx_IQK_Tone_A, bMaskDWord, 0x01008c00);
+- ODM_SetBBReg(pDM_Odm, rRx_IQK_Tone_A, bMaskDWord, 0x01008c00);
++ PHY_SetBBReg(pDM_Odm->Adapter, rTx_IQK_Tone_A, bMaskDWord, 0x01008c00);
++ PHY_SetBBReg(pDM_Odm->Adapter, rRx_IQK_Tone_A, bMaskDWord, 0x01008c00);
+
+ }
+ ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("phy_IQCalibrate_8723B() <==\n"));
+@@ -1859,12 +1859,12 @@ phy_LCCalibrate_8723B(
+ PADAPTER pAdapter = pDM_Odm->Adapter;
+
+ //Check continuous TX and Packet TX
+- tmpReg = ODM_Read1Byte(pDM_Odm, 0xd03);
++ tmpReg = rtw_read8(pDM_Odm->Adapter, 0xd03);
+
+ if((tmpReg&0x70) != 0) //Deal with contisuous TX case
+- ODM_Write1Byte(pDM_Odm, 0xd03, tmpReg&0x8F); //disable all continuous TX
++ rtw_write8(pDM_Odm->Adapter, 0xd03, tmpReg&0x8F); //disable all continuous TX
+ else // Deal with Packet TX case
+- ODM_Write1Byte(pDM_Odm, REG_TXPAUSE, 0xFF); // block all queues
++ rtw_write8(pDM_Odm->Adapter, REG_TXPAUSE, 0xFF); // block all queues
+
+ if((tmpReg&0x70) != 0)
+ {
+@@ -1878,44 +1878,44 @@ phy_LCCalibrate_8723B(
+
+ //2. Set RF mode = standby mode
+ //Path-A
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, RF_AC, bMask12Bits, (RF_Amode&0x8FFFF)|0x10000);
++ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_AC, bMask12Bits, (RF_Amode&0x8FFFF)|0x10000);
+
+ //Path-B
+ if(is2T)
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_B, RF_AC, bMask12Bits, (RF_Bmode&0x8FFFF)|0x10000);
++ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_B, RF_AC, bMask12Bits, (RF_Bmode&0x8FFFF)|0x10000);
+ }
+
+ //3. Read RF reg18
+ LC_Cal = PHY_QueryRFReg(pAdapter, ODM_RF_PATH_A, RF_CHNLBW, bMask12Bits);
+
+ //4. Set LC calibration begin bit15
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, 0xB0, bRFRegOffsetMask, 0xDFBE0); // LDO ON
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, RF_CHNLBW, bMask12Bits, LC_Cal|0x08000);
++ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0xB0, bRFRegOffsetMask, 0xDFBE0); // LDO ON
++ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_CHNLBW, bMask12Bits, LC_Cal|0x08000);
+
+ mdelay(100);
+
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, 0xB0, bRFRegOffsetMask, 0xDFFE0); // LDO OFF
++ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0xB0, bRFRegOffsetMask, 0xDFFE0); // LDO OFF
+
+ // Channel 10 LC calibration issue for 8723bs with 26M xtal
+ if(pDM_Odm->SupportInterface == ODM_ITRF_SDIO && pDM_Odm->PackageType >= 0x2)
+ {
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, RF_CHNLBW, bMask12Bits, LC_Cal);
++ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_CHNLBW, bMask12Bits, LC_Cal);
+ }
+
+ //Restore original situation
+ if((tmpReg&0x70) != 0) //Deal with contisuous TX case
+ {
+ //Path-A
+- ODM_Write1Byte(pDM_Odm, 0xd03, tmpReg);
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, RF_AC, bMask12Bits, RF_Amode);
++ rtw_write8(pDM_Odm->Adapter, 0xd03, tmpReg);
++ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_AC, bMask12Bits, RF_Amode);
+
+ //Path-B
+ if(is2T)
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_B, RF_AC, bMask12Bits, RF_Bmode);
++ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_B, RF_AC, bMask12Bits, RF_Bmode);
+ }
+ else // Deal with Packet TX case
+ {
+- ODM_Write1Byte(pDM_Odm, REG_TXPAUSE, 0x00);
++ rtw_write8(pDM_Odm->Adapter, REG_TXPAUSE, 0x00);
+ }
+ }
+
+@@ -1924,118 +1924,6 @@ phy_LCCalibrate_8723B(
+ #define APK_CURVE_REG_NUM 4
+ #define PATH_NUM 2
+
+-static void
+-phy_APCalibrate_8723B(
+- IN PADAPTER pAdapter,
+- IN s8 delta,
+- IN bool is2T
+- )
+-{
+- HAL_DATA_TYPE *pHalData = GET_HAL_DATA(pAdapter);
+- PDM_ODM_T pDM_Odm = &pHalData->odmpriv;
+- u4Byte regD[PATH_NUM];
+- u4Byte tmpReg, index, offset, apkbound;
+- u1Byte path, i, pathbound = PATH_NUM;
+- u4Byte BB_backup[APK_BB_REG_NUM];
+- u4Byte BB_REG[APK_BB_REG_NUM] = {
+- rFPGA1_TxBlock, rOFDM0_TRxPathEnable,
+- rFPGA0_RFMOD, rOFDM0_TRMuxPar,
+- rFPGA0_XCD_RFInterfaceSW, rFPGA0_XAB_RFInterfaceSW,
+- rFPGA0_XA_RFInterfaceOE, rFPGA0_XB_RFInterfaceOE };
+- u4Byte BB_AP_MODE[APK_BB_REG_NUM] = {
+- 0x00000020, 0x00a05430, 0x02040000,
+- 0x000800e4, 0x00204000 };
+- u4Byte BB_normal_AP_MODE[APK_BB_REG_NUM] = {
+- 0x00000020, 0x00a05430, 0x02040000,
+- 0x000800e4, 0x22204000 };
+-
+- u4Byte AFE_backup[IQK_ADDA_REG_NUM];
+- u4Byte AFE_REG[IQK_ADDA_REG_NUM] = {
+- rFPGA0_XCD_SwitchControl, rBlue_Tooth,
+- rRx_Wait_CCA, rTx_CCK_RFON,
+- rTx_CCK_BBON, rTx_OFDM_RFON,
+- rTx_OFDM_BBON, rTx_To_Rx,
+- rTx_To_Tx, rRx_CCK,
+- rRx_OFDM, rRx_Wait_RIFS,
+- rRx_TO_Rx, rStandby,
+- rSleep, rPMPD_ANAEN };
+-
+- u4Byte MAC_backup[IQK_MAC_REG_NUM];
+- u4Byte MAC_REG[IQK_MAC_REG_NUM] = {
+- REG_TXPAUSE, REG_BCN_CTRL,
+- REG_BCN_CTRL_1, REG_GPIO_MUXCFG};
+-
+- u4Byte APK_RF_init_value[PATH_NUM][APK_BB_REG_NUM] = {
+- {0x0852c, 0x1852c, 0x5852c, 0x1852c, 0x5852c},
+- {0x2852e, 0x0852e, 0x3852e, 0x0852e, 0x0852e}
+- };
+-
+- u4Byte APK_normal_RF_init_value[PATH_NUM][APK_BB_REG_NUM] = {
+- {0x0852c, 0x0a52c, 0x3a52c, 0x5a52c, 0x5a52c}, //path settings equal to path b settings
+- {0x0852c, 0x0a52c, 0x5a52c, 0x5a52c, 0x5a52c}
+- };
+-
+- u4Byte APK_RF_value_0[PATH_NUM][APK_BB_REG_NUM] = {
+- {0x52019, 0x52014, 0x52013, 0x5200f, 0x5208d},
+- {0x5201a, 0x52019, 0x52016, 0x52033, 0x52050}
+- };
+-
+- u4Byte APK_normal_RF_value_0[PATH_NUM][APK_BB_REG_NUM] = {
+- {0x52019, 0x52017, 0x52010, 0x5200d, 0x5206a}, //path settings equal to path b settings
+- {0x52019, 0x52017, 0x52010, 0x5200d, 0x5206a}
+- };
+-
+- u4Byte AFE_on_off[PATH_NUM] = {
+- 0x04db25a4, 0x0b1b25a4}; //path A on path B off / path A off path B on
+-
+- u4Byte APK_offset[PATH_NUM] = {
+- rConfig_AntA, rConfig_AntB};
+-
+- u4Byte APK_normal_offset[PATH_NUM] = {
+- rConfig_Pmpd_AntA, rConfig_Pmpd_AntB};
+-
+- u4Byte APK_value[PATH_NUM] = {
+- 0x92fc0000, 0x12fc0000};
+-
+- u4Byte APK_normal_value[PATH_NUM] = {
+- 0x92680000, 0x12680000};
+-
+- s8 APK_delta_mapping[APK_BB_REG_NUM][13] = {
+- {-4, -3, -2, -2, -1, -1, 0, 1, 2, 3, 4, 5, 6},
+- {-4, -3, -2, -2, -1, -1, 0, 1, 2, 3, 4, 5, 6},
+- {-6, -4, -2, -2, -1, -1, 0, 1, 2, 3, 4, 5, 6},
+- {-1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6},
+- {-11, -9, -7, -5, -3, -1, 0, 0, 0, 0, 0, 0, 0}
+- };
+-
+- u4Byte APK_normal_setting_value_1[13] = {
+- 0x01017018, 0xf7ed8f84, 0x1b1a1816, 0x2522201e, 0x322e2b28,
+- 0x433f3a36, 0x5b544e49, 0x7b726a62, 0xa69a8f84, 0xdfcfc0b3,
+- 0x12680000, 0x00880000, 0x00880000
+- };
+-
+- u4Byte APK_normal_setting_value_2[16] = {
+- 0x01c7021d, 0x01670183, 0x01000123, 0x00bf00e2, 0x008d00a3,
+- 0x0068007b, 0x004d0059, 0x003a0042, 0x002b0031, 0x001f0025,
+- 0x0017001b, 0x00110014, 0x000c000f, 0x0009000b, 0x00070008,
+- 0x00050006
+- };
+-
+- u4Byte APK_result[PATH_NUM][APK_BB_REG_NUM]; //val_1_1a, val_1_2a, val_2a, val_3a, val_4a
+-// u4Byte AP_curve[PATH_NUM][APK_CURVE_REG_NUM];
+-
+- s4Byte BB_offset, delta_V, delta_offset;
+-
+- ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("==>phy_APCalibrate_8188E() delta %d\n", delta));
+- ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("AP Calibration for %s\n", (is2T ? "2T2R" : "1T1R")));
+- if(!is2T)
+- pathbound = 1;
+-
+- //2 FOR NORMAL CHIP SETTINGS
+-}
+-
+-
+-
+ #define DP_BB_REG_NUM 7
+ #define DP_RF_REG_NUM 1
+ #define DP_RETRY_LIMIT 10
+@@ -2106,7 +1994,7 @@ PHY_IQCalibrate_8723B(
+ //#define PATH_S0 1 // RF_PATH_B
+ //#define PATH_S1 0 // RF_PATH_A
+
+- path = (ODM_GetBBReg(pDM_Odm,rS0S1_PathSwitch,bMaskByte0)==0x00) ? ODM_RF_PATH_A : ODM_RF_PATH_B;
++ path = (PHY_QueryBBReg(pDM_Odm->Adapter,rS0S1_PathSwitch,bMaskByte0)==0x00) ? ODM_RF_PATH_A : ODM_RF_PATH_B;
+
+ // Restore TX IQK
+ for (i = 0; i < 3; ++i) {
+@@ -2118,7 +2006,7 @@ PHY_IQCalibrate_8723B(
+ break;
+ }
+ //RT_TRACE(_module_mp_, _drv_notice_,("Switch to S1 TxIQC(offset, data) = (0x%X, 0x%X)\n", offset, data));
+- ODM_SetBBReg(pDM_Odm,offset, bMaskDWord, data);
++ PHY_SetBBReg(pDM_Odm->Adapter,offset, bMaskDWord, data);
+ }
+
+ // Restore RX IQK
+@@ -2131,15 +2019,15 @@ PHY_IQCalibrate_8723B(
+ break;
+ }
+ //RT_TRACE(_module_mp_, _drv_notice_,("Switch to S1 RxIQC (offset, data) = (0x%X, 0x%X)\n", offset, data));
+- ODM_SetBBReg(pDM_Odm,offset, bMaskDWord, data);
++ PHY_SetBBReg(pDM_Odm->Adapter,offset, bMaskDWord, data);
+ }
+
+ if (pDM_Odm->RFCalibrateInfo.TxLOK[ODM_RF_PATH_A] ==0) {
+ DBG_871X("%s => Restore Path-A TxLOK result failed \n",__FUNCTION__);
+ bResult = FAIL;
+ } else {
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, RF_TXM_IDAC, bRFRegOffsetMask, pDM_Odm->RFCalibrateInfo.TxLOK[ODM_RF_PATH_A]);
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_B, RF_TXM_IDAC, bRFRegOffsetMask, pDM_Odm->RFCalibrateInfo.TxLOK[ODM_RF_PATH_B]);
++ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_TXM_IDAC, bRFRegOffsetMask, pDM_Odm->RFCalibrateInfo.TxLOK[ODM_RF_PATH_A]);
++ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_B, RF_TXM_IDAC, bRFRegOffsetMask, pDM_Odm->RFCalibrateInfo.TxLOK[ODM_RF_PATH_B]);
+ }
+
+ if (bResult == SUCCESS)
+@@ -2156,14 +2044,14 @@ PHY_IQCalibrate_8723B(
+ ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("IQK:Start!!!\n"));
+
+ //save default GNT_BT
+- GNT_BT_default = ODM_GetBBReg(pDM_Odm, 0x764, bMaskDWord);
++ GNT_BT_default = PHY_QueryBBReg(pDM_Odm->Adapter, 0x764, bMaskDWord);
+ // Save RF Path
+-// Path_SEL_BB = ODM_GetBBReg(pDM_Odm, 0x948, bMaskDWord);
+-// Path_SEL_RF = ODM_GetRFReg(pDM_Odm, ODM_RF_PATH_A, 0xb0, 0xfffff);
++// Path_SEL_BB = PHY_QueryBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord);
++// Path_SEL_RF = PHY_QueryRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0xb0, 0xfffff);
+
+ //set GNT_BT=0, pause BT traffic
+-// ODM_SetBBReg(pDM_Odm, 0x764, BIT12, 0x0);
+-// ODM_SetBBReg(pDM_Odm, 0x764, BIT11, 0x1);
++// PHY_SetBBReg(pDM_Odm->Adapter, 0x764, BIT12, 0x0);
++// PHY_SetBBReg(pDM_Odm->Adapter, 0x764, BIT11, 0x1);
+
+
+ for(i = 0; i < 8; i++)
+@@ -2290,22 +2178,22 @@ PHY_IQCalibrate_8723B(
+ _PHY_SaveADDARegisters8723B(pAdapter, IQK_BB_REG_92C, pDM_Odm->RFCalibrateInfo.IQK_BB_backup_recover, 9);
+
+ //restore GNT_BT
+- ODM_SetBBReg(pDM_Odm, 0x764, bMaskDWord, GNT_BT_default);
++ PHY_SetBBReg(pDM_Odm->Adapter, 0x764, bMaskDWord, GNT_BT_default);
+ // Restore RF Path
+-// ODM_SetBBReg(pDM_Odm, 0x948, bMaskDWord, Path_SEL_BB);
+-// ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, 0xb0, 0xfffff, Path_SEL_RF);
++// PHY_SetBBReg(pDM_Odm->Adapter, 0x948, bMaskDWord, Path_SEL_BB);
++// PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0xb0, 0xfffff, Path_SEL_RF);
+
+ //Resotr RX mode table parameter
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, RF_WE_LUT, 0x80000, 0x1 );
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x18000 );
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0001f );
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xe6177 );
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, 0xed, 0x20, 0x1 );
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, 0x43, bRFRegOffsetMask, 0x300bd );
++ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_WE_LUT, 0x80000, 0x1 );
++ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x18000 );
++ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0001f );
++ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xe6177 );
++ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0xed, 0x20, 0x1 );
++ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, 0x43, bRFRegOffsetMask, 0x300bd );
+
+ //set GNT_BT= HW control
+-// ODM_SetBBReg(pDM_Odm, 0x764, BIT12, 0x0);
+-// ODM_SetBBReg(pDM_Odm, 0x764, BIT11, 0x0);
++// PHY_SetBBReg(pDM_Odm->Adapter, 0x764, BIT12, 0x0);
++// PHY_SetBBReg(pDM_Odm->Adapter, 0x764, BIT11, 0x0);
+
+ if (Is2ant) {
+ if (RF_Path == 0x0) //S1
+@@ -2367,59 +2255,3 @@ PHY_LCCalibrate_8723B(
+ ProgressingTime = jiffies_to_msecs(jiffies - StartTime);
+ ODM_RT_TRACE(pDM_Odm,ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("LCK ProgressingTime = %d\n", ProgressingTime));
+ }
+-
+-void
+-PHY_APCalibrate_8723B(
+- IN PADAPTER pAdapter,
+- IN s8 delta
+- )
+-{
+- HAL_DATA_TYPE *pHalData = GET_HAL_DATA(pAdapter);
+- PDM_ODM_T pDM_Odm = &pHalData->odmpriv;
+-#if DISABLE_BB_RF
+- return;
+-#endif
+-
+- return;
+-
+- if(!(pDM_Odm->SupportAbility & ODM_RF_CALIBRATION))
+- {
+- return;
+- }
+-
+- if(pDM_Odm->RFCalibrateInfo.bAPKdone)
+- return;
+-
+- // For 88C 1T1R
+- phy_APCalibrate_8723B(pAdapter, delta, false);
+-}
+-static void phy_SetRFPathSwitch_8723B(
+- IN PADAPTER pAdapter,
+- IN bool bMain,
+- IN bool is2T
+- )
+-{
+- HAL_DATA_TYPE *pHalData = GET_HAL_DATA(pAdapter);
+- PDM_ODM_T pDM_Odm = &pHalData->odmpriv;
+-
+- if(bMain) // Left antenna
+- {
+- ODM_SetBBReg(pDM_Odm, 0x92C, bMaskDWord, 0x1);
+- }
+- else
+- {
+- ODM_SetBBReg(pDM_Odm, 0x92C, bMaskDWord, 0x2);
+- }
+-}
+-void PHY_SetRFPathSwitch_8723B(
+- IN PADAPTER pAdapter,
+- IN bool bMain
+- )
+-{
+-
+-#if DISABLE_BB_RF
+- return;
+-#endif
+-
+- phy_SetRFPathSwitch_8723B(pAdapter, bMain, true);
+-}
+diff -Nurp linux/3rdparty/rtl8723bs.old/hal/HalPhyRf_8723B.h linux/3rdparty/rtl8723bs/hal/HalPhyRf_8723B.h
+--- linux/3rdparty/rtl8723bs.old/hal/HalPhyRf_8723B.h 2015-05-10 14:36:05.702668280 +0300
++++ linux/3rdparty/rtl8723bs/hal/HalPhyRf_8723B.h 2015-05-07 17:46:55.000000000 +0300
+@@ -76,10 +76,6 @@ PHY_LCCalibrate_8723B(
+ // AP calibrate
+ //
+ void
+-PHY_APCalibrate_8723B(
+- IN PADAPTER pAdapter,
+- IN s8 delta);
+-void
+ PHY_DigitalPredistortion_8723B( IN PADAPTER pAdapter);
+
+
+diff -Nurp linux/3rdparty/rtl8723bs.old/hal/HalPhyRf.c linux/3rdparty/rtl8723bs/hal/HalPhyRf.c
+--- linux/3rdparty/rtl8723bs.old/hal/HalPhyRf.c 2015-05-10 14:36:05.702668280 +0300
++++ linux/3rdparty/rtl8723bs/hal/HalPhyRf.c 2015-05-07 17:46:55.000000000 +0300
+@@ -129,7 +129,7 @@ ODM_TXPowerTrackingCallback_ThermalMeter
+ \n pDM_Odm->BbSwingIdxCckBase: %d, pDM_Odm->BbSwingIdxOfdmBase[A]: %d, pDM_Odm->DefaultOfdmIndex: %d\n",
+ pDM_Odm->BbSwingIdxCckBase, pDM_Odm->BbSwingIdxOfdmBase[ODM_RF_PATH_A], pDM_Odm->DefaultOfdmIndex));
+
+- ThermalValue = (u1Byte)ODM_GetRFReg(pDM_Odm, ODM_RF_PATH_A, c.ThermalRegAddr, 0xfc00); //0x42: RF Reg[15:10] 88E
++ ThermalValue = (u1Byte)PHY_QueryRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, c.ThermalRegAddr, 0xfc00); //0x42: RF Reg[15:10] 88E
+ if( ! pDM_Odm->RFCalibrateInfo.TxPowerTrackControl || pHalData->EEPROMThermalMeter == 0 ||
+ pHalData->EEPROMThermalMeter == 0xFF)
+ return;
+diff -Nurp linux/3rdparty/rtl8723bs.old/hal/hal_sdio.c linux/3rdparty/rtl8723bs/hal/hal_sdio.c
+--- linux/3rdparty/rtl8723bs.old/hal/hal_sdio.c 2015-05-10 14:36:05.703668291 +0300
++++ linux/3rdparty/rtl8723bs/hal/hal_sdio.c 2015-05-07 17:46:55.000000000 +0300
+@@ -49,7 +49,7 @@ void rtw_hal_sdio_update_tx_freepage(_ad
+ u8 RequiredPublicFreePgNum = 0;
+ //_irqL irql;
+
+- //_enter_critical_bh(&pHalData->SdioTxFIFOFreePageLock, &irql);
++ //spin_lock_bh(&pHalData->SdioTxFIFOFreePageLock);
+
+ DedicatedPgNum = pHalData->SdioTxFIFOFreePage[PageIdx];
+ if (RequiredPageNum <= DedicatedPgNum) {
+@@ -60,7 +60,7 @@ void rtw_hal_sdio_update_tx_freepage(_ad
+ pHalData->SdioTxFIFOFreePage[PUBLIC_QUEUE_IDX] -= RequiredPublicFreePgNum;
+ }
+
+- //_exit_critical_bh(&pHalData->SdioTxFIFOFreePageLock, &irql);
++ //spin_unlock_bh(&pHalData->SdioTxFIFOFreePageLock);
+ }
+
+ void rtw_hal_set_sdio_tx_max_length(PADAPTER padapter, u8 numHQ, u8 numNQ, u8 numLQ, u8 numPubQ)
+diff -Nurp linux/3rdparty/rtl8723bs.old/hal/hal_sdio_led.c linux/3rdparty/rtl8723bs/hal/hal_sdio_led.c
+--- linux/3rdparty/rtl8723bs.old/hal/hal_sdio_led.c 2015-05-10 14:36:05.704668302 +0300
++++ linux/3rdparty/rtl8723bs/hal/hal_sdio_led.c 1970-01-01 02:00:00.000000000 +0200
+@@ -1,2395 +0,0 @@
+-/******************************************************************************
+- *
+- * 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.
+- *
+- * 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.,
+- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+- *
+- *
+- ******************************************************************************/
+-
+-#include
+-
+-//
+-// Description:
+-// Implementation of LED blinking behavior.
+-// It toggle off LED and schedule corresponding timer if necessary.
+-//
+-static void
+-SwLedBlink(
+- PLED_SDIO pLed
+- )
+-{
+- _adapter *padapter = pLed->padapter;
+- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+- u8 bStopBlinking = false;
+-
+- // Change LED according to BlinkingLedState specified.
+- if( pLed->BlinkingLedState == RTW_LED_ON )
+- {
+- SwLedOn(padapter, pLed);
+- RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("Blinktimes (%d): turn on\n", pLed->BlinkTimes));
+- }
+- else
+- {
+- SwLedOff(padapter, pLed);
+- RT_TRACE(_module_rtl8712_led_c_,_drv_info_,( "Blinktimes (%d): turn off\n", pLed->BlinkTimes));
+- }
+-
+- // Determine if we shall change LED state again.
+- pLed->BlinkTimes--;
+- switch(pLed->CurrLedState)
+- {
+-
+- case LED_BLINK_NORMAL:
+- if(pLed->BlinkTimes == 0)
+- {
+- bStopBlinking = true;
+- }
+- break;
+-
+- case LED_BLINK_StartToBlink:
+- if( check_fwstate(pmlmepriv, _FW_LINKED) && check_fwstate(pmlmepriv, WIFI_STATION_STATE) )
+- {
+- bStopBlinking = true;
+- }
+- if( check_fwstate(pmlmepriv, _FW_LINKED) &&
+- (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) || check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) )
+- {
+- bStopBlinking = true;
+- }
+- else if(pLed->BlinkTimes == 0)
+- {
+- bStopBlinking = true;
+- }
+- break;
+-
+- case LED_BLINK_WPS:
+- if( pLed->BlinkTimes == 0 )
+- {
+- bStopBlinking = true;
+- }
+- break;
+-
+-
+- default:
+- bStopBlinking = true;
+- break;
+-
+- }
+-
+- if(bStopBlinking)
+- {
+- if( adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on )
+- {
+- SwLedOff(padapter, pLed);
+- }
+- else if( (check_fwstate(pmlmepriv, _FW_LINKED)== true) && (pLed->bLedOn == false))
+- {
+- SwLedOn(padapter, pLed);
+- }
+- else if( (check_fwstate(pmlmepriv, _FW_LINKED)== false) && pLed->bLedOn == true)
+- {
+- SwLedOff(padapter, pLed);
+- }
+-
+- pLed->BlinkTimes = 0;
+- pLed->bLedBlinkInProgress = false;
+- }
+- else
+- {
+- // Assign LED state to toggle.
+- if( pLed->BlinkingLedState == RTW_LED_ON )
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- else
+- pLed->BlinkingLedState = RTW_LED_ON;
+-
+- // Schedule a timer to toggle LED state.
+- switch( pLed->CurrLedState )
+- {
+- case LED_BLINK_NORMAL:
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL);
+- break;
+-
+- case LED_BLINK_SLOWLY:
+- case LED_BLINK_StartToBlink:
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_SLOWLY_INTERVAL);
+- break;
+-
+- case LED_BLINK_WPS:
+- {
+- if( pLed->BlinkingLedState == RTW_LED_ON )
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_LONG_INTERVAL);
+- else
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_LONG_INTERVAL);
+- }
+- break;
+-
+- default:
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_SLOWLY_INTERVAL);
+- break;
+- }
+- }
+-}
+-
+-static void
+-SwLedBlink1(
+- PLED_SDIO pLed
+- )
+-{
+- _adapter *padapter = pLed->padapter;
+- EEPROM_EFUSE_PRIV *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
+- struct led_priv *ledpriv = &(padapter->ledpriv);
+- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+- PLED_SDIO pLed1 = &(ledpriv->SwLed1);
+- u8 bStopBlinking = false;
+-
+- if(pEEPROM->CustomerID == RT_CID_819x_CAMEO)
+- pLed = &(ledpriv->SwLed1);
+-
+- // Change LED according to BlinkingLedState specified.
+- if( pLed->BlinkingLedState == RTW_LED_ON )
+- {
+- SwLedOn(padapter, pLed);
+- RT_TRACE(_module_rtl8712_led_c_,_drv_info_,( "Blinktimes (%d): turn on\n", pLed->BlinkTimes));
+- }
+- else
+- {
+- SwLedOff(padapter, pLed);
+- RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("Blinktimes (%d): turn off\n", pLed->BlinkTimes));
+- }
+-
+-
+- if(pEEPROM->CustomerID == RT_CID_DEFAULT)
+- {
+- if(check_fwstate(pmlmepriv, _FW_LINKED)== true)
+- {
+- if(!pLed1->bSWLedCtrl)
+- {
+- SwLedOn(padapter, pLed1);
+- pLed1->bSWLedCtrl = true;
+- }
+- else if(!pLed1->bLedOn)
+- SwLedOn(padapter, pLed1);
+- RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("Blinktimes (): turn on pLed1\n"));
+- }
+- else
+- {
+- if(!pLed1->bSWLedCtrl)
+- {
+- SwLedOff(padapter, pLed1);
+- pLed1->bSWLedCtrl = true;
+- }
+- else if(pLed1->bLedOn)
+- SwLedOff(padapter, pLed1);
+- RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("Blinktimes (): turn off pLed1\n"));
+- }
+- }
+-
+- switch(pLed->CurrLedState)
+- {
+- case LED_BLINK_SLOWLY:
+- if( pLed->bLedOn )
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- else
+- pLed->BlinkingLedState = RTW_LED_ON;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA);
+- break;
+-
+- case LED_BLINK_NORMAL:
+- if( pLed->bLedOn )
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- else
+- pLed->BlinkingLedState = RTW_LED_ON;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_LINK_INTERVAL_ALPHA);
+- break;
+-
+- case LED_BLINK_SCAN:
+- pLed->BlinkTimes--;
+- if( pLed->BlinkTimes == 0 )
+- {
+- bStopBlinking = true;
+- }
+-
+- if(bStopBlinking)
+- {
+- if( adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on )
+- {
+- SwLedOff(padapter, pLed);
+- }
+- else if(check_fwstate(pmlmepriv, _FW_LINKED)== true)
+- {
+- pLed->bLedLinkBlinkInProgress = true;
+- pLed->CurrLedState = LED_BLINK_NORMAL;
+- if( pLed->bLedOn )
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- else
+- pLed->BlinkingLedState = RTW_LED_ON;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_LINK_INTERVAL_ALPHA);
+- RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("CurrLedState %d\n", pLed->CurrLedState));
+-
+- }
+- else if(check_fwstate(pmlmepriv, _FW_LINKED)== false)
+- {
+- pLed->bLedNoLinkBlinkInProgress = true;
+- pLed->CurrLedState = LED_BLINK_SLOWLY;
+- if( pLed->bLedOn )
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- else
+- pLed->BlinkingLedState = RTW_LED_ON;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA);
+- RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("CurrLedState %d\n", pLed->CurrLedState));
+- }
+- pLed->bLedScanBlinkInProgress = false;
+- }
+- else
+- {
+- if( adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on )
+- {
+- SwLedOff(padapter, pLed);
+- }
+- else
+- {
+- if( pLed->bLedOn )
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- else
+- pLed->BlinkingLedState = RTW_LED_ON;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA);
+- }
+- }
+- break;
+-
+- case LED_BLINK_TXRX:
+- pLed->BlinkTimes--;
+- if( pLed->BlinkTimes == 0 )
+- {
+- bStopBlinking = true;
+- }
+- if(bStopBlinking)
+- {
+- if( adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on )
+- {
+- SwLedOff(padapter, pLed);
+- }
+- else if(check_fwstate(pmlmepriv, _FW_LINKED)== true)
+- {
+- pLed->bLedLinkBlinkInProgress = true;
+- pLed->CurrLedState = LED_BLINK_NORMAL;
+- if( pLed->bLedOn )
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- else
+- pLed->BlinkingLedState = RTW_LED_ON;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_LINK_INTERVAL_ALPHA);
+- RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("CurrLedState %d\n", pLed->CurrLedState));
+- }
+- else if(check_fwstate(pmlmepriv, _FW_LINKED)== false)
+- {
+- pLed->bLedNoLinkBlinkInProgress = true;
+- pLed->CurrLedState = LED_BLINK_SLOWLY;
+- if( pLed->bLedOn )
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- else
+- pLed->BlinkingLedState = RTW_LED_ON;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA);
+- RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("CurrLedState %d\n", pLed->CurrLedState));
+- }
+- pLed->BlinkTimes = 0;
+- pLed->bLedBlinkInProgress = false;
+- }
+- else
+- {
+- if( adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on )
+- {
+- SwLedOff(padapter, pLed);
+- }
+- else
+- {
+- if( pLed->bLedOn )
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- else
+- pLed->BlinkingLedState = RTW_LED_ON;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA);
+- }
+- }
+- break;
+-
+- case LED_BLINK_WPS:
+- if( pLed->bLedOn )
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- else
+- pLed->BlinkingLedState = RTW_LED_ON;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA);
+- break;
+-
+- case LED_BLINK_WPS_STOP: //WPS success
+- if(pLed->BlinkingLedState == RTW_LED_ON)
+- {
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_WPS_SUCESS_INTERVAL_ALPHA);
+- bStopBlinking = false;
+- }
+- else
+- {
+- bStopBlinking = true;
+- }
+-
+- if(bStopBlinking)
+- {
+- if( adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on )
+- {
+- SwLedOff(padapter, pLed);
+- }
+- else
+- {
+- pLed->bLedLinkBlinkInProgress = true;
+- pLed->CurrLedState = LED_BLINK_NORMAL;
+- if( pLed->bLedOn )
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- else
+- pLed->BlinkingLedState = RTW_LED_ON;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_LINK_INTERVAL_ALPHA);
+- RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("CurrLedState %d\n", pLed->CurrLedState));
+- }
+- pLed->bLedWPSBlinkInProgress = false;
+- }
+- break;
+-
+- default:
+- break;
+- }
+-
+-}
+-
+-static void
+-SwLedBlink2(
+- PLED_SDIO pLed
+- )
+-{
+- _adapter *padapter = pLed->padapter;
+- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+- u8 bStopBlinking = false;
+-
+- // Change LED according to BlinkingLedState specified.
+- if( pLed->BlinkingLedState == RTW_LED_ON)
+- {
+- SwLedOn(padapter, pLed);
+- RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("Blinktimes (%d): turn on\n", pLed->BlinkTimes));
+- }
+- else
+- {
+- SwLedOff(padapter, pLed);
+- RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("Blinktimes (%d): turn off\n", pLed->BlinkTimes));
+- }
+-
+- switch(pLed->CurrLedState)
+- {
+- case LED_BLINK_SCAN:
+- pLed->BlinkTimes--;
+- if( pLed->BlinkTimes == 0 )
+- {
+- bStopBlinking = true;
+- }
+-
+- if(bStopBlinking)
+- {
+- if( adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on )
+- {
+- SwLedOff(padapter, pLed);
+- }
+- else if(check_fwstate(pmlmepriv, _FW_LINKED)== true)
+- {
+- pLed->CurrLedState = RTW_LED_ON;
+- pLed->BlinkingLedState = RTW_LED_ON;
+- SwLedOn(padapter, pLed);
+- RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("stop scan blink CurrLedState %d\n", pLed->CurrLedState));
+-
+- }
+- else if(check_fwstate(pmlmepriv, _FW_LINKED)== false)
+- {
+- pLed->CurrLedState = RTW_LED_OFF;
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- SwLedOff(padapter, pLed);
+- RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("stop scan blink CurrLedState %d\n", pLed->CurrLedState));
+- }
+- pLed->bLedScanBlinkInProgress = false;
+- }
+- else
+- {
+- if( adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on )
+- {
+- SwLedOff(padapter, pLed);
+- }
+- else
+- {
+- if( pLed->bLedOn )
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- else
+- pLed->BlinkingLedState = RTW_LED_ON;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA);
+- }
+- }
+- break;
+-
+- case LED_BLINK_TXRX:
+- pLed->BlinkTimes--;
+- if( pLed->BlinkTimes == 0 )
+- {
+- bStopBlinking = true;
+- }
+- if(bStopBlinking)
+- {
+- if( adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on )
+- {
+- SwLedOff(padapter, pLed);
+- }
+- else if(check_fwstate(pmlmepriv, _FW_LINKED)== true)
+- {
+- pLed->CurrLedState = RTW_LED_ON;
+- pLed->BlinkingLedState = RTW_LED_ON;
+- SwLedOn(padapter, pLed);
+- RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("stop CurrLedState %d\n", pLed->CurrLedState));
+-
+- }
+- else if(check_fwstate(pmlmepriv, _FW_LINKED)== false)
+- {
+- pLed->CurrLedState = RTW_LED_OFF;
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- SwLedOff(padapter, pLed);
+- RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("stop CurrLedState %d\n", pLed->CurrLedState));
+- }
+- pLed->bLedBlinkInProgress = false;
+- }
+- else
+- {
+- if( adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on )
+- {
+- SwLedOff(padapter, pLed);
+- }
+- else
+- {
+- if( pLed->bLedOn )
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- else
+- pLed->BlinkingLedState = RTW_LED_ON;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA);
+- }
+- }
+- break;
+-
+- default:
+- break;
+- }
+-
+-}
+-
+-static void
+-SwLedBlink3(
+- PLED_SDIO pLed
+- )
+-{
+- _adapter *padapter = pLed->padapter;
+- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+- u8 bStopBlinking = false;
+-
+- // Change LED according to BlinkingLedState specified.
+- if( pLed->BlinkingLedState == RTW_LED_ON )
+- {
+- SwLedOn(padapter, pLed);
+- RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("Blinktimes (%d): turn on\n", pLed->BlinkTimes));
+- }
+- else
+- {
+- if(pLed->CurrLedState != LED_BLINK_WPS_STOP)
+- SwLedOff(padapter, pLed);
+- RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("Blinktimes (%d): turn off\n", pLed->BlinkTimes));
+- }
+-
+- switch(pLed->CurrLedState)
+- {
+- case LED_BLINK_SCAN:
+- pLed->BlinkTimes--;
+- if( pLed->BlinkTimes == 0 )
+- {
+- bStopBlinking = true;
+- }
+-
+- if(bStopBlinking)
+- {
+- if( adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on )
+- {
+- SwLedOff(padapter, pLed);
+- }
+- else if(check_fwstate(pmlmepriv, _FW_LINKED)== true)
+- {
+- pLed->CurrLedState = RTW_LED_ON;
+- pLed->BlinkingLedState = RTW_LED_ON;
+- if( !pLed->bLedOn )
+- SwLedOn(padapter, pLed);
+-
+- RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("CurrLedState %d\n", pLed->CurrLedState));
+- }
+- else if(check_fwstate(pmlmepriv, _FW_LINKED)== false)
+- {
+- pLed->CurrLedState = RTW_LED_OFF;
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- if( pLed->bLedOn )
+- SwLedOff(padapter, pLed);
+-
+- RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("CurrLedState %d\n", pLed->CurrLedState));
+- }
+- pLed->bLedScanBlinkInProgress = false;
+- }
+- else
+- {
+- if( adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on )
+- {
+- SwLedOff(padapter, pLed);
+- }
+- else
+- {
+- if( pLed->bLedOn )
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- else
+- pLed->BlinkingLedState = RTW_LED_ON;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA);
+- }
+- }
+- break;
+-
+- case LED_BLINK_TXRX:
+- pLed->BlinkTimes--;
+- if( pLed->BlinkTimes == 0 )
+- {
+- bStopBlinking = true;
+- }
+- if(bStopBlinking)
+- {
+- if( adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on )
+- {
+- SwLedOff(padapter, pLed);
+- }
+- else if(check_fwstate(pmlmepriv, _FW_LINKED)== true)
+- {
+- pLed->CurrLedState = RTW_LED_ON;
+- pLed->BlinkingLedState = RTW_LED_ON;
+-
+- if( !pLed->bLedOn )
+- SwLedOn(padapter, pLed);
+-
+- RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("CurrLedState %d\n", pLed->CurrLedState));
+- }
+- else if(check_fwstate(pmlmepriv, _FW_LINKED)== false)
+- {
+- pLed->CurrLedState = RTW_LED_OFF;
+- pLed->BlinkingLedState = RTW_LED_OFF;
+-
+- if( pLed->bLedOn )
+- SwLedOff(padapter, pLed);
+-
+-
+- RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("CurrLedState %d\n", pLed->CurrLedState));
+- }
+- pLed->bLedBlinkInProgress = false;
+- }
+- else
+- {
+- if( adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on )
+- {
+- SwLedOff(padapter, pLed);
+- }
+- else
+- {
+- if( pLed->bLedOn )
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- else
+- pLed->BlinkingLedState = RTW_LED_ON;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA);
+- }
+- }
+- break;
+-
+- case LED_BLINK_WPS:
+- if( pLed->bLedOn )
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- else
+- pLed->BlinkingLedState = RTW_LED_ON;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA);
+- break;
+-
+- case LED_BLINK_WPS_STOP: //WPS success
+- if(pLed->BlinkingLedState == RTW_LED_ON)
+- {
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_WPS_SUCESS_INTERVAL_ALPHA);
+- bStopBlinking = false;
+- }
+- else
+- {
+- bStopBlinking = true;
+- }
+-
+- if(bStopBlinking)
+- {
+- if( adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on )
+- {
+- SwLedOff(padapter, pLed);
+- }
+- else
+- {
+- pLed->CurrLedState = RTW_LED_ON;
+- pLed->BlinkingLedState = RTW_LED_ON;
+- SwLedOn(padapter, pLed);
+- RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("CurrLedState %d\n", pLed->CurrLedState));
+- }
+- pLed->bLedWPSBlinkInProgress = false;
+- }
+- break;
+-
+-
+- default:
+- break;
+- }
+-
+-}
+-
+-
+-static void
+-SwLedBlink4(
+- PLED_SDIO pLed
+- )
+-{
+- _adapter *padapter = pLed->padapter;
+- struct led_priv *ledpriv = &(padapter->ledpriv);
+- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+- PLED_SDIO pLed1 = &(ledpriv->SwLed1);
+- u8 bStopBlinking = false;
+-
+- // Change LED according to BlinkingLedState specified.
+- if( pLed->BlinkingLedState == RTW_LED_ON )
+- {
+- SwLedOn(padapter, pLed);
+- RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("Blinktimes (%d): turn on\n", pLed->BlinkTimes));
+- }
+- else
+- {
+- SwLedOff(padapter, pLed);
+- RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("Blinktimes (%d): turn off\n", pLed->BlinkTimes));
+- }
+-
+- if(!pLed1->bLedWPSBlinkInProgress && pLed1->BlinkingLedState == LED_UNKNOWN)
+- {
+- pLed1->BlinkingLedState = RTW_LED_OFF;
+- pLed1->CurrLedState = RTW_LED_OFF;
+- SwLedOff(padapter, pLed1);
+- }
+-
+- switch(pLed->CurrLedState)
+- {
+- case LED_BLINK_SLOWLY:
+- if( pLed->bLedOn )
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- else
+- pLed->BlinkingLedState = RTW_LED_ON;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA);
+- break;
+-
+- case LED_BLINK_StartToBlink:
+- if( pLed->bLedOn )
+- {
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_SLOWLY_INTERVAL);
+- }
+- else
+- {
+- pLed->BlinkingLedState = RTW_LED_ON;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL);
+- }
+- break;
+-
+- case LED_BLINK_SCAN:
+- pLed->BlinkTimes--;
+- if( pLed->BlinkTimes == 0 )
+- {
+- bStopBlinking = false;
+- }
+-
+- if(bStopBlinking)
+- {
+- if( adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on && adapter_to_pwrctl(padapter)->rfoff_reason > RF_CHANGE_BY_PS)
+- {
+- SwLedOff(padapter, pLed);
+- }
+- else
+- {
+- pLed->bLedNoLinkBlinkInProgress = false;
+- pLed->CurrLedState = LED_BLINK_SLOWLY;
+- if( pLed->bLedOn )
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- else
+- pLed->BlinkingLedState = RTW_LED_ON;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA);
+- }
+- pLed->bLedScanBlinkInProgress = false;
+- }
+- else
+- {
+- if( adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on && adapter_to_pwrctl(padapter)->rfoff_reason > RF_CHANGE_BY_PS)
+- {
+- SwLedOff(padapter, pLed);
+- }
+- else
+- {
+- if( pLed->bLedOn )
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- else
+- pLed->BlinkingLedState = RTW_LED_ON;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA);
+- }
+- }
+- break;
+-
+- case LED_BLINK_TXRX:
+- pLed->BlinkTimes--;
+- if( pLed->BlinkTimes == 0 )
+- {
+- bStopBlinking = true;
+- }
+- if(bStopBlinking)
+- {
+- if( adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on && adapter_to_pwrctl(padapter)->rfoff_reason > RF_CHANGE_BY_PS)
+- {
+- SwLedOff(padapter, pLed);
+- }
+- else
+- {
+- pLed->bLedNoLinkBlinkInProgress = true;
+- pLed->CurrLedState = LED_BLINK_SLOWLY;
+- if( pLed->bLedOn )
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- else
+- pLed->BlinkingLedState = RTW_LED_ON;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA);
+- }
+- pLed->bLedBlinkInProgress = false;
+- }
+- else
+- {
+- if( adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on && adapter_to_pwrctl(padapter)->rfoff_reason > RF_CHANGE_BY_PS)
+- {
+- SwLedOff(padapter, pLed);
+- }
+- else
+- {
+- if( pLed->bLedOn )
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- else
+- pLed->BlinkingLedState = RTW_LED_ON;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA);
+- }
+- }
+- break;
+-
+- case LED_BLINK_WPS:
+- if( pLed->bLedOn )
+- {
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_SLOWLY_INTERVAL);
+- }
+- else
+- {
+- pLed->BlinkingLedState = RTW_LED_ON;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL);
+- }
+- break;
+-
+- case LED_BLINK_WPS_STOP: //WPS authentication fail
+- if( pLed->bLedOn )
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- else
+- pLed->BlinkingLedState = RTW_LED_ON;
+-
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL);
+- break;
+-
+- case LED_BLINK_WPS_STOP_OVERLAP: //WPS session overlap
+- pLed->BlinkTimes--;
+- if(pLed->BlinkTimes == 0)
+- {
+- if(pLed->bLedOn)
+- {
+- pLed->BlinkTimes = 1;
+- }
+- else
+- {
+- bStopBlinking = true;
+- }
+- }
+-
+- if(bStopBlinking)
+- {
+- pLed->BlinkTimes = 10;
+- pLed->BlinkingLedState = RTW_LED_ON;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_LINK_INTERVAL_ALPHA);
+- }
+- else
+- {
+- if( pLed->bLedOn )
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- else
+- pLed->BlinkingLedState = RTW_LED_ON;
+-
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL);
+- }
+- break;
+-
+- default:
+- break;
+- }
+-
+- RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("SwLedBlink4 CurrLedState %d\n", pLed->CurrLedState));
+-
+-
+-}
+-
+-static void
+-SwLedBlink5(
+- PLED_SDIO pLed
+- )
+-{
+- _adapter *padapter = pLed->padapter;
+- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+- u8 bStopBlinking = false;
+-
+- // Change LED according to BlinkingLedState specified.
+- if( pLed->BlinkingLedState == RTW_LED_ON )
+- {
+- SwLedOn(padapter, pLed);
+- RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("Blinktimes (%d): turn on\n", pLed->BlinkTimes));
+- }
+- else
+- {
+- SwLedOff(padapter, pLed);
+- RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("Blinktimes (%d): turn off\n", pLed->BlinkTimes));
+- }
+-
+- switch(pLed->CurrLedState)
+- {
+- case LED_BLINK_SCAN:
+- pLed->BlinkTimes--;
+- if( pLed->BlinkTimes == 0 )
+- {
+- bStopBlinking = true;
+- }
+-
+- if(bStopBlinking)
+- {
+- if( adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on && adapter_to_pwrctl(padapter)->rfoff_reason > RF_CHANGE_BY_PS)
+- {
+- pLed->CurrLedState = RTW_LED_OFF;
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- if(pLed->bLedOn)
+- SwLedOff(padapter, pLed);
+- }
+- else
+- { pLed->CurrLedState = RTW_LED_ON;
+- pLed->BlinkingLedState = RTW_LED_ON;
+- if(!pLed->bLedOn)
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA);
+- }
+-
+- pLed->bLedScanBlinkInProgress = false;
+- }
+- else
+- {
+- if( adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on && adapter_to_pwrctl(padapter)->rfoff_reason > RF_CHANGE_BY_PS)
+- {
+- SwLedOff(padapter, pLed);
+- }
+- else
+- {
+- if( pLed->bLedOn )
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- else
+- pLed->BlinkingLedState = RTW_LED_ON;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA);
+- }
+- }
+- break;
+-
+-
+- case LED_BLINK_TXRX:
+- pLed->BlinkTimes--;
+- if( pLed->BlinkTimes == 0 )
+- {
+- bStopBlinking = true;
+- }
+-
+- if(bStopBlinking)
+- {
+- if( adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on && adapter_to_pwrctl(padapter)->rfoff_reason > RF_CHANGE_BY_PS)
+- {
+- pLed->CurrLedState = RTW_LED_OFF;
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- if(pLed->bLedOn)
+- SwLedOff(padapter, pLed);
+- }
+- else
+- {
+- pLed->CurrLedState = RTW_LED_ON;
+- pLed->BlinkingLedState = RTW_LED_ON;
+- if(!pLed->bLedOn)
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA);
+- }
+-
+- pLed->bLedBlinkInProgress = false;
+- }
+- else
+- {
+- if( adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on && adapter_to_pwrctl(padapter)->rfoff_reason > RF_CHANGE_BY_PS)
+- {
+- SwLedOff(padapter, pLed);
+- }
+- else
+- {
+- if( pLed->bLedOn )
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- else
+- pLed->BlinkingLedState = RTW_LED_ON;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA);
+- }
+- }
+- break;
+-
+- default:
+- break;
+- }
+-
+- RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("SwLedBlink5 CurrLedState %d\n", pLed->CurrLedState));
+-
+-
+-}
+-
+-static void
+-SwLedBlink6(
+- PLED_SDIO pLed
+- )
+-{
+- _adapter *padapter = pLed->padapter;
+- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+- u8 bStopBlinking = false;
+-
+- // Change LED according to BlinkingLedState specified.
+- if( pLed->BlinkingLedState == RTW_LED_ON )
+- {
+- SwLedOn(padapter, pLed);
+- RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("Blinktimes (%d): turn on\n", pLed->BlinkTimes));
+- }
+- else
+- {
+- SwLedOff(padapter, pLed);
+- RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("Blinktimes (%d): turn off\n", pLed->BlinkTimes));
+- }
+-
+- RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("<==== blink6\n"));
+-}
+-
+-//
+-// Description:
+-// Handler function of LED Blinking.
+-// We dispatch acture LED blink action according to LedStrategy.
+-//
+-void BlinkHandler(PLED_SDIO pLed)
+-{
+- _adapter *padapter = pLed->padapter;
+- struct led_priv *ledpriv = &(padapter->ledpriv);
+-
+- //DBG_871X("%s (%s:%d)\n",__FUNCTION__, current->comm, current->pid);
+-
+- if( (padapter->bSurpriseRemoved == true) || ( padapter->bDriverStopped == true))
+- {
+- //DBG_871X("%s bSurpriseRemoved:%d, bDriverStopped:%d\n", __FUNCTION__, padapter->bSurpriseRemoved, padapter->bDriverStopped);
+- return;
+- }
+-
+- switch(ledpriv->LedStrategy)
+- {
+- case SW_LED_MODE0:
+- SwLedBlink(pLed);
+- break;
+-
+- case SW_LED_MODE1:
+- SwLedBlink1(pLed);
+- break;
+-
+- case SW_LED_MODE2:
+- SwLedBlink2(pLed);
+- break;
+-
+- case SW_LED_MODE3:
+- SwLedBlink3(pLed);
+- break;
+-
+- case SW_LED_MODE4:
+- SwLedBlink4(pLed);
+- break;
+-
+- case SW_LED_MODE5:
+- SwLedBlink5(pLed);
+- break;
+-
+- case SW_LED_MODE6:
+- SwLedBlink6(pLed);
+- break;
+-
+- default:
+- //RT_TRACE(COMP_LED, DBG_LOUD, ("BlinkWorkItemCallback 0x%x \n", pHalData->LedStrategy));
+- //SwLedBlink(pLed);
+- break;
+- }
+-}
+-
+-//
+-// Description:
+-// Callback function of LED BlinkTimer,
+-// it just schedules to corresponding BlinkWorkItem/led_blink_hdl
+-//
+-void BlinkTimerCallback(void *data)
+-{
+- PLED_SDIO pLed = (PLED_SDIO)data;
+- _adapter *padapter = pLed->padapter;
+-
+- //DBG_871X("%s\n", __FUNCTION__);
+-
+- if( (padapter->bSurpriseRemoved == true) || ( padapter->bDriverStopped == true))
+- {
+- //DBG_871X("%s bSurpriseRemoved:%d, bDriverStopped:%d\n", __FUNCTION__, padapter->bSurpriseRemoved, padapter->bDriverStopped);
+- return;
+- }
+-
+- _set_workitem(&(pLed->BlinkWorkItem));
+-}
+-
+-//
+-// Description:
+-// Callback function of LED BlinkWorkItem.
+-// We dispatch acture LED blink action according to LedStrategy.
+-//
+-void BlinkWorkItemCallback(_workitem *work)
+-{
+- PLED_SDIO pLed = container_of(work, LED_SDIO, BlinkWorkItem);
+- BlinkHandler(pLed);
+-}
+-
+-static void
+-SwLedControlMode0(
+- _adapter *padapter,
+- LED_CTL_MODE LedAction
+-)
+-{
+- struct led_priv *ledpriv = &(padapter->ledpriv);
+- PLED_SDIO pLed = &(ledpriv->SwLed1);
+-
+- // Decide led state
+- switch(LedAction)
+- {
+- case LED_CTL_TX:
+- case LED_CTL_RX:
+- if( pLed->bLedBlinkInProgress == false )
+- {
+- pLed->bLedBlinkInProgress = true;
+-
+- pLed->CurrLedState = LED_BLINK_NORMAL;
+- pLed->BlinkTimes = 2;
+-
+- if( pLed->bLedOn )
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- else
+- pLed->BlinkingLedState = RTW_LED_ON;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL);
+- }
+- break;
+-
+- case LED_CTL_START_TO_LINK:
+- if( pLed->bLedBlinkInProgress == false )
+- {
+- pLed->bLedBlinkInProgress = true;
+-
+- pLed->CurrLedState = LED_BLINK_StartToBlink;
+- pLed->BlinkTimes = 24;
+-
+- if( pLed->bLedOn )
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- else
+- pLed->BlinkingLedState = RTW_LED_ON;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_SLOWLY_INTERVAL);
+- }
+- else
+- {
+- pLed->CurrLedState = LED_BLINK_StartToBlink;
+- }
+- break;
+-
+- case LED_CTL_LINK:
+- pLed->CurrLedState = RTW_LED_ON;
+- if( pLed->bLedBlinkInProgress == false )
+- {
+- pLed->BlinkingLedState = RTW_LED_ON;
+- _set_timer(&(pLed->BlinkTimer), 0);
+- }
+- break;
+-
+- case LED_CTL_NO_LINK:
+- pLed->CurrLedState = RTW_LED_OFF;
+- if( pLed->bLedBlinkInProgress == false )
+- {
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- _set_timer(&(pLed->BlinkTimer), 0);
+- }
+- break;
+-
+- case LED_CTL_POWER_OFF:
+- pLed->CurrLedState = RTW_LED_OFF;
+- if(pLed->bLedBlinkInProgress)
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedBlinkInProgress = false;
+- }
+- SwLedOff(padapter, pLed);
+- break;
+-
+- case LED_CTL_START_WPS:
+- if( pLed->bLedBlinkInProgress == false || pLed->CurrLedState == RTW_LED_ON)
+- {
+- pLed->bLedBlinkInProgress = true;
+-
+- pLed->CurrLedState = LED_BLINK_WPS;
+- pLed->BlinkTimes = 20;
+-
+- if( pLed->bLedOn )
+- {
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_LONG_INTERVAL);
+- }
+- else
+- {
+- pLed->BlinkingLedState = RTW_LED_ON;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_LONG_INTERVAL);
+- }
+- }
+- break;
+-
+- case LED_CTL_STOP_WPS:
+- if(pLed->bLedBlinkInProgress)
+- {
+- pLed->CurrLedState = RTW_LED_OFF;
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedBlinkInProgress = false;
+- }
+- break;
+-
+-
+- default:
+- break;
+- }
+-
+- RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("Led %d\n", pLed->CurrLedState));
+-
+-}
+-
+- //ALPHA, added by chiyoko, 20090106
+-static void
+-SwLedControlMode1(
+- _adapter *padapter,
+- LED_CTL_MODE LedAction
+-)
+-{
+- struct led_priv *ledpriv = &(padapter->ledpriv);
+- PLED_SDIO pLed = &(ledpriv->SwLed0);
+- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+- EEPROM_EFUSE_PRIV *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
+-
+- if(pEEPROM->CustomerID == RT_CID_819x_CAMEO)
+- pLed = &(ledpriv->SwLed1);
+-
+- switch(LedAction)
+- {
+- case LED_CTL_POWER_ON:
+- case LED_CTL_START_TO_LINK:
+- case LED_CTL_NO_LINK:
+- if( pLed->bLedNoLinkBlinkInProgress == false )
+- {
+- if(pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed))
+- {
+- return;
+- }
+- if( pLed->bLedLinkBlinkInProgress == true )
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedLinkBlinkInProgress = false;
+- }
+- if(pLed->bLedBlinkInProgress ==true)
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedBlinkInProgress = false;
+- }
+-
+- pLed->bLedNoLinkBlinkInProgress = true;
+- pLed->CurrLedState = LED_BLINK_SLOWLY;
+- if( pLed->bLedOn )
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- else
+- pLed->BlinkingLedState = RTW_LED_ON;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA);
+- }
+- break;
+-
+- case LED_CTL_LINK:
+- if( pLed->bLedLinkBlinkInProgress == false )
+- {
+- if(pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed))
+- {
+- return;
+- }
+- if(pLed->bLedNoLinkBlinkInProgress == true)
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedNoLinkBlinkInProgress = false;
+- }
+- if(pLed->bLedBlinkInProgress ==true)
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedBlinkInProgress = false;
+- }
+- pLed->bLedLinkBlinkInProgress = true;
+- pLed->CurrLedState = LED_BLINK_NORMAL;
+- if( pLed->bLedOn )
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- else
+- pLed->BlinkingLedState = RTW_LED_ON;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_LINK_INTERVAL_ALPHA);
+- }
+- break;
+-
+- case LED_CTL_SITE_SURVEY:
+- if((pmlmepriv->LinkDetectInfo.bBusyTraffic) && (check_fwstate(pmlmepriv, _FW_LINKED)== true))
+- ;
+- else if(pLed->bLedScanBlinkInProgress ==false)
+- {
+- if(IS_LED_WPS_BLINKING(pLed))
+- return;
+-
+- if(pLed->bLedNoLinkBlinkInProgress == true)
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedNoLinkBlinkInProgress = false;
+- }
+- if( pLed->bLedLinkBlinkInProgress == true )
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedLinkBlinkInProgress = false;
+- }
+- if(pLed->bLedBlinkInProgress ==true)
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedBlinkInProgress = false;
+- }
+- pLed->bLedScanBlinkInProgress = true;
+- pLed->CurrLedState = LED_BLINK_SCAN;
+- pLed->BlinkTimes = 24;
+- if( pLed->bLedOn )
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- else
+- pLed->BlinkingLedState = RTW_LED_ON;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA);
+-
+- }
+- break;
+-
+- case LED_CTL_TX:
+- case LED_CTL_RX:
+- if(pLed->bLedBlinkInProgress ==false)
+- {
+- if(pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed))
+- {
+- return;
+- }
+- if(pLed->bLedNoLinkBlinkInProgress == true)
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedNoLinkBlinkInProgress = false;
+- }
+- if( pLed->bLedLinkBlinkInProgress == true )
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedLinkBlinkInProgress = false;
+- }
+- pLed->bLedBlinkInProgress = true;
+- pLed->CurrLedState = LED_BLINK_TXRX;
+- pLed->BlinkTimes = 2;
+- if( pLed->bLedOn )
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- else
+- pLed->BlinkingLedState = RTW_LED_ON;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA);
+- }
+- break;
+-
+- case LED_CTL_START_WPS: //wait until xinpin finish
+- case LED_CTL_START_WPS_BOTTON:
+- if(pLed->bLedWPSBlinkInProgress ==false)
+- {
+- if(pLed->bLedNoLinkBlinkInProgress == true)
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedNoLinkBlinkInProgress = false;
+- }
+- if( pLed->bLedLinkBlinkInProgress == true )
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedLinkBlinkInProgress = false;
+- }
+- if(pLed->bLedBlinkInProgress ==true)
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedBlinkInProgress = false;
+- }
+- if(pLed->bLedScanBlinkInProgress ==true)
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedScanBlinkInProgress = false;
+- }
+- pLed->bLedWPSBlinkInProgress = true;
+- pLed->CurrLedState = LED_BLINK_WPS;
+- if( pLed->bLedOn )
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- else
+- pLed->BlinkingLedState = RTW_LED_ON;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA);
+- }
+- break;
+-
+-
+- case LED_CTL_STOP_WPS:
+- if(pLed->bLedNoLinkBlinkInProgress == true)
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedNoLinkBlinkInProgress = false;
+- }
+- if( pLed->bLedLinkBlinkInProgress == true )
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedLinkBlinkInProgress = false;
+- }
+- if(pLed->bLedBlinkInProgress ==true)
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedBlinkInProgress = false;
+- }
+- if(pLed->bLedScanBlinkInProgress ==true)
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedScanBlinkInProgress = false;
+- }
+- if(pLed->bLedWPSBlinkInProgress)
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- }
+- else
+- {
+- pLed->bLedWPSBlinkInProgress = true;
+- }
+-
+- pLed->CurrLedState = LED_BLINK_WPS_STOP;
+- if(pLed->bLedOn)
+- {
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_WPS_SUCESS_INTERVAL_ALPHA);
+- }
+- else
+- {
+- pLed->BlinkingLedState = RTW_LED_ON;
+- _set_timer(&(pLed->BlinkTimer), 0);
+- }
+- break;
+-
+- case LED_CTL_STOP_WPS_FAIL:
+- if(pLed->bLedWPSBlinkInProgress)
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedWPSBlinkInProgress = false;
+- }
+-
+- pLed->bLedNoLinkBlinkInProgress = true;
+- pLed->CurrLedState = LED_BLINK_SLOWLY;
+- if( pLed->bLedOn )
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- else
+- pLed->BlinkingLedState = RTW_LED_ON;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA);
+- break;
+-
+- case LED_CTL_POWER_OFF:
+- pLed->CurrLedState = RTW_LED_OFF;
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- if( pLed->bLedNoLinkBlinkInProgress)
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedNoLinkBlinkInProgress = false;
+- }
+- if( pLed->bLedLinkBlinkInProgress)
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedLinkBlinkInProgress = false;
+- }
+- if( pLed->bLedBlinkInProgress)
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedBlinkInProgress = false;
+- }
+- if( pLed->bLedWPSBlinkInProgress )
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedWPSBlinkInProgress = false;
+- }
+- if( pLed->bLedScanBlinkInProgress)
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedScanBlinkInProgress = false;
+- }
+-
+- SwLedOff(padapter, pLed);
+- break;
+-
+- default:
+- break;
+-
+- }
+-
+- RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("Led %d\n", pLed->CurrLedState));
+-}
+-
+- //Arcadyan/Sitecom , added by chiyoko, 20090216
+-static void
+-SwLedControlMode2(
+- _adapter *padapter,
+- LED_CTL_MODE LedAction
+-)
+-{
+- struct led_priv *ledpriv = &(padapter->ledpriv);
+- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+- PLED_SDIO pLed = &(ledpriv->SwLed0);
+-
+- switch(LedAction)
+- {
+- case LED_CTL_SITE_SURVEY:
+- if(pmlmepriv->LinkDetectInfo.bBusyTraffic)
+- ;
+- else if(pLed->bLedScanBlinkInProgress ==false)
+- {
+- if(IS_LED_WPS_BLINKING(pLed))
+- return;
+-
+- if(pLed->bLedBlinkInProgress ==true)
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedBlinkInProgress = false;
+- }
+- pLed->bLedScanBlinkInProgress = true;
+- pLed->CurrLedState = LED_BLINK_SCAN;
+- pLed->BlinkTimes = 24;
+- if( pLed->bLedOn )
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- else
+- pLed->BlinkingLedState = RTW_LED_ON;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA);
+- }
+- break;
+-
+- case LED_CTL_TX:
+- case LED_CTL_RX:
+- if((pLed->bLedBlinkInProgress ==false) && (check_fwstate(pmlmepriv, _FW_LINKED)== true))
+- {
+- if(pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed))
+- {
+- return;
+- }
+-
+- pLed->bLedBlinkInProgress = true;
+- pLed->CurrLedState = LED_BLINK_TXRX;
+- pLed->BlinkTimes = 2;
+- if( pLed->bLedOn )
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- else
+- pLed->BlinkingLedState = RTW_LED_ON;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA);
+- }
+- break;
+-
+- case LED_CTL_LINK:
+- pLed->CurrLedState = RTW_LED_ON;
+- pLed->BlinkingLedState = RTW_LED_ON;
+- if( pLed->bLedBlinkInProgress)
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedBlinkInProgress = false;
+- }
+- if( pLed->bLedScanBlinkInProgress)
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedScanBlinkInProgress = false;
+- }
+-
+- _set_timer(&(pLed->BlinkTimer), 0);
+- break;
+-
+- case LED_CTL_START_WPS: //wait until xinpin finish
+- case LED_CTL_START_WPS_BOTTON:
+- if(pLed->bLedWPSBlinkInProgress ==false)
+- {
+- if(pLed->bLedBlinkInProgress ==true)
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedBlinkInProgress = false;
+- }
+- if(pLed->bLedScanBlinkInProgress ==true)
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedScanBlinkInProgress = false;
+- }
+- pLed->bLedWPSBlinkInProgress = true;
+- pLed->CurrLedState = RTW_LED_ON;
+- pLed->BlinkingLedState = RTW_LED_ON;
+- _set_timer(&(pLed->BlinkTimer), 0);
+- }
+- break;
+-
+- case LED_CTL_STOP_WPS:
+- pLed->bLedWPSBlinkInProgress = false;
+- if(adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on)
+- {
+- pLed->CurrLedState = RTW_LED_OFF;
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- _set_timer(&(pLed->BlinkTimer), 0);
+- }
+- else
+- {
+- pLed->CurrLedState = RTW_LED_ON;
+- pLed->BlinkingLedState = RTW_LED_ON;
+- _set_timer(&(pLed->BlinkTimer), 0);
+- RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("CurrLedState %d\n", pLed->CurrLedState));
+- }
+- break;
+-
+- case LED_CTL_STOP_WPS_FAIL:
+- pLed->bLedWPSBlinkInProgress = false;
+- pLed->CurrLedState = RTW_LED_OFF;
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- _set_timer(&(pLed->BlinkTimer), 0);
+- RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("CurrLedState %d\n", pLed->CurrLedState));
+- break;
+-
+- case LED_CTL_START_TO_LINK:
+- case LED_CTL_NO_LINK:
+- if(!IS_LED_BLINKING(pLed))
+- {
+- pLed->CurrLedState = RTW_LED_OFF;
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- _set_timer(&(pLed->BlinkTimer), 0);
+- }
+- break;
+-
+- case LED_CTL_POWER_OFF:
+- pLed->CurrLedState = RTW_LED_OFF;
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- if( pLed->bLedBlinkInProgress)
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedBlinkInProgress = false;
+- }
+- if( pLed->bLedScanBlinkInProgress)
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedScanBlinkInProgress = false;
+- }
+- if( pLed->bLedWPSBlinkInProgress )
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedWPSBlinkInProgress = false;
+- }
+-
+- SwLedOff(padapter, pLed);
+- break;
+-
+- default:
+- break;
+-
+- }
+-
+- RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("CurrLedState %d\n", pLed->CurrLedState));
+-}
+-
+- //COREGA, added by chiyoko, 20090316
+- static void
+- SwLedControlMode3(
+- _adapter *padapter,
+- LED_CTL_MODE LedAction
+-)
+-{
+- struct led_priv *ledpriv = &(padapter->ledpriv);
+- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+- PLED_SDIO pLed = &(ledpriv->SwLed0);
+-
+- switch(LedAction)
+- {
+- case LED_CTL_SITE_SURVEY:
+- if(pmlmepriv->LinkDetectInfo.bBusyTraffic)
+- ;
+- else if(pLed->bLedScanBlinkInProgress ==false)
+- {
+- if(IS_LED_WPS_BLINKING(pLed))
+- return;
+-
+- if(pLed->bLedBlinkInProgress ==true)
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedBlinkInProgress = false;
+- }
+- pLed->bLedScanBlinkInProgress = true;
+- pLed->CurrLedState = LED_BLINK_SCAN;
+- pLed->BlinkTimes = 24;
+- if( pLed->bLedOn )
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- else
+- pLed->BlinkingLedState = RTW_LED_ON;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA);
+- }
+- break;
+-
+- case LED_CTL_TX:
+- case LED_CTL_RX:
+- if((pLed->bLedBlinkInProgress ==false) && (check_fwstate(pmlmepriv, _FW_LINKED)== true))
+- {
+- if(pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed))
+- {
+- return;
+- }
+-
+- pLed->bLedBlinkInProgress = true;
+- pLed->CurrLedState = LED_BLINK_TXRX;
+- pLed->BlinkTimes = 2;
+- if( pLed->bLedOn )
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- else
+- pLed->BlinkingLedState = RTW_LED_ON;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA);
+- }
+- break;
+-
+- case LED_CTL_LINK:
+- if(IS_LED_WPS_BLINKING(pLed))
+- return;
+-
+- pLed->CurrLedState = RTW_LED_ON;
+- pLed->BlinkingLedState = RTW_LED_ON;
+- if( pLed->bLedBlinkInProgress)
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedBlinkInProgress = false;
+- }
+- if( pLed->bLedScanBlinkInProgress)
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedScanBlinkInProgress = false;
+- }
+-
+- _set_timer(&(pLed->BlinkTimer), 0);
+- break;
+-
+- case LED_CTL_START_WPS: //wait until xinpin finish
+- case LED_CTL_START_WPS_BOTTON:
+- if(pLed->bLedWPSBlinkInProgress ==false)
+- {
+- if(pLed->bLedBlinkInProgress ==true)
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedBlinkInProgress = false;
+- }
+- if(pLed->bLedScanBlinkInProgress ==true)
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedScanBlinkInProgress = false;
+- }
+- pLed->bLedWPSBlinkInProgress = true;
+- pLed->CurrLedState = LED_BLINK_WPS;
+- if( pLed->bLedOn )
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- else
+- pLed->BlinkingLedState = RTW_LED_ON;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA);
+- }
+- break;
+-
+- case LED_CTL_STOP_WPS:
+- if(pLed->bLedWPSBlinkInProgress)
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedWPSBlinkInProgress = false;
+- }
+- else
+- {
+- pLed->bLedWPSBlinkInProgress = true;
+- }
+-
+- pLed->CurrLedState = LED_BLINK_WPS_STOP;
+- if(pLed->bLedOn)
+- {
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_WPS_SUCESS_INTERVAL_ALPHA);
+- }
+- else
+- {
+- pLed->BlinkingLedState = RTW_LED_ON;
+- _set_timer(&(pLed->BlinkTimer), 0);
+- }
+-
+- break;
+-
+- case LED_CTL_STOP_WPS_FAIL:
+- if(pLed->bLedWPSBlinkInProgress)
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedWPSBlinkInProgress = false;
+- }
+-
+- pLed->CurrLedState = RTW_LED_OFF;
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- _set_timer(&(pLed->BlinkTimer), 0);
+- break;
+-
+- case LED_CTL_START_TO_LINK:
+- case LED_CTL_NO_LINK:
+- if(!IS_LED_BLINKING(pLed))
+- {
+- pLed->CurrLedState = RTW_LED_OFF;
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- _set_timer(&(pLed->BlinkTimer), 0);
+- }
+- break;
+-
+- case LED_CTL_POWER_OFF:
+- pLed->CurrLedState = RTW_LED_OFF;
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- if( pLed->bLedBlinkInProgress)
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedBlinkInProgress = false;
+- }
+- if( pLed->bLedScanBlinkInProgress)
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedScanBlinkInProgress = false;
+- }
+- if( pLed->bLedWPSBlinkInProgress )
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedWPSBlinkInProgress = false;
+- }
+-
+- SwLedOff(padapter, pLed);
+- break;
+-
+- default:
+- break;
+-
+- }
+-
+- RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("CurrLedState %d\n", pLed->CurrLedState));
+-}
+-
+-
+- //Edimax-Belkin, added by chiyoko, 20090413
+-static void
+-SwLedControlMode4(
+- _adapter *padapter,
+- LED_CTL_MODE LedAction
+-)
+-{
+- struct led_priv *ledpriv = &(padapter->ledpriv);
+- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+- PLED_SDIO pLed = &(ledpriv->SwLed0);
+- PLED_SDIO pLed1 = &(ledpriv->SwLed1);
+-
+- switch(LedAction)
+- {
+- case LED_CTL_START_TO_LINK:
+- if(pLed1->bLedWPSBlinkInProgress)
+- {
+- pLed1->bLedWPSBlinkInProgress = false;
+- _cancel_timer_ex(&(pLed1->BlinkTimer));
+-
+- pLed1->BlinkingLedState = RTW_LED_OFF;
+- pLed1->CurrLedState = RTW_LED_OFF;
+-
+- if(pLed1->bLedOn)
+- _set_timer(&(pLed->BlinkTimer), 0);
+- }
+-
+- if( pLed->bLedStartToLinkBlinkInProgress == false )
+- {
+- if(pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed))
+- {
+- return;
+- }
+- if(pLed->bLedBlinkInProgress ==true)
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedBlinkInProgress = false;
+- }
+- if(pLed->bLedNoLinkBlinkInProgress ==true)
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedNoLinkBlinkInProgress = false;
+- }
+-
+- pLed->bLedStartToLinkBlinkInProgress = true;
+- pLed->CurrLedState = LED_BLINK_StartToBlink;
+- if( pLed->bLedOn )
+- {
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_SLOWLY_INTERVAL);
+- }
+- else
+- {
+- pLed->BlinkingLedState = RTW_LED_ON;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL);
+- }
+- }
+- break;
+-
+- case LED_CTL_LINK:
+- case LED_CTL_NO_LINK:
+- //LED1 settings
+- if(LedAction == LED_CTL_LINK)
+- {
+- if(pLed1->bLedWPSBlinkInProgress)
+- {
+- pLed1->bLedWPSBlinkInProgress = false;
+- _cancel_timer_ex(&(pLed1->BlinkTimer));
+-
+- pLed1->BlinkingLedState = RTW_LED_OFF;
+- pLed1->CurrLedState = RTW_LED_OFF;
+-
+- if(pLed1->bLedOn)
+- _set_timer(&(pLed->BlinkTimer), 0);
+- }
+- }
+-
+- if( pLed->bLedNoLinkBlinkInProgress == false )
+- {
+- if(pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed))
+- {
+- return;
+- }
+- if(pLed->bLedBlinkInProgress ==true)
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedBlinkInProgress = false;
+- }
+-
+- pLed->bLedNoLinkBlinkInProgress = true;
+- pLed->CurrLedState = LED_BLINK_SLOWLY;
+- if( pLed->bLedOn )
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- else
+- pLed->BlinkingLedState = RTW_LED_ON;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA);
+- }
+- break;
+-
+- case LED_CTL_SITE_SURVEY:
+- if((pmlmepriv->LinkDetectInfo.bBusyTraffic) && (check_fwstate(pmlmepriv, _FW_LINKED)== true))
+- ;
+- else if(pLed->bLedScanBlinkInProgress ==false)
+- {
+- if(IS_LED_WPS_BLINKING(pLed))
+- return;
+-
+- if(pLed->bLedNoLinkBlinkInProgress == true)
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedNoLinkBlinkInProgress = false;
+- }
+- if(pLed->bLedBlinkInProgress ==true)
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedBlinkInProgress = false;
+- }
+- pLed->bLedScanBlinkInProgress = true;
+- pLed->CurrLedState = LED_BLINK_SCAN;
+- pLed->BlinkTimes = 24;
+- if( pLed->bLedOn )
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- else
+- pLed->BlinkingLedState = RTW_LED_ON;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA);
+- }
+- break;
+-
+- case LED_CTL_TX:
+- case LED_CTL_RX:
+- if(pLed->bLedBlinkInProgress ==false)
+- {
+- if(pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed))
+- {
+- return;
+- }
+- if(pLed->bLedNoLinkBlinkInProgress == true)
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedNoLinkBlinkInProgress = false;
+- }
+- pLed->bLedBlinkInProgress = true;
+- pLed->CurrLedState = LED_BLINK_TXRX;
+- pLed->BlinkTimes = 2;
+- if( pLed->bLedOn )
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- else
+- pLed->BlinkingLedState = RTW_LED_ON;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA);
+- }
+- break;
+-
+- case LED_CTL_START_WPS: //wait until xinpin finish
+- case LED_CTL_START_WPS_BOTTON:
+- if(pLed1->bLedWPSBlinkInProgress)
+- {
+- pLed1->bLedWPSBlinkInProgress = false;
+- _cancel_timer_ex(&(pLed1->BlinkTimer));
+-
+- pLed1->BlinkingLedState = RTW_LED_OFF;
+- pLed1->CurrLedState = RTW_LED_OFF;
+-
+- if(pLed1->bLedOn)
+- _set_timer(&(pLed->BlinkTimer), 0);
+- }
+-
+- if(pLed->bLedWPSBlinkInProgress ==false)
+- {
+- if(pLed->bLedNoLinkBlinkInProgress == true)
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedNoLinkBlinkInProgress = false;
+- }
+- if(pLed->bLedBlinkInProgress ==true)
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedBlinkInProgress = false;
+- }
+- if(pLed->bLedScanBlinkInProgress ==true)
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedScanBlinkInProgress = false;
+- }
+- pLed->bLedWPSBlinkInProgress = true;
+- pLed->CurrLedState = LED_BLINK_WPS;
+- if( pLed->bLedOn )
+- {
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_SLOWLY_INTERVAL);
+- }
+- else
+- {
+- pLed->BlinkingLedState = RTW_LED_ON;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL);
+- }
+- }
+- break;
+-
+- case LED_CTL_STOP_WPS: //WPS connect success
+- if(pLed->bLedWPSBlinkInProgress)
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedWPSBlinkInProgress = false;
+- }
+-
+- pLed->bLedNoLinkBlinkInProgress = true;
+- pLed->CurrLedState = LED_BLINK_SLOWLY;
+- if( pLed->bLedOn )
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- else
+- pLed->BlinkingLedState = RTW_LED_ON;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA);
+-
+- break;
+-
+- case LED_CTL_STOP_WPS_FAIL: //WPS authentication fail
+- if(pLed->bLedWPSBlinkInProgress)
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedWPSBlinkInProgress = false;
+- }
+-
+- pLed->bLedNoLinkBlinkInProgress = true;
+- pLed->CurrLedState = LED_BLINK_SLOWLY;
+- if( pLed->bLedOn )
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- else
+- pLed->BlinkingLedState = RTW_LED_ON;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA);
+-
+- //LED1 settings
+- if(pLed1->bLedWPSBlinkInProgress)
+- _cancel_timer_ex(&(pLed1->BlinkTimer));
+- else
+- pLed1->bLedWPSBlinkInProgress = true;
+-
+- pLed1->CurrLedState = LED_BLINK_WPS_STOP;
+- if( pLed1->bLedOn )
+- pLed1->BlinkingLedState = RTW_LED_OFF;
+- else
+- pLed1->BlinkingLedState = RTW_LED_ON;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL);
+-
+- break;
+-
+- case LED_CTL_STOP_WPS_FAIL_OVERLAP: //WPS session overlap
+- if(pLed->bLedWPSBlinkInProgress)
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedWPSBlinkInProgress = false;
+- }
+-
+- pLed->bLedNoLinkBlinkInProgress = true;
+- pLed->CurrLedState = LED_BLINK_SLOWLY;
+- if( pLed->bLedOn )
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- else
+- pLed->BlinkingLedState = RTW_LED_ON;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA);
+-
+- //LED1 settings
+- if(pLed1->bLedWPSBlinkInProgress)
+- _cancel_timer_ex(&(pLed1->BlinkTimer));
+- else
+- pLed1->bLedWPSBlinkInProgress = true;
+-
+- pLed1->CurrLedState = LED_BLINK_WPS_STOP_OVERLAP;
+- pLed1->BlinkTimes = 10;
+- if( pLed1->bLedOn )
+- pLed1->BlinkingLedState = RTW_LED_OFF;
+- else
+- pLed1->BlinkingLedState = RTW_LED_ON;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL);
+-
+- break;
+-
+- case LED_CTL_POWER_OFF:
+- pLed->CurrLedState = RTW_LED_OFF;
+- pLed->BlinkingLedState = RTW_LED_OFF;
+-
+- if( pLed->bLedNoLinkBlinkInProgress)
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedNoLinkBlinkInProgress = false;
+- }
+- if( pLed->bLedLinkBlinkInProgress)
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedLinkBlinkInProgress = false;
+- }
+- if( pLed->bLedBlinkInProgress)
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedBlinkInProgress = false;
+- }
+- if( pLed->bLedWPSBlinkInProgress )
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedWPSBlinkInProgress = false;
+- }
+- if( pLed->bLedScanBlinkInProgress)
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedScanBlinkInProgress = false;
+- }
+- if( pLed->bLedStartToLinkBlinkInProgress)
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedStartToLinkBlinkInProgress = false;
+- }
+-
+- if( pLed1->bLedWPSBlinkInProgress )
+- {
+- _cancel_timer_ex(&(pLed1->BlinkTimer));
+- pLed1->bLedWPSBlinkInProgress = false;
+- }
+-
+- pLed1->BlinkingLedState = LED_UNKNOWN;
+- SwLedOff(padapter, pLed);
+- SwLedOff(padapter, pLed1);
+- break;
+-
+- default:
+- break;
+-
+- }
+-
+- RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("Led %d\n", pLed->CurrLedState));
+-}
+-
+-
+-
+- //Sercomm-Belkin, added by chiyoko, 20090415
+-static void
+-SwLedControlMode5(
+- _adapter *padapter,
+- LED_CTL_MODE LedAction
+-)
+-{
+- struct led_priv *ledpriv = &(padapter->ledpriv);
+- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+- EEPROM_EFUSE_PRIV *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
+- PLED_SDIO pLed = &(ledpriv->SwLed0);
+-
+- if(pEEPROM->CustomerID == RT_CID_819x_CAMEO)
+- pLed = &(ledpriv->SwLed1);
+-
+- switch(LedAction)
+- {
+- case LED_CTL_POWER_ON:
+- case LED_CTL_NO_LINK:
+- case LED_CTL_LINK: //solid blue
+- pLed->CurrLedState = RTW_LED_ON;
+- pLed->BlinkingLedState = RTW_LED_ON;
+-
+- _set_timer(&(pLed->BlinkTimer), 0);
+- break;
+-
+- case LED_CTL_SITE_SURVEY:
+- if((pmlmepriv->LinkDetectInfo.bBusyTraffic) && (check_fwstate(pmlmepriv, _FW_LINKED)== true))
+- ;
+- else if(pLed->bLedScanBlinkInProgress ==false)
+- {
+- if(pLed->bLedBlinkInProgress ==true)
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedBlinkInProgress = false;
+- }
+- pLed->bLedScanBlinkInProgress = true;
+- pLed->CurrLedState = LED_BLINK_SCAN;
+- pLed->BlinkTimes = 24;
+- if( pLed->bLedOn )
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- else
+- pLed->BlinkingLedState = RTW_LED_ON;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA);
+- }
+- break;
+-
+- case LED_CTL_TX:
+- case LED_CTL_RX:
+- if(pLed->bLedBlinkInProgress ==false)
+- {
+- if(pLed->CurrLedState == LED_BLINK_SCAN)
+- {
+- return;
+- }
+- pLed->bLedBlinkInProgress = true;
+- pLed->CurrLedState = LED_BLINK_TXRX;
+- pLed->BlinkTimes = 2;
+- if( pLed->bLedOn )
+- pLed->BlinkingLedState = RTW_LED_OFF;
+- else
+- pLed->BlinkingLedState = RTW_LED_ON;
+- _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA);
+- }
+- break;
+-
+- case LED_CTL_POWER_OFF:
+- pLed->CurrLedState = RTW_LED_OFF;
+- pLed->BlinkingLedState = RTW_LED_OFF;
+-
+- if( pLed->bLedBlinkInProgress)
+- {
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- pLed->bLedBlinkInProgress = false;
+- }
+-
+- SwLedOff(padapter, pLed);
+- break;
+-
+- default:
+- break;
+-
+- }
+-
+- RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("Led %d\n", pLed->CurrLedState));
+-}
+-
+- //WNC-Corega, added by chiyoko, 20090902
+-static void
+-SwLedControlMode6(
+- _adapter *padapter,
+- LED_CTL_MODE LedAction
+-)
+-{
+- struct led_priv *ledpriv = &(padapter->ledpriv);
+- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+- PLED_SDIO pLed0 = &(ledpriv->SwLed0);
+-
+- switch(LedAction)
+- {
+- case LED_CTL_POWER_ON:
+- case LED_CTL_LINK:
+- case LED_CTL_NO_LINK:
+- _cancel_timer_ex(&(pLed0->BlinkTimer));
+- pLed0->CurrLedState = RTW_LED_ON;
+- pLed0->BlinkingLedState = RTW_LED_ON;
+- _set_timer(&(pLed0->BlinkTimer), 0);
+- break;
+-
+- case LED_CTL_POWER_OFF:
+- SwLedOff(padapter, pLed0);
+- break;
+-
+- default:
+- break;
+- }
+-
+- RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("ledcontrol 6 Led %d\n", pLed0->CurrLedState));
+-}
+-
+-void
+-LedControlSDIO(
+- _adapter *padapter,
+- LED_CTL_MODE LedAction
+- )
+-{
+- struct led_priv *ledpriv = &(padapter->ledpriv);
+-
+- if( (padapter->bSurpriseRemoved == true) ||(padapter->hw_init_completed == false) )
+- {
+- return;
+- }
+-
+- if( ledpriv->bRegUseLed == false)
+- return;
+-
+- //if(priv->bInHctTest)
+- // return;
+-
+- if( (adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on &&
+- adapter_to_pwrctl(padapter)->rfoff_reason > RF_CHANGE_BY_PS) &&
+- (LedAction == LED_CTL_TX || LedAction == LED_CTL_RX ||
+- LedAction == LED_CTL_SITE_SURVEY ||
+- LedAction == LED_CTL_LINK ||
+- LedAction == LED_CTL_NO_LINK ||
+- LedAction == LED_CTL_POWER_ON) )
+- {
+- return;
+- }
+-
+- switch(ledpriv->LedStrategy)
+- {
+- case SW_LED_MODE0:
+- SwLedControlMode0(padapter, LedAction);
+- break;
+-
+- case SW_LED_MODE1:
+- SwLedControlMode1(padapter, LedAction);
+- break;
+- case SW_LED_MODE2:
+- SwLedControlMode2(padapter, LedAction);
+- break;
+-
+- case SW_LED_MODE3:
+- SwLedControlMode3(padapter, LedAction);
+- break;
+-
+- case SW_LED_MODE4:
+- SwLedControlMode4(padapter, LedAction);
+- break;
+-
+- case SW_LED_MODE5:
+- SwLedControlMode5(padapter, LedAction);
+- break;
+-
+- case SW_LED_MODE6:
+- SwLedControlMode6(padapter, LedAction);
+- break;
+-
+- default:
+- break;
+- }
+-
+- RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("LedStrategy:%d, LedAction %d\n", ledpriv->LedStrategy,LedAction));
+-}
+-
+-//
+-// Description:
+-// Reset status of LED_871x object.
+-//
+-void ResetLedStatus(PLED_SDIO pLed) {
+-
+- pLed->CurrLedState = RTW_LED_OFF; // Current LED state.
+- pLed->bLedOn = false; // true if LED is ON, false if LED is OFF.
+-
+- pLed->bLedBlinkInProgress = false; // true if it is blinking, false o.w..
+- pLed->bLedWPSBlinkInProgress = false;
+-
+- pLed->BlinkTimes = 0; // Number of times to toggle led state for blinking.
+- pLed->BlinkingLedState = LED_UNKNOWN; // Next state for blinking, either RTW_LED_ON or RTW_LED_OFF are.
+-
+- pLed->bLedNoLinkBlinkInProgress = false;
+- pLed->bLedLinkBlinkInProgress = false;
+- pLed->bLedStartToLinkBlinkInProgress = false;
+- pLed->bLedScanBlinkInProgress = false;
+-}
+-
+- //
+-// Description:
+-// Initialize an LED_871x object.
+-//
+-void
+-InitLed(
+- _adapter *padapter,
+- PLED_SDIO pLed,
+- LED_PIN LedPin
+- )
+-{
+- pLed->padapter = padapter;
+- pLed->LedPin = LedPin;
+-
+- ResetLedStatus(pLed);
+-
+- _init_timer(&(pLed->BlinkTimer), padapter->pnetdev, BlinkTimerCallback, pLed);
+-
+- _init_workitem(&(pLed->BlinkWorkItem), BlinkWorkItemCallback, pLed);
+-}
+-
+-
+-//
+-// Description:
+-// DeInitialize an LED_871x object.
+-//
+-void
+-DeInitLed(
+- PLED_SDIO pLed
+- )
+-{
+- _cancel_workitem_sync(&(pLed->BlinkWorkItem));
+- _cancel_timer_ex(&(pLed->BlinkTimer));
+- ResetLedStatus(pLed);
+-}
+-
+-
+diff -Nurp linux/3rdparty/rtl8723bs.old/hal/odm_AntDiv.c linux/3rdparty/rtl8723bs/hal/odm_AntDiv.c
+--- linux/3rdparty/rtl8723bs.old/hal/odm_AntDiv.c 2015-05-10 14:36:05.704668302 +0300
++++ linux/3rdparty/rtl8723bs/hal/odm_AntDiv.c 1970-01-01 02:00:00.000000000 +0200
+@@ -1,79 +0,0 @@
+-/******************************************************************************
+- *
+- * 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.
+- *
+- * 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.,
+- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+- *
+- *
+- ******************************************************************************/
+-
+-//============================================================
+-// include files
+-//============================================================
+-
+-#include "odm_precomp.h"
+-
+-//======================================================
+-// when antenna test utility is on or some testing need to disable antenna diversity
+-// call this function to disable all ODM related mechanisms which will switch antenna.
+-//======================================================
+-void
+-ODM_StopAntennaSwitchDm(
+- IN PDM_ODM_T pDM_Odm
+- )
+-{
+- // disable ODM antenna diversity
+- pDM_Odm->SupportAbility &= ~ODM_BB_ANT_DIV;
+- ODM_RT_TRACE(pDM_Odm,ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("STOP Antenna Diversity \n"));
+-}
+-
+-void
+-ODM_SetAntConfig(
+- IN PDM_ODM_T pDM_Odm,
+- IN u1Byte antSetting // 0=A, 1=B, 2=C, ....
+- )
+-{
+- if(antSetting == 0) // ant A
+- ODM_SetBBReg(pDM_Odm, 0x948, bMaskDWord, 0x00000000);
+- else if(antSetting == 1)
+- ODM_SetBBReg(pDM_Odm, 0x948, bMaskDWord, 0x00000280);
+-}
+-
+-//======================================================
+-
+-
+-void
+-ODM_SwAntDivRestAfterLink(
+- IN PDM_ODM_T pDM_Odm
+- )
+-{
+- pSWAT_T pDM_SWAT_Table = &pDM_Odm->DM_SWAT_Table;
+- pFAT_T pDM_FatTable = &pDM_Odm->DM_FatTable;
+- u4Byte i;
+-
+- pDM_Odm->RSSI_test = false;
+- pDM_SWAT_Table->try_flag = 0xff;
+- pDM_SWAT_Table->RSSI_Trying = 0;
+- pDM_SWAT_Table->Double_chk_flag= 0;
+-
+- pDM_FatTable->RxIdleAnt=MAIN_ANT;
+-
+- for (i=0; iMainAnt_Sum[i] = 0;
+- pDM_FatTable->AuxAnt_Sum[i] = 0;
+- pDM_FatTable->MainAnt_Cnt[i] = 0;
+- pDM_FatTable->AuxAnt_Cnt[i] = 0;
+- }
+-}
+diff -Nurp linux/3rdparty/rtl8723bs.old/hal/odm_AntDiv.h linux/3rdparty/rtl8723bs/hal/odm_AntDiv.h
+--- linux/3rdparty/rtl8723bs.old/hal/odm_AntDiv.h 2015-05-10 14:36:05.704668302 +0300
++++ linux/3rdparty/rtl8723bs/hal/odm_AntDiv.h 2015-05-07 17:46:55.000000000 +0300
+@@ -40,14 +40,4 @@
+ #define CANCEL_ANTDIV_TIMMER 1
+ #define RELEASE_ANTDIV_TIMMER 2
+
+-void
+-ODM_StopAntennaSwitchDm(
+- IN PDM_ODM_T pDM_Odm
+- );
+-void
+-ODM_SetAntConfig(
+- IN PDM_ODM_T pDM_Odm,
+- IN u1Byte antSetting // 0=A, 1=B, 2=C, ....
+- );
+-
+ #endif //#ifndef __ODMANTDIV_H__
+diff -Nurp linux/3rdparty/rtl8723bs.old/hal/odm.c linux/3rdparty/rtl8723bs/hal/odm.c
+--- linux/3rdparty/rtl8723bs.old/hal/odm.c 2015-05-10 14:36:05.705668313 +0300
++++ linux/3rdparty/rtl8723bs/hal/odm.c 2015-05-07 17:46:55.000000000 +0300
+@@ -336,15 +336,6 @@ odm_CmnInfoInit_Debug(
+ );
+
+ void
+-odm_CmnInfoHook_Debug(
+- IN PDM_ODM_T pDM_Odm
+- );
+-
+-void
+-odm_CmnInfoUpdate_Debug(
+- IN PDM_ODM_T pDM_Odm
+- );
+-void
+ odm_BasicDbgMessage
+ (
+ IN PDM_ODM_T pDM_Odm
+@@ -363,20 +354,10 @@ odm_BasicDbgMessage
+ //END---------BB POWER SAVE-----------------------//
+
+ void
+-odm_RefreshRateAdaptiveMaskMP(
+- IN PDM_ODM_T pDM_Odm
+- );
+-
+-void
+ odm_RefreshRateAdaptiveMaskCE(
+ IN PDM_ODM_T pDM_Odm
+ );
+
+-void
+-odm_RefreshRateAdaptiveMaskAPADSL(
+- IN PDM_ODM_T pDM_Odm
+- );
+-
+ //Remove by YuChen
+
+ void
+@@ -384,21 +365,10 @@ odm_RSSIMonitorInit(
+ IN PDM_ODM_T pDM_Odm
+ );
+
+-void
+-odm_RSSIMonitorCheckMP(
+- IN PDM_ODM_T pDM_Odm
+- );
+-
+ void
+ odm_RSSIMonitorCheckCE(
+ IN PDM_ODM_T pDM_Odm
+ );
+-void
+-odm_RSSIMonitorCheckAP(
+- IN PDM_ODM_T pDM_Odm
+- );
+-
+-
+
+ void
+ odm_RSSIMonitorCheck(
+@@ -410,17 +380,6 @@ odm_SwAntDetectInit(
+ IN PDM_ODM_T pDM_Odm
+ );
+
+-void
+-odm_AntennaDiversityInit(
+- IN PDM_ODM_T pDM_Odm
+- );
+-
+-void
+-odm_AntennaDiversity(
+- IN PDM_ODM_T pDM_Odm
+- );
+-
+-
+ void odm_SwAntDivChkAntSwitchCallback(void *FunctionContext);
+
+
+@@ -431,11 +390,6 @@ odm_GlobalAdapterCheck(
+ );
+
+ void
+-odm_RefreshBasicRateMask(
+- IN PDM_ODM_T pDM_Odm
+- );
+-
+-void
+ odm_RefreshRateAdaptiveMask(
+ IN PDM_ODM_T pDM_Odm
+ );
+@@ -446,11 +400,6 @@ ODM_TXPowerTrackingCheck(
+ );
+
+ void
+-odm_TXPowerTrackingCheckAP(
+- IN PDM_ODM_T pDM_Odm
+- );
+-
+-void
+ odm_RateAdaptiveMaskInit(
+ IN PDM_ODM_T pDM_Odm
+ );
+@@ -467,12 +416,6 @@ odm_TXPowerTrackingInit(
+ );
+
+ void
+-odm_TXPowerTrackingCheckMP(
+- IN PDM_ODM_T pDM_Odm
+- );
+-
+-
+-void
+ odm_TXPowerTrackingCheckCE(
+ IN PDM_ODM_T pDM_Odm
+ );
+@@ -536,7 +479,6 @@ ODM_DMInit(
+ ODM_EdcaTurboInit(pDM_Odm);
+ odm_RSSIMonitorInit(pDM_Odm);
+ odm_TXPowerTrackingInit(pDM_Odm);
+- odm_AntennaDiversityInit(pDM_Odm);
+
+ ODM_ClearTxPowerTrackingState(pDM_Odm);
+
+@@ -549,13 +491,6 @@ ODM_DMInit(
+ odm_SwAntDetectInit(pDM_Odm);
+ }
+
+-void
+-ODM_DMReset(
+- IN PDM_ODM_T pDM_Odm
+- )
+-{
+-}
+-
+ //
+ // 2011/09/20 MH This is the entry pointer for all team to execute HW out source DM.
+ // You can not add any dummy function here, be care, you can only use DM structure
+@@ -605,11 +540,9 @@ ODM_DMWatchdog(
+
+
+ odm_RefreshRateAdaptiveMask(pDM_Odm);
+- odm_RefreshBasicRateMask(pDM_Odm);
+ odm_EdcaTurboCheck(pDM_Odm);
+ odm_PathDiversity(pDM_Odm);
+ ODM_CfoTracking(pDM_Odm);
+- odm_AntennaDiversity(pDM_Odm);
+
+ ODM_TXPowerTrackingCheck(pDM_Odm);
+
+@@ -1035,8 +968,8 @@ odm_CommonInfoSelfInit(
+ )
+ {
+ pFAT_T pDM_FatTable = &pDM_Odm->DM_FatTable;
+- pDM_Odm->bCckHighPower = (bool) ODM_GetBBReg(pDM_Odm, ODM_REG(CCK_RPT_FORMAT,pDM_Odm), ODM_BIT(CCK_RPT_FORMAT,pDM_Odm));
+- pDM_Odm->RFPathRxEnable = (u1Byte) ODM_GetBBReg(pDM_Odm, ODM_REG(BB_RX_PATH,pDM_Odm), ODM_BIT(BB_RX_PATH,pDM_Odm));
++ pDM_Odm->bCckHighPower = (bool) PHY_QueryBBReg(pDM_Odm->Adapter, ODM_REG(CCK_RPT_FORMAT,pDM_Odm), ODM_BIT(CCK_RPT_FORMAT,pDM_Odm));
++ pDM_Odm->RFPathRxEnable = (u1Byte) PHY_QueryBBReg(pDM_Odm->Adapter, ODM_REG(BB_RX_PATH,pDM_Odm), ODM_BIT(BB_RX_PATH,pDM_Odm));
+
+ ODM_InitDebugSetting(pDM_Odm);
+
+@@ -1099,36 +1032,6 @@ odm_CmnInfoInit_Debug(
+ }
+
+ void
+-odm_CmnInfoHook_Debug(
+- IN PDM_ODM_T pDM_Odm
+- )
+-{
+- ODM_RT_TRACE(pDM_Odm,ODM_COMP_COMMON, ODM_DBG_LOUD, ("odm_CmnInfoHook_Debug==>\n"));
+- ODM_RT_TRACE(pDM_Odm,ODM_COMP_COMMON, ODM_DBG_LOUD, ("pNumTxBytesUnicast=%llu\n",*(pDM_Odm->pNumTxBytesUnicast)) );
+- ODM_RT_TRACE(pDM_Odm,ODM_COMP_COMMON, ODM_DBG_LOUD, ("pNumRxBytesUnicast=%llu\n",*(pDM_Odm->pNumRxBytesUnicast)) );
+- ODM_RT_TRACE(pDM_Odm,ODM_COMP_COMMON, ODM_DBG_LOUD, ("pWirelessMode=0x%x\n",*(pDM_Odm->pWirelessMode)) );
+- ODM_RT_TRACE(pDM_Odm,ODM_COMP_COMMON, ODM_DBG_LOUD, ("pSecChOffset=%d\n",*(pDM_Odm->pSecChOffset)) );
+- ODM_RT_TRACE(pDM_Odm,ODM_COMP_COMMON, ODM_DBG_LOUD, ("pSecurity=%d\n",*(pDM_Odm->pSecurity)) );
+- ODM_RT_TRACE(pDM_Odm,ODM_COMP_COMMON, ODM_DBG_LOUD, ("pBandWidth=%d\n",*(pDM_Odm->pBandWidth)) );
+- ODM_RT_TRACE(pDM_Odm,ODM_COMP_COMMON, ODM_DBG_LOUD, ("pChannel=%d\n",*(pDM_Odm->pChannel)) );
+-
+- ODM_RT_TRACE(pDM_Odm,ODM_COMP_COMMON, ODM_DBG_LOUD, ("pbScanInProcess=%d\n",*(pDM_Odm->pbScanInProcess)) );
+- ODM_RT_TRACE(pDM_Odm,ODM_COMP_COMMON, ODM_DBG_LOUD, ("pbPowerSaving=%d\n",*(pDM_Odm->pbPowerSaving)) );
+-}
+-
+-void
+-odm_CmnInfoUpdate_Debug(
+- IN PDM_ODM_T pDM_Odm
+- )
+-{
+- ODM_RT_TRACE(pDM_Odm,ODM_COMP_COMMON, ODM_DBG_LOUD, ("odm_CmnInfoUpdate_Debug==>\n"));
+- ODM_RT_TRACE(pDM_Odm,ODM_COMP_COMMON, ODM_DBG_LOUD, ("bWIFI_Direct=%d\n",pDM_Odm->bWIFI_Direct) );
+- ODM_RT_TRACE(pDM_Odm,ODM_COMP_COMMON, ODM_DBG_LOUD, ("bWIFI_Display=%d\n",pDM_Odm->bWIFI_Display) );
+- ODM_RT_TRACE(pDM_Odm,ODM_COMP_COMMON, ODM_DBG_LOUD, ("bLinked=%d\n",pDM_Odm->bLinked) );
+- ODM_RT_TRACE(pDM_Odm,ODM_COMP_COMMON, ODM_DBG_LOUD, ("RSSI_Min=%d\n",pDM_Odm->RSSI_Min) );
+-}
+-
+-void
+ odm_BasicDbgMessage
+ (
+ IN PDM_ODM_T pDM_Odm
+@@ -1387,13 +1290,6 @@ u4Byte ODM_Get_Rate_Bitmap(
+
+ }
+
+-void
+-odm_RefreshBasicRateMask(
+- IN PDM_ODM_T pDM_Odm
+- )
+-{
+-}
+-
+ /*-----------------------------------------------------------------------------
+ * Function: odm_RefreshRateAdaptiveMask()
+ *
+@@ -1426,14 +1322,6 @@ odm_RefreshRateAdaptiveMask(
+ }
+
+ void
+-odm_RefreshRateAdaptiveMaskMP(
+- IN PDM_ODM_T pDM_Odm
+- )
+-{
+-}
+-
+-
+-void
+ odm_RefreshRateAdaptiveMaskCE(
+ IN PDM_ODM_T pDM_Odm
+ )
+@@ -1475,13 +1363,6 @@ odm_RefreshRateAdaptiveMaskCE(
+ }
+ }
+
+-void
+-odm_RefreshRateAdaptiveMaskAPADSL(
+- IN PDM_ODM_T pDM_Odm
+- )
+-{
+-}
+-
+ // Return Value: bool
+ // - true: RATRState is changed.
+ bool
+@@ -1576,14 +1457,6 @@ odm_RSSIMonitorCheck(
+
+ } // odm_RSSIMonitorCheck
+
+-
+-void
+-odm_RSSIMonitorCheckMP(
+- IN PDM_ODM_T pDM_Odm
+- )
+-{
+-}
+-
+ static void
+ FindMinimumRSSI(
+ IN PADAPTER pAdapter
+@@ -1697,38 +1570,6 @@ odm_RSSIMonitorCheckCE(
+ //ODM_CmnInfoUpdate(&pHalData->odmpriv ,ODM_CMNINFO_RSSI_MIN, pdmpriv->MinUndecoratedPWDBForDM);
+ }
+
+-void
+-odm_RSSIMonitorCheckAP(
+- IN PDM_ODM_T pDM_Odm
+- )
+-{
+-}
+-
+-
+-
+-void
+-ODM_InitAllTimers(
+- IN PDM_ODM_T pDM_Odm
+- )
+-{
+-}
+-
+-void
+-ODM_CancelAllTimers(
+- IN PDM_ODM_T pDM_Odm
+- )
+-{
+-}
+-
+-
+-void
+-ODM_ReleaseAllTimers(
+- IN PDM_ODM_T pDM_Odm
+- )
+-{
+-}
+-
+-
+ //3============================================================
+ //3 Tx Power Tracking
+ //3============================================================
+@@ -1842,7 +1683,7 @@ odm_TXPowerTrackingCheckCE(
+ if(!pDM_Odm->RFCalibrateInfo.TM_Trigger) //at least delay 1 sec
+ {
+ //pHalData->TxPowerCheckCnt++; //cosa add for debug
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, RF_T_METER_NEW, (BIT17 | BIT16), 0x03);
++ PHY_SetRFReg(pDM_Odm->Adapter, ODM_RF_PATH_A, RF_T_METER_NEW, (BIT17 | BIT16), 0x03);
+
+ //DBG_871X("Trigger Thermal Meter!!\n");
+
+@@ -1857,526 +1698,17 @@ odm_TXPowerTrackingCheckCE(
+ }
+ }
+
+-void
+-odm_TXPowerTrackingCheckMP(
+- IN PDM_ODM_T pDM_Odm
+- )
+-{
+-}
+-
+-
+-void
+-odm_TXPowerTrackingCheckAP(
+- IN PDM_ODM_T pDM_Odm
+- )
+-{
+-}
+-
+ //3============================================================
+ //3 SW Antenna Diversity
+ //3============================================================
+ void
+-odm_AntennaDiversityInit(
+- IN PDM_ODM_T pDM_Odm
+-)
+-{
+- if(*(pDM_Odm->mp_mode) == true)
+- return;
+-}
+-
+-void
+-odm_AntennaDiversity(
+- IN PDM_ODM_T pDM_Odm
+-)
+-{
+- if(*(pDM_Odm->mp_mode) == true)
+- return;
+-}
+-
+-
+-void
+ odm_SwAntDetectInit(
+ IN PDM_ODM_T pDM_Odm
+ )
+ {
+ pSWAT_T pDM_SWAT_Table = &pDM_Odm->DM_SWAT_Table;
+- pDM_SWAT_Table->SWAS_NoLink_BK_Reg92c = ODM_Read4Byte(pDM_Odm, rDPDT_control);
++ pDM_SWAT_Table->SWAS_NoLink_BK_Reg92c = rtw_read32(pDM_Odm->Adapter, rDPDT_control);
+ pDM_SWAT_Table->PreAntenna = MAIN_ANT;
+ pDM_SWAT_Table->CurAntenna = MAIN_ANT;
+ pDM_SWAT_Table->SWAS_NoLink_State = 0;
+ }
+-
+-//============================================================
+-//EDCA Turbo
+-//============================================================
+-
+-// need to ODM CE Platform
+-//move to here for ANT detection mechanism using
+-
+-u4Byte
+-GetPSDData(
+- IN PDM_ODM_T pDM_Odm,
+- unsigned int point,
+- u1Byte initial_gain_psd)
+-{
+- //unsigned int val, rfval;
+- //int psd_report;
+- u4Byte psd_report;
+-
+- //HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);
+- //Debug Message
+- //val = PHY_QueryBBReg(Adapter,0x908, bMaskDWord);
+- //DbgPrint("Reg908 = 0x%x\n",val);
+- //val = PHY_QueryBBReg(Adapter,0xDF4, bMaskDWord);
+- //rfval = PHY_QueryRFReg(Adapter, ODM_RF_PATH_A, 0x00, bRFRegOffsetMask);
+- //DbgPrint("RegDF4 = 0x%x, RFReg00 = 0x%x\n",val, rfval);
+- //DbgPrint("PHYTXON = %x, OFDMCCA_PP = %x, CCKCCA_PP = %x, RFReg00 = %x\n",
+- //(val&BIT25)>>25, (val&BIT14)>>14, (val&BIT15)>>15, rfval);
+-
+- //Set DCO frequency index, offset=(40MHz/SamplePts)*point
+- ODM_SetBBReg(pDM_Odm, 0x808, 0x3FF, point);
+-
+- //Start PSD calculation, Reg808[22]=0->1
+- ODM_SetBBReg(pDM_Odm, 0x808, BIT22, 1);
+- //Need to wait for HW PSD report
+- udelay(1000);
+- ODM_SetBBReg(pDM_Odm, 0x808, BIT22, 0);
+- //Read PSD report, Reg8B4[15:0]
+- psd_report = ODM_GetBBReg(pDM_Odm,0x8B4, bMaskDWord) & 0x0000FFFF;
+-
+- psd_report = (u4Byte) (ConvertTo_dB(psd_report))+(u4Byte)(initial_gain_psd-0x1c);
+-
+- return psd_report;
+-
+-}
+-
+-u4Byte
+-ConvertTo_dB(
+- u4Byte Value)
+-{
+- u1Byte i;
+- u1Byte j;
+- u4Byte dB;
+-
+- Value = Value & 0xFFFF;
+-
+- for (i=0;i<8;i++)
+- {
+- if (Value <= dB_Invert_Table[i][11])
+- {
+- break;
+- }
+- }
+-
+- if (i >= 8)
+- {
+- return (96); // maximum 96 dB
+- }
+-
+- for (j=0;j<12;j++)
+- {
+- if (Value <= dB_Invert_Table[i][j])
+- {
+- break;
+- }
+- }
+-
+- dB = i*12 + j + 1;
+-
+- return (dB);
+-}
+-
+-//
+-// Description:
+-// Set Single/Dual Antenna default setting for products that do not do detection in advance.
+-//
+-// Added by Joseph, 2012.03.22
+-//
+-void
+-ODM_SingleDualAntennaDefaultSetting(
+- IN PDM_ODM_T pDM_Odm
+- )
+-{
+- pSWAT_T pDM_SWAT_Table = &pDM_Odm->DM_SWAT_Table;
+- PADAPTER pAdapter = pDM_Odm->Adapter;
+- u1Byte btAntNum = 2;
+-
+- btAntNum = hal_btcoex_GetPgAntNum(pAdapter);
+-
+- // Set default antenna A and B status
+- if(btAntNum == 2)
+- {
+- pDM_SWAT_Table->ANTA_ON=true;
+- pDM_SWAT_Table->ANTB_ON=true;
+- //RT_TRACE(COMP_ANTENNA, DBG_LOUD, ("Dual antenna\n"));
+- }
+- else if(btAntNum == 1)
+- {// Set antenna A as default
+- pDM_SWAT_Table->ANTA_ON=true;
+- pDM_SWAT_Table->ANTB_ON=false;
+- //RT_TRACE(COMP_ANTENNA, DBG_LOUD, ("Single antenna\n"));
+- }
+- else
+- {
+- //RT_ASSERT(false, ("Incorrect antenna number!!\n"));
+- }
+-}
+-
+-
+-
+-//2 8723A ANT DETECT
+-//
+-// Description:
+-// Implement IQK single tone for RF DPK loopback and BB PSD scanning.
+-// This function is cooperated with BB team Neil.
+-//
+-// Added by Roger, 2011.12.15
+-//
+-bool
+-ODM_SingleDualAntennaDetection(
+- IN PDM_ODM_T pDM_Odm,
+- IN u1Byte mode
+- )
+-{
+- PADAPTER pAdapter = pDM_Odm->Adapter;
+- pSWAT_T pDM_SWAT_Table = &pDM_Odm->DM_SWAT_Table;
+- u4Byte CurrentChannel,RfLoopReg;
+- u1Byte n;
+- u4Byte Reg88c, Regc08, Reg874, Regc50, Reg948=0, Regb2c=0, Reg92c=0, AFE_rRx_Wait_CCA=0;
+- u1Byte initial_gain = 0x5a;
+- u4Byte PSD_report_tmp;
+- u4Byte AntA_report = 0x0, AntB_report = 0x0,AntO_report=0x0;
+- bool bResult = true;
+- u4Byte AFE_Backup[16];
+- u4Byte AFE_REG_8723A[16] = {
+- rRx_Wait_CCA, rTx_CCK_RFON,
+- rTx_CCK_BBON, rTx_OFDM_RFON,
+- rTx_OFDM_BBON, rTx_To_Rx,
+- rTx_To_Tx, rRx_CCK,
+- rRx_OFDM, rRx_Wait_RIFS,
+- rRx_TO_Rx, rStandby,
+- rSleep, rPMPD_ANAEN,
+- rFPGA0_XCD_SwitchControl, rBlue_Tooth};
+-
+- ODM_RT_TRACE(pDM_Odm,ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("ODM_SingleDualAntennaDetection()============> \n"));
+-
+-
+- // Retrieve antenna detection registry info, added by Roger, 2012.11.27.
+- if(!IS_ANT_DETECT_SUPPORT_SINGLE_TONE(pAdapter))
+- return bResult;
+-
+- //1 Backup Current RF/BB Settings
+-
+- CurrentChannel = ODM_GetRFReg(pDM_Odm, ODM_RF_PATH_A, ODM_CHANNEL, bRFRegOffsetMask);
+- RfLoopReg = ODM_GetRFReg(pDM_Odm, ODM_RF_PATH_A, 0x00, bRFRegOffsetMask);
+-
+- Reg92c = ODM_GetBBReg(pDM_Odm, 0x92c, bMaskDWord);
+- Reg948 = ODM_GetBBReg(pDM_Odm, rS0S1_PathSwitch, bMaskDWord);
+- Regb2c = ODM_GetBBReg(pDM_Odm, AGC_table_select, bMaskDWord);
+- ODM_SetBBReg(pDM_Odm, rDPDT_control, 0x3, 0x1);
+- ODM_SetBBReg(pDM_Odm, rfe_ctrl_anta_src, 0xff, 0x77);
+- ODM_SetBBReg(pDM_Odm, rS0S1_PathSwitch, 0x3ff, 0x000);
+- ODM_SetBBReg(pDM_Odm, AGC_table_select, BIT31, 0x0);
+-
+- udelay(10);
+-
+- //Store A Path Register 88c, c08, 874, c50
+- Reg88c = ODM_GetBBReg(pDM_Odm, rFPGA0_AnalogParameter4, bMaskDWord);
+- Regc08 = ODM_GetBBReg(pDM_Odm, rOFDM0_TRMuxPar, bMaskDWord);
+- Reg874 = ODM_GetBBReg(pDM_Odm, rFPGA0_XCD_RFInterfaceSW, bMaskDWord);
+- Regc50 = ODM_GetBBReg(pDM_Odm, rOFDM0_XAAGCCore1, bMaskDWord);
+-
+- // Store AFE Registers
+- AFE_rRx_Wait_CCA = ODM_GetBBReg(pDM_Odm, rRx_Wait_CCA,bMaskDWord);
+-
+- //Set PSD 128 pts
+- ODM_SetBBReg(pDM_Odm, rFPGA0_PSDFunction, BIT14|BIT15, 0x0); //128 pts
+-
+- // To SET CH1 to do
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, ODM_CHANNEL, bRFRegOffsetMask, 0x7401); //Channel 1
+-
+- // AFE all on step
+- ODM_SetBBReg(pDM_Odm, rRx_Wait_CCA, bMaskDWord, 0x01c00016);
+-
+- // 3 wire Disable
+- ODM_SetBBReg(pDM_Odm, rFPGA0_AnalogParameter4, bMaskDWord, 0xCCF000C0);
+-
+- //BB IQK Setting
+- ODM_SetBBReg(pDM_Odm, rOFDM0_TRMuxPar, bMaskDWord, 0x000800E4);
+- ODM_SetBBReg(pDM_Odm, rFPGA0_XCD_RFInterfaceSW, bMaskDWord, 0x22208000);
+-
+- //IQK setting tone@ 4.34Mhz
+- ODM_SetBBReg(pDM_Odm, rTx_IQK_Tone_A, bMaskDWord, 0x10008C1C);
+- ODM_SetBBReg(pDM_Odm, rTx_IQK, bMaskDWord, 0x01007c00);
+-
+- //Page B init
+- ODM_SetBBReg(pDM_Odm, rConfig_AntA, bMaskDWord, 0x00080000);
+- ODM_SetBBReg(pDM_Odm, rConfig_AntA, bMaskDWord, 0x0f600000);
+- ODM_SetBBReg(pDM_Odm, rRx_IQK, bMaskDWord, 0x01004800);
+- ODM_SetBBReg(pDM_Odm, rRx_IQK_Tone_A, bMaskDWord, 0x10008c1f);
+- ODM_SetBBReg(pDM_Odm, rTx_IQK_PI_A, bMaskDWord, 0x82150008);
+- ODM_SetBBReg(pDM_Odm, rRx_IQK_PI_A, bMaskDWord, 0x28150008);
+- ODM_SetBBReg(pDM_Odm, rIQK_AGC_Rsp, bMaskDWord, 0x001028d0);
+-
+- //IQK Single tone start
+- ODM_SetBBReg(pDM_Odm, rFPGA0_IQK, bMaskH3Bytes, 0x808000);
+- ODM_SetBBReg(pDM_Odm, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
+- ODM_SetBBReg(pDM_Odm, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
+-
+- udelay(10000);
+-
+- // PSD report of antenna A
+- PSD_report_tmp=0x0;
+- for (n=0;n<2;n++)
+- {
+- PSD_report_tmp = GetPSDData(pDM_Odm, 14, initial_gain);
+- if(PSD_report_tmp >AntA_report)
+- AntA_report=PSD_report_tmp;
+- }
+-
+- // change to Antenna B
+- ODM_SetBBReg(pDM_Odm, rDPDT_control, 0x3, 0x2);
+-
+- udelay(10);
+-
+- // PSD report of antenna B
+- PSD_report_tmp=0x0;
+- for (n=0;n<2;n++)
+- {
+- PSD_report_tmp = GetPSDData(pDM_Odm, 14, initial_gain);
+- if(PSD_report_tmp > AntB_report)
+- AntB_report=PSD_report_tmp;
+- }
+-
+- // change to open case
+- ODM_SetBBReg(pDM_Odm, rDPDT_control, 0x3, 0x0);
+-
+- udelay(10);
+-
+- // PSD report of open case
+- PSD_report_tmp=0x0;
+- for (n=0;n<2;n++)
+- {
+- PSD_report_tmp = GetPSDData(pDM_Odm, 14, initial_gain);
+- if(PSD_report_tmp > AntO_report)
+- AntO_report=PSD_report_tmp;
+- }
+-
+- //Close IQK Single Tone function
+- ODM_SetBBReg(pDM_Odm, rFPGA0_IQK, bMaskH3Bytes, 0x000000);
+-
+- // external DPDT
+- ODM_SetBBReg(pDM_Odm, rDPDT_control, bMaskDWord, Reg92c);
+-
+- //internal S0/S1
+- ODM_SetBBReg(pDM_Odm, rS0S1_PathSwitch, bMaskDWord, Reg948);
+- ODM_SetBBReg(pDM_Odm, AGC_table_select, bMaskDWord, Regb2c);
+-
+- ODM_SetBBReg(pDM_Odm, rFPGA0_AnalogParameter4, bMaskDWord, Reg88c);
+- ODM_SetBBReg(pDM_Odm, rOFDM0_TRMuxPar, bMaskDWord, Regc08);
+- ODM_SetBBReg(pDM_Odm, rFPGA0_XCD_RFInterfaceSW, bMaskDWord, Reg874);
+- ODM_SetBBReg(pDM_Odm, rOFDM0_XAAGCCore1, 0x7F, 0x40);
+- ODM_SetBBReg(pDM_Odm, rOFDM0_XAAGCCore1, bMaskDWord, Regc50);
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, RF_CHNLBW, bRFRegOffsetMask,CurrentChannel);
+- ODM_SetRFReg(pDM_Odm, ODM_RF_PATH_A, 0x00, bRFRegOffsetMask,RfLoopReg);
+-
+- //Reload AFE Registers
+- ODM_SetBBReg(pDM_Odm, rRx_Wait_CCA, bMaskDWord, AFE_rRx_Wait_CCA);
+-
+- ODM_RT_TRACE(pDM_Odm,ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("psd_report_A[%d]= %d \n", 2416, AntA_report));
+- ODM_RT_TRACE(pDM_Odm,ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("psd_report_B[%d]= %d \n", 2416, AntB_report));
+- ODM_RT_TRACE(pDM_Odm,ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("psd_report_O[%d]= %d \n", 2416, AntO_report));
+-
+- //2 Test Ant B based on Ant A is ON
+- if(mode==ANTTESTB)
+- {
+- if(AntA_report >=100 && AntA_report <= 116)
+- {
+- if(AntB_report >= (AntA_report+4) && AntB_report > 116)
+- {
+- pDM_SWAT_Table->ANTB_ON=false;
+- ODM_RT_TRACE(pDM_Odm,ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("ODM_SingleDualAntennaDetection(): Single Antenna A\n"));
+- }
+- else if(AntB_report >=100 && AntB_report <= 116)
+- {
+- pDM_SWAT_Table->ANTB_ON=true;
+- ODM_RT_TRACE(pDM_Odm,ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("ODM_SingleDualAntennaDetection(): Dual Antenna is A and B\n"));
+- }
+- else
+- {
+- ODM_RT_TRACE(pDM_Odm,ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("ODM_SingleDualAntennaDetection(): Need to check again\n"));
+- pDM_SWAT_Table->ANTB_ON=false; // Set Antenna B off as default
+- bResult = false;
+- }
+- }
+- else
+- {
+- ODM_RT_TRACE(pDM_Odm,ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("ODM_SingleDualAntennaDetection(): Need to check again\n"));
+- pDM_SWAT_Table->ANTB_ON=false; // Set Antenna B off as default
+- bResult = false;
+- }
+- }
+- //2 Test Ant A and B based on DPDT Open
+- else if(mode==ANTTESTALL)
+- {
+- if((AntA_report >= 100) && (AntB_report >= 100) && (AntA_report <= 120) && (AntB_report <= 120))
+- {
+- if((AntA_report - AntB_report < 2) || (AntB_report - AntA_report < 2))
+- {
+- pDM_SWAT_Table->ANTA_ON=true;
+- pDM_SWAT_Table->ANTB_ON=true;
+- ODM_RT_TRACE(pDM_Odm,ODM_COMP_ANT_DIV, ODM_DBG_LOUD,("ODM_SingleDualAntennaDetection(): Dual Antenna\n"));
+- }
+- else if(((AntA_report - AntB_report >= 2) && (AntA_report - AntB_report <= 4)) ||
+- ((AntB_report - AntA_report >= 2) && (AntB_report - AntA_report <= 4)))
+- {
+- pDM_SWAT_Table->ANTA_ON=false;
+- pDM_SWAT_Table->ANTB_ON=false;
+- bResult = false;
+- ODM_RT_TRACE(pDM_Odm,ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("ODM_SingleDualAntennaDetection(): Need to check again\n"));
+- }
+- else
+- {
+- pDM_SWAT_Table->ANTA_ON = true;
+- pDM_SWAT_Table->ANTB_ON=false;
+- ODM_RT_TRACE(pDM_Odm,ODM_COMP_ANT_DIV, ODM_DBG_LOUD,("ODM_SingleDualAntennaDetection(): Single Antenna A\n"));
+- }
+-
+- pDM_Odm->AntDetectedInfo.bAntDetected= true;
+- pDM_Odm->AntDetectedInfo.dBForAntA = AntA_report;
+- pDM_Odm->AntDetectedInfo.dBForAntB = AntB_report;
+- pDM_Odm->AntDetectedInfo.dBForAntO = AntO_report;
+-
+- }
+- else
+- {
+- ODM_RT_TRACE(pDM_Odm,ODM_COMP_ANT_DIV, ODM_DBG_LOUD,("return false!!\n"));
+- bResult = false;
+- }
+- }
+-
+- return bResult;
+-
+-}
+-
+-static void
+-odm_Set_RA_DM_ARFB_by_Noisy(
+- IN PDM_ODM_T pDM_Odm
+-)
+-{
+- //DbgPrint("DM_ARFB ====> \n");
+- if (pDM_Odm->bNoisyState){
+- ODM_Write4Byte(pDM_Odm,0x430,0x00000000);
+- ODM_Write4Byte(pDM_Odm,0x434,0x05040200);
+- //DbgPrint("DM_ARFB ====> Noisy State\n");
+- }
+- else{
+- ODM_Write4Byte(pDM_Odm,0x430,0x02010000);
+- ODM_Write4Byte(pDM_Odm,0x434,0x07050403);
+- //DbgPrint("DM_ARFB ====> Clean State\n");
+- }
+-
+-}
+-
+-void
+-ODM_UpdateNoisyState(
+- IN PDM_ODM_T pDM_Odm,
+- IN bool bNoisyStateFromC2H
+- )
+-{
+- //DbgPrint("Get C2H Command! NoisyState=0x%x\n ", bNoisyStateFromC2H);
+- pDM_Odm->bNoisyState = bNoisyStateFromC2H;
+- odm_Set_RA_DM_ARFB_by_Noisy(pDM_Odm);
+-};
+-
+-u4Byte
+-Set_RA_DM_Ratrbitmap_by_Noisy(
+- IN PDM_ODM_T pDM_Odm,
+- IN WIRELESS_MODE WirelessMode,
+- IN u4Byte ratr_bitmap,
+- IN u1Byte rssi_level
+-)
+-{
+- u4Byte ret_bitmap = ratr_bitmap;
+- switch (WirelessMode)
+- {
+- case WIRELESS_MODE_AC_24G :
+- case WIRELESS_MODE_AC_5G :
+- case WIRELESS_MODE_AC_ONLY:
+- if (pDM_Odm->bNoisyState){ // in Noisy State
+- if (rssi_level==1)
+- ret_bitmap&=0xfe3f0e08;
+- else if (rssi_level==2)
+- ret_bitmap&=0xff3f8f8c;
+- else if (rssi_level==3)
+- ret_bitmap&=0xffffffcc ;
+- else
+- ret_bitmap&=0xffffffff ;
+- }
+- else{ // in SNR State
+- if (rssi_level==1){
+- ret_bitmap&=0xfc3e0c08;
+- }
+- else if (rssi_level==2){
+- ret_bitmap&=0xfe3f0e08;
+- }
+- else if (rssi_level==3){
+- ret_bitmap&=0xffbfefcc;
+- }
+- else{
+- ret_bitmap&=0x0fffffff;
+- }
+- }
+- break;
+- case WIRELESS_MODE_B:
+- case WIRELESS_MODE_A:
+- case WIRELESS_MODE_G:
+- case WIRELESS_MODE_N_24G:
+- case WIRELESS_MODE_N_5G:
+- if (pDM_Odm->bNoisyState){
+- if (rssi_level==1)
+- ret_bitmap&=0x0f0e0c08;
+- else if (rssi_level==2)
+- ret_bitmap&=0x0f8f0e0c;
+- else if (rssi_level==3)
+- ret_bitmap&=0x0fefefcc ;
+- else
+- ret_bitmap&=0xffffffff ;
+- }
+- else{
+- if (rssi_level==1){
+- ret_bitmap&=0x0f8f0e08;
+- }
+- else if (rssi_level==2){
+- ret_bitmap&=0x0fcf8f8c;
+- }
+- else if (rssi_level==3){
+- ret_bitmap&=0x0fffffcc;
+- }
+- else{
+- ret_bitmap&=0x0fffffff;
+- }
+- }
+- break;
+- default:
+- break;
+- }
+- //DbgPrint("DM_RAMask ====> rssi_LV = %d, BITMAP = %x \n", rssi_level, ret_bitmap);
+- return ret_bitmap;
+-
+-}
+-
+-
+-
+-void
+-ODM_UpdateInitRate(
+- IN PDM_ODM_T pDM_Odm,
+- IN u1Byte Rate
+- )
+-{
+- u1Byte p = 0;
+-
+- ODM_RT_TRACE(pDM_Odm,ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD,("Get C2H Command! Rate=0x%x\n", Rate));
+-
+- pDM_Odm->TxRate = Rate;
+-}
+diff -Nurp linux/3rdparty/rtl8723bs.old/hal/odm_CfoTracking.c linux/3rdparty/rtl8723bs/hal/odm_CfoTracking.c
+--- linux/3rdparty/rtl8723bs.old/hal/odm_CfoTracking.c 2015-05-10 14:36:05.705668313 +0300
++++ linux/3rdparty/rtl8723bs/hal/odm_CfoTracking.c 2015-05-07 17:46:55.000000000 +0300
+@@ -41,7 +41,7 @@ odm_SetCrystalCap(
+
+ // 0x2C[23:18] = 0x2C[17:12] = CrystalCap
+ CrystalCap = CrystalCap & 0x3F;
+- ODM_SetBBReg(pDM_Odm, REG_MAC_PHY_CTRL, 0x00FFF000, (CrystalCap | (CrystalCap << 6)));
++ PHY_SetBBReg(pDM_Odm->Adapter, REG_MAC_PHY_CTRL, 0x00FFF000, (CrystalCap | (CrystalCap << 6)));
+
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD, ("odm_SetCrystalCap(): CrystalCap = 0x%x\n", CrystalCap));
+ }
+@@ -76,7 +76,7 @@ odm_SetATCStatus(
+ if(pCfoTrack->bATCStatus == ATCStatus)
+ return;
+
+- ODM_SetBBReg(pDM_Odm, ODM_REG(BB_ATC,pDM_Odm), ODM_BIT(BB_ATC,pDM_Odm), ATCStatus);
++ PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG(BB_ATC,pDM_Odm), ODM_BIT(BB_ATC,pDM_Odm), ATCStatus);
+ pCfoTrack->bATCStatus = ATCStatus;
+ }
+
+@@ -88,7 +88,7 @@ odm_GetATCStatus(
+ bool ATCStatus;
+ PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
+
+- ATCStatus = (bool)ODM_GetBBReg(pDM_Odm, ODM_REG(BB_ATC,pDM_Odm), ODM_BIT(BB_ATC,pDM_Odm));
++ ATCStatus = (bool)PHY_QueryBBReg(pDM_Odm->Adapter, ODM_REG(BB_ATC,pDM_Odm), ODM_BIT(BB_ATC,pDM_Odm));
+ return ATCStatus;
+ }
+
+diff -Nurp linux/3rdparty/rtl8723bs.old/hal/odm_DIG.c linux/3rdparty/rtl8723bs/hal/odm_DIG.c
+--- linux/3rdparty/rtl8723bs.old/hal/odm_DIG.c 2015-05-10 14:36:05.706668324 +0300
++++ linux/3rdparty/rtl8723bs/hal/odm_DIG.c 2015-05-07 17:46:55.000000000 +0300
+@@ -27,52 +27,6 @@
+
+
+ void
+-ODM_ChangeDynamicInitGainThresh(
+- IN void * pDM_VOID,
+- IN u4Byte DM_Type,
+- IN u4Byte DM_Value
+- )
+-{
+- PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
+- pDIG_T pDM_DigTable = &pDM_Odm->DM_DigTable;
+-
+- if (DM_Type == DIG_TYPE_THRESH_HIGH)
+- {
+- pDM_DigTable->RssiHighThresh = DM_Value;
+- }
+- else if (DM_Type == DIG_TYPE_THRESH_LOW)
+- {
+- pDM_DigTable->RssiLowThresh = DM_Value;
+- }
+- else if (DM_Type == DIG_TYPE_ENABLE)
+- {
+- pDM_DigTable->Dig_Enable_Flag = true;
+- }
+- else if (DM_Type == DIG_TYPE_DISABLE)
+- {
+- pDM_DigTable->Dig_Enable_Flag = false;
+- }
+- else if (DM_Type == DIG_TYPE_BACKOFF)
+- {
+- if(DM_Value > 30)
+- DM_Value = 30;
+- pDM_DigTable->BackoffVal = (u1Byte)DM_Value;
+- }
+- else if(DM_Type == DIG_TYPE_RX_GAIN_MIN)
+- {
+- if(DM_Value == 0)
+- DM_Value = 0x1;
+- pDM_DigTable->rx_gain_range_min = (u1Byte)DM_Value;
+- }
+- else if(DM_Type == DIG_TYPE_RX_GAIN_MAX)
+- {
+- if(DM_Value > 0x50)
+- DM_Value = 0x50;
+- pDM_DigTable->rx_gain_range_max = (u1Byte)DM_Value;
+- }
+-} // DM_ChangeDynamicInitGainThresh //
+-
+-void
+ odm_NHMCounterStatisticsInit(
+ IN void * pDM_VOID
+ )
+@@ -80,15 +34,15 @@ odm_NHMCounterStatisticsInit(
+ PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
+
+ //PHY parameters initialize for n series
+- ODM_Write2Byte(pDM_Odm, ODM_REG_NHM_TIMER_11N+2, 0x2710); //0x894[31:16]=0x2710 Time duration for NHM unit: 4us, 0x2710=40ms
+- //ODM_Write2Byte(pDM_Odm, ODM_REG_NHM_TIMER_11N+2, 0x4e20); //0x894[31:16]=0x4e20 Time duration for NHM unit: 4us, 0x4e20=80ms
+- ODM_Write2Byte(pDM_Odm, ODM_REG_NHM_TH9_TH10_11N+2, 0xffff); //0x890[31:16]=0xffff th_9, th_10
+- //ODM_Write4Byte(pDM_Odm, ODM_REG_NHM_TH3_TO_TH0_11N, 0xffffff5c); //0x898=0xffffff5c th_3, th_2, th_1, th_0
+- ODM_Write4Byte(pDM_Odm, ODM_REG_NHM_TH3_TO_TH0_11N, 0xffffff52); //0x898=0xffffff52 th_3, th_2, th_1, th_0
+- ODM_Write4Byte(pDM_Odm, ODM_REG_NHM_TH7_TO_TH4_11N, 0xffffffff); //0x89c=0xffffffff th_7, th_6, th_5, th_4
+- ODM_SetBBReg(pDM_Odm, ODM_REG_FPGA0_IQK_11N, bMaskByte0, 0xff); //0xe28[7:0]=0xff th_8
+- ODM_SetBBReg(pDM_Odm, ODM_REG_NHM_TH9_TH10_11N, BIT10|BIT9|BIT8, 0x7); //0x890[9:8]=3 enable CCX
+- ODM_SetBBReg(pDM_Odm, ODM_REG_OFDM_FA_RSTC_11N, BIT7, 0x1); //0xc0c[7]=1 max power among all RX ants
++ rtw_write16(pDM_Odm->Adapter, ODM_REG_NHM_TIMER_11N+2, 0x2710); //0x894[31:16]=0x2710 Time duration for NHM unit: 4us, 0x2710=40ms
++ //rtw_write16(pDM_Odm->Adapter, ODM_REG_NHM_TIMER_11N+2, 0x4e20); //0x894[31:16]=0x4e20 Time duration for NHM unit: 4us, 0x4e20=80ms
++ rtw_write16(pDM_Odm->Adapter, ODM_REG_NHM_TH9_TH10_11N+2, 0xffff); //0x890[31:16]=0xffff th_9, th_10
++ //rtw_write32(pDM_Odm->Adapter, ODM_REG_NHM_TH3_TO_TH0_11N, 0xffffff5c); //0x898=0xffffff5c th_3, th_2, th_1, th_0
++ rtw_write32(pDM_Odm->Adapter, ODM_REG_NHM_TH3_TO_TH0_11N, 0xffffff52); //0x898=0xffffff52 th_3, th_2, th_1, th_0
++ rtw_write32(pDM_Odm->Adapter, ODM_REG_NHM_TH7_TO_TH4_11N, 0xffffffff); //0x89c=0xffffffff th_7, th_6, th_5, th_4
++ PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_FPGA0_IQK_11N, bMaskByte0, 0xff); //0xe28[7:0]=0xff th_8
++ PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_NHM_TH9_TH10_11N, BIT10|BIT9|BIT8, 0x7); //0x890[9:8]=3 enable CCX
++ PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_OFDM_FA_RSTC_11N, BIT7, 0x1); //0xc0c[7]=1 max power among all RX ants
+ }
+
+ void
+@@ -113,7 +67,7 @@ odm_GetNHMCounterStatistics(
+ PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
+ u4Byte value32 = 0;
+
+- value32 = ODM_GetBBReg(pDM_Odm, ODM_REG_NHM_CNT_11N, bMaskDWord);
++ value32 = PHY_QueryBBReg(pDM_Odm->Adapter, ODM_REG_NHM_CNT_11N, bMaskDWord);
+
+ pDM_Odm->NHM_cnt_0 = (u1Byte)(value32 & bMaskByte0);
+ }
+@@ -125,8 +79,8 @@ odm_NHMCounterStatisticsReset(
+ {
+ PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
+
+- ODM_SetBBReg(pDM_Odm, ODM_REG_NHM_TH9_TH10_11N, BIT1, 0);
+- ODM_SetBBReg(pDM_Odm, ODM_REG_NHM_TH9_TH10_11N, BIT1, 1);
++ PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_NHM_TH9_TH10_11N, BIT1, 0);
++ PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_NHM_TH9_TH10_11N, BIT1, 1);
+ }
+
+ void
+@@ -170,8 +124,6 @@ odm_NHMBB(
+ //Enable EDCCA since it is possible running Adaptivity testing
+ //test_status = 1;
+ pDM_Odm->adaptivity_flag = true;
+- ODM_SetMACReg(pDM_Odm, REG_TX_PTCL_CTRL, BIT15, 0); //don't ignore EDCCA reg520[15]=0
+- ODM_SetMACReg(pDM_Odm, REG_RD_CTRL, BIT11, 1); //reg524[11]=1
+ pDM_Odm->tolerance_cnt = 0;
+ }
+ else
+@@ -184,8 +136,6 @@ odm_NHMBB(
+ if(pDM_Odm->tolerance_cnt > 3)
+ {
+ //test_status = 3;
+- ODM_SetMACReg(pDM_Odm, REG_TX_PTCL_CTRL, BIT15, 1); //ignore EDCCA reg520[15]=1
+- ODM_SetMACReg(pDM_Odm, REG_RD_CTRL, BIT11, 0); //reg524[11]=0
+ pDM_Odm->adaptivity_flag = false;
+ }
+ }
+@@ -195,8 +145,6 @@ odm_NHMBB(
+ if(pDM_Odm->adaptivity_flag == true && pDM_Odm->NHM_cnt_0 <= 200)
+ {
+ //test_status = 2;
+- ODM_SetMACReg(pDM_Odm, REG_TX_PTCL_CTRL, BIT15, 0); //don't ignore EDCCA reg520[15]=0
+- ODM_SetMACReg(pDM_Odm, REG_RD_CTRL, BIT11, 1); //reg524[11]=1
+ pDM_Odm->tolerance_cnt = 0;
+ }
+ else
+@@ -209,8 +157,6 @@ odm_NHMBB(
+ if(pDM_Odm->tolerance_cnt >3)
+ {
+ //test_status = 4;
+- ODM_SetMACReg(pDM_Odm, REG_TX_PTCL_CTRL, BIT15, 1); //ignore EDCCA reg520[15]=1
+- ODM_SetMACReg(pDM_Odm, REG_RD_CTRL, BIT11, 0); //reg524[11]=0
+ pDM_Odm->adaptivity_flag = false;
+ }
+ }
+@@ -241,8 +187,8 @@ odm_SearchPwdBLowerBound(
+ if(TH_L2H_dmc > 10)
+ TH_L2H_dmc = 10;
+ TH_H2L_dmc = TH_L2H_dmc - pDM_Odm->TH_EDCCA_HL_diff;
+- ODM_SetBBReg(pDM_Odm,rOFDM0_ECCAThreshold, bMaskByte0, (u1Byte)TH_L2H_dmc);
+- ODM_SetBBReg(pDM_Odm,rOFDM0_ECCAThreshold, bMaskByte2, (u1Byte)TH_H2L_dmc);
++ PHY_SetBBReg(pDM_Odm->Adapter,rOFDM0_ECCAThreshold, bMaskByte0, (u1Byte)TH_L2H_dmc);
++ PHY_SetBBReg(pDM_Odm->Adapter,rOFDM0_ECCAThreshold, bMaskByte2, (u1Byte)TH_H2L_dmc);
+
+ mdelay(5);
+
+@@ -250,7 +196,7 @@ odm_SearchPwdBLowerBound(
+ {
+ for(cnt=0; cnt<20; cnt ++)
+ {
+- value32 = ODM_GetBBReg(pDM_Odm,ODM_REG_RPT_11N, bMaskDWord);
++ value32 = PHY_QueryBBReg(pDM_Odm->Adapter,ODM_REG_RPT_11N, bMaskDWord);
+
+ if (value32 & BIT30)
+ pDM_Odm->txEdcca1 = pDM_Odm->txEdcca1 + 1;
+@@ -268,8 +214,8 @@ odm_SearchPwdBLowerBound(
+ if(TH_L2H_dmc > 10)
+ TH_L2H_dmc = 10;
+ TH_H2L_dmc = TH_L2H_dmc - pDM_Odm->TH_EDCCA_HL_diff;
+- ODM_SetBBReg(pDM_Odm,rOFDM0_ECCAThreshold, bMaskByte0, (u1Byte)TH_L2H_dmc);
+- ODM_SetBBReg(pDM_Odm,rOFDM0_ECCAThreshold, bMaskByte2, (u1Byte)TH_H2L_dmc);
++ PHY_SetBBReg(pDM_Odm->Adapter,rOFDM0_ECCAThreshold, bMaskByte0, (u1Byte)TH_L2H_dmc);
++ PHY_SetBBReg(pDM_Odm->Adapter,rOFDM0_ECCAThreshold, bMaskByte2, (u1Byte)TH_H2L_dmc);
+
+ pDM_Odm->TxHangFlg = true;
+ pDM_Odm->txEdcca1 = 0;
+@@ -332,7 +278,7 @@ odm_AdaptivityInit(
+ pDM_Odm->Adaptivity_IGI_upper = 0;
+ odm_NHMBBInit(pDM_Odm);
+
+- ODM_SetBBReg(pDM_Odm, REG_RD_CTRL, BIT11, 1); // stop counting if EDCCA is asserted
++ PHY_SetBBReg(pDM_Odm->Adapter, REG_RD_CTRL, BIT11, 1); // stop counting if EDCCA is asserted
+ }
+
+
+@@ -369,14 +315,14 @@ odm_Adaptivity(
+ //Search pwdB lower bound
+ if(pDM_Odm->TxHangFlg == true)
+ {
+- ODM_SetBBReg(pDM_Odm,ODM_REG_DBG_RPT_11N, bMaskDWord, 0x208);
++ PHY_SetBBReg(pDM_Odm->Adapter,ODM_REG_DBG_RPT_11N, bMaskDWord, 0x208);
+ odm_SearchPwdBLowerBound(pDM_Odm, pDM_Odm->IGI_target );
+ }
+
+ if((!pDM_Odm->bLinked)||(*pDM_Odm->pChannel > 149)) // Band4 doesn't need adaptivity
+ {
+- ODM_SetBBReg(pDM_Odm,rOFDM0_ECCAThreshold, bMaskByte0, 0x7f);
+- ODM_SetBBReg(pDM_Odm,rOFDM0_ECCAThreshold, bMaskByte2, 0x7f);
++ PHY_SetBBReg(pDM_Odm->Adapter,rOFDM0_ECCAThreshold, bMaskByte0, 0x7f);
++ PHY_SetBBReg(pDM_Odm->Adapter,rOFDM0_ECCAThreshold, bMaskByte2, 0x7f);
+ return;
+ }
+
+@@ -418,8 +364,8 @@ odm_Adaptivity(
+ }
+ ODM_RT_TRACE(pDM_Odm,ODM_COMP_DIG, ODM_DBG_LOUD, ("IGI=0x%x, TH_L2H_dmc = %d, TH_H2L_dmc = %d\n",
+ IGI, TH_L2H_dmc, TH_H2L_dmc));
+- ODM_SetBBReg(pDM_Odm,rOFDM0_ECCAThreshold, bMaskByte0, (u1Byte)TH_L2H_dmc);
+- ODM_SetBBReg(pDM_Odm,rOFDM0_ECCAThreshold, bMaskByte2, (u1Byte)TH_H2L_dmc);
++ PHY_SetBBReg(pDM_Odm->Adapter,rOFDM0_ECCAThreshold, bMaskByte0, (u1Byte)TH_L2H_dmc);
++ PHY_SetBBReg(pDM_Odm->Adapter,rOFDM0_ECCAThreshold, bMaskByte2, (u1Byte)TH_H2L_dmc);
+ }
+
+ void
+@@ -454,10 +400,10 @@ ODM_Write_DIG(
+ }
+
+ //1 Set IGI value
+- ODM_SetBBReg(pDM_Odm, ODM_REG(IGI_A,pDM_Odm), ODM_BIT(IGI,pDM_Odm), CurrentIGI);
++ PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG(IGI_A,pDM_Odm), ODM_BIT(IGI,pDM_Odm), CurrentIGI);
+
+ if(pDM_Odm->RFType > ODM_1T1R)
+- ODM_SetBBReg(pDM_Odm, ODM_REG(IGI_B,pDM_Odm), ODM_BIT(IGI,pDM_Odm), CurrentIGI);
++ PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG(IGI_B,pDM_Odm), ODM_BIT(IGI,pDM_Odm), CurrentIGI);
+
+ pDM_DigTable->CurIGValue = CurrentIGI;
+ }
+@@ -582,7 +528,7 @@ odm_DIGInit(
+
+ pDM_DigTable->bStopDIG = false;
+ pDM_DigTable->bPSDInProgress = false;
+- pDM_DigTable->CurIGValue = (u1Byte) ODM_GetBBReg(pDM_Odm, ODM_REG(IGI_A,pDM_Odm), ODM_BIT(IGI,pDM_Odm));
++ pDM_DigTable->CurIGValue = (u1Byte) PHY_QueryBBReg(pDM_Odm->Adapter, ODM_REG(IGI_A,pDM_Odm), ODM_BIT(IGI,pDM_Odm));
+ pDM_DigTable->RssiLowThresh = DM_DIG_THRESH_LOW;
+ pDM_DigTable->RssiHighThresh = DM_DIG_THRESH_HIGH;
+ pDM_DigTable->FALowThresh = DMfalseALARM_THRESH_LOW;
+@@ -925,14 +871,6 @@ odm_DIGbyRSSI_LPS(
+ ODM_Write_DIG(pDM_Odm, CurrentIGI);//ODM_Write_DIG(pDM_Odm, pDM_DigTable->CurIGValue);
+ }
+
+-void
+-odm_DigForBtHsMode(
+- IN void * pDM_VOID
+- )
+-{
+-}
+-
+-
+ //3============================================================
+ //3 FASLE ALARM CHECK
+ //3============================================================
+@@ -950,22 +888,22 @@ odm_FalseAlarmCounterStatistics(
+ return;
+
+ //hold ofdm counter
+- ODM_SetBBReg(pDM_Odm, ODM_REG_OFDM_FA_HOLDC_11N, BIT31, 1); //hold page C counter
+- ODM_SetBBReg(pDM_Odm, ODM_REG_OFDM_FA_RSTD_11N, BIT31, 1); //hold page D counter
++ PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_OFDM_FA_HOLDC_11N, BIT31, 1); //hold page C counter
++ PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_OFDM_FA_RSTD_11N, BIT31, 1); //hold page D counter
+
+- ret_value = ODM_GetBBReg(pDM_Odm, ODM_REG_OFDM_FA_TYPE1_11N, bMaskDWord);
++ ret_value = PHY_QueryBBReg(pDM_Odm->Adapter, ODM_REG_OFDM_FA_TYPE1_11N, bMaskDWord);
+ FalseAlmCnt->Cnt_Fast_Fsync = (ret_value&0xffff);
+ FalseAlmCnt->Cnt_SB_Search_fail = ((ret_value&0xffff0000)>>16);
+
+- ret_value = ODM_GetBBReg(pDM_Odm, ODM_REG_OFDM_FA_TYPE2_11N, bMaskDWord);
++ ret_value = PHY_QueryBBReg(pDM_Odm->Adapter, ODM_REG_OFDM_FA_TYPE2_11N, bMaskDWord);
+ FalseAlmCnt->Cnt_OFDM_CCA = (ret_value&0xffff);
+ FalseAlmCnt->Cnt_Parity_Fail = ((ret_value&0xffff0000)>>16);
+
+- ret_value = ODM_GetBBReg(pDM_Odm, ODM_REG_OFDM_FA_TYPE3_11N, bMaskDWord);
++ ret_value = PHY_QueryBBReg(pDM_Odm->Adapter, ODM_REG_OFDM_FA_TYPE3_11N, bMaskDWord);
+ FalseAlmCnt->Cnt_Rate_Illegal = (ret_value&0xffff);
+ FalseAlmCnt->Cnt_Crc8_fail = ((ret_value&0xffff0000)>>16);
+
+- ret_value = ODM_GetBBReg(pDM_Odm, ODM_REG_OFDM_FA_TYPE4_11N, bMaskDWord);
++ ret_value = PHY_QueryBBReg(pDM_Odm->Adapter, ODM_REG_OFDM_FA_TYPE4_11N, bMaskDWord);
+ FalseAlmCnt->Cnt_Mcs_fail = (ret_value&0xffff);
+
+ FalseAlmCnt->Cnt_Ofdm_fail = FalseAlmCnt->Cnt_Parity_Fail + FalseAlmCnt->Cnt_Rate_Illegal +
+@@ -974,16 +912,16 @@ odm_FalseAlarmCounterStatistics(
+
+ {
+ //hold cck counter
+- ODM_SetBBReg(pDM_Odm, ODM_REG_CCK_FA_RST_11N, BIT12, 1);
+- ODM_SetBBReg(pDM_Odm, ODM_REG_CCK_FA_RST_11N, BIT14, 1);
++ PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_CCK_FA_RST_11N, BIT12, 1);
++ PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_CCK_FA_RST_11N, BIT14, 1);
+
+- ret_value = ODM_GetBBReg(pDM_Odm, ODM_REG_CCK_FA_LSB_11N, bMaskByte0);
++ ret_value = PHY_QueryBBReg(pDM_Odm->Adapter, ODM_REG_CCK_FA_LSB_11N, bMaskByte0);
+ FalseAlmCnt->Cnt_Cck_fail = ret_value;
+
+- ret_value = ODM_GetBBReg(pDM_Odm, ODM_REG_CCK_FA_MSB_11N, bMaskByte3);
++ ret_value = PHY_QueryBBReg(pDM_Odm->Adapter, ODM_REG_CCK_FA_MSB_11N, bMaskByte3);
+ FalseAlmCnt->Cnt_Cck_fail += (ret_value& 0xff)<<8;
+
+- ret_value = ODM_GetBBReg(pDM_Odm, ODM_REG_CCK_CCA_CNT_11N, bMaskDWord);
++ ret_value = PHY_QueryBBReg(pDM_Odm->Adapter, ODM_REG_CCK_CCA_CNT_11N, bMaskDWord);
+ FalseAlmCnt->Cnt_CCK_CCA = ((ret_value&0xFF)<<8) |((ret_value&0xFF00)>>8);
+ }
+
+@@ -1115,82 +1053,11 @@ odm_ForbiddenIGICheck(
+
+ }
+
+-void
+-odm_InbandNoiseCalculate (
+- IN void * pDM_VOID
+- )
+-{
+- return;
+-}
+-
+ //3============================================================
+ //3 CCK Packet Detect Threshold
+ //3============================================================
+
+ void
+-odm_PauseCCKPacketDetection(
+- IN void * pDM_VOID,
+- IN ODM_Pause_CCKPD_TYPE PauseType,
+- IN u1Byte CCKPDThreshold
+-)
+-{
+- PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
+- pDIG_T pDM_DigTable = &pDM_Odm->DM_DigTable;
+- static bool bPaused = false;
+-
+- ODM_RT_TRACE(pDM_Odm,ODM_COMP_CCK_PD, ODM_DBG_LOUD, ("odm_PauseCCKPacketDetection()=========>\n"));
+-
+- if(!bPaused && (!(pDM_Odm->SupportAbility & ODM_BB_CCK_PD) || !(pDM_Odm->SupportAbility & ODM_BB_FA_CNT)))
+- {
+- ODM_RT_TRACE(pDM_Odm,ODM_COMP_CCK_PD, ODM_DBG_LOUD, ("Return: SupportAbility ODM_BB_CCK_PD or ODM_BB_FA_CNT is disabled\n"));
+- return;
+- }
+-
+- switch(PauseType)
+- {
+- //1 Pause CCK Packet Detection Threshold
+- case ODM_PAUSE_CCKPD:
+- //2 Disable DIG
+- ODM_CmnInfoUpdate(pDM_Odm, ODM_CMNINFO_ABILITY, pDM_Odm->SupportAbility & (~ODM_BB_CCK_PD));
+- ODM_RT_TRACE(pDM_Odm,ODM_COMP_CCK_PD, ODM_DBG_LOUD, ("Pause CCK packet detection threshold !!\n"));
+-
+- //2 Backup CCK Packet Detection Threshold value
+- if(!bPaused)
+- {
+- pDM_DigTable->CCKPDBackup = pDM_DigTable->CurCCK_CCAThres;
+- bPaused = true;
+- }
+- ODM_RT_TRACE(pDM_Odm,ODM_COMP_CCK_PD, ODM_DBG_LOUD, ("Backup CCK packet detection tgreshold = %d\n", pDM_DigTable->CCKPDBackup));
+-
+- //2 Write new CCK Packet Detection Threshold value
+- ODM_Write_CCK_CCA_Thres(pDM_Odm, CCKPDThreshold);
+- ODM_RT_TRACE(pDM_Odm,ODM_COMP_CCK_PD, ODM_DBG_LOUD, ("Write new CCK packet detection tgreshold = %d\n", CCKPDThreshold));
+- break;
+-
+- //1 Resume CCK Packet Detection Threshold
+- case ODM_RESUME_CCKPD:
+- if(bPaused)
+- {
+- //2 Write backup CCK Packet Detection Threshold value
+- ODM_Write_CCK_CCA_Thres(pDM_Odm, pDM_DigTable->CCKPDBackup);
+- bPaused = false;
+- ODM_RT_TRACE(pDM_Odm,ODM_COMP_CCK_PD, ODM_DBG_LOUD, ("Write original CCK packet detection tgreshold = %d\n", pDM_DigTable->CCKPDBackup));
+-
+- //2 Enable CCK Packet Detection Threshold
+- ODM_CmnInfoUpdate(pDM_Odm, ODM_CMNINFO_ABILITY, pDM_Odm->SupportAbility | ODM_BB_CCK_PD);
+- ODM_RT_TRACE(pDM_Odm,ODM_COMP_CCK_PD, ODM_DBG_LOUD, ("Resume CCK packet detection threshold !!\n"));
+- }
+- break;
+-
+- default:
+- ODM_RT_TRACE(pDM_Odm,ODM_COMP_CCK_PD, ODM_DBG_LOUD, ("Wrong type !!\n"));
+- break;
+- }
+- return;
+-}
+-
+-
+-void
+ odm_CCKPacketDetectionThresh(
+ IN void * pDM_VOID
+ )
+@@ -1249,7 +1116,7 @@ ODM_Write_CCK_CCA_Thres(
+
+ if(pDM_DigTable->CurCCK_CCAThres!=CurCCK_CCAThres) //modify by Guo.Mingzhi 2012-01-03
+ {
+- ODM_Write1Byte(pDM_Odm, ODM_REG(CCK_CCA,pDM_Odm), CurCCK_CCAThres);
++ rtw_write8(pDM_Odm->Adapter, ODM_REG(CCK_CCA,pDM_Odm), CurCCK_CCAThres);
+ }
+ pDM_DigTable->PreCCK_CCAThres = pDM_DigTable->CurCCK_CCAThres;
+ pDM_DigTable->CurCCK_CCAThres = CurCCK_CCAThres;
+diff -Nurp linux/3rdparty/rtl8723bs.old/hal/odm_DIG.h linux/3rdparty/rtl8723bs/hal/odm_DIG.h
+--- linux/3rdparty/rtl8723bs.old/hal/odm_DIG.h 2015-05-10 14:36:05.707668335 +0300
++++ linux/3rdparty/rtl8723bs/hal/odm_DIG.h 2015-05-07 17:46:55.000000000 +0300
+@@ -189,13 +189,6 @@ typedef enum tag_DIG_Connect_Definition
+ #define RSSI_OFFSET_DIG 0x05
+
+ void
+-ODM_ChangeDynamicInitGainThresh(
+- IN void * pDM_VOID,
+- IN u4Byte DM_Type,
+- IN u4Byte DM_Value
+- );
+-
+-void
+ odm_NHMCounterStatisticsInit(
+ IN void * pDM_VOID
+ );
+@@ -271,11 +264,6 @@ odm_DIGbyRSSI_LPS(
+ );
+
+ void
+-odm_DigForBtHsMode(
+- IN void * pDM_VOID
+- );
+-
+-void
+ odm_FalseAlarmCounterStatistics(
+ IN void * pDM_VOID
+ );
+@@ -297,24 +285,12 @@ odm_ForbiddenIGICheck(
+ IN u1Byte CurrentIGI
+ );
+
+-void
+-odm_InbandNoiseCalculate (
+- IN void * pDM_VOID
+- );
+-
+ bool
+ odm_DigAbort(
+ IN void * pDM_VOID
+ );
+
+ void
+-odm_PauseCCKPacketDetection(
+- IN void * pDM_VOID,
+- IN ODM_Pause_CCKPD_TYPE PauseType,
+- IN u1Byte CCKPDThreshold
+- );
+-
+-void
+ odm_CCKPacketDetectionThresh(
+ IN void * pDM_VOID
+ );
+diff -Nurp linux/3rdparty/rtl8723bs.old/hal/odm_DynamicBBPowerSaving.c linux/3rdparty/rtl8723bs/hal/odm_DynamicBBPowerSaving.c
+--- linux/3rdparty/rtl8723bs.old/hal/odm_DynamicBBPowerSaving.c 2015-05-10 14:36:05.707668335 +0300
++++ linux/3rdparty/rtl8723bs/hal/odm_DynamicBBPowerSaving.c 2015-05-07 17:46:55.000000000 +0300
+@@ -40,61 +40,6 @@ odm_DynamicBBPowerSavingInit(
+ pDM_PSTable->initialize = 0;
+ }
+
+-
+-void
+-odm_1R_CCA(
+- IN void * pDM_VOID
+- )
+-{
+- PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
+- pPS_T pDM_PSTable = &pDM_Odm->DM_PSTable;
+-
+- if(pDM_Odm->RSSI_Min!= 0xFF)
+- {
+-
+- if(pDM_PSTable->PreCCAState == CCA_2R)
+- {
+- if(pDM_Odm->RSSI_Min >= 35)
+- pDM_PSTable->CurCCAState = CCA_1R;
+- else
+- pDM_PSTable->CurCCAState = CCA_2R;
+-
+- }
+- else{
+- if(pDM_Odm->RSSI_Min <= 30)
+- pDM_PSTable->CurCCAState = CCA_2R;
+- else
+- pDM_PSTable->CurCCAState = CCA_1R;
+- }
+- }
+- else{
+- pDM_PSTable->CurCCAState=CCA_MAX;
+- }
+-
+- if(pDM_PSTable->PreCCAState != pDM_PSTable->CurCCAState)
+- {
+- if(pDM_PSTable->CurCCAState == CCA_1R)
+- {
+- if( pDM_Odm->RFType ==ODM_2T2R )
+- {
+- ODM_SetBBReg(pDM_Odm, 0xc04 , bMaskByte0, 0x13);
+- //PHY_SetBBReg(pAdapter, 0xe70, bMaskByte3, 0x20);
+- }
+- else
+- {
+- ODM_SetBBReg(pDM_Odm, 0xc04 , bMaskByte0, 0x23);
+- //PHY_SetBBReg(pAdapter, 0xe70, 0x7fc00000, 0x10c); // Set RegE70[30:22] = 9b'100001100
+- }
+- }
+- else
+- {
+- ODM_SetBBReg(pDM_Odm, 0xc04 , bMaskByte0, 0x33);
+- //PHY_SetBBReg(pAdapter,0xe70, bMaskByte3, 0x63);
+- }
+- pDM_PSTable->PreCCAState = pDM_PSTable->CurCCAState;
+- }
+-}
+-
+ void
+ ODM_RF_Saving(
+ IN void * pDM_VOID,
+@@ -112,10 +57,10 @@ ODM_RF_Saving(
+ }
+ if(pDM_PSTable->initialize == 0){
+
+- pDM_PSTable->Reg874 = (ODM_GetBBReg(pDM_Odm, 0x874, bMaskDWord)&0x1CC000)>>14;
+- pDM_PSTable->RegC70 = (ODM_GetBBReg(pDM_Odm, 0xc70, bMaskDWord)&BIT3)>>3;
+- pDM_PSTable->Reg85C = (ODM_GetBBReg(pDM_Odm, 0x85c, bMaskDWord)&0xFF000000)>>24;
+- pDM_PSTable->RegA74 = (ODM_GetBBReg(pDM_Odm, 0xa74, bMaskDWord)&0xF000)>>12;
++ pDM_PSTable->Reg874 = (PHY_QueryBBReg(pDM_Odm->Adapter, 0x874, bMaskDWord)&0x1CC000)>>14;
++ pDM_PSTable->RegC70 = (PHY_QueryBBReg(pDM_Odm->Adapter, 0xc70, bMaskDWord)&BIT3)>>3;
++ pDM_PSTable->Reg85C = (PHY_QueryBBReg(pDM_Odm->Adapter, 0x85c, bMaskDWord)&0xFF000000)>>24;
++ pDM_PSTable->RegA74 = (PHY_QueryBBReg(pDM_Odm->Adapter, 0xa74, bMaskDWord)&0xF000)>>12;
+ //Reg818 = PHY_QueryBBReg(pAdapter, 0x818, bMaskDWord);
+ pDM_PSTable->initialize = 1;
+ }
+@@ -150,21 +95,21 @@ ODM_RF_Saving(
+ {
+ if(pDM_PSTable->CurRFState == RF_Save)
+ {
+- ODM_SetBBReg(pDM_Odm, 0x874 , 0x1C0000, 0x2); //Reg874[20:18]=3'b010
+- ODM_SetBBReg(pDM_Odm, 0xc70, BIT3, 0); //RegC70[3]=1'b0
+- ODM_SetBBReg(pDM_Odm, 0x85c, 0xFF000000, 0x63); //Reg85C[31:24]=0x63
+- ODM_SetBBReg(pDM_Odm, 0x874, 0xC000, 0x2); //Reg874[15:14]=2'b10
+- ODM_SetBBReg(pDM_Odm, 0xa74, 0xF000, 0x3); //RegA75[7:4]=0x3
+- ODM_SetBBReg(pDM_Odm, 0x818, BIT28, 0x0); //Reg818[28]=1'b0
+- ODM_SetBBReg(pDM_Odm, 0x818, BIT28, 0x1); //Reg818[28]=1'b1
++ PHY_SetBBReg(pDM_Odm->Adapter, 0x874 , 0x1C0000, 0x2); //Reg874[20:18]=3'b010
++ PHY_SetBBReg(pDM_Odm->Adapter, 0xc70, BIT3, 0); //RegC70[3]=1'b0
++ PHY_SetBBReg(pDM_Odm->Adapter, 0x85c, 0xFF000000, 0x63); //Reg85C[31:24]=0x63
++ PHY_SetBBReg(pDM_Odm->Adapter, 0x874, 0xC000, 0x2); //Reg874[15:14]=2'b10
++ PHY_SetBBReg(pDM_Odm->Adapter, 0xa74, 0xF000, 0x3); //RegA75[7:4]=0x3
++ PHY_SetBBReg(pDM_Odm->Adapter, 0x818, BIT28, 0x0); //Reg818[28]=1'b0
++ PHY_SetBBReg(pDM_Odm->Adapter, 0x818, BIT28, 0x1); //Reg818[28]=1'b1
+ }
+ else
+ {
+- ODM_SetBBReg(pDM_Odm, 0x874 , 0x1CC000, pDM_PSTable->Reg874);
+- ODM_SetBBReg(pDM_Odm, 0xc70, BIT3, pDM_PSTable->RegC70);
+- ODM_SetBBReg(pDM_Odm, 0x85c, 0xFF000000, pDM_PSTable->Reg85C);
+- ODM_SetBBReg(pDM_Odm, 0xa74, 0xF000, pDM_PSTable->RegA74);
+- ODM_SetBBReg(pDM_Odm,0x818, BIT28, 0x0);
++ PHY_SetBBReg(pDM_Odm->Adapter, 0x874 , 0x1CC000, pDM_PSTable->Reg874);
++ PHY_SetBBReg(pDM_Odm->Adapter, 0xc70, BIT3, pDM_PSTable->RegC70);
++ PHY_SetBBReg(pDM_Odm->Adapter, 0x85c, 0xFF000000, pDM_PSTable->Reg85C);
++ PHY_SetBBReg(pDM_Odm->Adapter, 0xa74, 0xF000, pDM_PSTable->RegA74);
++ PHY_SetBBReg(pDM_Odm->Adapter,0x818, BIT28, 0x0);
+ }
+ pDM_PSTable->PreRFState =pDM_PSTable->CurRFState;
+ }
+diff -Nurp linux/3rdparty/rtl8723bs.old/hal/odm_DynamicBBPowerSaving.h linux/3rdparty/rtl8723bs/hal/odm_DynamicBBPowerSaving.h
+--- linux/3rdparty/rtl8723bs.old/hal/odm_DynamicBBPowerSaving.h 2015-05-10 14:36:05.707668335 +0300
++++ linux/3rdparty/rtl8723bs/hal/odm_DynamicBBPowerSaving.h 2015-05-07 17:46:55.000000000 +0300
+@@ -48,9 +48,4 @@ odm_DynamicBBPowerSavingInit(
+ IN void * pDM_VOID
+ );
+
+-void
+-odm_1R_CCA(
+- IN void * pDM_VOID
+- );
+-
+ #endif
+diff -Nurp linux/3rdparty/rtl8723bs.old/hal/odm_DynamicTxPower.c linux/3rdparty/rtl8723bs/hal/odm_DynamicTxPower.c
+--- linux/3rdparty/rtl8723bs.old/hal/odm_DynamicTxPower.c 2015-05-10 14:36:05.707668335 +0300
++++ linux/3rdparty/rtl8723bs/hal/odm_DynamicTxPower.c 2015-05-07 17:46:55.000000000 +0300
+@@ -39,50 +39,3 @@ odm_DynamicTxPowerInit(
+ pdmpriv->LastDTPLvl = TxHighPwrLevel_Normal;
+ pdmpriv->DynamicTxHighPowerLvl = TxHighPwrLevel_Normal;
+ }
+-
+-void
+-odm_DynamicTxPowerSavePowerIndex(
+- IN void * pDM_VOID
+- )
+-{
+- PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
+- u1Byte index;
+- u4Byte Power_Index_REG[6] = {0xc90, 0xc91, 0xc92, 0xc98, 0xc99, 0xc9a};
+-
+- PADAPTER Adapter = pDM_Odm->Adapter;
+- HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);
+- struct dm_priv *pdmpriv = &pHalData->dmpriv;
+- for(index = 0; index< 6; index++)
+- pdmpriv->PowerIndex_backup[index] = rtw_read8(Adapter, Power_Index_REG[index]);
+-}
+-
+-void
+-odm_DynamicTxPowerRestorePowerIndex(
+- IN void * pDM_VOID
+- )
+-{
+- PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
+- u1Byte index;
+- PADAPTER Adapter = pDM_Odm->Adapter;
+- HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);
+- u4Byte Power_Index_REG[6] = {0xc90, 0xc91, 0xc92, 0xc98, 0xc99, 0xc9a};
+-
+- struct dm_priv *pdmpriv = &pHalData->dmpriv;
+- for(index = 0; index< 6; index++)
+- rtw_write8(Adapter, Power_Index_REG[index], pdmpriv->PowerIndex_backup[index]);
+-}
+-
+-void
+-odm_DynamicTxPowerWritePowerIndex(
+- IN void * pDM_VOID,
+- IN u1Byte Value)
+-{
+- PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
+- u1Byte index;
+- u4Byte Power_Index_REG[6] = {0xc90, 0xc91, 0xc92, 0xc98, 0xc99, 0xc9a};
+-
+- for(index = 0; index< 6; index++)
+- //PlatformEFIOWrite1Byte(Adapter, Power_Index_REG[index], Value);
+- ODM_Write1Byte(pDM_Odm, Power_Index_REG[index], Value);
+-
+-}
+diff -Nurp linux/3rdparty/rtl8723bs.old/hal/odm_DynamicTxPower.h linux/3rdparty/rtl8723bs/hal/odm_DynamicTxPower.h
+--- linux/3rdparty/rtl8723bs.old/hal/odm_DynamicTxPower.h 2015-05-10 14:36:05.707668335 +0300
++++ linux/3rdparty/rtl8723bs/hal/odm_DynamicTxPower.h 2015-05-07 17:46:55.000000000 +0300
+@@ -42,19 +42,4 @@ odm_DynamicTxPowerInit(
+ IN void * pDM_VOID
+ );
+
+-void
+-odm_DynamicTxPowerRestorePowerIndex(
+- IN void * pDM_VOID
+- );
+-
+-void
+-odm_DynamicTxPowerSavePowerIndex(
+- IN void * pDM_VOID
+- );
+-
+-void
+-odm_DynamicTxPowerWritePowerIndex(
+- IN void * pDM_VOID,
+- IN u1Byte Value);
+-
+ #endif
+diff -Nurp linux/3rdparty/rtl8723bs.old/hal/odm_EdcaTurboCheck.c linux/3rdparty/rtl8723bs/hal/odm_EdcaTurboCheck.c
+--- linux/3rdparty/rtl8723bs.old/hal/odm_EdcaTurboCheck.c 2015-05-10 14:36:05.707668335 +0300
++++ linux/3rdparty/rtl8723bs/hal/odm_EdcaTurboCheck.c 2015-05-07 17:46:55.000000000 +0300
+@@ -34,10 +34,10 @@ ODM_EdcaTurboInit(
+ pDM_Odm->DM_EDCA_Table.bIsCurRDLState = false;
+ Adapter->recvpriv.bIsAnyNonBEPkts =false;
+
+- ODM_RT_TRACE(pDM_Odm,ODM_COMP_EDCA_TURBO,ODM_DBG_LOUD,("Orginial VO PARAM: 0x%x\n",ODM_Read4Byte(pDM_Odm,ODM_EDCA_VO_PARAM)));
+- ODM_RT_TRACE(pDM_Odm,ODM_COMP_EDCA_TURBO,ODM_DBG_LOUD,("Orginial VI PARAM: 0x%x\n",ODM_Read4Byte(pDM_Odm,ODM_EDCA_VI_PARAM)));
+- ODM_RT_TRACE(pDM_Odm,ODM_COMP_EDCA_TURBO,ODM_DBG_LOUD,("Orginial BE PARAM: 0x%x\n",ODM_Read4Byte(pDM_Odm,ODM_EDCA_BE_PARAM)));
+- ODM_RT_TRACE(pDM_Odm,ODM_COMP_EDCA_TURBO,ODM_DBG_LOUD,("Orginial BK PARAM: 0x%x\n",ODM_Read4Byte(pDM_Odm,ODM_EDCA_BK_PARAM)));
++ ODM_RT_TRACE(pDM_Odm,ODM_COMP_EDCA_TURBO,ODM_DBG_LOUD,("Orginial VO PARAM: 0x%x\n",rtw_read32(pDM_Odm->Adapter,ODM_EDCA_VO_PARAM)));
++ ODM_RT_TRACE(pDM_Odm,ODM_COMP_EDCA_TURBO,ODM_DBG_LOUD,("Orginial VI PARAM: 0x%x\n",rtw_read32(pDM_Odm->Adapter,ODM_EDCA_VI_PARAM)));
++ ODM_RT_TRACE(pDM_Odm,ODM_COMP_EDCA_TURBO,ODM_DBG_LOUD,("Orginial BE PARAM: 0x%x\n",rtw_read32(pDM_Odm->Adapter,ODM_EDCA_BE_PARAM)));
++ ODM_RT_TRACE(pDM_Odm,ODM_COMP_EDCA_TURBO,ODM_DBG_LOUD,("Orginial BK PARAM: 0x%x\n",rtw_read32(pDM_Odm->Adapter,ODM_EDCA_BK_PARAM)));
+
+
+ } // ODM_InitEdcaTurbo
+diff -Nurp linux/3rdparty/rtl8723bs.old/hal/odm.h linux/3rdparty/rtl8723bs/hal/odm.h
+--- linux/3rdparty/rtl8723bs.old/hal/odm.h 2015-05-10 14:36:05.708668346 +0300
++++ linux/3rdparty/rtl8723bs/hal/odm.h 2015-05-07 17:46:55.000000000 +0300
+@@ -1515,9 +1515,6 @@ ODM_SetAntenna(
+
+ //Remove BB power saving by Yuchen
+
+-#define SwAntDivRestAfterLink ODM_SwAntDivRestAfterLink
+-void ODM_SwAntDivRestAfterLink( IN PDM_ODM_T pDM_Odm);
+-
+ #define dm_CheckTXPowerTracking ODM_TXPowerTrackingCheck
+ void
+ ODM_TXPowerTrackingCheck(
+@@ -1539,14 +1536,6 @@ void ODM_SwAntDivChkPerPktRssi(
+ IN PODM_PHY_INFO_T pPhyInfo
+ );
+
+-u4Byte ConvertTo_dB(u4Byte Value);
+-
+-u4Byte
+-GetPSDData(
+- PDM_ODM_T pDM_Odm,
+- unsigned int point,
+- u1Byte initial_gain_psd);
+-
+ u4Byte ODM_Get_Rate_Bitmap(
+ IN PDM_ODM_T pDM_Odm,
+ IN u4Byte macid,
+@@ -1572,11 +1561,6 @@ ODM_DMInit(
+ );
+
+ void
+-ODM_DMReset(
+- IN PDM_ODM_T pDM_Odm
+- );
+-
+-void
+ ODM_DMWatchdog(
+ IN PDM_ODM_T pDM_Odm // For common use in the future
+ );
+@@ -1634,56 +1618,6 @@ ODM_AntselStatistics_88C(
+ );
+
+ void
+-ODM_SingleDualAntennaDefaultSetting(
+- IN PDM_ODM_T pDM_Odm
+- );
+-
+-bool
+-ODM_SingleDualAntennaDetection(
+- IN PDM_ODM_T pDM_Odm,
+- IN u1Byte mode
+- );
+-
+-void
+-ODM_UpdateNoisyState(
+- IN PDM_ODM_T pDM_Odm,
+- IN bool bNoisyStateFromC2H
+-);
+-
+-u4Byte
+-Set_RA_DM_Ratrbitmap_by_Noisy(
+- IN PDM_ODM_T pDM_Odm,
+- IN WIRELESS_MODE WirelessMode,
+- IN u4Byte ratr_bitmap,
+- IN u1Byte rssi_level
+-);
+-
+-void
+-ODM_UpdateInitRate(
+- IN PDM_ODM_T pDM_Odm,
+- IN u1Byte Rate
+- );
+-
+-void
+-ODM_InitializeTimer(
+- IN PDM_ODM_T pDM_Odm,
+- IN PRT_TIMER pTimer,
+- IN RT_TIMER_CALL_BACK CallBackFunc,
+- IN void * pContext,
+- IN const char* szID
+-);
+-
+-void
+-ODM_CancelAllTimers(
+- IN PDM_ODM_T pDM_Odm
+-);
+-
+-void
+-ODM_ReleaseAllTimers(
+- IN PDM_ODM_T pDM_Odm
+-);
+-
+-void
+ ODM_DynamicARFBSelect(
+ IN PDM_ODM_T pDM_Odm,
+ IN u1Byte rate,
+diff -Nurp linux/3rdparty/rtl8723bs.old/hal/odm_HWConfig.c linux/3rdparty/rtl8723bs/hal/odm_HWConfig.c
+--- linux/3rdparty/rtl8723bs.old/hal/odm_HWConfig.c 2015-05-10 14:36:05.708668346 +0300
++++ linux/3rdparty/rtl8723bs/hal/odm_HWConfig.c 2015-05-07 17:46:55.000000000 +0300
+@@ -339,14 +339,6 @@ odm_RxPhyStatus92CSeries_Parsing(
+ //isCCKrate, pPhyInfo->RxPWDBAll, pPhyStaRpt->cck_agc_rpt_ofdm_cfosho_a);
+ }
+
+-void
+-odm_Init_RSSIForDM(
+- IN OUT PDM_ODM_T pDM_Odm
+- )
+-{
+-
+-}
+-
+ static void
+ odm_Process_RSSIForDM(
+ IN OUT PDM_ODM_T pDM_Odm,
+@@ -563,22 +555,6 @@ ODM_PhyStatusQuery(
+
+ ODM_PhyStatusQuery_92CSeries(pDM_Odm,pPhyInfo,pPhyStatus,pPktinfo);
+ }
+-
+-// For future use.
+-void
+-ODM_MacStatusQuery(
+- IN OUT PDM_ODM_T pDM_Odm,
+- IN pu1Byte pMacStatus,
+- IN u1Byte MacID,
+- IN bool bPacketMatchBSSID,
+- IN bool bPacketToSelf,
+- IN bool bPacketBeacon
+- )
+-{
+- // 2011/10/19 Driver team will handle in the future.
+-
+-}
+-
+
+ //
+ // If you want to add a new IC, Please follow below template and generate a new one.
+diff -Nurp linux/3rdparty/rtl8723bs.old/hal/odm_HWConfig.h linux/3rdparty/rtl8723bs/hal/odm_HWConfig.h
+--- linux/3rdparty/rtl8723bs.old/hal/odm_HWConfig.h 2015-05-10 14:36:05.709668358 +0300
++++ linux/3rdparty/rtl8723bs/hal/odm_HWConfig.h 2015-05-07 17:46:55.000000000 +0300
+@@ -137,11 +137,6 @@ typedef struct _Phy_Status_Rpt_8812
+
+
+ void
+-odm_Init_RSSIForDM(
+- IN OUT PDM_ODM_T pDM_Odm
+- );
+-
+-void
+ ODM_PhyStatusQuery(
+ IN OUT PDM_ODM_T pDM_Odm,
+ OUT PODM_PHY_INFO_T pPhyInfo,
+@@ -149,15 +144,6 @@ ODM_PhyStatusQuery(
+ IN PODM_PACKET_INFO_T pPktinfo
+ );
+
+-void
+-ODM_MacStatusQuery(
+- IN OUT PDM_ODM_T pDM_Odm,
+- IN pu1Byte pMacStatus,
+- IN u1Byte MacID,
+- IN bool bPacketMatchBSSID,
+- IN bool bPacketToSelf,
+- IN bool bPacketBeacon
+- );
+ HAL_STATUS
+ ODM_ConfigRFWithTxPwrTrackHeaderFile(
+ IN PDM_ODM_T pDM_Odm
+diff -Nurp linux/3rdparty/rtl8723bs.old/hal/odm_interface.c linux/3rdparty/rtl8723bs/hal/odm_interface.c
+--- linux/3rdparty/rtl8723bs.old/hal/odm_interface.c 2015-05-10 14:36:05.709668358 +0300
++++ linux/3rdparty/rtl8723bs/hal/odm_interface.c 1970-01-01 02:00:00.000000000 +0200
+@@ -1,268 +0,0 @@
+-/******************************************************************************
+- *
+- * 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.
+- *
+- * 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.,
+- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+- *
+- *
+- ******************************************************************************/
+-
+-//============================================================
+-// include files
+-//============================================================
+-
+-
+-#include "odm_precomp.h"
+-
+-//
+-// ODM IO Relative API.
+-//
+-
+-u1Byte
+-ODM_Read1Byte(
+- IN PDM_ODM_T pDM_Odm,
+- IN u4Byte RegAddr
+- )
+-{
+- PADAPTER Adapter = pDM_Odm->Adapter;
+- return rtw_read8(Adapter,RegAddr);
+-}
+-
+-
+-u2Byte
+-ODM_Read2Byte(
+- IN PDM_ODM_T pDM_Odm,
+- IN u4Byte RegAddr
+- )
+-{
+- PADAPTER Adapter = pDM_Odm->Adapter;
+- return rtw_read16(Adapter,RegAddr);
+-}
+-
+-
+-u4Byte
+-ODM_Read4Byte(
+- IN PDM_ODM_T pDM_Odm,
+- IN u4Byte RegAddr
+- )
+-{
+- PADAPTER Adapter = pDM_Odm->Adapter;
+- return rtw_read32(Adapter,RegAddr);
+-}
+-
+-
+-void
+-ODM_Write1Byte(
+- IN PDM_ODM_T pDM_Odm,
+- IN u4Byte RegAddr,
+- IN u1Byte Data
+- )
+-{
+- PADAPTER Adapter = pDM_Odm->Adapter;
+- rtw_write8(Adapter,RegAddr, Data);
+-}
+-
+-
+-void
+-ODM_Write2Byte(
+- IN PDM_ODM_T pDM_Odm,
+- IN u4Byte RegAddr,
+- IN u2Byte Data
+- )
+-{
+- PADAPTER Adapter = pDM_Odm->Adapter;
+- rtw_write16(Adapter,RegAddr, Data);
+-}
+-
+-
+-void
+-ODM_Write4Byte(
+- IN PDM_ODM_T pDM_Odm,
+- IN u4Byte RegAddr,
+- IN u4Byte Data
+- )
+-{
+- PADAPTER Adapter = pDM_Odm->Adapter;
+- rtw_write32(Adapter,RegAddr, Data);
+-}
+-
+-
+-void
+-ODM_SetMACReg(
+- IN PDM_ODM_T pDM_Odm,
+- IN u4Byte RegAddr,
+- IN u4Byte BitMask,
+- IN u4Byte Data
+- )
+-{
+-}
+-
+-
+-u4Byte
+-ODM_GetMACReg(
+- IN PDM_ODM_T pDM_Odm,
+- IN u4Byte RegAddr,
+- IN u4Byte BitMask
+- )
+-{
+- return PHY_QueryBBReg(pDM_Odm->Adapter, RegAddr, BitMask);
+-}
+-
+-
+-void
+-ODM_SetBBReg(
+- IN PDM_ODM_T pDM_Odm,
+- IN u4Byte RegAddr,
+- IN u4Byte BitMask,
+- IN u4Byte Data
+- )
+-{
+- PADAPTER Adapter = pDM_Odm->Adapter;
+- PHY_SetBBReg(Adapter, RegAddr, BitMask, Data);
+-}
+-
+-
+-u4Byte
+-ODM_GetBBReg(
+- IN PDM_ODM_T pDM_Odm,
+- IN u4Byte RegAddr,
+- IN u4Byte BitMask
+- )
+-{
+- PADAPTER Adapter = pDM_Odm->Adapter;
+- return PHY_QueryBBReg(Adapter, RegAddr, BitMask);
+-}
+-
+-
+-void
+-ODM_SetRFReg(
+- IN PDM_ODM_T pDM_Odm,
+- IN ODM_RF_RADIO_PATH_E eRFPath,
+- IN u4Byte RegAddr,
+- IN u4Byte BitMask,
+- IN u4Byte Data
+- )
+-{
+- PADAPTER Adapter = pDM_Odm->Adapter;
+- PHY_SetRFReg(Adapter, eRFPath, RegAddr, BitMask, Data);
+-}
+-
+-
+-u4Byte
+-ODM_GetRFReg(
+- IN PDM_ODM_T pDM_Odm,
+- IN ODM_RF_RADIO_PATH_E eRFPath,
+- IN u4Byte RegAddr,
+- IN u4Byte BitMask
+- )
+-{
+- PADAPTER Adapter = pDM_Odm->Adapter;
+- return PHY_QueryRFReg(Adapter, eRFPath, RegAddr, BitMask);
+-}
+-
+-//
+-// ODM Memory relative API.
+-//
+-void
+-ODM_AllocateMemory(
+- IN PDM_ODM_T pDM_Odm,
+- OUT void * *pPtr,
+- IN u4Byte length
+- )
+-{
+- *pPtr = rtw_zvmalloc(length);
+-}
+-
+-// length could be ignored, used to detect memory leakage.
+-void
+-ODM_FreeMemory(
+- IN PDM_ODM_T pDM_Odm,
+- OUT void * pPtr,
+- IN u4Byte length
+- )
+-{
+- rtw_vmfree(pPtr, length);
+-}
+-
+-//
+-// ODM Timer relative API.
+-//
+-void
+-ODM_SetTimer(
+- IN PDM_ODM_T pDM_Odm,
+- IN PRT_TIMER pTimer,
+- IN u4Byte msDelay
+- )
+-{
+- _set_timer(pTimer,msDelay ); //ms
+-}
+-
+-void
+-ODM_InitializeTimer(
+- IN PDM_ODM_T pDM_Odm,
+- IN PRT_TIMER pTimer,
+- IN RT_TIMER_CALL_BACK CallBackFunc,
+- IN void * pContext,
+- IN const char* szID
+- )
+-{
+- PADAPTER Adapter = pDM_Odm->Adapter;
+- _init_timer(pTimer,Adapter->pnetdev,CallBackFunc,pDM_Odm);
+-}
+-
+-
+-void
+-ODM_CancelTimer(
+- IN PDM_ODM_T pDM_Odm,
+- IN PRT_TIMER pTimer
+- )
+-{
+- _cancel_timer_ex(pTimer);
+-}
+-
+-
+-void
+-ODM_ReleaseTimer(
+- IN PDM_ODM_T pDM_Odm,
+- IN PRT_TIMER pTimer
+- )
+-{
+-}
+-
+-
+-//
+-// ODM FW relative API.
+-//
+-void
+-ODM_FillH2CCmd(
+- IN PDM_ODM_T pDM_Odm,
+- IN u1Byte ElementID,
+- IN u4Byte CmdLen,
+- IN pu1Byte pCmdBuffer
+-)
+-{
+- PADAPTER Adapter = pDM_Odm->Adapter;
+-
+- switch(ElementID)
+- {
+- case ODM_H2C_RSSI_REPORT:
+- FillH2CCmd8723B(Adapter, H2C_8723B_RSSI_SETTING, CmdLen, pCmdBuffer);
+- break;
+- case ODM_H2C_WIFI_CALIBRATION:
+- FillH2CCmd8723B(Adapter, H2C_8723B_BT_WLAN_CALIBRATION, CmdLen, pCmdBuffer);
+- break;
+- default:
+- break;
+- }
+-}
+diff -Nurp linux/3rdparty/rtl8723bs.old/hal/odm_interface.h linux/3rdparty/rtl8723bs/hal/odm_interface.h
+--- linux/3rdparty/rtl8723bs.old/hal/odm_interface.h 2015-05-10 14:36:05.709668358 +0300
++++ linux/3rdparty/rtl8723bs/hal/odm_interface.h 2015-05-07 17:46:55.000000000 +0300
+@@ -68,169 +68,4 @@ typedef enum _ODM_H2C_CMD
+ }ODM_H2C_CMD;
+
+
+-//
+-// 2012/02/17 MH For non-MP compile pass only. Linux does not support workitem.
+-// Suggest HW team to use thread instead of workitem. Windows also support the feature.
+-//
+-typedef void *PRT_WORK_ITEM ;
+-typedef void RT_WORKITEM_HANDLE,*PRT_WORKITEM_HANDLE;
+-typedef void (*RT_WORKITEM_CALL_BACK)(void * pContext);
+-
+-//
+-// =========== Extern Variable ??? It should be forbidden.
+-//
+-
+-
+-//
+-// =========== EXtern Function Prototype
+-//
+-
+-
+-u1Byte
+-ODM_Read1Byte(
+- IN PDM_ODM_T pDM_Odm,
+- IN u4Byte RegAddr
+- );
+-
+-u2Byte
+-ODM_Read2Byte(
+- IN PDM_ODM_T pDM_Odm,
+- IN u4Byte RegAddr
+- );
+-
+-u4Byte
+-ODM_Read4Byte(
+- IN PDM_ODM_T pDM_Odm,
+- IN u4Byte RegAddr
+- );
+-
+-void
+-ODM_Write1Byte(
+- IN PDM_ODM_T pDM_Odm,
+- IN u4Byte RegAddr,
+- IN u1Byte Data
+- );
+-
+-void
+-ODM_Write2Byte(
+- IN PDM_ODM_T pDM_Odm,
+- IN u4Byte RegAddr,
+- IN u2Byte Data
+- );
+-
+-void
+-ODM_Write4Byte(
+- IN PDM_ODM_T pDM_Odm,
+- IN u4Byte RegAddr,
+- IN u4Byte Data
+- );
+-
+-void
+-ODM_SetMACReg(
+- IN PDM_ODM_T pDM_Odm,
+- IN u4Byte RegAddr,
+- IN u4Byte BitMask,
+- IN u4Byte Data
+- );
+-
+-u4Byte
+-ODM_GetMACReg(
+- IN PDM_ODM_T pDM_Odm,
+- IN u4Byte RegAddr,
+- IN u4Byte BitMask
+- );
+-
+-void
+-ODM_SetBBReg(
+- IN PDM_ODM_T pDM_Odm,
+- IN u4Byte RegAddr,
+- IN u4Byte BitMask,
+- IN u4Byte Data
+- );
+-
+-u4Byte
+-ODM_GetBBReg(
+- IN PDM_ODM_T pDM_Odm,
+- IN u4Byte RegAddr,
+- IN u4Byte BitMask
+- );
+-
+-void
+-ODM_SetRFReg(
+- IN PDM_ODM_T pDM_Odm,
+- IN ODM_RF_RADIO_PATH_E eRFPath,
+- IN u4Byte RegAddr,
+- IN u4Byte BitMask,
+- IN u4Byte Data
+- );
+-
+-u4Byte
+-ODM_GetRFReg(
+- IN PDM_ODM_T pDM_Odm,
+- IN ODM_RF_RADIO_PATH_E eRFPath,
+- IN u4Byte RegAddr,
+- IN u4Byte BitMask
+- );
+-
+-
+-//
+-// Memory Relative Function.
+-//
+-void
+-ODM_AllocateMemory(
+- IN PDM_ODM_T pDM_Odm,
+- OUT void * *pPtr,
+- IN u4Byte length
+- );
+-void
+-ODM_FreeMemory(
+- IN PDM_ODM_T pDM_Odm,
+- OUT void * pPtr,
+- IN u4Byte length
+- );
+-
+-//
+-// ODM Timer relative API.
+-//
+-void
+-ODM_SetTimer(
+- IN PDM_ODM_T pDM_Odm,
+- IN PRT_TIMER pTimer,
+- IN u4Byte msDelay
+- );
+-
+-void
+-ODM_InitializeTimer(
+- IN PDM_ODM_T pDM_Odm,
+- IN PRT_TIMER pTimer,
+- IN RT_TIMER_CALL_BACK CallBackFunc,
+- IN void * pContext,
+- IN const char* szID
+- );
+-
+-void
+-ODM_CancelTimer(
+- IN PDM_ODM_T pDM_Odm,
+- IN PRT_TIMER pTimer
+- );
+-
+-void
+-ODM_ReleaseTimer(
+- IN PDM_ODM_T pDM_Odm,
+- IN PRT_TIMER pTimer
+- );
+-
+-
+-//
+-// ODM FW relative API.
+-//
+-void
+-ODM_FillH2CCmd(
+- IN PDM_ODM_T pDM_Odm,
+- IN u1Byte ElementID,
+- IN u4Byte CmdLen,
+- IN pu1Byte pCmdBuffer
+-);
+-
+ #endif // __ODM_INTERFACE_H__
+-
+diff -Nurp linux/3rdparty/rtl8723bs.old/hal/odm_NoiseMonitor.c linux/3rdparty/rtl8723bs/hal/odm_NoiseMonitor.c
+--- linux/3rdparty/rtl8723bs.old/hal/odm_NoiseMonitor.c 2015-05-10 14:36:05.709668358 +0300
++++ linux/3rdparty/rtl8723bs/hal/odm_NoiseMonitor.c 2015-05-07 17:46:55.000000000 +0300
+@@ -79,18 +79,18 @@ static s16 odm_InbandNoise_Monitor_NSeri
+ {
+
+ //Stop updating idle time pwer report (for driver read)
+- ODM_SetBBReg(pDM_Odm, rFPGA0_TxGainStage, BIT25, 1);
++ PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_TxGainStage, BIT25, 1);
+
+ //Read Noise Floor Report
+- tmp4b = ODM_GetBBReg(pDM_Odm, 0x8f8,bMaskDWord );
++ tmp4b = PHY_QueryBBReg(pDM_Odm->Adapter, 0x8f8,bMaskDWord );
+ ODM_RT_TRACE(pDM_Odm,ODM_COMP_COMMON, ODM_DBG_LOUD,("Noise Floor Report (0x8f8) = 0x%08x\n", tmp4b));
+
+- //ODM_SetBBReg(pDM_Odm, rOFDM0_XAAGCCore1, bMaskByte0, TestInitialGain);
++ //PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_XAAGCCore1, bMaskByte0, TestInitialGain);
+ //if(max_rf_path == 2)
+- // ODM_SetBBReg(pDM_Odm, rOFDM0_XBAGCCore1, bMaskByte0, TestInitialGain);
++ // PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_XBAGCCore1, bMaskByte0, TestInitialGain);
+
+ //update idle time pwer report per 5us
+- ODM_SetBBReg(pDM_Odm, rFPGA0_TxGainStage, BIT25, 0);
++ PHY_SetBBReg(pDM_Odm->Adapter, rFPGA0_TxGainStage, BIT25, 0);
+
+ noise_data.value[ODM_RF_PATH_A] = (u1Byte)(tmp4b&0xff);
+ noise_data.value[ODM_RF_PATH_B] = (u1Byte)((tmp4b&0xff00)>>8);
+@@ -142,14 +142,14 @@ static s16 odm_InbandNoise_Monitor_NSeri
+ break;
+ }
+ }
+- reg_c50 = (s4Byte)ODM_GetBBReg(pDM_Odm,rOFDM0_XAAGCCore1,bMaskByte0);
++ reg_c50 = (s4Byte)PHY_QueryBBReg(pDM_Odm->Adapter,rOFDM0_XAAGCCore1,bMaskByte0);
+ reg_c50 &= ~BIT7;
+ ODM_RT_TRACE(pDM_Odm,ODM_COMP_COMMON, ODM_DBG_LOUD,("0x%x = 0x%02x(%d)\n", rOFDM0_XAAGCCore1, reg_c50, reg_c50));
+ pDM_Odm->noise_level.noise[ODM_RF_PATH_A] = -110 + reg_c50 + noise_data.sum[ODM_RF_PATH_A];
+ pDM_Odm->noise_level.noise_all += pDM_Odm->noise_level.noise[ODM_RF_PATH_A];
+
+ if(max_rf_path == 2){
+- reg_c58 = (s4Byte)ODM_GetBBReg(pDM_Odm,rOFDM0_XBAGCCore1,bMaskByte0);
++ reg_c58 = (s4Byte)PHY_QueryBBReg(pDM_Odm->Adapter,rOFDM0_XBAGCCore1,bMaskByte0);
+ reg_c58 &= ~BIT7;
+ ODM_RT_TRACE(pDM_Odm,ODM_COMP_COMMON, ODM_DBG_LOUD,("0x%x = 0x%02x(%d)\n", rOFDM0_XBAGCCore1, reg_c58, reg_c58));
+ pDM_Odm->noise_level.noise[ODM_RF_PATH_B] = -110 + reg_c58 + noise_data.sum[ODM_RF_PATH_B];
+diff -Nurp linux/3rdparty/rtl8723bs.old/hal/odm_precomp.h linux/3rdparty/rtl8723bs/hal/odm_precomp.h
+--- linux/3rdparty/rtl8723bs.old/hal/odm_precomp.h 2015-05-10 14:36:05.710668369 +0300
++++ linux/3rdparty/rtl8723bs/hal/odm_precomp.h 2015-05-07 17:46:55.000000000 +0300
+@@ -27,7 +27,6 @@
+
+ //2 Config Flags and Structs - defined by each ODM Type
+
+- //#include