Staging: Added Realtek rtl8192u driver to staging

Add Realtek linux driver for rtl8192u as provided by Realtek

rtl8192u_linux_2.6.0006.1031.2008.tar.gz, send to me C/C staging ML.

This version won't compile against upstream, doesn't follow
Linux CodingStyle and has their own ieee80211 stack.

Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
Jerry Chuang 2009-11-03 07:17:11 -02:00 committed by Greg Kroah-Hartman
parent 9b84375747
commit 8fc8598e61
70 changed files with 49627 additions and 0 deletions

View File

@ -0,0 +1,6 @@
config RTL8192U
tristate "RealTek RTL8192U Wireless LAN NIC driver"
depends on PCI && WLAN
depends on WIRELESS_EXT
default N
---help---

View File

@ -0,0 +1,32 @@
NIC_SELECT = RTL8192U
EXTRA_CFLAGS += -std=gnu89
EXTRA_CFLAGS += -O2
EXTRA_CFLAGS += -mhard-float -DCONFIG_FORCE_HARD_FLOAT=y
EXTRA_CFLAGS += -DJACKSON_NEW_8187 -DJACKSON_NEW_RX
EXTRA_CFLAGS += -DTHOMAS_BEACON -DTHOMAS_TASKLET -DTHOMAS_SKB -DTHOMAS_TURBO
#EXTRA_CFLAGS += -DUSB_TX_DRIVER_AGGREGATION_ENABLE
#EXTRA_CFLAGS += -DUSB_RX_AGGREGATION_SUPPORT
EXTRA_CFLAGS += -DUSE_ONE_PIPE
EXTRA_CFLAGS += -DENABLE_DOT11D
r8192u_usb-objs := r8192U_core.o r8180_93cx6.o r8192U_wx.o \
r8190_rtl8256.o r819xU_phy.o r819xU_firmware.o \
r819xU_cmdpkt.o r8192U_dm.o r819xU_firmware_img.o \
ieee80211/ieee80211_crypt.o \
ieee80211/ieee80211_crypt_tkip.o \
ieee80211/ieee80211_crypt_ccmp.o \
ieee80211/ieee80211_crypt_wep.o \
ieee80211/ieee80211_rx.o \
ieee80211/ieee80211_softmac.o \
ieee80211/ieee80211_tx.o \
ieee80211/ieee80211_wx.o \
ieee80211/ieee80211_module.o \
ieee80211/ieee80211_softmac_wx.o \
ieee80211/rtl819x_HTProc.o \
ieee80211/rtl819x_TSProc.o \
ieee80211/rtl819x_BAProc.o \
ieee80211/dot11d.o
obj-$(CONFIG_RTL8192U) += r8192u_usb.o

View File

@ -0,0 +1 @@
Andrea Merello <andreamrl@tiscali.it>

View File

@ -0,0 +1,5 @@
v 0.1
First version.
This is based on the rtl8180-sa2400 pre-0.22-CVS code..

View File

@ -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.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <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.

View File

@ -0,0 +1,102 @@
#ifndef __INC_DOT11D_H
#define __INC_DOT11D_H
#ifdef ENABLE_DOT11D
#include "ieee80211.h"
//#define ENABLE_DOT11D
//#define DOT11D_MAX_CHNL_NUM 83
typedef struct _CHNL_TXPOWER_TRIPLE {
u8 FirstChnl;
u8 NumChnls;
u8 MaxTxPowerInDbm;
}CHNL_TXPOWER_TRIPLE, *PCHNL_TXPOWER_TRIPLE;
typedef enum _DOT11D_STATE {
DOT11D_STATE_NONE = 0,
DOT11D_STATE_LEARNED,
DOT11D_STATE_DONE,
}DOT11D_STATE;
typedef struct _RT_DOT11D_INFO {
//DECLARE_RT_OBJECT(RT_DOT11D_INFO);
bool bEnabled; // dot11MultiDomainCapabilityEnabled
u16 CountryIeLen; // > 0 if CountryIeBuf[] contains valid country information element.
u8 CountryIeBuf[MAX_IE_LEN];
u8 CountryIeSrcAddr[6]; // Source AP of the country IE.
u8 CountryIeWatchdog;
u8 channel_map[MAX_CHANNEL_NUMBER+1]; //!!!Value 0: Invalid, 1: Valid (active scan), 2: Valid (passive scan)
//u8 ChnlListLen; // #Bytes valid in ChnlList[].
//u8 ChnlList[DOT11D_MAX_CHNL_NUM];
u8 MaxTxPwrDbmList[MAX_CHANNEL_NUMBER+1];
DOT11D_STATE State;
}RT_DOT11D_INFO, *PRT_DOT11D_INFO;
#define eqMacAddr(a,b) ( ((a)[0]==(b)[0] && (a)[1]==(b)[1] && (a)[2]==(b)[2] && (a)[3]==(b)[3] && (a)[4]==(b)[4] && (a)[5]==(b)[5]) ? 1:0 )
#define cpMacAddr(des,src) ((des)[0]=(src)[0],(des)[1]=(src)[1],(des)[2]=(src)[2],(des)[3]=(src)[3],(des)[4]=(src)[4],(des)[5]=(src)[5])
#define GET_DOT11D_INFO(__pIeeeDev) ((PRT_DOT11D_INFO)((__pIeeeDev)->pDot11dInfo))
#define IS_DOT11D_ENABLE(__pIeeeDev) GET_DOT11D_INFO(__pIeeeDev)->bEnabled
#define IS_COUNTRY_IE_VALID(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)->CountryIeLen > 0)
#define IS_EQUAL_CIE_SRC(__pIeeeDev, __pTa) eqMacAddr(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa)
#define UPDATE_CIE_SRC(__pIeeeDev, __pTa) cpMacAddr(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa)
#define IS_COUNTRY_IE_CHANGED(__pIeeeDev, __Ie) \
(((__Ie).Length == 0 || (__Ie).Length != GET_DOT11D_INFO(__pIeeeDev)->CountryIeLen) ? \
FALSE : \
(!memcmp(GET_DOT11D_INFO(__pIeeeDev)->CountryIeBuf, (__Ie).Octet, (__Ie).Length)))
#define CIE_WATCHDOG_TH 1
#define GET_CIE_WATCHDOG(__pIeeeDev) GET_DOT11D_INFO(__pIeeeDev)->CountryIeWatchdog
#define RESET_CIE_WATCHDOG(__pIeeeDev) GET_CIE_WATCHDOG(__pIeeeDev) = 0
#define UPDATE_CIE_WATCHDOG(__pIeeeDev) ++GET_CIE_WATCHDOG(__pIeeeDev)
#define IS_DOT11D_STATE_DONE(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)->State == DOT11D_STATE_DONE)
void
Dot11d_Init(
struct ieee80211_device *dev
);
void
Dot11d_Reset(
struct ieee80211_device *dev
);
void
Dot11d_UpdateCountryIe(
struct ieee80211_device *dev,
u8 * pTaddr,
u16 CoutryIeLen,
u8 * pCoutryIe
);
u8
DOT11D_GetMaxTxPwrInDbm(
struct ieee80211_device *dev,
u8 Channel
);
void
DOT11D_ScanComplete(
struct ieee80211_device * dev
);
int IsLegalChannel(
struct ieee80211_device * dev,
u8 channel
);
int ToLegalChannel(
struct ieee80211_device * dev,
u8 channel
);
#endif //ENABLE_DOT11D
#endif // #ifndef __INC_DOT11D_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,199 @@
#ifndef __INC_ENDIANFREE_H
#define __INC_ENDIANFREE_H
/*
* Call endian free function when
* 1. Read/write packet content.
* 2. Before write integer to IO.
* 3. After read integer from IO.
*/
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20))
#ifndef bool
typedef enum{false = 0, true} bool;
#endif
#endif
#define __MACHINE_LITTLE_ENDIAN 1234 /* LSB first: i386, vax */
#define __MACHINE_BIG_ENDIAN 4321 /* MSB first: 68000, ibm, net, ppc */
#define BYTE_ORDER __MACHINE_LITTLE_ENDIAN
#if BYTE_ORDER == __MACHINE_LITTLE_ENDIAN
// Convert data
#define EF1Byte(_val) ((u8)(_val))
#define EF2Byte(_val) ((u16)(_val))
#define EF4Byte(_val) ((u32)(_val))
#else
// Convert data
#define EF1Byte(_val) ((u8)(_val))
#define EF2Byte(_val) (((((u16)(_val))&0x00ff)<<8)|((((u16)(_val))&0xff00)>>8))
#define EF4Byte(_val) (((((u32)(_val))&0x000000ff)<<24)|\
((((u32)(_val))&0x0000ff00)<<8)|\
((((u32)(_val))&0x00ff0000)>>8)|\
((((u32)(_val))&0xff000000)>>24))
#endif
// Read data from memory
#define ReadEF1Byte(_ptr) EF1Byte(*((u8 *)(_ptr)))
#define ReadEF2Byte(_ptr) EF2Byte(*((u16 *)(_ptr)))
#define ReadEF4Byte(_ptr) EF4Byte(*((u32 *)(_ptr)))
// Write data to memory
#define WriteEF1Byte(_ptr, _val) (*((u8 *)(_ptr)))=EF1Byte(_val)
#define WriteEF2Byte(_ptr, _val) (*((u16 *)(_ptr)))=EF2Byte(_val)
#define WriteEF4Byte(_ptr, _val) (*((u32 *)(_ptr)))=EF4Byte(_val)
// Convert Host system specific byte ording (litten or big endia) to Network byte ording (big endian).
// 2006.05.07, by rcnjko.
#if BYTE_ORDER == __MACHINE_LITTLE_ENDIAN
#define H2N1BYTE(_val) ((u8)(_val))
#define H2N2BYTE(_val) (((((u16)(_val))&0x00ff)<<8)|\
((((u16)(_val))&0xff00)>>8))
#define H2N4BYTE(_val) (((((u32)(_val))&0x000000ff)<<24)|\
((((u32)(_val))&0x0000ff00)<<8) |\
((((u32)(_val))&0x00ff0000)>>8) |\
((((u32)(_val))&0xff000000)>>24))
#else
#define H2N1BYTE(_val) ((u8)(_val))
#define H2N2BYTE(_val) ((u16)(_val))
#define H2N4BYTE(_val) ((u32)(_val))
#endif
// Convert from Network byte ording (big endian) to Host system specific byte ording (litten or big endia).
// 2006.05.07, by rcnjko.
#if BYTE_ORDER == __MACHINE_LITTLE_ENDIAN
#define N2H1BYTE(_val) ((u8)(_val))
#define N2H2BYTE(_val) (((((u16)(_val))&0x00ff)<<8)|\
((((u16)(_val))&0xff00)>>8))
#define N2H4BYTE(_val) (((((u32)(_val))&0x000000ff)<<24)|\
((((u32)(_val))&0x0000ff00)<<8) |\
((((u32)(_val))&0x00ff0000)>>8) |\
((((u32)(_val))&0xff000000)>>24))
#else
#define N2H1BYTE(_val) ((u8)(_val))
#define N2H2BYTE(_val) ((u16)(_val))
#define N2H4BYTE(_val) ((u32)(_val))
#endif
//
// Example:
// BIT_LEN_MASK_32(0) => 0x00000000
// BIT_LEN_MASK_32(1) => 0x00000001
// BIT_LEN_MASK_32(2) => 0x00000003
// BIT_LEN_MASK_32(32) => 0xFFFFFFFF
//
#define BIT_LEN_MASK_32(__BitLen) (0xFFFFFFFF >> (32 - (__BitLen)))
//
// Example:
// BIT_OFFSET_LEN_MASK_32(0, 2) => 0x00000003
// BIT_OFFSET_LEN_MASK_32(16, 2) => 0x00030000
//
#define BIT_OFFSET_LEN_MASK_32(__BitOffset, __BitLen) (BIT_LEN_MASK_32(__BitLen) << (__BitOffset))
//
// Description:
// Return 4-byte value in host byte ordering from
// 4-byte pointer in litten-endian system.
//
#define LE_P4BYTE_TO_HOST_4BYTE(__pStart) (EF4Byte(*((u32 *)(__pStart))))
//
// Description:
// Translate subfield (continuous bits in little-endian) of 4-byte value in litten byte to
// 4-byte value in host byte ordering.
//
#define LE_BITS_TO_4BYTE(__pStart, __BitOffset, __BitLen) \
( \
( LE_P4BYTE_TO_HOST_4BYTE(__pStart) >> (__BitOffset) ) \
& \
BIT_LEN_MASK_32(__BitLen) \
)
//
// Description:
// Mask subfield (continuous bits in little-endian) of 4-byte value in litten byte oredering
// and return the result in 4-byte value in host byte ordering.
//
#define LE_BITS_CLEARED_TO_4BYTE(__pStart, __BitOffset, __BitLen) \
( \
LE_P4BYTE_TO_HOST_4BYTE(__pStart) \
& \
( ~BIT_OFFSET_LEN_MASK_32(__BitOffset, __BitLen) ) \
)
//
// Description:
// Set subfield of little-endian 4-byte value to specified value.
//
#define SET_BITS_TO_LE_4BYTE(__pStart, __BitOffset, __BitLen, __Value) \
*((u32 *)(__pStart)) = \
EF4Byte( \
LE_BITS_CLEARED_TO_4BYTE(__pStart, __BitOffset, __BitLen) \
| \
( (((u32)__Value) & BIT_LEN_MASK_32(__BitLen)) << (__BitOffset) ) \
);
#define BIT_LEN_MASK_16(__BitLen) \
(0xFFFF >> (16 - (__BitLen)))
#define BIT_OFFSET_LEN_MASK_16(__BitOffset, __BitLen) \
(BIT_LEN_MASK_16(__BitLen) << (__BitOffset))
#define LE_P2BYTE_TO_HOST_2BYTE(__pStart) \
(EF2Byte(*((u16 *)(__pStart))))
#define LE_BITS_TO_2BYTE(__pStart, __BitOffset, __BitLen) \
( \
( LE_P2BYTE_TO_HOST_2BYTE(__pStart) >> (__BitOffset) ) \
& \
BIT_LEN_MASK_16(__BitLen) \
)
#define LE_BITS_CLEARED_TO_2BYTE(__pStart, __BitOffset, __BitLen) \
( \
LE_P2BYTE_TO_HOST_2BYTE(__pStart) \
& \
( ~BIT_OFFSET_LEN_MASK_16(__BitOffset, __BitLen) ) \
)
#define SET_BITS_TO_LE_2BYTE(__pStart, __BitOffset, __BitLen, __Value) \
*((u16 *)(__pStart)) = \
EF2Byte( \
LE_BITS_CLEARED_TO_2BYTE(__pStart, __BitOffset, __BitLen) \
| \
( (((u16)__Value) & BIT_LEN_MASK_16(__BitLen)) << (__BitOffset) ) \
);
#define BIT_LEN_MASK_8(__BitLen) \
(0xFF >> (8 - (__BitLen)))
#define BIT_OFFSET_LEN_MASK_8(__BitOffset, __BitLen) \
(BIT_LEN_MASK_8(__BitLen) << (__BitOffset))
#define LE_P1BYTE_TO_HOST_1BYTE(__pStart) \
(EF1Byte(*((u8 *)(__pStart))))
#define LE_BITS_TO_1BYTE(__pStart, __BitOffset, __BitLen) \
( \
( LE_P1BYTE_TO_HOST_1BYTE(__pStart) >> (__BitOffset) ) \
& \
BIT_LEN_MASK_8(__BitLen) \
)
#define LE_BITS_CLEARED_TO_1BYTE(__pStart, __BitOffset, __BitLen) \
( \
LE_P1BYTE_TO_HOST_1BYTE(__pStart) \
& \
( ~BIT_OFFSET_LEN_MASK_8(__BitOffset, __BitLen) ) \
)
#define SET_BITS_TO_LE_1BYTE(__pStart, __BitOffset, __BitLen, __Value) \
*((u8 *)(__pStart)) = \
EF1Byte( \
LE_BITS_CLEARED_TO_1BYTE(__pStart, __BitOffset, __BitLen) \
| \
( (((u8)__Value) & BIT_LEN_MASK_8(__BitLen)) << (__BitOffset) ) \
);
#endif // #ifndef __INC_ENDIANFREE_H

View File

@ -0,0 +1,139 @@
NIC_SELECT = RTL8192U
KVER := $(shell uname -r)
MODDESTDIR := /lib/modules/$(KVER)/kernel/drivers/net/wireless/$(NIC_SELECT)
CC = gcc
ifneq ($(shell uname -r|cut -d. -f1,2), 2.4)
EXTRA_CFLAGS += -I$(TOPDIR)/drivers/net/wireless
EXTRA_CFLAGS += -O2
EXTRA_CFLAGS += -DJACKSON_NEW_8187 -DJACKSON_NEW_RX
#it will fail to compile in suse linux enterprise 10 sp2. This flag is to solve this problem.
ifeq ($(shell uname -r | cut -d. -f1,2,3,4), 2.6.16.60-0)
EXTRA_CFLAGS += -DOPENSUSE_SLED
endif
ifeq ($(NIC_SELECT),RTL8192U)
#EXTRA_CFLAGS += -DUSB_TX_DRIVER_AGGREGATION_ENABLE
#EXTRA_CFLAGS += -DUSB_RX_AGGREGATION_SUPPORT
endif
#EXTRA_CFLAGS += -DJOHN_NOCPY
#flags to enable or disble 80211D feature
EXTRA_CFLAGS += -DENABLE_DOT11D
ieee80211-rsl-objs := ieee80211_rx.o \
ieee80211_softmac.o \
ieee80211_tx.o \
ieee80211_wx.o \
ieee80211_module.o \
ieee80211_softmac_wx.o\
rtl819x_HTProc.o\
rtl819x_TSProc.o\
rtl819x_BAProc.o\
dot11d.o
ieee80211_crypt-rsl-objs := ieee80211_crypt.o
ieee80211_crypt_tkip-rsl-objs := ieee80211_crypt_tkip.o
ieee80211_crypt_ccmp-rsl-objs := ieee80211_crypt_ccmp.o
ieee80211_crypt_wep-rsl-objs := ieee80211_crypt_wep.o
obj-m +=ieee80211-rsl.o
obj-m +=ieee80211_crypt-rsl.o
obj-m +=ieee80211_crypt_wep-rsl.o
obj-m +=ieee80211_crypt_tkip-rsl.o
obj-m +=ieee80211_crypt_ccmp-rsl.o
KSRC := /lib/modules/$(KVER)/build
INSTALL_PREFIX :=
all: modules
modules:
$(MAKE) -C $(KSRC) M=$(PWD) CC=$(CC) modules
install: modules
rm -fr $(MODDESTDIR)
mkdir -p $(MODDESTDIR)
@install -p -m 644 ieee80211_crypt-rsl.ko $(MODDESTDIR)
@install -p -m 644 ieee80211_crypt_wep-rsl.ko $(MODDESTDIR)
@install -p -m 644 ieee80211_crypt_tkip-rsl.ko $(MODDESTDIR)
@install -p -m 644 ieee80211_crypt_ccmp-rsl.ko $(MODDESTDIR)
@install -p -m 644 ieee80211-rsl.ko $(MODDESTDIR)
depmod -a
uninstall:
rm -fr $(MODDESTDIR)
depmod -a
else
LD := ld
KSRC := /lib/modules/$(KVER)/build
CONFIG_FILE := $(KSRC)/include/linux/autoconf.h
CFLAGS += -DLINUX -D__KERNEL__ -DMODULE -O2 -pipe -Wall
CFLAGS += -I$(KSRC)/include -I.
#Kernel 2.4.31
CFLAGS += -DMODVERSIONS -DEXPORT_SYMTAB -include $(KSRC)/include/linux/modversions.h
#Kernel 2.4.20
#CFLAGS += -D__NO_VERSION__ -DEXPORT_SYMTAB
#CFLAGS += -DENABLE_DOT11D
SMP := $(shell $(CC) $(MODCFLAGS) -E -dM $(CONFIG_FILE) | \
grep CONFIG_SMP | awk '{print $$3}')
ifneq ($(SMP),1)
SMP := 0
endif
ifeq ($(SMP),1)
CFLAGS += -D__SMP__
endif
#CFLAGS += -DJOHN_NOCPY
OBJS := ${patsubst %.c, %.o, ${wildcard *.c}}
all:${OBJS} ieee80211_crypt-rsl.o michael_mic-rsl.o aes-rsl.o ieee80211_crypt_wep-rsl.o ieee80211_crypt_tkip-rsl.o ieee80211_crypt_ccmp-rsl.o crypto-rsl.o ieee80211-rsl.o
ieee80211_crypt-rsl.o: ieee80211_crypt.o
mv $^ $@
michael_mic-rsl.o: michael_mic.o
mv $^ $@
aes-rsl.o: aes.o
mv $^ $@
ieee80211_crypt_wep-rsl.o: ieee80211_crypt_wep.o
mv $^ $@
ieee80211_crypt_tkip-rsl.o: ieee80211_crypt_tkip.o
mv $^ $@
ieee80211_crypt_ccmp-rsl.o: ieee80211_crypt_ccmp.o
mv $^ $@
crypto-rsl.o: arc4.o api.o autoload.o cipher.o compress.o digest.o scatterwalk.o proc.o
$(LD) -r $^ -o $@
ieee80211-rsl.o: ieee80211_rx.o ieee80211_tx.o ieee80211_wx.o ieee80211_module.o ieee80211_softmac_wx.o ieee80211_softmac.o rtl819x_HTProc.o rtl819x_TSProc.o rtl819x_BAProc.o dot11d.o
$(LD) -r $^ -o $@
install:
rm -fr $(MODDESTDIR)
mkdir -p $(MODDESTDIR)
@install -p -m 644 ieee80211_crypt-rsl.o $(MODDESTDIR)
@install -p -m 644 crypto-rsl.o $(MODDESTDIR)
@install -p -m 644 michael_mic-rsl.o $(MODDESTDIR)
@install -p -m 644 aes-rsl.o $(MODDESTDIR)
@install -p -m 644 ieee80211_crypt_wep-rsl.o $(MODDESTDIR)
@install -p -m 644 ieee80211_crypt_tkip-rsl.o $(MODDESTDIR)
@install -p -m 644 ieee80211_crypt_ccmp-rsl.o $(MODDESTDIR)
@install -p -m 644 ieee80211-rsl.o $(MODDESTDIR)
/sbin/depmod -a ${shell uname -r}
uninstall:
rm -fr $(MODDESTDIR)
/sbin/depmod -a ${shell uname -r}
endif
.PHONY: clean
clean:
rm -fr *.mod.c *.mod *.o .*.cmd *.mod.* *.ko *.o *~
rm -rf .tmp_versions
rm -rf Module.symvers

View File

@ -0,0 +1,469 @@
/*
* Cryptographic API.
*
* AES Cipher Algorithm.
*
* Based on Brian Gladman's code.
*
* Linux developers:
* Alexander Kjeldaas <astor@fast.no>
* Herbert Valerio Riedel <hvr@hvrlab.org>
* Kyle McMartin <kyle@debian.org>
* Adam J. Richter <adam@yggdrasil.com> (conversion to 2.5 API).
*
* 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.
*
* ---------------------------------------------------------------------------
* Copyright (c) 2002, Dr Brian Gladman <brg@gladman.me.uk>, Worcester, UK.
* All rights reserved.
*
* LICENSE TERMS
*
* The free distribution and use of this software in both source and binary
* form is allowed (with or without changes) provided that:
*
* 1. distributions of this source code include the above copyright
* notice, this list of conditions and the following disclaimer;
*
* 2. distributions in binary form include the above copyright
* notice, this list of conditions and the following disclaimer
* in the documentation and/or other associated materials;
*
* 3. the copyright holder's name is not used to endorse products
* built using this software without specific written permission.
*
* ALTERNATIVELY, provided that this notice is retained in full, this product
* may be distributed under the terms of the GNU General Public License (GPL),
* in which case the provisions of the GPL apply INSTEAD OF those given above.
*
* DISCLAIMER
*
* This software is provided 'as is' with no explicit or implied warranties
* in respect of its properties, including, but not limited to, correctness
* and/or fitness for purpose.
* ---------------------------------------------------------------------------
*/
/* Some changes from the Gladman version:
s/RIJNDAEL(e_key)/E_KEY/g
s/RIJNDAEL(d_key)/D_KEY/g
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/errno.h>
//#include <linux/crypto.h>
#include "rtl_crypto.h"
#include <asm/byteorder.h>
#define AES_MIN_KEY_SIZE 16
#define AES_MAX_KEY_SIZE 32
#define AES_BLOCK_SIZE 16
static inline
u32 generic_rotr32 (const u32 x, const unsigned bits)
{
const unsigned n = bits % 32;
return (x >> n) | (x << (32 - n));
}
static inline
u32 generic_rotl32 (const u32 x, const unsigned bits)
{
const unsigned n = bits % 32;
return (x << n) | (x >> (32 - n));
}
#define rotl generic_rotl32
#define rotr generic_rotr32
/*
* #define byte(x, nr) ((unsigned char)((x) >> (nr*8)))
*/
inline static u8
byte(const u32 x, const unsigned n)
{
return x >> (n << 3);
}
#define u32_in(x) le32_to_cpu(*(const u32 *)(x))
#define u32_out(to, from) (*(u32 *)(to) = cpu_to_le32(from))
struct aes_ctx {
int key_length;
u32 E[60];
u32 D[60];
};
#define E_KEY ctx->E
#define D_KEY ctx->D
static u8 pow_tab[256] __initdata;
static u8 log_tab[256] __initdata;
static u8 sbx_tab[256] __initdata;
static u8 isb_tab[256] __initdata;
static u32 rco_tab[10];
static u32 ft_tab[4][256];
static u32 it_tab[4][256];
static u32 fl_tab[4][256];
static u32 il_tab[4][256];
static inline u8 __init
f_mult (u8 a, u8 b)
{
u8 aa = log_tab[a], cc = aa + log_tab[b];
return pow_tab[cc + (cc < aa ? 1 : 0)];
}
#define ff_mult(a,b) (a && b ? f_mult(a, b) : 0)
#define f_rn(bo, bi, n, k) \
bo[n] = ft_tab[0][byte(bi[n],0)] ^ \
ft_tab[1][byte(bi[(n + 1) & 3],1)] ^ \
ft_tab[2][byte(bi[(n + 2) & 3],2)] ^ \
ft_tab[3][byte(bi[(n + 3) & 3],3)] ^ *(k + n)
#define i_rn(bo, bi, n, k) \
bo[n] = it_tab[0][byte(bi[n],0)] ^ \
it_tab[1][byte(bi[(n + 3) & 3],1)] ^ \
it_tab[2][byte(bi[(n + 2) & 3],2)] ^ \
it_tab[3][byte(bi[(n + 1) & 3],3)] ^ *(k + n)
#define ls_box(x) \
( fl_tab[0][byte(x, 0)] ^ \
fl_tab[1][byte(x, 1)] ^ \
fl_tab[2][byte(x, 2)] ^ \
fl_tab[3][byte(x, 3)] )
#define f_rl(bo, bi, n, k) \
bo[n] = fl_tab[0][byte(bi[n],0)] ^ \
fl_tab[1][byte(bi[(n + 1) & 3],1)] ^ \
fl_tab[2][byte(bi[(n + 2) & 3],2)] ^ \
fl_tab[3][byte(bi[(n + 3) & 3],3)] ^ *(k + n)
#define i_rl(bo, bi, n, k) \
bo[n] = il_tab[0][byte(bi[n],0)] ^ \
il_tab[1][byte(bi[(n + 3) & 3],1)] ^ \
il_tab[2][byte(bi[(n + 2) & 3],2)] ^ \
il_tab[3][byte(bi[(n + 1) & 3],3)] ^ *(k + n)
static void __init
gen_tabs (void)
{
u32 i, t;
u8 p, q;
/* log and power tables for GF(2**8) finite field with
0x011b as modular polynomial - the simplest primitive
root is 0x03, used here to generate the tables */
for (i = 0, p = 1; i < 256; ++i) {
pow_tab[i] = (u8) p;
log_tab[p] = (u8) i;
p ^= (p << 1) ^ (p & 0x80 ? 0x01b : 0);
}
log_tab[1] = 0;
for (i = 0, p = 1; i < 10; ++i) {
rco_tab[i] = p;
p = (p << 1) ^ (p & 0x80 ? 0x01b : 0);
}
for (i = 0; i < 256; ++i) {
p = (i ? pow_tab[255 - log_tab[i]] : 0);
q = ((p >> 7) | (p << 1)) ^ ((p >> 6) | (p << 2));
p ^= 0x63 ^ q ^ ((q >> 6) | (q << 2));
sbx_tab[i] = p;
isb_tab[p] = (u8) i;
}
for (i = 0; i < 256; ++i) {
p = sbx_tab[i];
t = p;
fl_tab[0][i] = t;
fl_tab[1][i] = rotl (t, 8);
fl_tab[2][i] = rotl (t, 16);
fl_tab[3][i] = rotl (t, 24);
t = ((u32) ff_mult (2, p)) |
((u32) p << 8) |
((u32) p << 16) | ((u32) ff_mult (3, p) << 24);
ft_tab[0][i] = t;
ft_tab[1][i] = rotl (t, 8);
ft_tab[2][i] = rotl (t, 16);
ft_tab[3][i] = rotl (t, 24);
p = isb_tab[i];
t = p;
il_tab[0][i] = t;
il_tab[1][i] = rotl (t, 8);
il_tab[2][i] = rotl (t, 16);
il_tab[3][i] = rotl (t, 24);
t = ((u32) ff_mult (14, p)) |
((u32) ff_mult (9, p) << 8) |
((u32) ff_mult (13, p) << 16) |
((u32) ff_mult (11, p) << 24);
it_tab[0][i] = t;
it_tab[1][i] = rotl (t, 8);
it_tab[2][i] = rotl (t, 16);
it_tab[3][i] = rotl (t, 24);
}
}
#define star_x(x) (((x) & 0x7f7f7f7f) << 1) ^ ((((x) & 0x80808080) >> 7) * 0x1b)
#define imix_col(y,x) \
u = star_x(x); \
v = star_x(u); \
w = star_x(v); \
t = w ^ (x); \
(y) = u ^ v ^ w; \
(y) ^= rotr(u ^ t, 8) ^ \
rotr(v ^ t, 16) ^ \
rotr(t,24)
/* initialise the key schedule from the user supplied key */
#define loop4(i) \
{ t = rotr(t, 8); t = ls_box(t) ^ rco_tab[i]; \
t ^= E_KEY[4 * i]; E_KEY[4 * i + 4] = t; \
t ^= E_KEY[4 * i + 1]; E_KEY[4 * i + 5] = t; \
t ^= E_KEY[4 * i + 2]; E_KEY[4 * i + 6] = t; \
t ^= E_KEY[4 * i + 3]; E_KEY[4 * i + 7] = t; \
}
#define loop6(i) \
{ t = rotr(t, 8); t = ls_box(t) ^ rco_tab[i]; \
t ^= E_KEY[6 * i]; E_KEY[6 * i + 6] = t; \
t ^= E_KEY[6 * i + 1]; E_KEY[6 * i + 7] = t; \
t ^= E_KEY[6 * i + 2]; E_KEY[6 * i + 8] = t; \
t ^= E_KEY[6 * i + 3]; E_KEY[6 * i + 9] = t; \
t ^= E_KEY[6 * i + 4]; E_KEY[6 * i + 10] = t; \
t ^= E_KEY[6 * i + 5]; E_KEY[6 * i + 11] = t; \
}
#define loop8(i) \
{ t = rotr(t, 8); ; t = ls_box(t) ^ rco_tab[i]; \
t ^= E_KEY[8 * i]; E_KEY[8 * i + 8] = t; \
t ^= E_KEY[8 * i + 1]; E_KEY[8 * i + 9] = t; \
t ^= E_KEY[8 * i + 2]; E_KEY[8 * i + 10] = t; \
t ^= E_KEY[8 * i + 3]; E_KEY[8 * i + 11] = t; \
t = E_KEY[8 * i + 4] ^ ls_box(t); \
E_KEY[8 * i + 12] = t; \
t ^= E_KEY[8 * i + 5]; E_KEY[8 * i + 13] = t; \
t ^= E_KEY[8 * i + 6]; E_KEY[8 * i + 14] = t; \
t ^= E_KEY[8 * i + 7]; E_KEY[8 * i + 15] = t; \
}
static int
aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags)
{
struct aes_ctx *ctx = ctx_arg;
u32 i, t, u, v, w;
if (key_len != 16 && key_len != 24 && key_len != 32) {
*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
return -EINVAL;
}
ctx->key_length = key_len;
E_KEY[0] = u32_in (in_key);
E_KEY[1] = u32_in (in_key + 4);
E_KEY[2] = u32_in (in_key + 8);
E_KEY[3] = u32_in (in_key + 12);
switch (key_len) {
case 16:
t = E_KEY[3];
for (i = 0; i < 10; ++i)
loop4 (i);
break;
case 24:
E_KEY[4] = u32_in (in_key + 16);
t = E_KEY[5] = u32_in (in_key + 20);
for (i = 0; i < 8; ++i)
loop6 (i);
break;
case 32:
E_KEY[4] = u32_in (in_key + 16);
E_KEY[5] = u32_in (in_key + 20);
E_KEY[6] = u32_in (in_key + 24);
t = E_KEY[7] = u32_in (in_key + 28);
for (i = 0; i < 7; ++i)
loop8 (i);
break;
}
D_KEY[0] = E_KEY[0];
D_KEY[1] = E_KEY[1];
D_KEY[2] = E_KEY[2];
D_KEY[3] = E_KEY[3];
for (i = 4; i < key_len + 24; ++i) {
imix_col (D_KEY[i], E_KEY[i]);
}
return 0;
}
/* encrypt a block of text */
#define f_nround(bo, bi, k) \
f_rn(bo, bi, 0, k); \
f_rn(bo, bi, 1, k); \
f_rn(bo, bi, 2, k); \
f_rn(bo, bi, 3, k); \
k += 4
#define f_lround(bo, bi, k) \
f_rl(bo, bi, 0, k); \
f_rl(bo, bi, 1, k); \
f_rl(bo, bi, 2, k); \
f_rl(bo, bi, 3, k)
static void aes_encrypt(void *ctx_arg, u8 *out, const u8 *in)
{
const struct aes_ctx *ctx = ctx_arg;
u32 b0[4], b1[4];
const u32 *kp = E_KEY + 4;
b0[0] = u32_in (in) ^ E_KEY[0];
b0[1] = u32_in (in + 4) ^ E_KEY[1];
b0[2] = u32_in (in + 8) ^ E_KEY[2];
b0[3] = u32_in (in + 12) ^ E_KEY[3];
if (ctx->key_length > 24) {
f_nround (b1, b0, kp);
f_nround (b0, b1, kp);
}
if (ctx->key_length > 16) {
f_nround (b1, b0, kp);
f_nround (b0, b1, kp);
}
f_nround (b1, b0, kp);
f_nround (b0, b1, kp);
f_nround (b1, b0, kp);
f_nround (b0, b1, kp);
f_nround (b1, b0, kp);
f_nround (b0, b1, kp);
f_nround (b1, b0, kp);
f_nround (b0, b1, kp);
f_nround (b1, b0, kp);
f_lround (b0, b1, kp);
u32_out (out, b0[0]);
u32_out (out + 4, b0[1]);
u32_out (out + 8, b0[2]);
u32_out (out + 12, b0[3]);
}
/* decrypt a block of text */
#define i_nround(bo, bi, k) \
i_rn(bo, bi, 0, k); \
i_rn(bo, bi, 1, k); \
i_rn(bo, bi, 2, k); \
i_rn(bo, bi, 3, k); \
k -= 4
#define i_lround(bo, bi, k) \
i_rl(bo, bi, 0, k); \
i_rl(bo, bi, 1, k); \
i_rl(bo, bi, 2, k); \
i_rl(bo, bi, 3, k)
static void aes_decrypt(void *ctx_arg, u8 *out, const u8 *in)
{
const struct aes_ctx *ctx = ctx_arg;
u32 b0[4], b1[4];
const int key_len = ctx->key_length;
const u32 *kp = D_KEY + key_len + 20;
b0[0] = u32_in (in) ^ E_KEY[key_len + 24];
b0[1] = u32_in (in + 4) ^ E_KEY[key_len + 25];
b0[2] = u32_in (in + 8) ^ E_KEY[key_len + 26];
b0[3] = u32_in (in + 12) ^ E_KEY[key_len + 27];
if (key_len > 24) {
i_nround (b1, b0, kp);
i_nround (b0, b1, kp);
}
if (key_len > 16) {
i_nround (b1, b0, kp);
i_nround (b0, b1, kp);
}
i_nround (b1, b0, kp);
i_nround (b0, b1, kp);
i_nround (b1, b0, kp);
i_nround (b0, b1, kp);
i_nround (b1, b0, kp);
i_nround (b0, b1, kp);
i_nround (b1, b0, kp);
i_nround (b0, b1, kp);
i_nround (b1, b0, kp);
i_lround (b0, b1, kp);
u32_out (out, b0[0]);
u32_out (out + 4, b0[1]);
u32_out (out + 8, b0[2]);
u32_out (out + 12, b0[3]);
}
static struct crypto_alg aes_alg = {
.cra_name = "aes",
.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
.cra_blocksize = AES_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct aes_ctx),
.cra_module = THIS_MODULE,
.cra_list = LIST_HEAD_INIT(aes_alg.cra_list),
.cra_u = {
.cipher = {
.cia_min_keysize = AES_MIN_KEY_SIZE,
.cia_max_keysize = AES_MAX_KEY_SIZE,
.cia_setkey = aes_set_key,
.cia_encrypt = aes_encrypt,
.cia_decrypt = aes_decrypt
}
}
};
static int __init aes_init(void)
{
gen_tabs();
return crypto_register_alg(&aes_alg);
}
static void __exit aes_fini(void)
{
crypto_unregister_alg(&aes_alg);
}
module_init(aes_init);
module_exit(aes_fini);
MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm");
MODULE_LICENSE("Dual BSD/GPL");

View File

@ -0,0 +1,246 @@
/*
* Scatterlist Cryptographic API.
*
* Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
* Copyright (c) 2002 David S. Miller (davem@redhat.com)
*
* Portions derived from Cryptoapi, by Alexander Kjeldaas <astor@fast.no>
* and Nettle, by Niels M鰈ler.
*
* 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.
*
*/
#include "kmap_types.h"
#include <linux/init.h>
#include <linux/module.h>
//#include <linux/crypto.h>
#include "rtl_crypto.h"
#include <linux/errno.h>
#include <linux/rwsem.h>
#include <linux/slab.h>
#include "internal.h"
LIST_HEAD(crypto_alg_list);
DECLARE_RWSEM(crypto_alg_sem);
static inline int crypto_alg_get(struct crypto_alg *alg)
{
return try_inc_mod_count(alg->cra_module);
}
static inline void crypto_alg_put(struct crypto_alg *alg)
{
if (alg->cra_module)
__MOD_DEC_USE_COUNT(alg->cra_module);
}
struct crypto_alg *crypto_alg_lookup(const char *name)
{
struct crypto_alg *q, *alg = NULL;
if (!name)
return NULL;
down_read(&crypto_alg_sem);
list_for_each_entry(q, &crypto_alg_list, cra_list) {
if (!(strcmp(q->cra_name, name))) {
if (crypto_alg_get(q))
alg = q;
break;
}
}
up_read(&crypto_alg_sem);
return alg;
}
static int crypto_init_flags(struct crypto_tfm *tfm, u32 flags)
{
tfm->crt_flags = 0;
switch (crypto_tfm_alg_type(tfm)) {
case CRYPTO_ALG_TYPE_CIPHER:
return crypto_init_cipher_flags(tfm, flags);
case CRYPTO_ALG_TYPE_DIGEST:
return crypto_init_digest_flags(tfm, flags);
case CRYPTO_ALG_TYPE_COMPRESS:
return crypto_init_compress_flags(tfm, flags);
default:
break;
}
BUG();
return -EINVAL;
}
static int crypto_init_ops(struct crypto_tfm *tfm)
{
switch (crypto_tfm_alg_type(tfm)) {
case CRYPTO_ALG_TYPE_CIPHER:
return crypto_init_cipher_ops(tfm);
case CRYPTO_ALG_TYPE_DIGEST:
return crypto_init_digest_ops(tfm);
case CRYPTO_ALG_TYPE_COMPRESS:
return crypto_init_compress_ops(tfm);
default:
break;
}
BUG();
return -EINVAL;
}
static void crypto_exit_ops(struct crypto_tfm *tfm)
{
switch (crypto_tfm_alg_type(tfm)) {
case CRYPTO_ALG_TYPE_CIPHER:
crypto_exit_cipher_ops(tfm);
break;
case CRYPTO_ALG_TYPE_DIGEST:
crypto_exit_digest_ops(tfm);
break;
case CRYPTO_ALG_TYPE_COMPRESS:
crypto_exit_compress_ops(tfm);
break;
default:
BUG();
}
}
struct crypto_tfm *crypto_alloc_tfm(const char *name, u32 flags)
{
struct crypto_tfm *tfm = NULL;
struct crypto_alg *alg;
alg = crypto_alg_mod_lookup(name);
if (alg == NULL)
goto out;
tfm = kmalloc(sizeof(*tfm) + alg->cra_ctxsize, GFP_KERNEL);
if (tfm == NULL)
goto out_put;
memset(tfm, 0, sizeof(*tfm) + alg->cra_ctxsize);
tfm->__crt_alg = alg;
if (crypto_init_flags(tfm, flags))
goto out_free_tfm;
if (crypto_init_ops(tfm)) {
crypto_exit_ops(tfm);
goto out_free_tfm;
}
goto out;
out_free_tfm:
kfree(tfm);
tfm = NULL;
out_put:
crypto_alg_put(alg);
out:
return tfm;
}
void crypto_free_tfm(struct crypto_tfm *tfm)
{
struct crypto_alg *alg = tfm->__crt_alg;
int size = sizeof(*tfm) + alg->cra_ctxsize;
crypto_exit_ops(tfm);
crypto_alg_put(alg);
memset(tfm, 0, size);
kfree(tfm);
}
int crypto_register_alg(struct crypto_alg *alg)
{
int ret = 0;
struct crypto_alg *q;
down_write(&crypto_alg_sem);
list_for_each_entry(q, &crypto_alg_list, cra_list) {
if (!(strcmp(q->cra_name, alg->cra_name))) {
ret = -EEXIST;
goto out;
}
}
list_add_tail(&alg->cra_list, &crypto_alg_list);
out:
up_write(&crypto_alg_sem);
return ret;
}
int crypto_unregister_alg(struct crypto_alg *alg)
{
int ret = -ENOENT;
struct crypto_alg *q;
BUG_ON(!alg->cra_module);
down_write(&crypto_alg_sem);
list_for_each_entry(q, &crypto_alg_list, cra_list) {
if (alg == q) {
list_del(&alg->cra_list);
ret = 0;
goto out;
}
}
out:
up_write(&crypto_alg_sem);
return ret;
}
int crypto_alg_available(const char *name, u32 flags)
{
int ret = 0;
struct crypto_alg *alg = crypto_alg_mod_lookup(name);
if (alg) {
crypto_alg_put(alg);
ret = 1;
}
return ret;
}
static int __init init_crypto(void)
{
printk(KERN_INFO "Initializing Cryptographic API\n");
crypto_init_proc();
return 0;
}
__initcall(init_crypto);
/*
EXPORT_SYMBOL_GPL(crypto_register_alg);
EXPORT_SYMBOL_GPL(crypto_unregister_alg);
EXPORT_SYMBOL_GPL(crypto_alloc_tfm);
EXPORT_SYMBOL_GPL(crypto_free_tfm);
EXPORT_SYMBOL_GPL(crypto_alg_available);
*/
EXPORT_SYMBOL_NOVERS(crypto_register_alg);
EXPORT_SYMBOL_NOVERS(crypto_unregister_alg);
EXPORT_SYMBOL_NOVERS(crypto_alloc_tfm);
EXPORT_SYMBOL_NOVERS(crypto_free_tfm);
EXPORT_SYMBOL_NOVERS(crypto_alg_available);

View File

@ -0,0 +1,103 @@
/*
* Cryptographic API
*
* ARC4 Cipher Algorithm
*
* Jon Oberheide <jon@oberheide.org>
*
* 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.
*
*/
#include <linux/module.h>
#include <linux/init.h>
#include "rtl_crypto.h"
#define ARC4_MIN_KEY_SIZE 1
#define ARC4_MAX_KEY_SIZE 256
#define ARC4_BLOCK_SIZE 1
struct arc4_ctx {
u8 S[256];
u8 x, y;
};
static int arc4_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags)
{
struct arc4_ctx *ctx = ctx_arg;
int i, j = 0, k = 0;
ctx->x = 1;
ctx->y = 0;
for(i = 0; i < 256; i++)
ctx->S[i] = i;
for(i = 0; i < 256; i++)
{
u8 a = ctx->S[i];
j = (j + in_key[k] + a) & 0xff;
ctx->S[i] = ctx->S[j];
ctx->S[j] = a;
if((unsigned int)++k >= key_len)
k = 0;
}
return 0;
}
static void arc4_crypt(void *ctx_arg, u8 *out, const u8 *in)
{
struct arc4_ctx *ctx = ctx_arg;
u8 *const S = ctx->S;
u8 x = ctx->x;
u8 y = ctx->y;
u8 a, b;
a = S[x];
y = (y + a) & 0xff;
b = S[y];
S[x] = b;
S[y] = a;
x = (x + 1) & 0xff;
*out++ = *in ^ S[(a + b) & 0xff];
ctx->x = x;
ctx->y = y;
}
static struct crypto_alg arc4_alg = {
.cra_name = "arc4",
.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
.cra_blocksize = ARC4_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct arc4_ctx),
.cra_module = THIS_MODULE,
.cra_list = LIST_HEAD_INIT(arc4_alg.cra_list),
.cra_u = { .cipher = {
.cia_min_keysize = ARC4_MIN_KEY_SIZE,
.cia_max_keysize = ARC4_MAX_KEY_SIZE,
.cia_setkey = arc4_set_key,
.cia_encrypt = arc4_crypt,
.cia_decrypt = arc4_crypt } }
};
static int __init arc4_init(void)
{
return crypto_register_alg(&arc4_alg);
}
static void __exit arc4_exit(void)
{
crypto_unregister_alg(&arc4_alg);
}
module_init(arc4_init);
module_exit(arc4_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("ARC4 Cipher Algorithm");
MODULE_AUTHOR("Jon Oberheide <jon@oberheide.org>");

View File

@ -0,0 +1,40 @@
/*
* Cryptographic API.
*
* Algorithm autoloader.
*
* Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
*
* 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.
*
*/
#include "kmap_types.h"
#include <linux/kernel.h>
//#include <linux/crypto.h>
#include "rtl_crypto.h"
#include <linux/string.h>
#include <linux/kmod.h>
#include "internal.h"
/*
* A far more intelligent version of this is planned. For now, just
* try an exact match on the name of the algorithm.
*/
void crypto_alg_autoload(const char *name)
{
request_module(name);
}
struct crypto_alg *crypto_alg_mod_lookup(const char *name)
{
struct crypto_alg *alg = crypto_alg_lookup(name);
if (alg == NULL) {
crypto_alg_autoload(name);
alg = crypto_alg_lookup(name);
}
return alg;
}

View File

@ -0,0 +1,299 @@
/*
* Cryptographic API.
*
* Cipher operations.
*
* Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
*
* 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.
*
*/
#include <linux/kernel.h>
//#include <linux/crypto.h>
#include "rtl_crypto.h"
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <asm/scatterlist.h>
#include "internal.h"
#include "scatterwalk.h"
typedef void (cryptfn_t)(void *, u8 *, const u8 *);
typedef void (procfn_t)(struct crypto_tfm *, u8 *,
u8*, cryptfn_t, int enc, void *, int);
static inline void xor_64(u8 *a, const u8 *b)
{
((u32 *)a)[0] ^= ((u32 *)b)[0];
((u32 *)a)[1] ^= ((u32 *)b)[1];
}
static inline void xor_128(u8 *a, const u8 *b)
{
((u32 *)a)[0] ^= ((u32 *)b)[0];
((u32 *)a)[1] ^= ((u32 *)b)[1];
((u32 *)a)[2] ^= ((u32 *)b)[2];
((u32 *)a)[3] ^= ((u32 *)b)[3];
}
/*
* Generic encrypt/decrypt wrapper for ciphers, handles operations across
* multiple page boundaries by using temporary blocks. In user context,
* the kernel is given a chance to schedule us once per block.
*/
static int crypt(struct crypto_tfm *tfm,
struct scatterlist *dst,
struct scatterlist *src,
unsigned int nbytes, cryptfn_t crfn,
procfn_t prfn, int enc, void *info)
{
struct scatter_walk walk_in, walk_out;
const unsigned int bsize = crypto_tfm_alg_blocksize(tfm);
u8 tmp_src[bsize];
u8 tmp_dst[bsize];
if (!nbytes)
return 0;
if (nbytes % bsize) {
tfm->crt_flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN;
return -EINVAL;
}
scatterwalk_start(&walk_in, src);
scatterwalk_start(&walk_out, dst);
for(;;) {
u8 *src_p, *dst_p;
int in_place;
scatterwalk_map(&walk_in, 0);
scatterwalk_map(&walk_out, 1);
src_p = scatterwalk_whichbuf(&walk_in, bsize, tmp_src);
dst_p = scatterwalk_whichbuf(&walk_out, bsize, tmp_dst);
in_place = scatterwalk_samebuf(&walk_in, &walk_out,
src_p, dst_p);
nbytes -= bsize;
scatterwalk_copychunks(src_p, &walk_in, bsize, 0);
prfn(tfm, dst_p, src_p, crfn, enc, info, in_place);
scatterwalk_done(&walk_in, 0, nbytes);
scatterwalk_copychunks(dst_p, &walk_out, bsize, 1);
scatterwalk_done(&walk_out, 1, nbytes);
if (!nbytes)
return 0;
crypto_yield(tfm);
}
}
static void cbc_process(struct crypto_tfm *tfm, u8 *dst, u8 *src,
cryptfn_t fn, int enc, void *info, int in_place)
{
u8 *iv = info;
/* Null encryption */
if (!iv)
return;
if (enc) {
tfm->crt_u.cipher.cit_xor_block(iv, src);
fn(crypto_tfm_ctx(tfm), dst, iv);
memcpy(iv, dst, crypto_tfm_alg_blocksize(tfm));
} else {
u8 stack[in_place ? crypto_tfm_alg_blocksize(tfm) : 0];
u8 *buf = in_place ? stack : dst;
fn(crypto_tfm_ctx(tfm), buf, src);
tfm->crt_u.cipher.cit_xor_block(buf, iv);
memcpy(iv, src, crypto_tfm_alg_blocksize(tfm));
if (buf != dst)
memcpy(dst, buf, crypto_tfm_alg_blocksize(tfm));
}
}
static void ecb_process(struct crypto_tfm *tfm, u8 *dst, u8 *src,
cryptfn_t fn, int enc, void *info, int in_place)
{
fn(crypto_tfm_ctx(tfm), dst, src);
}
static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
{
struct cipher_alg *cia = &tfm->__crt_alg->cra_cipher;
if (keylen < cia->cia_min_keysize || keylen > cia->cia_max_keysize) {
tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
return -EINVAL;
} else
return cia->cia_setkey(crypto_tfm_ctx(tfm), key, keylen,
&tfm->crt_flags);
}
static int ecb_encrypt(struct crypto_tfm *tfm,
struct scatterlist *dst,
struct scatterlist *src, unsigned int nbytes)
{
return crypt(tfm, dst, src, nbytes,
tfm->__crt_alg->cra_cipher.cia_encrypt,
ecb_process, 1, NULL);
}
static int ecb_decrypt(struct crypto_tfm *tfm,
struct scatterlist *dst,
struct scatterlist *src,
unsigned int nbytes)
{
return crypt(tfm, dst, src, nbytes,
tfm->__crt_alg->cra_cipher.cia_decrypt,
ecb_process, 1, NULL);
}
static int cbc_encrypt(struct crypto_tfm *tfm,
struct scatterlist *dst,
struct scatterlist *src,
unsigned int nbytes)
{
return crypt(tfm, dst, src, nbytes,
tfm->__crt_alg->cra_cipher.cia_encrypt,
cbc_process, 1, tfm->crt_cipher.cit_iv);
}
static int cbc_encrypt_iv(struct crypto_tfm *tfm,
struct scatterlist *dst,
struct scatterlist *src,
unsigned int nbytes, u8 *iv)
{
return crypt(tfm, dst, src, nbytes,
tfm->__crt_alg->cra_cipher.cia_encrypt,
cbc_process, 1, iv);
}
static int cbc_decrypt(struct crypto_tfm *tfm,
struct scatterlist *dst,
struct scatterlist *src,
unsigned int nbytes)
{
return crypt(tfm, dst, src, nbytes,
tfm->__crt_alg->cra_cipher.cia_decrypt,
cbc_process, 0, tfm->crt_cipher.cit_iv);
}
static int cbc_decrypt_iv(struct crypto_tfm *tfm,
struct scatterlist *dst,
struct scatterlist *src,
unsigned int nbytes, u8 *iv)
{
return crypt(tfm, dst, src, nbytes,
tfm->__crt_alg->cra_cipher.cia_decrypt,
cbc_process, 0, iv);
}
static int nocrypt(struct crypto_tfm *tfm,
struct scatterlist *dst,
struct scatterlist *src,
unsigned int nbytes)
{
return -ENOSYS;
}
static int nocrypt_iv(struct crypto_tfm *tfm,
struct scatterlist *dst,
struct scatterlist *src,
unsigned int nbytes, u8 *iv)
{
return -ENOSYS;
}
int crypto_init_cipher_flags(struct crypto_tfm *tfm, u32 flags)
{
u32 mode = flags & CRYPTO_TFM_MODE_MASK;
tfm->crt_cipher.cit_mode = mode ? mode : CRYPTO_TFM_MODE_ECB;
if (flags & CRYPTO_TFM_REQ_WEAK_KEY)
tfm->crt_flags = CRYPTO_TFM_REQ_WEAK_KEY;
return 0;
}
int crypto_init_cipher_ops(struct crypto_tfm *tfm)
{
int ret = 0;
struct cipher_tfm *ops = &tfm->crt_cipher;
ops->cit_setkey = setkey;
switch (tfm->crt_cipher.cit_mode) {
case CRYPTO_TFM_MODE_ECB:
ops->cit_encrypt = ecb_encrypt;
ops->cit_decrypt = ecb_decrypt;
break;
case CRYPTO_TFM_MODE_CBC:
ops->cit_encrypt = cbc_encrypt;
ops->cit_decrypt = cbc_decrypt;
ops->cit_encrypt_iv = cbc_encrypt_iv;
ops->cit_decrypt_iv = cbc_decrypt_iv;
break;
case CRYPTO_TFM_MODE_CFB:
ops->cit_encrypt = nocrypt;
ops->cit_decrypt = nocrypt;
ops->cit_encrypt_iv = nocrypt_iv;
ops->cit_decrypt_iv = nocrypt_iv;
break;
case CRYPTO_TFM_MODE_CTR:
ops->cit_encrypt = nocrypt;
ops->cit_decrypt = nocrypt;
ops->cit_encrypt_iv = nocrypt_iv;
ops->cit_decrypt_iv = nocrypt_iv;
break;
default:
BUG();
}
if (ops->cit_mode == CRYPTO_TFM_MODE_CBC) {
switch (crypto_tfm_alg_blocksize(tfm)) {
case 8:
ops->cit_xor_block = xor_64;
break;
case 16:
ops->cit_xor_block = xor_128;
break;
default:
printk(KERN_WARNING "%s: block size %u not supported\n",
crypto_tfm_alg_name(tfm),
crypto_tfm_alg_blocksize(tfm));
ret = -EINVAL;
goto out;
}
ops->cit_ivsize = crypto_tfm_alg_blocksize(tfm);
ops->cit_iv = kmalloc(ops->cit_ivsize, GFP_KERNEL);
if (ops->cit_iv == NULL)
ret = -ENOMEM;
}
out:
return ret;
}
void crypto_exit_cipher_ops(struct crypto_tfm *tfm)
{
if (tfm->crt_cipher.cit_iv)
kfree(tfm->crt_cipher.cit_iv);
}

View File

@ -0,0 +1,64 @@
/*
* Cryptographic API.
*
* Compression operations.
*
* Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
*
* 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.
*
*/
#include <linux/types.h>
//#include <linux/crypto.h>
#include "rtl_crypto.h"
#include <linux/errno.h>
#include <asm/scatterlist.h>
#include <linux/string.h>
#include "internal.h"
static int crypto_compress(struct crypto_tfm *tfm,
const u8 *src, unsigned int slen,
u8 *dst, unsigned int *dlen)
{
return tfm->__crt_alg->cra_compress.coa_compress(crypto_tfm_ctx(tfm),
src, slen, dst,
dlen);
}
static int crypto_decompress(struct crypto_tfm *tfm,
const u8 *src, unsigned int slen,
u8 *dst, unsigned int *dlen)
{
return tfm->__crt_alg->cra_compress.coa_decompress(crypto_tfm_ctx(tfm),
src, slen, dst,
dlen);
}
int crypto_init_compress_flags(struct crypto_tfm *tfm, u32 flags)
{
return flags ? -EINVAL : 0;
}
int crypto_init_compress_ops(struct crypto_tfm *tfm)
{
int ret = 0;
struct compress_tfm *ops = &tfm->crt_compress;
ret = tfm->__crt_alg->cra_compress.coa_init(crypto_tfm_ctx(tfm));
if (ret)
goto out;
ops->cot_compress = crypto_compress;
ops->cot_decompress = crypto_decompress;
out:
return ret;
}
void crypto_exit_compress_ops(struct crypto_tfm *tfm)
{
tfm->__crt_alg->cra_compress.coa_exit(crypto_tfm_ctx(tfm));
}

View File

@ -0,0 +1,90 @@
/*
* Header file to maintain compatibility among different kernel versions.
*
* Copyright (c) 2004-2006 <lawrence_wang@realsil.com.cn>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. See README and COPYING for
* more details.
*/
#include <linux/crypto.h>
static inline int crypto_cipher_encrypt(struct crypto_tfm *tfm,
struct scatterlist *dst,
struct scatterlist *src,
unsigned int nbytes)
{
BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
return tfm->crt_cipher.cit_encrypt(tfm, dst, src, nbytes);
}
static inline int crypto_cipher_decrypt(struct crypto_tfm *tfm,
struct scatterlist *dst,
struct scatterlist *src,
unsigned int nbytes)
{
BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
return tfm->crt_cipher.cit_decrypt(tfm, dst, src, nbytes);
}
#if 0
/*
* crypto_free_tfm - Free crypto transform
* @tfm: Transform to free
*
* crypto_free_tfm() frees up the transform and any associated resources,
* then drops the refcount on the associated algorithm.
*/
void crypto_free_tfm(struct crypto_tfm *tfm)
{
struct crypto_alg *alg;
int size;
if (unlikely(!tfm))
return;
alg = tfm->__crt_alg;
size = sizeof(*tfm) + alg->cra_ctxsize;
if (alg->cra_exit)
alg->cra_exit(tfm);
crypto_exit_ops(tfm);
crypto_mod_put(alg);
memset(tfm, 0, size);
kfree(tfm);
}
#endif
#if 1
struct crypto_tfm *crypto_alloc_tfm(const char *name, u32 flags)
{
struct crypto_tfm *tfm = NULL;
int err;
printk("call crypto_alloc_tfm!!!\n");
do {
struct crypto_alg *alg;
alg = crypto_alg_mod_lookup(name, 0, CRYPTO_ALG_ASYNC);
err = PTR_ERR(alg);
if (IS_ERR(alg))
continue;
tfm = __crypto_alloc_tfm(alg, flags);
err = 0;
if (IS_ERR(tfm)) {
crypto_mod_put(alg);
err = PTR_ERR(tfm);
tfm = NULL;
}
} while (err == -EAGAIN && !signal_pending(current));
return tfm;
}
#endif
//EXPORT_SYMBOL_GPL(crypto_alloc_tfm);
//EXPORT_SYMBOL_GPL(crypto_free_tfm);

View File

@ -0,0 +1,108 @@
/*
* Cryptographic API.
*
* Digest operations.
*
* Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
*
* 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.
*
*/
//#include <linux/crypto.h>
#include "rtl_crypto.h"
#include <linux/mm.h>
#include <linux/errno.h>
#include <linux/highmem.h>
#include <asm/scatterlist.h>
#include "internal.h"
static void init(struct crypto_tfm *tfm)
{
tfm->__crt_alg->cra_digest.dia_init(crypto_tfm_ctx(tfm));
}
static void update(struct crypto_tfm *tfm,
struct scatterlist *sg, unsigned int nsg)
{
unsigned int i;
for (i = 0; i < nsg; i++) {
struct page *pg = sg[i].page;
unsigned int offset = sg[i].offset;
unsigned int l = sg[i].length;
do {
unsigned int bytes_from_page = min(l, ((unsigned int)
(PAGE_SIZE)) -
offset);
char *p = crypto_kmap(pg, 0) + offset;
tfm->__crt_alg->cra_digest.dia_update
(crypto_tfm_ctx(tfm), p,
bytes_from_page);
crypto_kunmap(p, 0);
crypto_yield(tfm);
offset = 0;
pg++;
l -= bytes_from_page;
} while (l > 0);
}
}
static void final(struct crypto_tfm *tfm, u8 *out)
{
tfm->__crt_alg->cra_digest.dia_final(crypto_tfm_ctx(tfm), out);
}
static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
{
u32 flags;
if (tfm->__crt_alg->cra_digest.dia_setkey == NULL)
return -ENOSYS;
return tfm->__crt_alg->cra_digest.dia_setkey(crypto_tfm_ctx(tfm),
key, keylen, &flags);
}
static void digest(struct crypto_tfm *tfm,
struct scatterlist *sg, unsigned int nsg, u8 *out)
{
unsigned int i;
tfm->crt_digest.dit_init(tfm);
for (i = 0; i < nsg; i++) {
char *p = crypto_kmap(sg[i].page, 0) + sg[i].offset;
tfm->__crt_alg->cra_digest.dia_update(crypto_tfm_ctx(tfm),
p, sg[i].length);
crypto_kunmap(p, 0);
crypto_yield(tfm);
}
crypto_digest_final(tfm, out);
}
int crypto_init_digest_flags(struct crypto_tfm *tfm, u32 flags)
{
return flags ? -EINVAL : 0;
}
int crypto_init_digest_ops(struct crypto_tfm *tfm)
{
struct digest_tfm *ops = &tfm->crt_digest;
ops->dit_init = init;
ops->dit_update = update;
ops->dit_final = final;
ops->dit_digest = digest;
ops->dit_setkey = setkey;
return crypto_alloc_hmac_block(tfm);
}
void crypto_exit_digest_ops(struct crypto_tfm *tfm)
{
crypto_free_hmac_block(tfm);
}

View File

@ -0,0 +1,239 @@
#ifdef ENABLE_DOT11D
//-----------------------------------------------------------------------------
// File:
// Dot11d.c
//
// Description:
// Implement 802.11d.
//
//-----------------------------------------------------------------------------
#include "dot11d.h"
void
Dot11d_Init(struct ieee80211_device *ieee)
{
PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(ieee);
pDot11dInfo->bEnabled = 0;
pDot11dInfo->State = DOT11D_STATE_NONE;
pDot11dInfo->CountryIeLen = 0;
memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1);
memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1);
RESET_CIE_WATCHDOG(ieee);
printk("Dot11d_Init()\n");
}
//
// Description:
// Reset to the state as we are just entering a regulatory domain.
//
void
Dot11d_Reset(struct ieee80211_device *ieee)
{
u32 i;
PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(ieee);
#if 0
if(!pDot11dInfo->bEnabled)
return;
#endif
// Clear old channel map
memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1);
memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1);
// Set new channel map
for (i=1; i<=11; i++) {
(pDot11dInfo->channel_map)[i] = 1;
}
for (i=12; i<=14; i++) {
(pDot11dInfo->channel_map)[i] = 2;
}
pDot11dInfo->State = DOT11D_STATE_NONE;
pDot11dInfo->CountryIeLen = 0;
RESET_CIE_WATCHDOG(ieee);
//printk("Dot11d_Reset()\n");
}
//
// Description:
// Update country IE from Beacon or Probe Resopnse
// and configure PHY for operation in the regulatory domain.
//
// TODO:
// Configure Tx power.
//
// Assumption:
// 1. IS_DOT11D_ENABLE() is TRUE.
// 2. Input IE is an valid one.
//
void
Dot11d_UpdateCountryIe(
struct ieee80211_device *dev,
u8 * pTaddr,
u16 CoutryIeLen,
u8 * pCoutryIe
)
{
PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
u8 i, j, NumTriples, MaxChnlNum;
PCHNL_TXPOWER_TRIPLE pTriple;
memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1);
memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1);
MaxChnlNum = 0;
NumTriples = (CoutryIeLen - 3) / 3; // skip 3-byte country string.
pTriple = (PCHNL_TXPOWER_TRIPLE)(pCoutryIe + 3);
for(i = 0; i < NumTriples; i++)
{
if(MaxChnlNum >= pTriple->FirstChnl)
{ // It is not in a monotonically increasing order, so stop processing.
printk("Dot11d_UpdateCountryIe(): Invalid country IE, skip it........1\n");
return;
}
if(MAX_CHANNEL_NUMBER < (pTriple->FirstChnl + pTriple->NumChnls))
{ // It is not a valid set of channel id, so stop processing.
printk("Dot11d_UpdateCountryIe(): Invalid country IE, skip it........2\n");
return;
}
for(j = 0 ; j < pTriple->NumChnls; j++)
{
pDot11dInfo->channel_map[pTriple->FirstChnl + j] = 1;
pDot11dInfo->MaxTxPwrDbmList[pTriple->FirstChnl + j] = pTriple->MaxTxPowerInDbm;
MaxChnlNum = pTriple->FirstChnl + j;
}
pTriple = (PCHNL_TXPOWER_TRIPLE)((u8*)pTriple + 3);
}
#if 1
//printk("Dot11d_UpdateCountryIe(): Channel List:\n");
printk("Channel List:");
for(i=1; i<= MAX_CHANNEL_NUMBER; i++)
if(pDot11dInfo->channel_map[i] > 0)
printk(" %d", i);
printk("\n");
#endif
UPDATE_CIE_SRC(dev, pTaddr);
pDot11dInfo->CountryIeLen = CoutryIeLen;
memcpy(pDot11dInfo->CountryIeBuf, pCoutryIe,CoutryIeLen);
pDot11dInfo->State = DOT11D_STATE_LEARNED;
}
u8
DOT11D_GetMaxTxPwrInDbm(
struct ieee80211_device *dev,
u8 Channel
)
{
PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
u8 MaxTxPwrInDbm = 255;
if(MAX_CHANNEL_NUMBER < Channel)
{
printk("DOT11D_GetMaxTxPwrInDbm(): Invalid Channel\n");
return MaxTxPwrInDbm;
}
if(pDot11dInfo->channel_map[Channel])
{
MaxTxPwrInDbm = pDot11dInfo->MaxTxPwrDbmList[Channel];
}
return MaxTxPwrInDbm;
}
void
DOT11D_ScanComplete(
struct ieee80211_device * dev
)
{
PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
switch(pDot11dInfo->State)
{
case DOT11D_STATE_LEARNED:
pDot11dInfo->State = DOT11D_STATE_DONE;
break;
case DOT11D_STATE_DONE:
if( GET_CIE_WATCHDOG(dev) == 0 )
{ // Reset country IE if previous one is gone.
Dot11d_Reset(dev);
}
break;
case DOT11D_STATE_NONE:
break;
}
}
int IsLegalChannel(
struct ieee80211_device * dev,
u8 channel
)
{
PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
if(MAX_CHANNEL_NUMBER < channel)
{
printk("IsLegalChannel(): Invalid Channel\n");
return 0;
}
if(pDot11dInfo->channel_map[channel] > 0)
return 1;
return 0;
}
int ToLegalChannel(
struct ieee80211_device * dev,
u8 channel
)
{
PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
u8 default_chn = 0;
u32 i = 0;
for (i=1; i<= MAX_CHANNEL_NUMBER; i++)
{
if(pDot11dInfo->channel_map[i] > 0)
{
default_chn = i;
break;
}
}
if(MAX_CHANNEL_NUMBER < channel)
{
printk("IsLegalChannel(): Invalid Channel\n");
return default_chn;
}
if(pDot11dInfo->channel_map[channel] > 0)
return channel;
return default_chn;
}
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
EXPORT_SYMBOL(Dot11d_Init);
EXPORT_SYMBOL(Dot11d_Reset);
EXPORT_SYMBOL(Dot11d_UpdateCountryIe);
EXPORT_SYMBOL(DOT11D_GetMaxTxPwrInDbm);
EXPORT_SYMBOL(DOT11D_ScanComplete);
EXPORT_SYMBOL(IsLegalChannel);
EXPORT_SYMBOL(ToLegalChannel);
#else
EXPORT_SYMBOL_NOVERS(Dot11d_Init);
EXPORT_SYMBOL_NOVERS(Dot11d_Reset);
EXPORT_SYMBOL_NOVERS(Dot11d_UpdateCountryIe);
EXPORT_SYMBOL_NOVERS(DOT11D_GetMaxTxPwrInDbm);
EXPORT_SYMBOL_NOVERS(DOT11D_ScanComplete);
EXPORT_SYMBOL_NOVERS(IsLegalChannel);
EXPORT_SYMBOL_NOVERS(ToLegalChannel);
#endif
#endif

View File

@ -0,0 +1,102 @@
#ifndef __INC_DOT11D_H
#define __INC_DOT11D_H
#ifdef ENABLE_DOT11D
#include "ieee80211.h"
//#define ENABLE_DOT11D
//#define DOT11D_MAX_CHNL_NUM 83
typedef struct _CHNL_TXPOWER_TRIPLE {
u8 FirstChnl;
u8 NumChnls;
u8 MaxTxPowerInDbm;
}CHNL_TXPOWER_TRIPLE, *PCHNL_TXPOWER_TRIPLE;
typedef enum _DOT11D_STATE {
DOT11D_STATE_NONE = 0,
DOT11D_STATE_LEARNED,
DOT11D_STATE_DONE,
}DOT11D_STATE;
typedef struct _RT_DOT11D_INFO {
//DECLARE_RT_OBJECT(RT_DOT11D_INFO);
bool bEnabled; // dot11MultiDomainCapabilityEnabled
u16 CountryIeLen; // > 0 if CountryIeBuf[] contains valid country information element.
u8 CountryIeBuf[MAX_IE_LEN];
u8 CountryIeSrcAddr[6]; // Source AP of the country IE.
u8 CountryIeWatchdog;
u8 channel_map[MAX_CHANNEL_NUMBER+1]; //!!!Value 0: Invalid, 1: Valid (active scan), 2: Valid (passive scan)
//u8 ChnlListLen; // #Bytes valid in ChnlList[].
//u8 ChnlList[DOT11D_MAX_CHNL_NUM];
u8 MaxTxPwrDbmList[MAX_CHANNEL_NUMBER+1];
DOT11D_STATE State;
}RT_DOT11D_INFO, *PRT_DOT11D_INFO;
#define eqMacAddr(a,b) ( ((a)[0]==(b)[0] && (a)[1]==(b)[1] && (a)[2]==(b)[2] && (a)[3]==(b)[3] && (a)[4]==(b)[4] && (a)[5]==(b)[5]) ? 1:0 )
#define cpMacAddr(des,src) ((des)[0]=(src)[0],(des)[1]=(src)[1],(des)[2]=(src)[2],(des)[3]=(src)[3],(des)[4]=(src)[4],(des)[5]=(src)[5])
#define GET_DOT11D_INFO(__pIeeeDev) ((PRT_DOT11D_INFO)((__pIeeeDev)->pDot11dInfo))
#define IS_DOT11D_ENABLE(__pIeeeDev) GET_DOT11D_INFO(__pIeeeDev)->bEnabled
#define IS_COUNTRY_IE_VALID(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)->CountryIeLen > 0)
#define IS_EQUAL_CIE_SRC(__pIeeeDev, __pTa) eqMacAddr(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa)
#define UPDATE_CIE_SRC(__pIeeeDev, __pTa) cpMacAddr(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa)
#define IS_COUNTRY_IE_CHANGED(__pIeeeDev, __Ie) \
(((__Ie).Length == 0 || (__Ie).Length != GET_DOT11D_INFO(__pIeeeDev)->CountryIeLen) ? \
FALSE : \
(!memcmp(GET_DOT11D_INFO(__pIeeeDev)->CountryIeBuf, (__Ie).Octet, (__Ie).Length)))
#define CIE_WATCHDOG_TH 1
#define GET_CIE_WATCHDOG(__pIeeeDev) GET_DOT11D_INFO(__pIeeeDev)->CountryIeWatchdog
#define RESET_CIE_WATCHDOG(__pIeeeDev) GET_CIE_WATCHDOG(__pIeeeDev) = 0
#define UPDATE_CIE_WATCHDOG(__pIeeeDev) ++GET_CIE_WATCHDOG(__pIeeeDev)
#define IS_DOT11D_STATE_DONE(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)->State == DOT11D_STATE_DONE)
void
Dot11d_Init(
struct ieee80211_device *dev
);
void
Dot11d_Reset(
struct ieee80211_device *dev
);
void
Dot11d_UpdateCountryIe(
struct ieee80211_device *dev,
u8 * pTaddr,
u16 CoutryIeLen,
u8 * pCoutryIe
);
u8
DOT11D_GetMaxTxPwrInDbm(
struct ieee80211_device *dev,
u8 Channel
);
void
DOT11D_ScanComplete(
struct ieee80211_device * dev
);
int IsLegalChannel(
struct ieee80211_device * dev,
u8 channel
);
int ToLegalChannel(
struct ieee80211_device * dev,
u8 channel
);
#endif //ENABLE_DOT11D
#endif // #ifndef __INC_DOT11D_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,273 @@
/*
* Host AP crypto routines
*
* Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
* Portions Copyright (C) 2004, Intel Corporation <jketreno@linux.intel.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. See README and COPYING for
* more details.
*
*/
//#include <linux/config.h>
#include <linux/version.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <asm/string.h>
#include <asm/errno.h>
#include "ieee80211.h"
MODULE_AUTHOR("Jouni Malinen");
MODULE_DESCRIPTION("HostAP crypto");
MODULE_LICENSE("GPL");
struct ieee80211_crypto_alg {
struct list_head list;
struct ieee80211_crypto_ops *ops;
};
struct ieee80211_crypto {
struct list_head algs;
spinlock_t lock;
};
static struct ieee80211_crypto *hcrypt;
void ieee80211_crypt_deinit_entries(struct ieee80211_device *ieee,
int force)
{
struct list_head *ptr, *n;
struct ieee80211_crypt_data *entry;
for (ptr = ieee->crypt_deinit_list.next, n = ptr->next;
ptr != &ieee->crypt_deinit_list; ptr = n, n = ptr->next) {
entry = list_entry(ptr, struct ieee80211_crypt_data, list);
if (atomic_read(&entry->refcnt) != 0 && !force)
continue;
list_del(ptr);
if (entry->ops) {
entry->ops->deinit(entry->priv);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
module_put(entry->ops->owner);
#else
__MOD_DEC_USE_COUNT(entry->ops->owner);
#endif
}
kfree(entry);
}
}
void ieee80211_crypt_deinit_handler(unsigned long data)
{
struct ieee80211_device *ieee = (struct ieee80211_device *)data;
unsigned long flags;
spin_lock_irqsave(&ieee->lock, flags);
ieee80211_crypt_deinit_entries(ieee, 0);
if (!list_empty(&ieee->crypt_deinit_list)) {
printk(KERN_DEBUG "%s: entries remaining in delayed crypt "
"deletion list\n", ieee->dev->name);
ieee->crypt_deinit_timer.expires = jiffies + HZ;
add_timer(&ieee->crypt_deinit_timer);
}
spin_unlock_irqrestore(&ieee->lock, flags);
}
void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee,
struct ieee80211_crypt_data **crypt)
{
struct ieee80211_crypt_data *tmp;
unsigned long flags;
if (*crypt == NULL)
return;
tmp = *crypt;
*crypt = NULL;
/* must not run ops->deinit() while there may be pending encrypt or
* decrypt operations. Use a list of delayed deinits to avoid needing
* locking. */
spin_lock_irqsave(&ieee->lock, flags);
list_add(&tmp->list, &ieee->crypt_deinit_list);
if (!timer_pending(&ieee->crypt_deinit_timer)) {
ieee->crypt_deinit_timer.expires = jiffies + HZ;
add_timer(&ieee->crypt_deinit_timer);
}
spin_unlock_irqrestore(&ieee->lock, flags);
}
int ieee80211_register_crypto_ops(struct ieee80211_crypto_ops *ops)
{
unsigned long flags;
struct ieee80211_crypto_alg *alg;
if (hcrypt == NULL)
return -1;
alg = kmalloc(sizeof(*alg), GFP_KERNEL);
if (alg == NULL)
return -ENOMEM;
memset(alg, 0, sizeof(*alg));
alg->ops = ops;
spin_lock_irqsave(&hcrypt->lock, flags);
list_add(&alg->list, &hcrypt->algs);
spin_unlock_irqrestore(&hcrypt->lock, flags);
printk(KERN_DEBUG "ieee80211_crypt: registered algorithm '%s'\n",
ops->name);
return 0;
}
int ieee80211_unregister_crypto_ops(struct ieee80211_crypto_ops *ops)
{
unsigned long flags;
struct list_head *ptr;
struct ieee80211_crypto_alg *del_alg = NULL;
if (hcrypt == NULL)
return -1;
spin_lock_irqsave(&hcrypt->lock, flags);
for (ptr = hcrypt->algs.next; ptr != &hcrypt->algs; ptr = ptr->next) {
struct ieee80211_crypto_alg *alg =
(struct ieee80211_crypto_alg *) ptr;
if (alg->ops == ops) {
list_del(&alg->list);
del_alg = alg;
break;
}
}
spin_unlock_irqrestore(&hcrypt->lock, flags);
if (del_alg) {
printk(KERN_DEBUG "ieee80211_crypt: unregistered algorithm "
"'%s'\n", ops->name);
kfree(del_alg);
}
return del_alg ? 0 : -1;
}
struct ieee80211_crypto_ops * ieee80211_get_crypto_ops(const char *name)
{
unsigned long flags;
struct list_head *ptr;
struct ieee80211_crypto_alg *found_alg = NULL;
if (hcrypt == NULL)
return NULL;
spin_lock_irqsave(&hcrypt->lock, flags);
for (ptr = hcrypt->algs.next; ptr != &hcrypt->algs; ptr = ptr->next) {
struct ieee80211_crypto_alg *alg =
(struct ieee80211_crypto_alg *) ptr;
if (strcmp(alg->ops->name, name) == 0) {
found_alg = alg;
break;
}
}
spin_unlock_irqrestore(&hcrypt->lock, flags);
if (found_alg)
return found_alg->ops;
else
return NULL;
}
static void * ieee80211_crypt_null_init(int keyidx) { return (void *) 1; }
static void ieee80211_crypt_null_deinit(void *priv) {}
static struct ieee80211_crypto_ops ieee80211_crypt_null = {
.name = "NULL",
.init = ieee80211_crypt_null_init,
.deinit = ieee80211_crypt_null_deinit,
.encrypt_mpdu = NULL,
.decrypt_mpdu = NULL,
.encrypt_msdu = NULL,
.decrypt_msdu = NULL,
.set_key = NULL,
.get_key = NULL,
.extra_prefix_len = 0,
.extra_postfix_len = 0,
.owner = THIS_MODULE,
};
static int __init ieee80211_crypto_init(void)
{
int ret = -ENOMEM;
hcrypt = kmalloc(sizeof(*hcrypt), GFP_KERNEL);
if (!hcrypt)
goto out;
memset(hcrypt, 0, sizeof(*hcrypt));
INIT_LIST_HEAD(&hcrypt->algs);
spin_lock_init(&hcrypt->lock);
ret = ieee80211_register_crypto_ops(&ieee80211_crypt_null);
if (ret < 0) {
kfree(hcrypt);
hcrypt = NULL;
}
out:
return ret;
}
static void __exit ieee80211_crypto_deinit(void)
{
struct list_head *ptr, *n;
if (hcrypt == NULL)
return;
for (ptr = hcrypt->algs.next, n = ptr->next; ptr != &hcrypt->algs;
ptr = n, n = ptr->next) {
struct ieee80211_crypto_alg *alg =
(struct ieee80211_crypto_alg *) ptr;
list_del(ptr);
printk(KERN_DEBUG "ieee80211_crypt: unregistered algorithm "
"'%s' (deinit)\n", alg->ops->name);
kfree(alg);
}
kfree(hcrypt);
}
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
EXPORT_SYMBOL(ieee80211_crypt_deinit_entries);
EXPORT_SYMBOL(ieee80211_crypt_deinit_handler);
EXPORT_SYMBOL(ieee80211_crypt_delayed_deinit);
EXPORT_SYMBOL(ieee80211_register_crypto_ops);
EXPORT_SYMBOL(ieee80211_unregister_crypto_ops);
EXPORT_SYMBOL(ieee80211_get_crypto_ops);
#else
EXPORT_SYMBOL_NOVERS(ieee80211_crypt_deinit_entries);
EXPORT_SYMBOL_NOVERS(ieee80211_crypt_deinit_handler);
EXPORT_SYMBOL_NOVERS(ieee80211_crypt_delayed_deinit);
EXPORT_SYMBOL_NOVERS(ieee80211_register_crypto_ops);
EXPORT_SYMBOL_NOVERS(ieee80211_unregister_crypto_ops);
EXPORT_SYMBOL_NOVERS(ieee80211_get_crypto_ops);
#endif
module_init(ieee80211_crypto_init);
module_exit(ieee80211_crypto_deinit);

View File

@ -0,0 +1,93 @@
/*
* Original code based on Host AP (software wireless LAN access point) driver
* for Intersil Prism2/2.5/3.
*
* Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
* <jkmaline@cc.hut.fi>
* Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
*
* Adaption to a generic IEEE 802.11 stack by James Ketrenos
* <jketreno@linux.intel.com>
*
* Copyright (c) 2004, Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. See README and COPYING for
* more details.
*/
/*
* This file defines the interface to the ieee80211 crypto module.
*/
#ifndef IEEE80211_CRYPT_H
#define IEEE80211_CRYPT_H
#include <linux/skbuff.h>
struct ieee80211_crypto_ops {
const char *name;
/* init new crypto context (e.g., allocate private data space,
* select IV, etc.); returns NULL on failure or pointer to allocated
* private data on success */
void * (*init)(int keyidx);
/* deinitialize crypto context and free allocated private data */
void (*deinit)(void *priv);
/* encrypt/decrypt return < 0 on error or >= 0 on success. The return
* value from decrypt_mpdu is passed as the keyidx value for
* decrypt_msdu. skb must have enough head and tail room for the
* encryption; if not, error will be returned; these functions are
* called for all MPDUs (i.e., fragments).
*/
int (*encrypt_mpdu)(struct sk_buff *skb, int hdr_len, void *priv);
int (*decrypt_mpdu)(struct sk_buff *skb, int hdr_len, void *priv);
/* These functions are called for full MSDUs, i.e. full frames.
* These can be NULL if full MSDU operations are not needed. */
int (*encrypt_msdu)(struct sk_buff *skb, int hdr_len, void *priv);
int (*decrypt_msdu)(struct sk_buff *skb, int keyidx, int hdr_len,
void *priv);
int (*set_key)(void *key, int len, u8 *seq, void *priv);
int (*get_key)(void *key, int len, u8 *seq, void *priv);
/* procfs handler for printing out key information and possible
* statistics */
char * (*print_stats)(char *p, void *priv);
/* maximum number of bytes added by encryption; encrypt buf is
* allocated with extra_prefix_len bytes, copy of in_buf, and
* extra_postfix_len; encrypt need not use all this space, but
* the result must start at the beginning of the buffer and correct
* length must be returned */
int extra_prefix_len, extra_postfix_len;
struct module *owner;
};
struct ieee80211_crypt_data {
struct list_head list; /* delayed deletion list */
struct ieee80211_crypto_ops *ops;
void *priv;
atomic_t refcnt;
};
int ieee80211_register_crypto_ops(struct ieee80211_crypto_ops *ops);
int ieee80211_unregister_crypto_ops(struct ieee80211_crypto_ops *ops);
struct ieee80211_crypto_ops * ieee80211_get_crypto_ops(const char *name);
void ieee80211_crypt_deinit_entries(struct ieee80211_device *, int);
void ieee80211_crypt_deinit_handler(unsigned long);
void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee,
struct ieee80211_crypt_data **crypt);
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
#define offset_in_page(p) ((unsigned long)(p) & ~PAGE_MASK)
#endif
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,31))
#define crypto_alloc_tfm crypto_alloc_tfm_rsl
#define crypto_free_tfm crypto_free_tfm_rsl
#endif
#endif

View File

@ -0,0 +1,534 @@
/*
* Host AP crypt: host-based CCMP encryption implementation for Host AP driver
*
* Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. See README and COPYING for
* more details.
*/
//#include <linux/config.h>
#include <linux/version.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/random.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/if_ether.h>
#include <linux/if_arp.h>
#include <asm/string.h>
#include <linux/wireless.h>
#include "ieee80211.h"
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
#include "rtl_crypto.h"
#else
#include <linux/crypto.h>
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
#include <asm/scatterlist.h>
#else
#include <linux/scatterlist.h>
#endif
//#include <asm/scatterlist.h>
MODULE_AUTHOR("Jouni Malinen");
MODULE_DESCRIPTION("Host AP crypt: CCMP");
MODULE_LICENSE("GPL");
#ifndef OPENSUSE_SLED
#define OPENSUSE_SLED 0
#endif
#define AES_BLOCK_LEN 16
#define CCMP_HDR_LEN 8
#define CCMP_MIC_LEN 8
#define CCMP_TK_LEN 16
#define CCMP_PN_LEN 6
struct ieee80211_ccmp_data {
u8 key[CCMP_TK_LEN];
int key_set;
u8 tx_pn[CCMP_PN_LEN];
u8 rx_pn[CCMP_PN_LEN];
u32 dot11RSNAStatsCCMPFormatErrors;
u32 dot11RSNAStatsCCMPReplays;
u32 dot11RSNAStatsCCMPDecryptErrors;
int key_idx;
struct crypto_tfm *tfm;
/* scratch buffers for virt_to_page() (crypto API) */
u8 tx_b0[AES_BLOCK_LEN], tx_b[AES_BLOCK_LEN],
tx_e[AES_BLOCK_LEN], tx_s0[AES_BLOCK_LEN];
u8 rx_b0[AES_BLOCK_LEN], rx_b[AES_BLOCK_LEN], rx_a[AES_BLOCK_LEN];
};
void ieee80211_ccmp_aes_encrypt(struct crypto_tfm *tfm,
const u8 pt[16], u8 ct[16])
{
#if((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) && (!OPENSUSE_SLED))
struct scatterlist src, dst;
src.page = virt_to_page(pt);
src.offset = offset_in_page(pt);
src.length = AES_BLOCK_LEN;
dst.page = virt_to_page(ct);
dst.offset = offset_in_page(ct);
dst.length = AES_BLOCK_LEN;
crypto_cipher_encrypt(tfm, &dst, &src, AES_BLOCK_LEN);
#else
crypto_cipher_encrypt_one((void*)tfm, ct, pt);
#endif
}
static void * ieee80211_ccmp_init(int key_idx)
{
struct ieee80211_ccmp_data *priv;
priv = kmalloc(sizeof(*priv), GFP_ATOMIC);
if (priv == NULL)
goto fail;
memset(priv, 0, sizeof(*priv));
priv->key_idx = key_idx;
#if((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) && (!OPENSUSE_SLED))
priv->tfm = crypto_alloc_tfm("aes", 0);
if (priv->tfm == NULL) {
printk(KERN_DEBUG "ieee80211_crypt_ccmp: could not allocate "
"crypto API aes\n");
goto fail;
}
#else
priv->tfm = (void*)crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
if (IS_ERR(priv->tfm)) {
printk(KERN_DEBUG "ieee80211_crypt_ccmp: could not allocate "
"crypto API aes\n");
priv->tfm = NULL;
goto fail;
}
#endif
return priv;
fail:
if (priv) {
if (priv->tfm)
#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21))
crypto_free_tfm(priv->tfm);
#else
crypto_free_cipher((void*)priv->tfm);
#endif
kfree(priv);
}
return NULL;
}
static void ieee80211_ccmp_deinit(void *priv)
{
struct ieee80211_ccmp_data *_priv = priv;
if (_priv && _priv->tfm)
#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21))
crypto_free_tfm(_priv->tfm);
#else
crypto_free_cipher((void*)_priv->tfm);
#endif
kfree(priv);
}
static inline void xor_block(u8 *b, u8 *a, size_t len)
{
int i;
for (i = 0; i < len; i++)
b[i] ^= a[i];
}
static void ccmp_init_blocks(struct crypto_tfm *tfm,
struct ieee80211_hdr_4addr *hdr,
u8 *pn, size_t dlen, u8 *b0, u8 *auth,
u8 *s0)
{
u8 *pos, qc = 0;
size_t aad_len;
u16 fc;
int a4_included, qc_included;
u8 aad[2 * AES_BLOCK_LEN];
fc = le16_to_cpu(hdr->frame_ctl);
a4_included = ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS));
/*
qc_included = ((WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA) &&
(WLAN_FC_GET_STYPE(fc) & 0x08));
*/
// fixed by David :2006.9.6
qc_included = ((WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA) &&
(WLAN_FC_GET_STYPE(fc) & 0x80));
aad_len = 22;
if (a4_included)
aad_len += 6;
if (qc_included) {
pos = (u8 *) &hdr->addr4;
if (a4_included)
pos += 6;
qc = *pos & 0x0f;
aad_len += 2;
}
/* CCM Initial Block:
* Flag (Include authentication header, M=3 (8-octet MIC),
* L=1 (2-octet Dlen))
* Nonce: 0x00 | A2 | PN
* Dlen */
b0[0] = 0x59;
b0[1] = qc;
memcpy(b0 + 2, hdr->addr2, ETH_ALEN);
memcpy(b0 + 8, pn, CCMP_PN_LEN);
b0[14] = (dlen >> 8) & 0xff;
b0[15] = dlen & 0xff;
/* AAD:
* FC with bits 4..6 and 11..13 masked to zero; 14 is always one
* A1 | A2 | A3
* SC with bits 4..15 (seq#) masked to zero
* A4 (if present)
* QC (if present)
*/
pos = (u8 *) hdr;
aad[0] = 0; /* aad_len >> 8 */
aad[1] = aad_len & 0xff;
aad[2] = pos[0] & 0x8f;
aad[3] = pos[1] & 0xc7;
memcpy(aad + 4, hdr->addr1, 3 * ETH_ALEN);
pos = (u8 *) &hdr->seq_ctl;
aad[22] = pos[0] & 0x0f;
aad[23] = 0; /* all bits masked */
memset(aad + 24, 0, 8);
if (a4_included)
memcpy(aad + 24, hdr->addr4, ETH_ALEN);
if (qc_included) {
aad[a4_included ? 30 : 24] = qc;
/* rest of QC masked */
}
/* Start with the first block and AAD */
ieee80211_ccmp_aes_encrypt(tfm, b0, auth);
xor_block(auth, aad, AES_BLOCK_LEN);
ieee80211_ccmp_aes_encrypt(tfm, auth, auth);
xor_block(auth, &aad[AES_BLOCK_LEN], AES_BLOCK_LEN);
ieee80211_ccmp_aes_encrypt(tfm, auth, auth);
b0[0] &= 0x07;
b0[14] = b0[15] = 0;
ieee80211_ccmp_aes_encrypt(tfm, b0, s0);
}
static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
{
struct ieee80211_ccmp_data *key = priv;
int data_len, i;
u8 *pos;
struct ieee80211_hdr_4addr *hdr;
cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
if (skb_headroom(skb) < CCMP_HDR_LEN ||
skb_tailroom(skb) < CCMP_MIC_LEN ||
skb->len < hdr_len)
return -1;
data_len = skb->len - hdr_len;
pos = skb_push(skb, CCMP_HDR_LEN);
memmove(pos, pos + CCMP_HDR_LEN, hdr_len);
pos += hdr_len;
// mic = skb_put(skb, CCMP_MIC_LEN);
i = CCMP_PN_LEN - 1;
while (i >= 0) {
key->tx_pn[i]++;
if (key->tx_pn[i] != 0)
break;
i--;
}
*pos++ = key->tx_pn[5];
*pos++ = key->tx_pn[4];
*pos++ = 0;
*pos++ = (key->key_idx << 6) | (1 << 5) /* Ext IV included */;
*pos++ = key->tx_pn[3];
*pos++ = key->tx_pn[2];
*pos++ = key->tx_pn[1];
*pos++ = key->tx_pn[0];
hdr = (struct ieee80211_hdr_4addr *) skb->data;
if (!tcb_desc->bHwSec)
{
int blocks, last, len;
u8 *mic;
u8 *b0 = key->tx_b0;
u8 *b = key->tx_b;
u8 *e = key->tx_e;
u8 *s0 = key->tx_s0;
//mic is moved to here by john
mic = skb_put(skb, CCMP_MIC_LEN);
ccmp_init_blocks(key->tfm, hdr, key->tx_pn, data_len, b0, b, s0);
blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN;
last = data_len % AES_BLOCK_LEN;
for (i = 1; i <= blocks; i++) {
len = (i == blocks && last) ? last : AES_BLOCK_LEN;
/* Authentication */
xor_block(b, pos, len);
ieee80211_ccmp_aes_encrypt(key->tfm, b, b);
/* Encryption, with counter */
b0[14] = (i >> 8) & 0xff;
b0[15] = i & 0xff;
ieee80211_ccmp_aes_encrypt(key->tfm, b0, e);
xor_block(pos, e, len);
pos += len;
}
for (i = 0; i < CCMP_MIC_LEN; i++)
mic[i] = b[i] ^ s0[i];
}
return 0;
}
static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
{
struct ieee80211_ccmp_data *key = priv;
u8 keyidx, *pos;
struct ieee80211_hdr_4addr *hdr;
cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
u8 pn[6];
if (skb->len < hdr_len + CCMP_HDR_LEN + CCMP_MIC_LEN) {
key->dot11RSNAStatsCCMPFormatErrors++;
return -1;
}
hdr = (struct ieee80211_hdr_4addr *) skb->data;
pos = skb->data + hdr_len;
keyidx = pos[3];
if (!(keyidx & (1 << 5))) {
if (net_ratelimit()) {
printk(KERN_DEBUG "CCMP: received packet without ExtIV"
" flag from " MAC_FMT "\n", MAC_ARG(hdr->addr2));
}
key->dot11RSNAStatsCCMPFormatErrors++;
return -2;
}
keyidx >>= 6;
if (key->key_idx != keyidx) {
printk(KERN_DEBUG "CCMP: RX tkey->key_idx=%d frame "
"keyidx=%d priv=%p\n", key->key_idx, keyidx, priv);
return -6;
}
if (!key->key_set) {
if (net_ratelimit()) {
printk(KERN_DEBUG "CCMP: received packet from " MAC_FMT
" with keyid=%d that does not have a configured"
" key\n", MAC_ARG(hdr->addr2), keyidx);
}
return -3;
}
pn[0] = pos[7];
pn[1] = pos[6];
pn[2] = pos[5];
pn[3] = pos[4];
pn[4] = pos[1];
pn[5] = pos[0];
pos += 8;
if (memcmp(pn, key->rx_pn, CCMP_PN_LEN) <= 0) {
if (net_ratelimit()) {
printk(KERN_DEBUG "CCMP: replay detected: STA=" MAC_FMT
" previous PN %02x%02x%02x%02x%02x%02x "
"received PN %02x%02x%02x%02x%02x%02x\n",
MAC_ARG(hdr->addr2), MAC_ARG(key->rx_pn),
MAC_ARG(pn));
}
key->dot11RSNAStatsCCMPReplays++;
return -4;
}
if (!tcb_desc->bHwSec)
{
size_t data_len = skb->len - hdr_len - CCMP_HDR_LEN - CCMP_MIC_LEN;
u8 *mic = skb->data + skb->len - CCMP_MIC_LEN;
u8 *b0 = key->rx_b0;
u8 *b = key->rx_b;
u8 *a = key->rx_a;
int i, blocks, last, len;
ccmp_init_blocks(key->tfm, hdr, pn, data_len, b0, a, b);
xor_block(mic, b, CCMP_MIC_LEN);
blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN;
last = data_len % AES_BLOCK_LEN;
for (i = 1; i <= blocks; i++) {
len = (i == blocks && last) ? last : AES_BLOCK_LEN;
/* Decrypt, with counter */
b0[14] = (i >> 8) & 0xff;
b0[15] = i & 0xff;
ieee80211_ccmp_aes_encrypt(key->tfm, b0, b);
xor_block(pos, b, len);
/* Authentication */
xor_block(a, pos, len);
ieee80211_ccmp_aes_encrypt(key->tfm, a, a);
pos += len;
}
if (memcmp(mic, a, CCMP_MIC_LEN) != 0) {
if (net_ratelimit()) {
printk(KERN_DEBUG "CCMP: decrypt failed: STA="
MAC_FMT "\n", MAC_ARG(hdr->addr2));
}
key->dot11RSNAStatsCCMPDecryptErrors++;
return -5;
}
memcpy(key->rx_pn, pn, CCMP_PN_LEN);
}
/* Remove hdr and MIC */
memmove(skb->data + CCMP_HDR_LEN, skb->data, hdr_len);
skb_pull(skb, CCMP_HDR_LEN);
skb_trim(skb, skb->len - CCMP_MIC_LEN);
return keyidx;
}
static int ieee80211_ccmp_set_key(void *key, int len, u8 *seq, void *priv)
{
struct ieee80211_ccmp_data *data = priv;
int keyidx;
struct crypto_tfm *tfm = data->tfm;
keyidx = data->key_idx;
memset(data, 0, sizeof(*data));
data->key_idx = keyidx;
data->tfm = tfm;
if (len == CCMP_TK_LEN) {
memcpy(data->key, key, CCMP_TK_LEN);
data->key_set = 1;
if (seq) {
data->rx_pn[0] = seq[5];
data->rx_pn[1] = seq[4];
data->rx_pn[2] = seq[3];
data->rx_pn[3] = seq[2];
data->rx_pn[4] = seq[1];
data->rx_pn[5] = seq[0];
}
crypto_cipher_setkey((void*)data->tfm, data->key, CCMP_TK_LEN);
} else if (len == 0)
data->key_set = 0;
else
return -1;
return 0;
}
static int ieee80211_ccmp_get_key(void *key, int len, u8 *seq, void *priv)
{
struct ieee80211_ccmp_data *data = priv;
if (len < CCMP_TK_LEN)
return -1;
if (!data->key_set)
return 0;
memcpy(key, data->key, CCMP_TK_LEN);
if (seq) {
seq[0] = data->tx_pn[5];
seq[1] = data->tx_pn[4];
seq[2] = data->tx_pn[3];
seq[3] = data->tx_pn[2];
seq[4] = data->tx_pn[1];
seq[5] = data->tx_pn[0];
}
return CCMP_TK_LEN;
}
static char * ieee80211_ccmp_print_stats(char *p, void *priv)
{
struct ieee80211_ccmp_data *ccmp = priv;
p += sprintf(p, "key[%d] alg=CCMP key_set=%d "
"tx_pn=%02x%02x%02x%02x%02x%02x "
"rx_pn=%02x%02x%02x%02x%02x%02x "
"format_errors=%d replays=%d decrypt_errors=%d\n",
ccmp->key_idx, ccmp->key_set,
MAC_ARG(ccmp->tx_pn), MAC_ARG(ccmp->rx_pn),
ccmp->dot11RSNAStatsCCMPFormatErrors,
ccmp->dot11RSNAStatsCCMPReplays,
ccmp->dot11RSNAStatsCCMPDecryptErrors);
return p;
}
void ieee80211_ccmp_null(void)
{
// printk("============>%s()\n", __FUNCTION__);
return;
}
static struct ieee80211_crypto_ops ieee80211_crypt_ccmp = {
.name = "CCMP",
.init = ieee80211_ccmp_init,
.deinit = ieee80211_ccmp_deinit,
.encrypt_mpdu = ieee80211_ccmp_encrypt,
.decrypt_mpdu = ieee80211_ccmp_decrypt,
.encrypt_msdu = NULL,
.decrypt_msdu = NULL,
.set_key = ieee80211_ccmp_set_key,
.get_key = ieee80211_ccmp_get_key,
.print_stats = ieee80211_ccmp_print_stats,
.extra_prefix_len = CCMP_HDR_LEN,
.extra_postfix_len = CCMP_MIC_LEN,
.owner = THIS_MODULE,
};
static int __init ieee80211_crypto_ccmp_init(void)
{
return ieee80211_register_crypto_ops(&ieee80211_crypt_ccmp);
}
static void __exit ieee80211_crypto_ccmp_exit(void)
{
ieee80211_unregister_crypto_ops(&ieee80211_crypt_ccmp);
}
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
EXPORT_SYMBOL(ieee80211_ccmp_null);
#else
EXPORT_SYMBOL_NOVERS(ieee80211_ccmp_null);
#endif
module_init(ieee80211_crypto_ccmp_init);
module_exit(ieee80211_crypto_ccmp_exit);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,397 @@
/*
* Host AP crypt: host-based WEP encryption implementation for Host AP driver
*
* Copyright (c) 2002-2004, Jouni Malinen <jkmaline@cc.hut.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. See README and COPYING for
* more details.
*/
//#include <linux/config.h>
#include <linux/version.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/random.h>
#include <linux/skbuff.h>
#include <asm/string.h>
#include "ieee80211.h"
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,20))
//#include "crypto_compat.h"
#endif
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
#include "rtl_crypto.h"
#else
#include <linux/crypto.h>
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
#include <asm/scatterlist.h>
#else
#include <linux/scatterlist.h>
#endif
//#include <asm/scatterlist.h>
#include <linux/crc32.h>
//
/*
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
#include "rtl_crypto.h"
#else
#include <linux/crypto.h>
#endif
#include <asm/scatterlist.h>
#include <linux/crc32.h>
*/
MODULE_AUTHOR("Jouni Malinen");
MODULE_DESCRIPTION("Host AP crypt: WEP");
MODULE_LICENSE("GPL");
#ifndef OPENSUSE_SLED
#define OPENSUSE_SLED 0
#endif
struct prism2_wep_data {
u32 iv;
#define WEP_KEY_LEN 13
u8 key[WEP_KEY_LEN + 1];
u8 key_len;
u8 key_idx;
#if((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) && (!OPENSUSE_SLED))
struct crypto_tfm *tfm;
#else
struct crypto_blkcipher *tx_tfm;
struct crypto_blkcipher *rx_tfm;
#endif
};
static void * prism2_wep_init(int keyidx)
{
struct prism2_wep_data *priv;
priv = kmalloc(sizeof(*priv), GFP_ATOMIC);
if (priv == NULL)
goto fail;
memset(priv, 0, sizeof(*priv));
priv->key_idx = keyidx;
#if((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) && (!OPENSUSE_SLED))
priv->tfm = crypto_alloc_tfm("arc4", 0);
if (priv->tfm == NULL) {
printk(KERN_DEBUG "ieee80211_crypt_wep: could not allocate "
"crypto API arc4\n");
goto fail;
}
#else
priv->tx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC);
if (IS_ERR(priv->tx_tfm)) {
printk(KERN_DEBUG "ieee80211_crypt_wep: could not allocate "
"crypto API arc4\n");
priv->tx_tfm = NULL;
goto fail;
}
priv->rx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC);
if (IS_ERR(priv->rx_tfm)) {
printk(KERN_DEBUG "ieee80211_crypt_wep: could not allocate "
"crypto API arc4\n");
priv->rx_tfm = NULL;
goto fail;
}
#endif
/* start WEP IV from a random value */
get_random_bytes(&priv->iv, 4);
return priv;
fail:
#if((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) && (!OPENSUSE_SLED))
if (priv) {
if (priv->tfm)
crypto_free_tfm(priv->tfm);
kfree(priv);
}
#else
if (priv) {
if (priv->tx_tfm)
crypto_free_blkcipher(priv->tx_tfm);
if (priv->rx_tfm)
crypto_free_blkcipher(priv->rx_tfm);
kfree(priv);
}
#endif
return NULL;
}
static void prism2_wep_deinit(void *priv)
{
struct prism2_wep_data *_priv = priv;
#if((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) && (!OPENSUSE_SLED))
if (_priv && _priv->tfm)
crypto_free_tfm(_priv->tfm);
#else
if (_priv) {
if (_priv->tx_tfm)
crypto_free_blkcipher(_priv->tx_tfm);
if (_priv->rx_tfm)
crypto_free_blkcipher(_priv->rx_tfm);
}
#endif
kfree(priv);
}
/* Perform WEP encryption on given skb that has at least 4 bytes of headroom
* for IV and 4 bytes of tailroom for ICV. Both IV and ICV will be transmitted,
* so the payload length increases with 8 bytes.
*
* WEP frame payload: IV + TX key idx, RC4(data), ICV = RC4(CRC32(data))
*/
static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
{
struct prism2_wep_data *wep = priv;
u32 klen, len;
u8 key[WEP_KEY_LEN + 3];
u8 *pos;
cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
#if((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)) || (OPENSUSE_SLED))
struct blkcipher_desc desc = {.tfm = wep->tx_tfm};
#endif
u32 crc;
u8 *icv;
struct scatterlist sg;
if (skb_headroom(skb) < 4 || skb_tailroom(skb) < 4 ||
skb->len < hdr_len)
return -1;
len = skb->len - hdr_len;
pos = skb_push(skb, 4);
memmove(pos, pos + 4, hdr_len);
pos += hdr_len;
klen = 3 + wep->key_len;
wep->iv++;
/* Fluhrer, Mantin, and Shamir have reported weaknesses in the key
* scheduling algorithm of RC4. At least IVs (KeyByte + 3, 0xff, N)
* can be used to speedup attacks, so avoid using them. */
if ((wep->iv & 0xff00) == 0xff00) {
u8 B = (wep->iv >> 16) & 0xff;
if (B >= 3 && B < klen)
wep->iv += 0x0100;
}
/* Prepend 24-bit IV to RC4 key and TX frame */
*pos++ = key[0] = (wep->iv >> 16) & 0xff;
*pos++ = key[1] = (wep->iv >> 8) & 0xff;
*pos++ = key[2] = wep->iv & 0xff;
*pos++ = wep->key_idx << 6;
/* Copy rest of the WEP key (the secret part) */
memcpy(key + 3, wep->key, wep->key_len);
if (!tcb_desc->bHwSec)
{
/* Append little-endian CRC32 and encrypt it to produce ICV */
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
crc = ~crc32_le(~0, pos, len);
#else
crc = ~ether_crc_le(len, pos);
#endif
icv = skb_put(skb, 4);
icv[0] = crc;
icv[1] = crc >> 8;
icv[2] = crc >> 16;
icv[3] = crc >> 24;
#if((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) && (!OPENSUSE_SLED))
crypto_cipher_setkey(wep->tfm, key, klen);
sg.page = virt_to_page(pos);
sg.offset = offset_in_page(pos);
sg.length = len + 4;
crypto_cipher_encrypt(wep->tfm, &sg, &sg, len + 4);
return 0;
#else
crypto_blkcipher_setkey(wep->tx_tfm, key, klen);
#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
sg.page = virt_to_page(pos);
sg.offset = offset_in_page(pos);
sg.length = len + 4;
#else
sg_init_one(&sg, pos, len+4);
#endif
return crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4);
#endif
}
return 0;
}
/* Perform WEP decryption on given buffer. Buffer includes whole WEP part of
* the frame: IV (4 bytes), encrypted payload (including SNAP header),
* ICV (4 bytes). len includes both IV and ICV.
*
* Returns 0 if frame was decrypted successfully and ICV was correct and -1 on
* failure. If frame is OK, IV and ICV will be removed.
*/
static int prism2_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
{
struct prism2_wep_data *wep = priv;
u32 klen, plen;
u8 key[WEP_KEY_LEN + 3];
u8 keyidx, *pos;
cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
#if((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)) || (OPENSUSE_SLED))
struct blkcipher_desc desc = {.tfm = wep->rx_tfm};
#endif
u32 crc;
u8 icv[4];
struct scatterlist sg;
if (skb->len < hdr_len + 8)
return -1;
pos = skb->data + hdr_len;
key[0] = *pos++;
key[1] = *pos++;
key[2] = *pos++;
keyidx = *pos++ >> 6;
if (keyidx != wep->key_idx)
return -1;
klen = 3 + wep->key_len;
/* Copy rest of the WEP key (the secret part) */
memcpy(key + 3, wep->key, wep->key_len);
/* Apply RC4 to data and compute CRC32 over decrypted data */
plen = skb->len - hdr_len - 8;
if (!tcb_desc->bHwSec)
{
#if((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) && (!OPENSUSE_SLED))
crypto_cipher_setkey(wep->tfm, key, klen);
sg.page = virt_to_page(pos);
sg.offset = offset_in_page(pos);
sg.length = plen + 4;
crypto_cipher_decrypt(wep->tfm, &sg, &sg, plen + 4);
#else
crypto_blkcipher_setkey(wep->rx_tfm, key, klen);
#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
sg.page = virt_to_page(pos);
sg.offset = offset_in_page(pos);
sg.length = plen + 4;
#else
sg_init_one(&sg, pos, plen+4);
#endif
if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4))
return -7;
#endif
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
crc = ~crc32_le(~0, pos, plen);
#else
crc = ~ether_crc_le(plen, pos);
#endif
icv[0] = crc;
icv[1] = crc >> 8;
icv[2] = crc >> 16;
icv[3] = crc >> 24;
if (memcmp(icv, pos + plen, 4) != 0) {
/* ICV mismatch - drop frame */
return -2;
}
}
/* Remove IV and ICV */
memmove(skb->data + 4, skb->data, hdr_len);
skb_pull(skb, 4);
skb_trim(skb, skb->len - 4);
return 0;
}
static int prism2_wep_set_key(void *key, int len, u8 *seq, void *priv)
{
struct prism2_wep_data *wep = priv;
if (len < 0 || len > WEP_KEY_LEN)
return -1;
memcpy(wep->key, key, len);
wep->key_len = len;
return 0;
}
static int prism2_wep_get_key(void *key, int len, u8 *seq, void *priv)
{
struct prism2_wep_data *wep = priv;
if (len < wep->key_len)
return -1;
memcpy(key, wep->key, wep->key_len);
return wep->key_len;
}
static char * prism2_wep_print_stats(char *p, void *priv)
{
struct prism2_wep_data *wep = priv;
p += sprintf(p, "key[%d] alg=WEP len=%d\n",
wep->key_idx, wep->key_len);
return p;
}
static struct ieee80211_crypto_ops ieee80211_crypt_wep = {
.name = "WEP",
.init = prism2_wep_init,
.deinit = prism2_wep_deinit,
.encrypt_mpdu = prism2_wep_encrypt,
.decrypt_mpdu = prism2_wep_decrypt,
.encrypt_msdu = NULL,
.decrypt_msdu = NULL,
.set_key = prism2_wep_set_key,
.get_key = prism2_wep_get_key,
.print_stats = prism2_wep_print_stats,
.extra_prefix_len = 4, /* IV */
.extra_postfix_len = 4, /* ICV */
.owner = THIS_MODULE,
};
static int __init ieee80211_crypto_wep_init(void)
{
return ieee80211_register_crypto_ops(&ieee80211_crypt_wep);
}
static void __exit ieee80211_crypto_wep_exit(void)
{
ieee80211_unregister_crypto_ops(&ieee80211_crypt_wep);
}
void ieee80211_wep_null(void)
{
// printk("============>%s()\n", __FUNCTION__);
return;
}
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
EXPORT_SYMBOL(ieee80211_wep_null);
#else
EXPORT_SYMBOL_NOVERS(ieee80211_wep_null);
#endif
module_init(ieee80211_crypto_wep_init);
module_exit(ieee80211_crypto_wep_exit);

View File

@ -0,0 +1,394 @@
/*******************************************************************************
Copyright(c) 2004 Intel Corporation. All rights reserved.
Portions of this file are based on the WEP enablement code provided by the
Host AP project hostap-drivers v0.1.3
Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
<jkmaline@cc.hut.fi>
Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
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 <ipw2100-admin@linux.intel.com>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/
#include <linux/compiler.h>
//#include <linux/config.h>
#include <linux/errno.h>
#include <linux/if_arp.h>
#include <linux/in6.h>
#include <linux/in.h>
#include <linux/ip.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/pci.h>
#include <linux/proc_fs.h>
#include <linux/skbuff.h>
#include <linux/slab.h>
#include <linux/tcp.h>
#include <linux/types.h>
#include <linux/version.h>
#include <linux/wireless.h>
#include <linux/etherdevice.h>
#include <asm/uaccess.h>
#include <net/arp.h>
#include "ieee80211.h"
MODULE_DESCRIPTION("802.11 data/management/control stack");
MODULE_AUTHOR("Copyright (C) 2004 Intel Corporation <jketreno@linux.intel.com>");
MODULE_LICENSE("GPL");
#define DRV_NAME "ieee80211"
static inline int ieee80211_networks_allocate(struct ieee80211_device *ieee)
{
if (ieee->networks)
return 0;
ieee->networks = kmalloc(
MAX_NETWORK_COUNT * sizeof(struct ieee80211_network),
GFP_KERNEL);
if (!ieee->networks) {
printk(KERN_WARNING "%s: Out of memory allocating beacons\n",
ieee->dev->name);
return -ENOMEM;
}
memset(ieee->networks, 0,
MAX_NETWORK_COUNT * sizeof(struct ieee80211_network));
return 0;
}
static inline void ieee80211_networks_free(struct ieee80211_device *ieee)
{
if (!ieee->networks)
return;
kfree(ieee->networks);
ieee->networks = NULL;
}
static inline void ieee80211_networks_initialize(struct ieee80211_device *ieee)
{
int i;
INIT_LIST_HEAD(&ieee->network_free_list);
INIT_LIST_HEAD(&ieee->network_list);
for (i = 0; i < MAX_NETWORK_COUNT; i++)
list_add_tail(&ieee->networks[i].list, &ieee->network_free_list);
}
struct net_device *alloc_ieee80211(int sizeof_priv)
{
struct ieee80211_device *ieee;
struct net_device *dev;
int i,err;
IEEE80211_DEBUG_INFO("Initializing...\n");
dev = alloc_etherdev(sizeof(struct ieee80211_device) + sizeof_priv);
if (!dev) {
IEEE80211_ERROR("Unable to network device.\n");
goto failed;
}
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0))
ieee = netdev_priv(dev);
#else
ieee = (struct ieee80211_device *)dev->priv;
#endif
dev->hard_start_xmit = ieee80211_xmit;
memset(ieee, 0, sizeof(struct ieee80211_device)+sizeof_priv);
ieee->dev = dev;
err = ieee80211_networks_allocate(ieee);
if (err) {
IEEE80211_ERROR("Unable to allocate beacon storage: %d\n",
err);
goto failed;
}
ieee80211_networks_initialize(ieee);
/* Default fragmentation threshold is maximum payload size */
ieee->fts = DEFAULT_FTS;
ieee->scan_age = DEFAULT_MAX_SCAN_AGE;
ieee->open_wep = 1;
/* Default to enabling full open WEP with host based encrypt/decrypt */
ieee->host_encrypt = 1;
ieee->host_decrypt = 1;
ieee->ieee802_1x = 1; /* Default to supporting 802.1x */
INIT_LIST_HEAD(&ieee->crypt_deinit_list);
init_timer(&ieee->crypt_deinit_timer);
ieee->crypt_deinit_timer.data = (unsigned long)ieee;
ieee->crypt_deinit_timer.function = ieee80211_crypt_deinit_handler;
spin_lock_init(&ieee->lock);
spin_lock_init(&ieee->wpax_suitlist_lock);
spin_lock_init(&ieee->bw_spinlock);
spin_lock_init(&ieee->reorder_spinlock);
//added by WB
atomic_set(&(ieee->atm_chnlop), 0);
atomic_set(&(ieee->atm_swbw), 0);
ieee->wpax_type_set = 0;
ieee->wpa_enabled = 0;
ieee->tkip_countermeasures = 0;
ieee->drop_unencrypted = 0;
ieee->privacy_invoked = 0;
ieee->ieee802_1x = 1;
ieee->raw_tx = 0;
//ieee->hwsec_support = 1; //defalt support hw security. //use module_param instead.
ieee->hwsec_active = 0; //disable hwsec, switch it on when necessary.
ieee80211_softmac_init(ieee);
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13))
ieee->pHTInfo = (RT_HIGH_THROUGHPUT*)kzalloc(sizeof(RT_HIGH_THROUGHPUT), GFP_KERNEL);
#else
ieee->pHTInfo = (RT_HIGH_THROUGHPUT*)kmalloc(sizeof(RT_HIGH_THROUGHPUT), GFP_KERNEL);
memset(ieee->pHTInfo,0,sizeof(RT_HIGH_THROUGHPUT));
#endif
if (ieee->pHTInfo == NULL)
{
IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc memory for HTInfo\n");
return NULL;
}
HTUpdateDefaultSetting(ieee);
HTInitializeHTInfo(ieee); //may move to other place.
TSInitialize(ieee);
#if 0
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
INIT_WORK(&ieee->ht_onAssRsp, (void(*)(void*)) HTOnAssocRsp_wq);
#else
INIT_WORK(&ieee->ht_onAssRsp, (void(*)(void*)) HTOnAssocRsp_wq, ieee);
#endif
#endif
for (i = 0; i < IEEE_IBSS_MAC_HASH_SIZE; i++)
INIT_LIST_HEAD(&ieee->ibss_mac_hash[i]);
for (i = 0; i < 17; i++) {
ieee->last_rxseq_num[i] = -1;
ieee->last_rxfrag_num[i] = -1;
ieee->last_packet_time[i] = 0;
}
//These function were added to load crypte module autoly
ieee80211_tkip_null();
ieee80211_wep_null();
ieee80211_ccmp_null();
return dev;
failed:
if (dev)
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0))
free_netdev(dev);
#else
kfree(dev);
#endif
return NULL;
}
void free_ieee80211(struct net_device *dev)
{
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0))
struct ieee80211_device *ieee = netdev_priv(dev);
#else
struct ieee80211_device *ieee = (struct ieee80211_device *)dev->priv;
#endif
int i;
//struct list_head *p, *q;
// del_timer_sync(&ieee->SwBwTimer);
#if 1
if (ieee->pHTInfo != NULL)
{
kfree(ieee->pHTInfo);
ieee->pHTInfo = NULL;
}
#endif
RemoveAllTS(ieee);
ieee80211_softmac_free(ieee);
del_timer_sync(&ieee->crypt_deinit_timer);
ieee80211_crypt_deinit_entries(ieee, 1);
for (i = 0; i < WEP_KEYS; i++) {
struct ieee80211_crypt_data *crypt = ieee->crypt[i];
if (crypt) {
if (crypt->ops) {
crypt->ops->deinit(crypt->priv);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
module_put(crypt->ops->owner);
#else
__MOD_DEC_USE_COUNT(crypt->ops->owner);
#endif
}
kfree(crypt);
ieee->crypt[i] = NULL;
}
}
ieee80211_networks_free(ieee);
#if 0
for (i = 0; i < IEEE_IBSS_MAC_HASH_SIZE; i++) {
list_for_each_safe(p, q, &ieee->ibss_mac_hash[i]) {
kfree(list_entry(p, struct ieee_ibss_seq, list));
list_del(p);
}
}
#endif
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0))
free_netdev(dev);
#else
kfree(dev);
#endif
}
#ifdef CONFIG_IEEE80211_DEBUG
u32 ieee80211_debug_level = 0;
static int debug = \
// IEEE80211_DL_INFO |
// IEEE80211_DL_WX |
// IEEE80211_DL_SCAN |
// IEEE80211_DL_STATE |
// IEEE80211_DL_MGMT |
// IEEE80211_DL_FRAG |
// IEEE80211_DL_EAP |
// IEEE80211_DL_DROP |
// IEEE80211_DL_TX |
// IEEE80211_DL_RX |
//IEEE80211_DL_QOS |
// IEEE80211_DL_HT |
// IEEE80211_DL_TS |
// IEEE80211_DL_BA |
// IEEE80211_DL_REORDER|
// IEEE80211_DL_TRACE |
//IEEE80211_DL_DATA |
IEEE80211_DL_ERR //awayls open this flags to show error out
;
struct proc_dir_entry *ieee80211_proc = NULL;
static int show_debug_level(char *page, char **start, off_t offset,
int count, int *eof, void *data)
{
return snprintf(page, count, "0x%08X\n", ieee80211_debug_level);
}
static int store_debug_level(struct file *file, const char *buffer,
unsigned long count, void *data)
{
char buf[] = "0x00000000";
unsigned long len = min(sizeof(buf) - 1, (u32)count);
char *p = (char *)buf;
unsigned long val;
if (copy_from_user(buf, buffer, len))
return count;
buf[len] = 0;
if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') {
p++;
if (p[0] == 'x' || p[0] == 'X')
p++;
val = simple_strtoul(p, &p, 16);
} else
val = simple_strtoul(p, &p, 10);
if (p == buf)
printk(KERN_INFO DRV_NAME
": %s is not in hex or decimal form.\n", buf);
else
ieee80211_debug_level = val;
return strnlen(buf, count);
}
static int __init ieee80211_init(void)
{
struct proc_dir_entry *e;
ieee80211_debug_level = debug;
#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
ieee80211_proc = create_proc_entry(DRV_NAME, S_IFDIR, proc_net);
#else
ieee80211_proc = create_proc_entry(DRV_NAME, S_IFDIR, init_net.proc_net);
#endif
if (ieee80211_proc == NULL) {
IEEE80211_ERROR("Unable to create " DRV_NAME
" proc directory\n");
return -EIO;
}
e = create_proc_entry("debug_level", S_IFREG | S_IRUGO | S_IWUSR,
ieee80211_proc);
if (!e) {
#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
remove_proc_entry(DRV_NAME, proc_net);
#else
remove_proc_entry(DRV_NAME, init_net.proc_net);
#endif
ieee80211_proc = NULL;
return -EIO;
}
e->read_proc = show_debug_level;
e->write_proc = store_debug_level;
e->data = NULL;
return 0;
}
static void __exit ieee80211_exit(void)
{
if (ieee80211_proc) {
remove_proc_entry("debug_level", ieee80211_proc);
#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
remove_proc_entry(DRV_NAME, proc_net);
#else
remove_proc_entry(DRV_NAME, init_net.proc_net);
#endif
ieee80211_proc = NULL;
}
}
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
#include <linux/moduleparam.h>
module_param(debug, int, 0444);
MODULE_PARM_DESC(debug, "debug output mask");
module_exit(ieee80211_exit);
module_init(ieee80211_init);
#endif
#endif
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
EXPORT_SYMBOL(alloc_ieee80211);
EXPORT_SYMBOL(free_ieee80211);
#else
EXPORT_SYMBOL_NOVERS(alloc_ieee80211);
EXPORT_SYMBOL_NOVERS(free_ieee80211);
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,693 @@
/* IEEE 802.11 SoftMAC layer
* Copyright (c) 2005 Andrea Merello <andreamrl@tiscali.it>
*
* Mostly extracted from the rtl8180-sa2400 driver for the
* in-kernel generic ieee802.11 stack.
*
* Some pieces of code might be stolen from ipw2100 driver
* copyright of who own it's copyright ;-)
*
* PS wx handler mostly stolen from hostap, copyright who
* own it's copyright ;-)
*
* released under the GPL
*/
#include "ieee80211.h"
#ifdef ENABLE_DOT11D
#include "dot11d.h"
#endif
/* FIXME: add A freqs */
const long ieee80211_wlan_frequencies[] = {
2412, 2417, 2422, 2427,
2432, 2437, 2442, 2447,
2452, 2457, 2462, 2467,
2472, 2484
};
int ieee80211_wx_set_freq(struct ieee80211_device *ieee, struct iw_request_info *a,
union iwreq_data *wrqu, char *b)
{
int ret;
struct iw_freq *fwrq = & wrqu->freq;
down(&ieee->wx_sem);
if(ieee->iw_mode == IW_MODE_INFRA){
ret = -EOPNOTSUPP;
goto out;
}
/* if setting by freq convert to channel */
if (fwrq->e == 1) {
if ((fwrq->m >= (int) 2.412e8 &&
fwrq->m <= (int) 2.487e8)) {
int f = fwrq->m / 100000;
int c = 0;
while ((c < 14) && (f != ieee80211_wlan_frequencies[c]))
c++;
/* hack to fall through */
fwrq->e = 0;
fwrq->m = c + 1;
}
}
if (fwrq->e > 0 || fwrq->m > 14 || fwrq->m < 1 ){
ret = -EOPNOTSUPP;
goto out;
}else { /* Set the channel */
#ifdef ENABLE_DOT11D
if (!(GET_DOT11D_INFO(ieee)->channel_map)[fwrq->m]) {
ret = -EINVAL;
goto out;
}
#endif
ieee->current_network.channel = fwrq->m;
ieee->set_chan(ieee->dev, ieee->current_network.channel);
if(ieee->iw_mode == IW_MODE_ADHOC || ieee->iw_mode == IW_MODE_MASTER)
if(ieee->state == IEEE80211_LINKED){
ieee80211_stop_send_beacons(ieee);
ieee80211_start_send_beacons(ieee);
}
}
ret = 0;
out:
up(&ieee->wx_sem);
return ret;
}
int ieee80211_wx_get_freq(struct ieee80211_device *ieee,
struct iw_request_info *a,
union iwreq_data *wrqu, char *b)
{
struct iw_freq *fwrq = & wrqu->freq;
if (ieee->current_network.channel == 0)
return -1;
//NM 0.7.0 will not accept channel any more.
fwrq->m = ieee80211_wlan_frequencies[ieee->current_network.channel-1] * 100000;
fwrq->e = 1;
// fwrq->m = ieee->current_network.channel;
// fwrq->e = 0;
return 0;
}
int ieee80211_wx_get_wap(struct ieee80211_device *ieee,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
unsigned long flags;
wrqu->ap_addr.sa_family = ARPHRD_ETHER;
if (ieee->iw_mode == IW_MODE_MONITOR)
return -1;
/* We want avoid to give to the user inconsistent infos*/
spin_lock_irqsave(&ieee->lock, flags);
if (ieee->state != IEEE80211_LINKED &&
ieee->state != IEEE80211_LINKED_SCANNING &&
ieee->wap_set == 0)
memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
else
memcpy(wrqu->ap_addr.sa_data,
ieee->current_network.bssid, ETH_ALEN);
spin_unlock_irqrestore(&ieee->lock, flags);
return 0;
}
int ieee80211_wx_set_wap(struct ieee80211_device *ieee,
struct iw_request_info *info,
union iwreq_data *awrq,
char *extra)
{
int ret = 0;
u8 zero[] = {0,0,0,0,0,0};
unsigned long flags;
short ifup = ieee->proto_started;//dev->flags & IFF_UP;
struct sockaddr *temp = (struct sockaddr *)awrq;
ieee->sync_scan_hurryup = 1;
down(&ieee->wx_sem);
/* use ifconfig hw ether */
if (ieee->iw_mode == IW_MODE_MASTER){
ret = -1;
goto out;
}
if (temp->sa_family != ARPHRD_ETHER){
ret = -EINVAL;
goto out;
}
if (ifup)
ieee80211_stop_protocol(ieee);
/* just to avoid to give inconsistent infos in the
* get wx method. not really needed otherwise
*/
spin_lock_irqsave(&ieee->lock, flags);
memcpy(ieee->current_network.bssid, temp->sa_data, ETH_ALEN);
ieee->wap_set = memcmp(temp->sa_data, zero,ETH_ALEN)!=0;
spin_unlock_irqrestore(&ieee->lock, flags);
if (ifup)
ieee80211_start_protocol(ieee);
out:
up(&ieee->wx_sem);
return ret;
}
int ieee80211_wx_get_essid(struct ieee80211_device *ieee, struct iw_request_info *a,union iwreq_data *wrqu,char *b)
{
int len,ret = 0;
unsigned long flags;
if (ieee->iw_mode == IW_MODE_MONITOR)
return -1;
/* We want avoid to give to the user inconsistent infos*/
spin_lock_irqsave(&ieee->lock, flags);
if (ieee->current_network.ssid[0] == '\0' ||
ieee->current_network.ssid_len == 0){
ret = -1;
goto out;
}
if (ieee->state != IEEE80211_LINKED &&
ieee->state != IEEE80211_LINKED_SCANNING &&
ieee->ssid_set == 0){
ret = -1;
goto out;
}
len = ieee->current_network.ssid_len;
wrqu->essid.length = len;
strncpy(b,ieee->current_network.ssid,len);
wrqu->essid.flags = 1;
out:
spin_unlock_irqrestore(&ieee->lock, flags);
return ret;
}
int ieee80211_wx_set_rate(struct ieee80211_device *ieee,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
u32 target_rate = wrqu->bitrate.value;
ieee->rate = target_rate/100000;
//FIXME: we might want to limit rate also in management protocols.
return 0;
}
int ieee80211_wx_get_rate(struct ieee80211_device *ieee,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
u32 tmp_rate;
#if 0
printk("===>mode:%d, halfNmode:%d\n", ieee->mode, ieee->bHalfWirelessN24GMode);
if (ieee->mode & (IEEE_A | IEEE_B | IEEE_G))
tmp_rate = ieee->rate;
else if (ieee->mode & IEEE_N_5G)
tmp_rate = 580;
else if (ieee->mode & IEEE_N_24G)
{
if (ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev))
tmp_rate = HTHalfMcsToDataRate(ieee, 15);
else
tmp_rate = HTMcsToDataRate(ieee, 15);
}
#else
tmp_rate = TxCountToDataRate(ieee, ieee->softmac_stats.CurrentShowTxate);
#endif
wrqu->bitrate.value = tmp_rate * 500000;
return 0;
}
int ieee80211_wx_set_rts(struct ieee80211_device *ieee,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
if (wrqu->rts.disabled || !wrqu->rts.fixed)
ieee->rts = DEFAULT_RTS_THRESHOLD;
else
{
if (wrqu->rts.value < MIN_RTS_THRESHOLD ||
wrqu->rts.value > MAX_RTS_THRESHOLD)
return -EINVAL;
ieee->rts = wrqu->rts.value;
}
return 0;
}
int ieee80211_wx_get_rts(struct ieee80211_device *ieee,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
wrqu->rts.value = ieee->rts;
wrqu->rts.fixed = 0; /* no auto select */
wrqu->rts.disabled = (wrqu->rts.value == DEFAULT_RTS_THRESHOLD);
return 0;
}
int ieee80211_wx_set_mode(struct ieee80211_device *ieee, struct iw_request_info *a,
union iwreq_data *wrqu, char *b)
{
ieee->sync_scan_hurryup = 1;
down(&ieee->wx_sem);
if (wrqu->mode == ieee->iw_mode)
goto out;
if (wrqu->mode == IW_MODE_MONITOR){
ieee->dev->type = ARPHRD_IEEE80211;
}else{
ieee->dev->type = ARPHRD_ETHER;
}
if (!ieee->proto_started){
ieee->iw_mode = wrqu->mode;
}else{
ieee80211_stop_protocol(ieee);
ieee->iw_mode = wrqu->mode;
ieee80211_start_protocol(ieee);
}
out:
up(&ieee->wx_sem);
return 0;
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
void ieee80211_wx_sync_scan_wq(struct work_struct *work)
{
struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, wx_sync_scan_wq);
#else
void ieee80211_wx_sync_scan_wq(struct ieee80211_device *ieee)
{
#endif
short chan;
HT_EXTCHNL_OFFSET chan_offset=0;
HT_CHANNEL_WIDTH bandwidth=0;
int b40M = 0;
static int count = 0;
chan = ieee->current_network.channel;
netif_carrier_off(ieee->dev);
if (ieee->data_hard_stop)
ieee->data_hard_stop(ieee->dev);
ieee80211_stop_send_beacons(ieee);
ieee->state = IEEE80211_LINKED_SCANNING;
ieee->link_change(ieee->dev);
ieee->InitialGainHandler(ieee->dev,IG_Backup);
if (ieee->pHTInfo->bCurrentHTSupport && ieee->pHTInfo->bEnableHT && ieee->pHTInfo->bCurBW40MHz) {
b40M = 1;
chan_offset = ieee->pHTInfo->CurSTAExtChnlOffset;
bandwidth = (HT_CHANNEL_WIDTH)ieee->pHTInfo->bCurBW40MHz;
printk("Scan in 40M, force to 20M first:%d, %d\n", chan_offset, bandwidth);
ieee->SetBWModeHandler(ieee->dev, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
}
ieee80211_start_scan_syncro(ieee);
if (b40M) {
printk("Scan in 20M, back to 40M\n");
if (chan_offset == HT_EXTCHNL_OFFSET_UPPER)
ieee->set_chan(ieee->dev, chan + 2);
else if (chan_offset == HT_EXTCHNL_OFFSET_LOWER)
ieee->set_chan(ieee->dev, chan - 2);
else
ieee->set_chan(ieee->dev, chan);
ieee->SetBWModeHandler(ieee->dev, bandwidth, chan_offset);
} else {
ieee->set_chan(ieee->dev, chan);
}
ieee->InitialGainHandler(ieee->dev,IG_Restore);
ieee->state = IEEE80211_LINKED;
ieee->link_change(ieee->dev);
// To prevent the immediately calling watch_dog after scan.
if(ieee->LinkDetectInfo.NumRecvBcnInPeriod==0||ieee->LinkDetectInfo.NumRecvDataInPeriod==0 )
{
ieee->LinkDetectInfo.NumRecvBcnInPeriod = 1;
ieee->LinkDetectInfo.NumRecvDataInPeriod= 1;
}
if (ieee->data_hard_resume)
ieee->data_hard_resume(ieee->dev);
if(ieee->iw_mode == IW_MODE_ADHOC || ieee->iw_mode == IW_MODE_MASTER)
ieee80211_start_send_beacons(ieee);
netif_carrier_on(ieee->dev);
count = 0;
up(&ieee->wx_sem);
}
int ieee80211_wx_set_scan(struct ieee80211_device *ieee, struct iw_request_info *a,
union iwreq_data *wrqu, char *b)
{
int ret = 0;
down(&ieee->wx_sem);
if (ieee->iw_mode == IW_MODE_MONITOR || !(ieee->proto_started)){
ret = -1;
goto out;
}
if ( ieee->state == IEEE80211_LINKED){
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
queue_work(ieee->wq, &ieee->wx_sync_scan_wq);
#else
schedule_task(&ieee->wx_sync_scan_wq);
#endif
/* intentionally forget to up sem */
return 0;
}
out:
up(&ieee->wx_sem);
return ret;
}
int ieee80211_wx_set_essid(struct ieee80211_device *ieee,
struct iw_request_info *a,
union iwreq_data *wrqu, char *extra)
{
int ret=0,len;
short proto_started;
unsigned long flags;
ieee->sync_scan_hurryup = 1;
down(&ieee->wx_sem);
proto_started = ieee->proto_started;
if (wrqu->essid.length > IW_ESSID_MAX_SIZE){
ret= -E2BIG;
goto out;
}
if (ieee->iw_mode == IW_MODE_MONITOR){
ret= -1;
goto out;
}
if(proto_started)
ieee80211_stop_protocol(ieee);
/* this is just to be sure that the GET wx callback
* has consisten infos. not needed otherwise
*/
spin_lock_irqsave(&ieee->lock, flags);
if (wrqu->essid.flags && wrqu->essid.length) {
//first flush current network.ssid
len = ((wrqu->essid.length-1) < IW_ESSID_MAX_SIZE) ? (wrqu->essid.length-1) : IW_ESSID_MAX_SIZE;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
strncpy(ieee->current_network.ssid, extra, len);
ieee->current_network.ssid_len = len;
#if 0
{
int i;
for (i=0; i<len; i++)
printk("%c ", extra[i]);
printk("\n");
}
#endif
#else
strncpy(ieee->current_network.ssid, extra, len+1);
ieee->current_network.ssid_len = len+1;
#if 0
{
int i;
for (i=0; i<len + 1; i++)
printk("%c ", extra[i]);
printk("\n");
}
#endif
#endif
ieee->ssid_set = 1;
}
else{
ieee->ssid_set = 0;
ieee->current_network.ssid[0] = '\0';
ieee->current_network.ssid_len = 0;
}
spin_unlock_irqrestore(&ieee->lock, flags);
if (proto_started)
ieee80211_start_protocol(ieee);
out:
up(&ieee->wx_sem);
return ret;
}
int ieee80211_wx_get_mode(struct ieee80211_device *ieee, struct iw_request_info *a,
union iwreq_data *wrqu, char *b)
{
wrqu->mode = ieee->iw_mode;
return 0;
}
int ieee80211_wx_set_rawtx(struct ieee80211_device *ieee,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
int *parms = (int *)extra;
int enable = (parms[0] > 0);
short prev = ieee->raw_tx;
down(&ieee->wx_sem);
if(enable)
ieee->raw_tx = 1;
else
ieee->raw_tx = 0;
printk(KERN_INFO"raw TX is %s\n",
ieee->raw_tx ? "enabled" : "disabled");
if(ieee->iw_mode == IW_MODE_MONITOR)
{
if(prev == 0 && ieee->raw_tx){
if (ieee->data_hard_resume)
ieee->data_hard_resume(ieee->dev);
netif_carrier_on(ieee->dev);
}
if(prev && ieee->raw_tx == 1)
netif_carrier_off(ieee->dev);
}
up(&ieee->wx_sem);
return 0;
}
int ieee80211_wx_get_name(struct ieee80211_device *ieee,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
strcpy(wrqu->name, "802.11");
if(ieee->modulation & IEEE80211_CCK_MODULATION){
strcat(wrqu->name, "b");
if(ieee->modulation & IEEE80211_OFDM_MODULATION)
strcat(wrqu->name, "/g");
}else if(ieee->modulation & IEEE80211_OFDM_MODULATION)
strcat(wrqu->name, "g");
if (ieee->mode & (IEEE_N_24G | IEEE_N_5G))
strcat(wrqu->name, "/n");
if((ieee->state == IEEE80211_LINKED) ||
(ieee->state == IEEE80211_LINKED_SCANNING))
strcat(wrqu->name," linked");
else if(ieee->state != IEEE80211_NOLINK)
strcat(wrqu->name," link..");
return 0;
}
/* this is mostly stolen from hostap */
int ieee80211_wx_set_power(struct ieee80211_device *ieee,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
int ret = 0;
#if 0
if(
(!ieee->sta_wake_up) ||
(!ieee->ps_request_tx_ack) ||
(!ieee->enter_sleep_state) ||
(!ieee->ps_is_queue_empty)){
// printk("ERROR. PS mode is tryied to be use but driver missed a callback\n\n");
return -1;
}
#endif
down(&ieee->wx_sem);
if (wrqu->power.disabled){
ieee->ps = IEEE80211_PS_DISABLED;
goto exit;
}
if (wrqu->power.flags & IW_POWER_TIMEOUT) {
//ieee->ps_period = wrqu->power.value / 1000;
ieee->ps_timeout = wrqu->power.value / 1000;
}
if (wrqu->power.flags & IW_POWER_PERIOD) {
//ieee->ps_timeout = wrqu->power.value / 1000;
ieee->ps_period = wrqu->power.value / 1000;
//wrq->value / 1024;
}
switch (wrqu->power.flags & IW_POWER_MODE) {
case IW_POWER_UNICAST_R:
ieee->ps = IEEE80211_PS_UNICAST;
break;
case IW_POWER_MULTICAST_R:
ieee->ps = IEEE80211_PS_MBCAST;
break;
case IW_POWER_ALL_R:
ieee->ps = IEEE80211_PS_UNICAST | IEEE80211_PS_MBCAST;
break;
case IW_POWER_ON:
// ieee->ps = IEEE80211_PS_DISABLED;
break;
default:
ret = -EINVAL;
goto exit;
}
exit:
up(&ieee->wx_sem);
return ret;
}
/* this is stolen from hostap */
int ieee80211_wx_get_power(struct ieee80211_device *ieee,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
int ret =0;
down(&ieee->wx_sem);
if(ieee->ps == IEEE80211_PS_DISABLED){
wrqu->power.disabled = 1;
goto exit;
}
wrqu->power.disabled = 0;
if ((wrqu->power.flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
wrqu->power.flags = IW_POWER_TIMEOUT;
wrqu->power.value = ieee->ps_timeout * 1000;
} else {
// ret = -EOPNOTSUPP;
// goto exit;
wrqu->power.flags = IW_POWER_PERIOD;
wrqu->power.value = ieee->ps_period * 1000;
//ieee->current_network.dtim_period * ieee->current_network.beacon_interval * 1024;
}
if ((ieee->ps & (IEEE80211_PS_MBCAST | IEEE80211_PS_UNICAST)) == (IEEE80211_PS_MBCAST | IEEE80211_PS_UNICAST))
wrqu->power.flags |= IW_POWER_ALL_R;
else if (ieee->ps & IEEE80211_PS_MBCAST)
wrqu->power.flags |= IW_POWER_MULTICAST_R;
else
wrqu->power.flags |= IW_POWER_UNICAST_R;
exit:
up(&ieee->wx_sem);
return ret;
}
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
EXPORT_SYMBOL(ieee80211_wx_get_essid);
EXPORT_SYMBOL(ieee80211_wx_set_essid);
EXPORT_SYMBOL(ieee80211_wx_set_rate);
EXPORT_SYMBOL(ieee80211_wx_get_rate);
EXPORT_SYMBOL(ieee80211_wx_set_wap);
EXPORT_SYMBOL(ieee80211_wx_get_wap);
EXPORT_SYMBOL(ieee80211_wx_set_mode);
EXPORT_SYMBOL(ieee80211_wx_get_mode);
EXPORT_SYMBOL(ieee80211_wx_set_scan);
EXPORT_SYMBOL(ieee80211_wx_get_freq);
EXPORT_SYMBOL(ieee80211_wx_set_freq);
EXPORT_SYMBOL(ieee80211_wx_set_rawtx);
EXPORT_SYMBOL(ieee80211_wx_get_name);
EXPORT_SYMBOL(ieee80211_wx_set_power);
EXPORT_SYMBOL(ieee80211_wx_get_power);
EXPORT_SYMBOL(ieee80211_wlan_frequencies);
EXPORT_SYMBOL(ieee80211_wx_set_rts);
EXPORT_SYMBOL(ieee80211_wx_get_rts);
#else
EXPORT_SYMBOL_NOVERS(ieee80211_wx_get_essid);
EXPORT_SYMBOL_NOVERS(ieee80211_wx_set_essid);
EXPORT_SYMBOL_NOVERS(ieee80211_wx_set_rate);
EXPORT_SYMBOL_NOVERS(ieee80211_wx_get_rate);
EXPORT_SYMBOL_NOVERS(ieee80211_wx_set_wap);
EXPORT_SYMBOL_NOVERS(ieee80211_wx_get_wap);
EXPORT_SYMBOL_NOVERS(ieee80211_wx_set_mode);
EXPORT_SYMBOL_NOVERS(ieee80211_wx_get_mode);
EXPORT_SYMBOL_NOVERS(ieee80211_wx_set_scan);
EXPORT_SYMBOL_NOVERS(ieee80211_wx_get_freq);
EXPORT_SYMBOL_NOVERS(ieee80211_wx_set_freq);
EXPORT_SYMBOL_NOVERS(ieee80211_wx_set_rawtx);
EXPORT_SYMBOL_NOVERS(ieee80211_wx_get_name);
EXPORT_SYMBOL_NOVERS(ieee80211_wx_set_power);
EXPORT_SYMBOL_NOVERS(ieee80211_wx_get_power);
EXPORT_SYMBOL_NOVERS(ieee80211_wlan_frequencies);
EXPORT_SYMBOL_NOVERS(ieee80211_wx_set_rts);
EXPORT_SYMBOL_NOVERS(ieee80211_wx_get_rts);
#endif

View File

@ -0,0 +1,929 @@
/******************************************************************************
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 <ipw2100-admin@linux.intel.com>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
******************************************************************************
Few modifications for Realtek's Wi-Fi drivers by
Andrea Merello <andreamrl@tiscali.it>
A special thanks goes to Realtek for their support !
******************************************************************************/
#include <linux/compiler.h>
//#include <linux/config.h>
#include <linux/errno.h>
#include <linux/if_arp.h>
#include <linux/in6.h>
#include <linux/in.h>
#include <linux/ip.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/pci.h>
#include <linux/proc_fs.h>
#include <linux/skbuff.h>
#include <linux/slab.h>
#include <linux/tcp.h>
#include <linux/types.h>
#include <linux/version.h>
#include <linux/wireless.h>
#include <linux/etherdevice.h>
#include <asm/uaccess.h>
#include <linux/if_vlan.h>
#include "ieee80211.h"
/*
802.11 Data Frame
802.11 frame_contorl for data frames - 2 bytes
,-----------------------------------------------------------------------------------------.
bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | a | b | c | d | e |
|----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|------|
val | 0 | 0 | 0 | 1 | x | 0 | 0 | 0 | 1 | 0 | x | x | x | x | x |
|----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|------|
desc | ^-ver-^ | ^type-^ | ^-----subtype-----^ | to |from |more |retry| pwr |more |wep |
| | | x=0 data,x=1 data+ack | DS | DS |frag | | mgm |data | |
'-----------------------------------------------------------------------------------------'
/\
|
802.11 Data Frame |
,--------- 'ctrl' expands to >-----------'
|
,--'---,-------------------------------------------------------------.
Bytes | 2 | 2 | 6 | 6 | 6 | 2 | 0..2312 | 4 |
|------|------|---------|---------|---------|------|---------|------|
Desc. | ctrl | dura | DA/RA | TA | SA | Sequ | Frame | fcs |
| | tion | (BSSID) | | | ence | data | |
`--------------------------------------------------| |------'
Total: 28 non-data bytes `----.----'
|
.- 'Frame data' expands to <---------------------------'
|
V
,---------------------------------------------------.
Bytes | 1 | 1 | 1 | 3 | 2 | 0-2304 |
|------|------|---------|----------|------|---------|
Desc. | SNAP | SNAP | Control |Eth Tunnel| Type | IP |
| DSAP | SSAP | | | | Packet |
| 0xAA | 0xAA |0x03 (UI)|0x00-00-F8| | |
`-----------------------------------------| |
Total: 8 non-data bytes `----.----'
|
.- 'IP Packet' expands, if WEP enabled, to <--'
|
V
,-----------------------.
Bytes | 4 | 0-2296 | 4 |
|-----|-----------|-----|
Desc. | IV | Encrypted | ICV |
| | IP Packet | |
`-----------------------'
Total: 8 non-data bytes
802.3 Ethernet Data Frame
,-----------------------------------------.
Bytes | 6 | 6 | 2 | Variable | 4 |
|-------|-------|------|-----------|------|
Desc. | Dest. | Source| Type | IP Packet | fcs |
| MAC | MAC | | | |
`-----------------------------------------'
Total: 18 non-data bytes
In the event that fragmentation is required, the incoming payload is split into
N parts of size ieee->fts. The first fragment contains the SNAP header and the
remaining packets are just data.
If encryption is enabled, each fragment payload size is reduced by enough space
to add the prefix and postfix (IV and ICV totalling 8 bytes in the case of WEP)
So if you have 1500 bytes of payload with ieee->fts set to 500 without
encryption it will take 3 frames. With WEP it will take 4 frames as the
payload of each frame is reduced to 492 bytes.
* SKB visualization
*
* ,- skb->data
* |
* | ETHERNET HEADER ,-<-- PAYLOAD
* | | 14 bytes from skb->data
* | 2 bytes for Type --> ,T. | (sizeof ethhdr)
* | | | |
* |,-Dest.--. ,--Src.---. | | |
* | 6 bytes| | 6 bytes | | | |
* v | | | | | |
* 0 | v 1 | v | v 2
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
* ^ | ^ | ^ |
* | | | | | |
* | | | | `T' <---- 2 bytes for Type
* | | | |
* | | '---SNAP--' <-------- 6 bytes for SNAP
* | |
* `-IV--' <-------------------- 4 bytes for IV (WEP)
*
* SNAP HEADER
*
*/
static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 };
static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 };
static inline int ieee80211_put_snap(u8 *data, u16 h_proto)
{
struct ieee80211_snap_hdr *snap;
u8 *oui;
snap = (struct ieee80211_snap_hdr *)data;
snap->dsap = 0xaa;
snap->ssap = 0xaa;
snap->ctrl = 0x03;
if (h_proto == 0x8137 || h_proto == 0x80f3)
oui = P802_1H_OUI;
else
oui = RFC1042_OUI;
snap->oui[0] = oui[0];
snap->oui[1] = oui[1];
snap->oui[2] = oui[2];
*(u16 *)(data + SNAP_SIZE) = htons(h_proto);
return SNAP_SIZE + sizeof(u16);
}
int ieee80211_encrypt_fragment(
struct ieee80211_device *ieee,
struct sk_buff *frag,
int hdr_len)
{
struct ieee80211_crypt_data* crypt = ieee->crypt[ieee->tx_keyidx];
int res;
if (!(crypt && crypt->ops))
{
printk("=========>%s(), crypt is null\n", __FUNCTION__);
return -1;
}
#ifdef CONFIG_IEEE80211_CRYPT_TKIP
struct ieee80211_hdr *header;
if (ieee->tkip_countermeasures &&
crypt && crypt->ops && strcmp(crypt->ops->name, "TKIP") == 0) {
header = (struct ieee80211_hdr *) frag->data;
if (net_ratelimit()) {
printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
"TX packet to " MAC_FMT "\n",
ieee->dev->name, MAC_ARG(header->addr1));
}
return -1;
}
#endif
/* To encrypt, frame format is:
* IV (4 bytes), clear payload (including SNAP), ICV (4 bytes) */
// PR: FIXME: Copied from hostap. Check fragmentation/MSDU/MPDU encryption.
/* Host-based IEEE 802.11 fragmentation for TX is not yet supported, so
* call both MSDU and MPDU encryption functions from here. */
atomic_inc(&crypt->refcnt);
res = 0;
if (crypt->ops->encrypt_msdu)
res = crypt->ops->encrypt_msdu(frag, hdr_len, crypt->priv);
if (res == 0 && crypt->ops->encrypt_mpdu)
res = crypt->ops->encrypt_mpdu(frag, hdr_len, crypt->priv);
atomic_dec(&crypt->refcnt);
if (res < 0) {
printk(KERN_INFO "%s: Encryption failed: len=%d.\n",
ieee->dev->name, frag->len);
ieee->ieee_stats.tx_discards++;
return -1;
}
return 0;
}
void ieee80211_txb_free(struct ieee80211_txb *txb) {
//int i;
if (unlikely(!txb))
return;
#if 0
for (i = 0; i < txb->nr_frags; i++)
if (txb->fragments[i])
dev_kfree_skb_any(txb->fragments[i]);
#endif
kfree(txb);
}
struct ieee80211_txb *ieee80211_alloc_txb(int nr_frags, int txb_size,
int gfp_mask)
{
struct ieee80211_txb *txb;
int i;
txb = kmalloc(
sizeof(struct ieee80211_txb) + (sizeof(u8*) * nr_frags),
gfp_mask);
if (!txb)
return NULL;
memset(txb, 0, sizeof(struct ieee80211_txb));
txb->nr_frags = nr_frags;
txb->frag_size = txb_size;
for (i = 0; i < nr_frags; i++) {
txb->fragments[i] = dev_alloc_skb(txb_size);
if (unlikely(!txb->fragments[i])) {
i--;
break;
}
memset(txb->fragments[i]->cb, 0, sizeof(txb->fragments[i]->cb));
}
if (unlikely(i != nr_frags)) {
while (i >= 0)
dev_kfree_skb_any(txb->fragments[i--]);
kfree(txb);
return NULL;
}
return txb;
}
// Classify the to-be send data packet
// Need to acquire the sent queue index.
static int
ieee80211_classify(struct sk_buff *skb, struct ieee80211_network *network)
{
struct ethhdr *eth;
struct iphdr *ip;
eth = (struct ethhdr *)skb->data;
if (eth->h_proto != htons(ETH_P_IP))
return 0;
// IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, skb->data, skb->len);
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22))
ip = ip_hdr(skb);
#else
ip = (struct iphdr*)(skb->data + sizeof(struct ether_header));
#endif
switch (ip->tos & 0xfc) {
case 0x20:
return 2;
case 0x40:
return 1;
case 0x60:
return 3;
case 0x80:
return 4;
case 0xa0:
return 5;
case 0xc0:
return 6;
case 0xe0:
return 7;
default:
return 0;
}
}
#define SN_LESS(a, b) (((a-b)&0x800)!=0)
void ieee80211_tx_query_agg_cap(struct ieee80211_device* ieee, struct sk_buff* skb, cb_desc* tcb_desc)
{
PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
PTX_TS_RECORD pTxTs = NULL;
struct ieee80211_hdr_1addr* hdr = (struct ieee80211_hdr_1addr*)skb->data;
if (!pHTInfo->bCurrentHTSupport||!pHTInfo->bEnableHT)
return;
if (!IsQoSDataFrame(skb->data))
return;
if (is_multicast_ether_addr(hdr->addr1) || is_broadcast_ether_addr(hdr->addr1))
return;
//check packet and mode later
#ifdef TO_DO_LIST
if(pTcb->PacketLength >= 4096)
return;
// For RTL819X, if pairwisekey = wep/tkip, we don't aggrregation.
if(!Adapter->HalFunc.GetNmodeSupportBySecCfgHandler(Adapter))
return;
#endif
#if 1
if(!ieee->GetNmodeSupportBySecCfg(ieee->dev))
{
return;
}
#endif
if(pHTInfo->bCurrentAMPDUEnable)
{
if (!GetTs(ieee, (PTS_COMMON_INFO*)(&pTxTs), hdr->addr1, skb->priority, TX_DIR, true))
{
printk("===>can't get TS\n");
return;
}
if (pTxTs->TxAdmittedBARecord.bValid == false)
{
TsStartAddBaProcess(ieee, pTxTs);
goto FORCED_AGG_SETTING;
}
else if (pTxTs->bUsingBa == false)
{
if (SN_LESS(pTxTs->TxAdmittedBARecord.BaStartSeqCtrl.field.SeqNum, (pTxTs->TxCurSeq+1)%4096))
pTxTs->bUsingBa = true;
else
goto FORCED_AGG_SETTING;
}
if (ieee->iw_mode == IW_MODE_INFRA)
{
tcb_desc->bAMPDUEnable = true;
tcb_desc->ampdu_factor = pHTInfo->CurrentAMPDUFactor;
tcb_desc->ampdu_density = pHTInfo->CurrentMPDUDensity;
}
}
FORCED_AGG_SETTING:
switch(pHTInfo->ForcedAMPDUMode )
{
case HT_AGG_AUTO:
break;
case HT_AGG_FORCE_ENABLE:
tcb_desc->bAMPDUEnable = true;
tcb_desc->ampdu_density = pHTInfo->ForcedMPDUDensity;
tcb_desc->ampdu_factor = pHTInfo->ForcedAMPDUFactor;
break;
case HT_AGG_FORCE_DISABLE:
tcb_desc->bAMPDUEnable = false;
tcb_desc->ampdu_density = 0;
tcb_desc->ampdu_factor = 0;
break;
}
return;
}
extern void ieee80211_qurey_ShortPreambleMode(struct ieee80211_device* ieee, cb_desc* tcb_desc)
{
tcb_desc->bUseShortPreamble = false;
if (tcb_desc->data_rate == 2)
{//// 1M can only use Long Preamble. 11B spec
return;
}
else if (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
{
tcb_desc->bUseShortPreamble = true;
}
return;
}
extern void
ieee80211_query_HTCapShortGI(struct ieee80211_device *ieee, cb_desc *tcb_desc)
{
PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
tcb_desc->bUseShortGI = false;
if(!pHTInfo->bCurrentHTSupport||!pHTInfo->bEnableHT)
return;
if(pHTInfo->bForcedShortGI)
{
tcb_desc->bUseShortGI = true;
return;
}
if((pHTInfo->bCurBW40MHz==true) && pHTInfo->bCurShortGI40MHz)
tcb_desc->bUseShortGI = true;
else if((pHTInfo->bCurBW40MHz==false) && pHTInfo->bCurShortGI20MHz)
tcb_desc->bUseShortGI = true;
}
void ieee80211_query_BandwidthMode(struct ieee80211_device* ieee, cb_desc *tcb_desc)
{
PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
tcb_desc->bPacketBW = false;
if(!pHTInfo->bCurrentHTSupport||!pHTInfo->bEnableHT)
return;
if(tcb_desc->bMulticast || tcb_desc->bBroadcast)
return;
if((tcb_desc->data_rate & 0x80)==0) // If using legacy rate, it shall use 20MHz channel.
return;
//BandWidthAutoSwitch is for auto switch to 20 or 40 in long distance
if(pHTInfo->bCurBW40MHz && pHTInfo->bCurTxBW40MHz && !ieee->bandwidth_auto_switch.bforced_tx20Mhz)
tcb_desc->bPacketBW = true;
return;
}
void ieee80211_query_protectionmode(struct ieee80211_device* ieee, cb_desc* tcb_desc, struct sk_buff* skb)
{
// Common Settings
tcb_desc->bRTSSTBC = false;
tcb_desc->bRTSUseShortGI = false; // Since protection frames are always sent by legacy rate, ShortGI will never be used.
tcb_desc->bCTSEnable = false; // Most of protection using RTS/CTS
tcb_desc->RTSSC = 0; // 20MHz: Don't care; 40MHz: Duplicate.
tcb_desc->bRTSBW = false; // RTS frame bandwidth is always 20MHz
if(tcb_desc->bBroadcast || tcb_desc->bMulticast)//only unicast frame will use rts/cts
return;
if (is_broadcast_ether_addr(skb->data+16)) //check addr3 as infrastructure add3 is DA.
return;
if (ieee->mode < IEEE_N_24G) //b, g mode
{
// (1) RTS_Threshold is compared to the MPDU, not MSDU.
// (2) If there are more than one frag in this MSDU, only the first frag uses protection frame.
// Other fragments are protected by previous fragment.
// So we only need to check the length of first fragment.
if (skb->len > ieee->rts)
{
tcb_desc->bRTSEnable = true;
tcb_desc->rts_rate = MGN_24M;
}
else if (ieee->current_network.buseprotection)
{
// Use CTS-to-SELF in protection mode.
tcb_desc->bRTSEnable = true;
tcb_desc->bCTSEnable = true;
tcb_desc->rts_rate = MGN_24M;
}
//otherwise return;
return;
}
else
{// 11n High throughput case.
PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
while (true)
{
//check ERP protection
if (ieee->current_network.buseprotection)
{// CTS-to-SELF
tcb_desc->bRTSEnable = true;
tcb_desc->bCTSEnable = true;
tcb_desc->rts_rate = MGN_24M;
break;
}
//check HT op mode
if(pHTInfo->bCurrentHTSupport && pHTInfo->bEnableHT)
{
u8 HTOpMode = pHTInfo->CurrentOpMode;
if((pHTInfo->bCurBW40MHz && (HTOpMode == 2 || HTOpMode == 3)) ||
(!pHTInfo->bCurBW40MHz && HTOpMode == 3) )
{
tcb_desc->rts_rate = MGN_24M; // Rate is 24Mbps.
tcb_desc->bRTSEnable = true;
break;
}
}
//check rts
if (skb->len > ieee->rts)
{
tcb_desc->rts_rate = MGN_24M; // Rate is 24Mbps.
tcb_desc->bRTSEnable = true;
break;
}
//to do list: check MIMO power save condition.
//check AMPDU aggregation for TXOP
if(tcb_desc->bAMPDUEnable)
{
tcb_desc->rts_rate = MGN_24M; // Rate is 24Mbps.
// According to 8190 design, firmware sends CF-End only if RTS/CTS is enabled. However, it degrads
// throughput around 10M, so we disable of this mechanism. 2007.08.03 by Emily
tcb_desc->bRTSEnable = false;
break;
}
//check IOT action
if(pHTInfo->IOTAction & HT_IOT_ACT_FORCED_CTS2SELF)
{
tcb_desc->bCTSEnable = true;
tcb_desc->rts_rate = MGN_24M;
tcb_desc->bRTSEnable = true;
break;
}
// Totally no protection case!!
goto NO_PROTECTION;
}
}
// For test , CTS replace with RTS
if( 0 )
{
tcb_desc->bCTSEnable = true;
tcb_desc->rts_rate = MGN_24M;
tcb_desc->bRTSEnable = true;
}
if (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
tcb_desc->bUseShortPreamble = true;
if (ieee->mode == IW_MODE_MASTER)
goto NO_PROTECTION;
return;
NO_PROTECTION:
tcb_desc->bRTSEnable = false;
tcb_desc->bCTSEnable = false;
tcb_desc->rts_rate = 0;
tcb_desc->RTSSC = 0;
tcb_desc->bRTSBW = false;
}
void ieee80211_txrate_selectmode(struct ieee80211_device* ieee, cb_desc* tcb_desc)
{
#ifdef TO_DO_LIST
if(!IsDataFrame(pFrame))
{
pTcb->bTxDisableRateFallBack = TRUE;
pTcb->bTxUseDriverAssingedRate = TRUE;
pTcb->RATRIndex = 7;
return;
}
if(pMgntInfo->ForcedDataRate!= 0)
{
pTcb->bTxDisableRateFallBack = TRUE;
pTcb->bTxUseDriverAssingedRate = TRUE;
return;
}
#endif
if(ieee->bTxDisableRateFallBack)
tcb_desc->bTxDisableRateFallBack = true;
if(ieee->bTxUseDriverAssingedRate)
tcb_desc->bTxUseDriverAssingedRate = true;
if(!tcb_desc->bTxDisableRateFallBack || !tcb_desc->bTxUseDriverAssingedRate)
{
if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC)
tcb_desc->RATRIndex = 0;
}
}
void ieee80211_query_seqnum(struct ieee80211_device*ieee, struct sk_buff* skb, u8* dst)
{
if (is_multicast_ether_addr(dst) || is_broadcast_ether_addr(dst))
return;
if (IsQoSDataFrame(skb->data)) //we deal qos data only
{
PTX_TS_RECORD pTS = NULL;
if (!GetTs(ieee, (PTS_COMMON_INFO*)(&pTS), dst, skb->priority, TX_DIR, true))
{
return;
}
pTS->TxCurSeq = (pTS->TxCurSeq+1)%4096;
}
}
int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
{
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0))
struct ieee80211_device *ieee = netdev_priv(dev);
#else
struct ieee80211_device *ieee = (struct ieee80211_device *)dev->priv;
#endif
struct ieee80211_txb *txb = NULL;
struct ieee80211_hdr_3addrqos *frag_hdr;
int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size;
unsigned long flags;
struct net_device_stats *stats = &ieee->stats;
int ether_type = 0, encrypt;
int bytes, fc, qos_ctl = 0, hdr_len;
struct sk_buff *skb_frag;
struct ieee80211_hdr_3addrqos header = { /* Ensure zero initialized */
.duration_id = 0,
.seq_ctl = 0,
.qos_ctl = 0
};
u8 dest[ETH_ALEN], src[ETH_ALEN];
int qos_actived = ieee->current_network.qos_data.active;
struct ieee80211_crypt_data* crypt;
cb_desc *tcb_desc;
spin_lock_irqsave(&ieee->lock, flags);
/* If there is no driver handler to take the TXB, dont' bother
* creating it... */
if ((!ieee->hard_start_xmit && !(ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE))||
((!ieee->softmac_data_hard_start_xmit && (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)))) {
printk(KERN_WARNING "%s: No xmit handler.\n",
ieee->dev->name);
goto success;
}
if(likely(ieee->raw_tx == 0)){
if (unlikely(skb->len < SNAP_SIZE + sizeof(u16))) {
printk(KERN_WARNING "%s: skb too small (%d).\n",
ieee->dev->name, skb->len);
goto success;
}
memset(skb->cb, 0, sizeof(skb->cb));
ether_type = ntohs(((struct ethhdr *)skb->data)->h_proto);
crypt = ieee->crypt[ieee->tx_keyidx];
encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) &&
ieee->host_encrypt && crypt && crypt->ops;
if (!encrypt && ieee->ieee802_1x &&
ieee->drop_unencrypted && ether_type != ETH_P_PAE) {
stats->tx_dropped++;
goto success;
}
#ifdef CONFIG_IEEE80211_DEBUG
if (crypt && !encrypt && ether_type == ETH_P_PAE) {
struct eapol *eap = (struct eapol *)(skb->data +
sizeof(struct ethhdr) - SNAP_SIZE - sizeof(u16));
IEEE80211_DEBUG_EAP("TX: IEEE 802.11 EAPOL frame: %s\n",
eap_get_type(eap->type));
}
#endif
/* Save source and destination addresses */
memcpy(&dest, skb->data, ETH_ALEN);
memcpy(&src, skb->data+ETH_ALEN, ETH_ALEN);
/* Advance the SKB to the start of the payload */
skb_pull(skb, sizeof(struct ethhdr));
/* Determine total amount of storage required for TXB packets */
bytes = skb->len + SNAP_SIZE + sizeof(u16);
if (encrypt)
fc = IEEE80211_FTYPE_DATA | IEEE80211_FCTL_WEP;
else
fc = IEEE80211_FTYPE_DATA;
//if(ieee->current_network.QoS_Enable)
if(qos_actived)
fc |= IEEE80211_STYPE_QOS_DATA;
else
fc |= IEEE80211_STYPE_DATA;
if (ieee->iw_mode == IW_MODE_INFRA) {
fc |= IEEE80211_FCTL_TODS;
/* To DS: Addr1 = BSSID, Addr2 = SA,
Addr3 = DA */
memcpy(&header.addr1, ieee->current_network.bssid, ETH_ALEN);
memcpy(&header.addr2, &src, ETH_ALEN);
memcpy(&header.addr3, &dest, ETH_ALEN);
} else if (ieee->iw_mode == IW_MODE_ADHOC) {
/* not From/To DS: Addr1 = DA, Addr2 = SA,
Addr3 = BSSID */
memcpy(&header.addr1, dest, ETH_ALEN);
memcpy(&header.addr2, src, ETH_ALEN);
memcpy(&header.addr3, ieee->current_network.bssid, ETH_ALEN);
}
header.frame_ctl = cpu_to_le16(fc);
/* Determine fragmentation size based on destination (multicast
* and broadcast are not fragmented) */
if (is_multicast_ether_addr(header.addr1) ||
is_broadcast_ether_addr(header.addr1)) {
frag_size = MAX_FRAG_THRESHOLD;
qos_ctl |= QOS_CTL_NOTCONTAIN_ACK;
}
else {
frag_size = ieee->fts;//default:392
qos_ctl = 0;
}
//if (ieee->current_network.QoS_Enable)
if(qos_actived)
{
hdr_len = IEEE80211_3ADDR_LEN + 2;
skb->priority = ieee80211_classify(skb, &ieee->current_network);
qos_ctl |= skb->priority; //set in the ieee80211_classify
header.qos_ctl = cpu_to_le16(qos_ctl & IEEE80211_QOS_TID);
} else {
hdr_len = IEEE80211_3ADDR_LEN;
}
/* Determine amount of payload per fragment. Regardless of if
* this stack is providing the full 802.11 header, one will
* eventually be affixed to this fragment -- so we must account for
* it when determining the amount of payload space. */
bytes_per_frag = frag_size - hdr_len;
if (ieee->config &
(CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
bytes_per_frag -= IEEE80211_FCS_LEN;
/* Each fragment may need to have room for encryptiong pre/postfix */
if (encrypt)
bytes_per_frag -= crypt->ops->extra_prefix_len +
crypt->ops->extra_postfix_len;
/* Number of fragments is the total bytes_per_frag /
* payload_per_fragment */
nr_frags = bytes / bytes_per_frag;
bytes_last_frag = bytes % bytes_per_frag;
if (bytes_last_frag)
nr_frags++;
else
bytes_last_frag = bytes_per_frag;
/* When we allocate the TXB we allocate enough space for the reserve
* and full fragment bytes (bytes_per_frag doesn't include prefix,
* postfix, header, FCS, etc.) */
txb = ieee80211_alloc_txb(nr_frags, frag_size + ieee->tx_headroom, GFP_ATOMIC);
if (unlikely(!txb)) {
printk(KERN_WARNING "%s: Could not allocate TXB\n",
ieee->dev->name);
goto failed;
}
txb->encrypted = encrypt;
txb->payload_size = bytes;
//if (ieee->current_network.QoS_Enable)
if(qos_actived)
{
txb->queue_index = UP2AC(skb->priority);
} else {
txb->queue_index = WME_AC_BK;;
}
for (i = 0; i < nr_frags; i++) {
skb_frag = txb->fragments[i];
tcb_desc = (cb_desc *)(skb_frag->cb + MAX_DEV_ADDR_SIZE);
if(qos_actived){
skb_frag->priority = skb->priority;//UP2AC(skb->priority);
tcb_desc->queue_index = UP2AC(skb->priority);
} else {
skb_frag->priority = WME_AC_BK;
tcb_desc->queue_index = WME_AC_BK;
}
skb_reserve(skb_frag, ieee->tx_headroom);
if (encrypt){
if (ieee->hwsec_active)
tcb_desc->bHwSec = 1;
else
tcb_desc->bHwSec = 0;
skb_reserve(skb_frag, crypt->ops->extra_prefix_len);
}
else
{
tcb_desc->bHwSec = 0;
}
frag_hdr = (struct ieee80211_hdr_3addrqos *)skb_put(skb_frag, hdr_len);
memcpy(frag_hdr, &header, hdr_len);
/* If this is not the last fragment, then add the MOREFRAGS
* bit to the frame control */
if (i != nr_frags - 1) {
frag_hdr->frame_ctl = cpu_to_le16(
fc | IEEE80211_FCTL_MOREFRAGS);
bytes = bytes_per_frag;
} else {
/* The last fragment takes the remaining length */
bytes = bytes_last_frag;
}
//if(ieee->current_network.QoS_Enable)
if(qos_actived)
{
// add 1 only indicate to corresponding seq number control 2006/7/12
frag_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl[UP2AC(skb->priority)+1]<<4 | i);
} else {
frag_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0]<<4 | i);
}
/* Put a SNAP header on the first fragment */
if (i == 0) {
ieee80211_put_snap(
skb_put(skb_frag, SNAP_SIZE + sizeof(u16)),
ether_type);
bytes -= SNAP_SIZE + sizeof(u16);
}
memcpy(skb_put(skb_frag, bytes), skb->data, bytes);
/* Advance the SKB... */
skb_pull(skb, bytes);
/* Encryption routine will move the header forward in order
* to insert the IV between the header and the payload */
if (encrypt)
ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len);
if (ieee->config &
(CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
skb_put(skb_frag, 4);
}
if(qos_actived)
{
if (ieee->seq_ctrl[UP2AC(skb->priority) + 1] == 0xFFF)
ieee->seq_ctrl[UP2AC(skb->priority) + 1] = 0;
else
ieee->seq_ctrl[UP2AC(skb->priority) + 1]++;
} else {
if (ieee->seq_ctrl[0] == 0xFFF)
ieee->seq_ctrl[0] = 0;
else
ieee->seq_ctrl[0]++;
}
}else{
if (unlikely(skb->len < sizeof(struct ieee80211_hdr_3addr))) {
printk(KERN_WARNING "%s: skb too small (%d).\n",
ieee->dev->name, skb->len);
goto success;
}
txb = ieee80211_alloc_txb(1, skb->len, GFP_ATOMIC);
if(!txb){
printk(KERN_WARNING "%s: Could not allocate TXB\n",
ieee->dev->name);
goto failed;
}
txb->encrypted = 0;
txb->payload_size = skb->len;
memcpy(skb_put(txb->fragments[0],skb->len), skb->data, skb->len);
}
success:
//WB add to fill data tcb_desc here. only first fragment is considered, need to change, and you may remove to other place.
if (txb)
{
#if 1
cb_desc *tcb_desc = (cb_desc *)(txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE);
tcb_desc->bTxEnableFwCalcDur = 1;
if (is_multicast_ether_addr(header.addr1))
tcb_desc->bMulticast = 1;
if (is_broadcast_ether_addr(header.addr1))
tcb_desc->bBroadcast = 1;
ieee80211_txrate_selectmode(ieee, tcb_desc);
if ( tcb_desc->bMulticast || tcb_desc->bBroadcast)
tcb_desc->data_rate = ieee->basic_rate;
else
//tcb_desc->data_rate = CURRENT_RATE(ieee->current_network.mode, ieee->rate, ieee->HTCurrentOperaRate);
tcb_desc->data_rate = CURRENT_RATE(ieee->mode, ieee->rate, ieee->HTCurrentOperaRate);
ieee80211_qurey_ShortPreambleMode(ieee, tcb_desc);
ieee80211_tx_query_agg_cap(ieee, txb->fragments[0], tcb_desc);
ieee80211_query_HTCapShortGI(ieee, tcb_desc);
ieee80211_query_BandwidthMode(ieee, tcb_desc);
ieee80211_query_protectionmode(ieee, tcb_desc, txb->fragments[0]);
ieee80211_query_seqnum(ieee, txb->fragments[0], header.addr1);
// IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, txb->fragments[0]->data, txb->fragments[0]->len);
//IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, tcb_desc, sizeof(cb_desc));
#endif
}
spin_unlock_irqrestore(&ieee->lock, flags);
dev_kfree_skb_any(skb);
if (txb) {
if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE){
ieee80211_softmac_xmit(txb, ieee);
}else{
if ((*ieee->hard_start_xmit)(txb, dev) == 0) {
stats->tx_packets++;
stats->tx_bytes += txb->payload_size;
return 0;
}
ieee80211_txb_free(txb);
}
}
return 0;
failed:
spin_unlock_irqrestore(&ieee->lock, flags);
netif_stop_queue(dev);
stats->tx_errors++;
return 1;
}
EXPORT_SYMBOL(ieee80211_txb_free);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,115 @@
/*
* Cryptographic API.
*
* Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
*
* 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.
*
*/
#ifndef _CRYPTO_INTERNAL_H
#define _CRYPTO_INTERNAL_H
//#include <linux/crypto.h>
#include "rtl_crypto.h"
#include <linux/mm.h>
#include <linux/highmem.h>
#include <linux/init.h>
#include <asm/hardirq.h>
#include <asm/softirq.h>
#include <asm/kmap_types.h>
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,20))
#define list_for_each_entry(pos, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member), \
prefetch(pos->member.next); \
&pos->member != (head); \
pos = list_entry(pos->member.next, typeof(*pos), member), \
prefetch(pos->member.next))
static inline void cond_resched(void)
{
if (need_resched()) {
set_current_state(TASK_RUNNING);
schedule();
}
}
#endif
extern enum km_type crypto_km_types[];
static inline enum km_type crypto_kmap_type(int out)
{
return crypto_km_types[(in_softirq() ? 2 : 0) + out];
}
static inline void *crypto_kmap(struct page *page, int out)
{
return kmap_atomic(page, crypto_kmap_type(out));
}
static inline void crypto_kunmap(void *vaddr, int out)
{
kunmap_atomic(vaddr, crypto_kmap_type(out));
}
static inline void crypto_yield(struct crypto_tfm *tfm)
{
if (!in_softirq())
cond_resched();
}
static inline void *crypto_tfm_ctx(struct crypto_tfm *tfm)
{
return (void *)&tfm[1];
}
struct crypto_alg *crypto_alg_lookup(const char *name);
#ifdef CONFIG_KMOD
void crypto_alg_autoload(const char *name);
struct crypto_alg *crypto_alg_mod_lookup(const char *name);
#else
static inline struct crypto_alg *crypto_alg_mod_lookup(const char *name)
{
return crypto_alg_lookup(name);
}
#endif
#ifdef CONFIG_CRYPTO_HMAC
int crypto_alloc_hmac_block(struct crypto_tfm *tfm);
void crypto_free_hmac_block(struct crypto_tfm *tfm);
#else
static inline int crypto_alloc_hmac_block(struct crypto_tfm *tfm)
{
return 0;
}
static inline void crypto_free_hmac_block(struct crypto_tfm *tfm)
{ }
#endif
#ifdef CONFIG_PROC_FS
void __init crypto_init_proc(void);
#else
static inline void crypto_init_proc(void)
{ }
#endif
int crypto_init_digest_flags(struct crypto_tfm *tfm, u32 flags);
int crypto_init_cipher_flags(struct crypto_tfm *tfm, u32 flags);
int crypto_init_compress_flags(struct crypto_tfm *tfm, u32 flags);
int crypto_init_digest_ops(struct crypto_tfm *tfm);
int crypto_init_cipher_ops(struct crypto_tfm *tfm);
int crypto_init_compress_ops(struct crypto_tfm *tfm);
void crypto_exit_digest_ops(struct crypto_tfm *tfm);
void crypto_exit_cipher_ops(struct crypto_tfm *tfm);
void crypto_exit_compress_ops(struct crypto_tfm *tfm);
#endif /* _CRYPTO_INTERNAL_H */

View File

@ -0,0 +1,20 @@
#ifndef __KMAP_TYPES_H
#define __KMAP_TYPES_H
enum km_type {
KM_BOUNCE_READ,
KM_SKB_SUNRPC_DATA,
KM_SKB_DATA_SOFTIRQ,
KM_USER0,
KM_USER1,
KM_BH_IRQ,
KM_SOFTIRQ0,
KM_SOFTIRQ1,
KM_TYPE_NR
};
#define _ASM_KMAP_TYPES_H
#endif

View File

@ -0,0 +1,194 @@
/*
* Cryptographic API
*
* Michael MIC (IEEE 802.11i/TKIP) keyed digest
*
* Copyright (c) 2004 Jouni Malinen <jkmaline@cc.hut.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/string.h>
//#include <linux/crypto.h>
#include "rtl_crypto.h"
struct michael_mic_ctx {
u8 pending[4];
size_t pending_len;
u32 l, r;
};
static inline u32 rotl(u32 val, int bits)
{
return (val << bits) | (val >> (32 - bits));
}
static inline u32 rotr(u32 val, int bits)
{
return (val >> bits) | (val << (32 - bits));
}
static inline u32 xswap(u32 val)
{
return ((val & 0x00ff00ff) << 8) | ((val & 0xff00ff00) >> 8);
}
#define michael_block(l, r) \
do { \
r ^= rotl(l, 17); \
l += r; \
r ^= xswap(l); \
l += r; \
r ^= rotl(l, 3); \
l += r; \
r ^= rotr(l, 2); \
l += r; \
} while (0)
static inline u32 get_le32(const u8 *p)
{
return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
}
static inline void put_le32(u8 *p, u32 v)
{
p[0] = v;
p[1] = v >> 8;
p[2] = v >> 16;
p[3] = v >> 24;
}
static void michael_init(void *ctx)
{
struct michael_mic_ctx *mctx = ctx;
mctx->pending_len = 0;
}
static void michael_update(void *ctx, const u8 *data, unsigned int len)
{
struct michael_mic_ctx *mctx = ctx;
if (mctx->pending_len) {
int flen = 4 - mctx->pending_len;
if (flen > len)
flen = len;
memcpy(&mctx->pending[mctx->pending_len], data, flen);
mctx->pending_len += flen;
data += flen;
len -= flen;
if (mctx->pending_len < 4)
return;
mctx->l ^= get_le32(mctx->pending);
michael_block(mctx->l, mctx->r);
mctx->pending_len = 0;
}
while (len >= 4) {
mctx->l ^= get_le32(data);
michael_block(mctx->l, mctx->r);
data += 4;
len -= 4;
}
if (len > 0) {
mctx->pending_len = len;
memcpy(mctx->pending, data, len);
}
}
static void michael_final(void *ctx, u8 *out)
{
struct michael_mic_ctx *mctx = ctx;
u8 *data = mctx->pending;
/* Last block and padding (0x5a, 4..7 x 0) */
switch (mctx->pending_len) {
case 0:
mctx->l ^= 0x5a;
break;
case 1:
mctx->l ^= data[0] | 0x5a00;
break;
case 2:
mctx->l ^= data[0] | (data[1] << 8) | 0x5a0000;
break;
case 3:
mctx->l ^= data[0] | (data[1] << 8) | (data[2] << 16) |
0x5a000000;
break;
}
michael_block(mctx->l, mctx->r);
/* l ^= 0; */
michael_block(mctx->l, mctx->r);
put_le32(out, mctx->l);
put_le32(out + 4, mctx->r);
}
static int michael_setkey(void *ctx, const u8 *key, unsigned int keylen,
u32 *flags)
{
struct michael_mic_ctx *mctx = ctx;
if (keylen != 8) {
if (flags)
*flags = CRYPTO_TFM_RES_BAD_KEY_LEN;
return -EINVAL;
}
mctx->l = get_le32(key);
mctx->r = get_le32(key + 4);
return 0;
}
static struct crypto_alg michael_mic_alg = {
.cra_name = "michael_mic",
.cra_flags = CRYPTO_ALG_TYPE_DIGEST,
.cra_blocksize = 8,
.cra_ctxsize = sizeof(struct michael_mic_ctx),
.cra_module = THIS_MODULE,
.cra_list = LIST_HEAD_INIT(michael_mic_alg.cra_list),
.cra_u = { .digest = {
.dia_digestsize = 8,
.dia_init = michael_init,
.dia_update = michael_update,
.dia_final = michael_final,
.dia_setkey = michael_setkey } }
};
static int __init michael_mic_init(void)
{
return crypto_register_alg(&michael_mic_alg);
}
static void __exit michael_mic_exit(void)
{
crypto_unregister_alg(&michael_mic_alg);
}
module_init(michael_mic_init);
module_exit(michael_mic_exit);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("Michael MIC");
MODULE_AUTHOR("Jouni Malinen <jkmaline@cc.hut.fi>");

View File

@ -0,0 +1,116 @@
/*
* Scatterlist Cryptographic API.
*
* Procfs information.
*
* Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
*
* 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.
*
*/
#include <linux/init.h>
//#include <linux/crypto.h>
#include "rtl_crypto.h"
#include <linux/rwsem.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include "internal.h"
extern struct list_head crypto_alg_list;
extern struct rw_semaphore crypto_alg_sem;
static void *c_start(struct seq_file *m, loff_t *pos)
{
struct list_head *v;
loff_t n = *pos;
down_read(&crypto_alg_sem);
list_for_each(v, &crypto_alg_list)
if (!n--)
return list_entry(v, struct crypto_alg, cra_list);
return NULL;
}
static void *c_next(struct seq_file *m, void *p, loff_t *pos)
{
struct list_head *v = p;
(*pos)++;
v = v->next;
return (v == &crypto_alg_list) ?
NULL : list_entry(v, struct crypto_alg, cra_list);
}
static void c_stop(struct seq_file *m, void *p)
{
up_read(&crypto_alg_sem);
}
static int c_show(struct seq_file *m, void *p)
{
struct crypto_alg *alg = (struct crypto_alg *)p;
seq_printf(m, "name : %s\n", alg->cra_name);
seq_printf(m, "module : %s\n",
(alg->cra_module ?
alg->cra_module->name :
"kernel"));
switch (alg->cra_flags & CRYPTO_ALG_TYPE_MASK) {
case CRYPTO_ALG_TYPE_CIPHER:
seq_printf(m, "type : cipher\n");
seq_printf(m, "blocksize : %u\n", alg->cra_blocksize);
seq_printf(m, "min keysize : %u\n",
alg->cra_cipher.cia_min_keysize);
seq_printf(m, "max keysize : %u\n",
alg->cra_cipher.cia_max_keysize);
break;
case CRYPTO_ALG_TYPE_DIGEST:
seq_printf(m, "type : digest\n");
seq_printf(m, "blocksize : %u\n", alg->cra_blocksize);
seq_printf(m, "digestsize : %u\n",
alg->cra_digest.dia_digestsize);
break;
case CRYPTO_ALG_TYPE_COMPRESS:
seq_printf(m, "type : compression\n");
break;
default:
seq_printf(m, "type : unknown\n");
break;
}
seq_putc(m, '\n');
return 0;
}
static struct seq_operations crypto_seq_ops = {
.start = c_start,
.next = c_next,
.stop = c_stop,
.show = c_show
};
static int crypto_info_open(struct inode *inode, struct file *file)
{
return seq_open(file, &crypto_seq_ops);
}
static struct file_operations proc_crypto_ops = {
.open = crypto_info_open,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release
};
void __init crypto_init_proc(void)
{
struct proc_dir_entry *proc;
proc = create_proc_entry("crypto", 0, NULL);
if (proc)
proc->proc_fops = &proc_crypto_ops;
}

View File

@ -0,0 +1,69 @@
#ifndef _BATYPE_H_
#define _BATYPE_H_
#define TOTAL_TXBA_NUM 16
#define TOTAL_RXBA_NUM 16
#define BA_SETUP_TIMEOUT 200
#define BA_INACT_TIMEOUT 60000
#define BA_POLICY_DELAYED 0
#define BA_POLICY_IMMEDIATE 1
#define ADDBA_STATUS_SUCCESS 0
#define ADDBA_STATUS_REFUSED 37
#define ADDBA_STATUS_INVALID_PARAM 38
#define DELBA_REASON_QSTA_LEAVING 36
#define DELBA_REASON_END_BA 37
#define DELBA_REASON_UNKNOWN_BA 38
#define DELBA_REASON_TIMEOUT 39
/* whether need define BA Action frames here?
struct ieee80211_ADDBA_Req{
struct ieee80211_header_data header;
u8 category;
u8
} __attribute__ ((packed));
*/
//Is this need?I put here just to make it easier to define structure BA_RECORD //WB
typedef union _SEQUENCE_CONTROL{
u16 ShortData;
struct
{
u16 FragNum:4;
u16 SeqNum:12;
}field;
}SEQUENCE_CONTROL, *PSEQUENCE_CONTROL;
typedef union _BA_PARAM_SET {
u8 charData[2];
u16 shortData;
struct {
u16 AMSDU_Support:1;
u16 BAPolicy:1;
u16 TID:4;
u16 BufferSize:10;
} field;
} BA_PARAM_SET, *PBA_PARAM_SET;
typedef union _DELBA_PARAM_SET {
u8 charData[2];
u16 shortData;
struct {
u16 Reserved:11;
u16 Initiator:1;
u16 TID:4;
} field;
} DELBA_PARAM_SET, *PDELBA_PARAM_SET;
typedef struct _BA_RECORD {
struct timer_list Timer;
u8 bValid;
u8 DialogToken;
BA_PARAM_SET BaParamSet;
u16 BaTimeoutValue;
SEQUENCE_CONTROL BaStartSeqCtrl;
} BA_RECORD, *PBA_RECORD;
#endif //end _BATYPE_H_

View File

@ -0,0 +1,779 @@
/********************************************************************************************************************************
* This file is created to process BA Action Frame. According to 802.11 spec, there are 3 BA action types at all. And as BA is
* related to TS, this part need some struture defined in QOS side code. Also TX RX is going to be resturctured, so how to send
* ADDBAREQ ADDBARSP and DELBA packet is still on consideration. Temporarily use MANAGE QUEUE instead of Normal Queue.
* WB 2008-05-27
* *****************************************************************************************************************************/
#include "ieee80211.h"
#include "rtl819x_BA.h"
/********************************************************************************************************************
*function: Activate BA entry. And if Time is nozero, start timer.
* input: PBA_RECORD pBA //BA entry to be enabled
* u16 Time //indicate time delay.
* output: none
********************************************************************************************************************/
void ActivateBAEntry(struct ieee80211_device* ieee, PBA_RECORD pBA, u16 Time)
{
pBA->bValid = true;
if(Time != 0)
mod_timer(&pBA->Timer, jiffies + MSECS(Time));
}
/********************************************************************************************************************
*function: deactivate BA entry, including its timer.
* input: PBA_RECORD pBA //BA entry to be disabled
* output: none
********************************************************************************************************************/
void DeActivateBAEntry( struct ieee80211_device* ieee, PBA_RECORD pBA)
{
pBA->bValid = false;
del_timer_sync(&pBA->Timer);
}
/********************************************************************************************************************
*function: deactivete BA entry in Tx Ts, and send DELBA.
* input:
* PTX_TS_RECORD pTxTs //Tx Ts which is to deactivate BA entry.
* output: none
* notice: As PTX_TS_RECORD structure will be defined in QOS, so wait to be merged. //FIXME
********************************************************************************************************************/
u8 TxTsDeleteBA( struct ieee80211_device* ieee, PTX_TS_RECORD pTxTs)
{
PBA_RECORD pAdmittedBa = &pTxTs->TxAdmittedBARecord; //These two BA entries must exist in TS structure
PBA_RECORD pPendingBa = &pTxTs->TxPendingBARecord;
u8 bSendDELBA = false;
// Delete pending BA
if(pPendingBa->bValid)
{
DeActivateBAEntry(ieee, pPendingBa);
bSendDELBA = true;
}
// Delete admitted BA
if(pAdmittedBa->bValid)
{
DeActivateBAEntry(ieee, pAdmittedBa);
bSendDELBA = true;
}
return bSendDELBA;
}
/********************************************************************************************************************
*function: deactivete BA entry in Tx Ts, and send DELBA.
* input:
* PRX_TS_RECORD pRxTs //Rx Ts which is to deactivate BA entry.
* output: none
* notice: As PRX_TS_RECORD structure will be defined in QOS, so wait to be merged. //FIXME, same with above
********************************************************************************************************************/
u8 RxTsDeleteBA( struct ieee80211_device* ieee, PRX_TS_RECORD pRxTs)
{
PBA_RECORD pBa = &pRxTs->RxAdmittedBARecord;
u8 bSendDELBA = false;
if(pBa->bValid)
{
DeActivateBAEntry(ieee, pBa);
bSendDELBA = true;
}
return bSendDELBA;
}
/********************************************************************************************************************
*function: reset BA entry
* input:
* PBA_RECORD pBA //entry to be reset
* output: none
********************************************************************************************************************/
void ResetBaEntry( PBA_RECORD pBA)
{
pBA->bValid = false;
pBA->BaParamSet.shortData = 0;
pBA->BaTimeoutValue = 0;
pBA->DialogToken = 0;
pBA->BaStartSeqCtrl.ShortData = 0;
}
//These functions need porting here or not?
/*******************************************************************************************************************************
*function: construct ADDBAREQ and ADDBARSP frame here together.
* input: u8* Dst //ADDBA frame's destination
* PBA_RECORD pBA //BA_RECORD entry which stores the necessary information for BA.
* u16 StatusCode //status code in RSP and I will use it to indicate whether it's RSP or REQ(will I?)
* u8 type //indicate whether it's RSP(ACT_ADDBARSP) ow REQ(ACT_ADDBAREQ)
* output: none
* return: sk_buff* skb //return constructed skb to xmit
*******************************************************************************************************************************/
static struct sk_buff* ieee80211_ADDBA(struct ieee80211_device* ieee, u8* Dst, PBA_RECORD pBA, u16 StatusCode, u8 type)
{
struct sk_buff *skb = NULL;
struct ieee80211_hdr_3addr* BAReq = NULL;
u8* tag = NULL;
u16 tmp = 0;
u16 len = ieee->tx_headroom + 9;
//category(1) + action field(1) + Dialog Token(1) + BA Parameter Set(2) + BA Timeout Value(2) + BA Start SeqCtrl(2)(or StatusCode(2))
IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "========>%s(), frame(%d) sentd to:"MAC_FMT", ieee->dev:%p\n", __FUNCTION__, type, MAC_ARG(Dst), ieee->dev);
if (pBA == NULL||ieee == NULL)
{
IEEE80211_DEBUG(IEEE80211_DL_ERR, "pBA(%p) is NULL or ieee(%p) is NULL\n", pBA, ieee);
return NULL;
}
skb = dev_alloc_skb(len + sizeof( struct ieee80211_hdr_3addr)); //need to add something others? FIXME
if (skb == NULL)
{
IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc skb for ADDBA_REQ\n");
return NULL;
}
memset(skb->data, 0, sizeof( struct ieee80211_hdr_3addr)); //I wonder whether it's necessary. Apparently kernel will not do it when alloc a skb.
skb_reserve(skb, ieee->tx_headroom);
BAReq = ( struct ieee80211_hdr_3addr *) skb_put(skb,sizeof( struct ieee80211_hdr_3addr));
memcpy(BAReq->addr1, Dst, ETH_ALEN);
memcpy(BAReq->addr2, ieee->dev->dev_addr, ETH_ALEN);
memcpy(BAReq->addr3, ieee->current_network.bssid, ETH_ALEN);
BAReq->frame_ctl = cpu_to_le16(IEEE80211_STYPE_MANAGE_ACT); //action frame
//tag += sizeof( struct ieee80211_hdr_3addr); //move to action field
tag = (u8*)skb_put(skb, 9);
*tag ++= ACT_CAT_BA;
*tag ++= type;
// Dialog Token
*tag ++= pBA->DialogToken;
if (ACT_ADDBARSP == type)
{
// Status Code
printk("=====>to send ADDBARSP\n");
tmp = cpu_to_le16(StatusCode);
memcpy(tag, (u8*)&tmp, 2);
tag += 2;
}
// BA Parameter Set
tmp = cpu_to_le16(pBA->BaParamSet.shortData);
memcpy(tag, (u8*)&tmp, 2);
tag += 2;
// BA Timeout Value
tmp = cpu_to_le16(pBA->BaTimeoutValue);
memcpy(tag, (u8*)&tmp, 2);
tag += 2;
if (ACT_ADDBAREQ == type)
{
// BA Start SeqCtrl
memcpy(tag,(u8*)&(pBA->BaStartSeqCtrl), 2);
tag += 2;
}
IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
return skb;
//return NULL;
}
#if 0 //I try to merge ADDBA_REQ and ADDBA_RSP frames together..
/********************************************************************************************************************
*function: construct ADDBAREQ frame
* input: u8* dst //ADDBARsp frame's destination
* PBA_RECORD pBA //BA_RECORD entry which stores the necessary information for BA_RSP.
* u16 StatusCode //status code.
* output: none
* return: sk_buff* skb //return constructed skb to xmit
********************************************************************************************************************/
static struct sk_buff* ieee80211_ADDBA_Rsp( IN struct ieee80211_device* ieee, u8* dst, PBA_RECORD pBA, u16 StatusCode)
{
OCTET_STRING osADDBAFrame, tmp;
FillOctetString(osADDBAFrame, Buffer, 0);
*pLength = 0;
ConstructMaFrameHdr(
Adapter,
Addr,
ACT_CAT_BA,
ACT_ADDBARSP,
&osADDBAFrame );
// Dialog Token
FillOctetString(tmp, &pBA->DialogToken, 1);
PacketAppendData(&osADDBAFrame, tmp);
// Status Code
FillOctetString(tmp, &StatusCode, 2);
PacketAppendData(&osADDBAFrame, tmp);
// BA Parameter Set
FillOctetString(tmp, &pBA->BaParamSet, 2);
PacketAppendData(&osADDBAFrame, tmp);
// BA Timeout Value
FillOctetString(tmp, &pBA->BaTimeoutValue, 2);
PacketAppendData(&osADDBAFrame, tmp);
*pLength = osADDBAFrame.Length;
}
#endif
/********************************************************************************************************************
*function: construct DELBA frame
* input: u8* dst //DELBA frame's destination
* PBA_RECORD pBA //BA_RECORD entry which stores the necessary information for BA
* TR_SELECT TxRxSelect //TX RX direction
* u16 ReasonCode //status code.
* output: none
* return: sk_buff* skb //return constructed skb to xmit
********************************************************************************************************************/
static struct sk_buff* ieee80211_DELBA(
struct ieee80211_device* ieee,
u8* dst,
PBA_RECORD pBA,
TR_SELECT TxRxSelect,
u16 ReasonCode
)
{
DELBA_PARAM_SET DelbaParamSet;
struct sk_buff *skb = NULL;
struct ieee80211_hdr_3addr* Delba = NULL;
u8* tag = NULL;
u16 tmp = 0;
//len = head len + DELBA Parameter Set(2) + Reason Code(2)
u16 len = 6 + ieee->tx_headroom;
if (net_ratelimit())
IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "========>%s(), ReasonCode(%d) sentd to:"MAC_FMT"\n", __FUNCTION__, ReasonCode, MAC_ARG(dst));
memset(&DelbaParamSet, 0, 2);
DelbaParamSet.field.Initiator = (TxRxSelect==TX_DIR)?1:0;
DelbaParamSet.field.TID = pBA->BaParamSet.field.TID;
skb = dev_alloc_skb(len + sizeof( struct ieee80211_hdr_3addr)); //need to add something others? FIXME
if (skb == NULL)
{
IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc skb for ADDBA_REQ\n");
return NULL;
}
// memset(skb->data, 0, len+sizeof( struct ieee80211_hdr_3addr));
skb_reserve(skb, ieee->tx_headroom);
Delba = ( struct ieee80211_hdr_3addr *) skb_put(skb,sizeof( struct ieee80211_hdr_3addr));
memcpy(Delba->addr1, dst, ETH_ALEN);
memcpy(Delba->addr2, ieee->dev->dev_addr, ETH_ALEN);
memcpy(Delba->addr3, ieee->current_network.bssid, ETH_ALEN);
Delba->frame_ctl = cpu_to_le16(IEEE80211_STYPE_MANAGE_ACT); //action frame
tag = (u8*)skb_put(skb, 6);
*tag ++= ACT_CAT_BA;
*tag ++= ACT_DELBA;
// DELBA Parameter Set
tmp = cpu_to_le16(DelbaParamSet.shortData);
memcpy(tag, (u8*)&tmp, 2);
tag += 2;
// Reason Code
tmp = cpu_to_le16(ReasonCode);
memcpy(tag, (u8*)&tmp, 2);
tag += 2;
IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
if (net_ratelimit())
IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "<=====%s()\n", __FUNCTION__);
return skb;
}
/********************************************************************************************************************
*function: send ADDBAReq frame out
* input: u8* dst //ADDBAReq frame's destination
* PBA_RECORD pBA //BA_RECORD entry which stores the necessary information for BA
* output: none
* notice: If any possible, please hide pBA in ieee. And temporarily use Manage Queue as softmac_mgmt_xmit() usually does
********************************************************************************************************************/
void ieee80211_send_ADDBAReq(struct ieee80211_device* ieee, u8* dst, PBA_RECORD pBA)
{
struct sk_buff *skb = NULL;
skb = ieee80211_ADDBA(ieee, dst, pBA, 0, ACT_ADDBAREQ); //construct ACT_ADDBAREQ frames so set statuscode zero.
if (skb)
{
softmac_mgmt_xmit(skb, ieee);
//add statistic needed here.
//and skb will be freed in softmac_mgmt_xmit(), so omit all dev_kfree_skb_any() outside softmac_mgmt_xmit()
//WB
}
else
{
IEEE80211_DEBUG(IEEE80211_DL_ERR, "alloc skb error in function %s()\n", __FUNCTION__);
}
return;
}
/********************************************************************************************************************
*function: send ADDBARSP frame out
* input: u8* dst //DELBA frame's destination
* PBA_RECORD pBA //BA_RECORD entry which stores the necessary information for BA
* u16 StatusCode //RSP StatusCode
* output: none
* notice: If any possible, please hide pBA in ieee. And temporarily use Manage Queue as softmac_mgmt_xmit() usually does
********************************************************************************************************************/
void ieee80211_send_ADDBARsp(struct ieee80211_device* ieee, u8* dst, PBA_RECORD pBA, u16 StatusCode)
{
struct sk_buff *skb = NULL;
skb = ieee80211_ADDBA(ieee, dst, pBA, StatusCode, ACT_ADDBARSP); //construct ACT_ADDBARSP frames
if (skb)
{
softmac_mgmt_xmit(skb, ieee);
//same above
}
else
{
IEEE80211_DEBUG(IEEE80211_DL_ERR, "alloc skb error in function %s()\n", __FUNCTION__);
}
return;
}
/********************************************************************************************************************
*function: send ADDBARSP frame out
* input: u8* dst //DELBA frame's destination
* PBA_RECORD pBA //BA_RECORD entry which stores the necessary information for BA
* TR_SELECT TxRxSelect //TX or RX
* u16 ReasonCode //DEL ReasonCode
* output: none
* notice: If any possible, please hide pBA in ieee. And temporarily use Manage Queue as softmac_mgmt_xmit() usually does
********************************************************************************************************************/
void ieee80211_send_DELBA(struct ieee80211_device* ieee, u8* dst, PBA_RECORD pBA, TR_SELECT TxRxSelect, u16 ReasonCode)
{
struct sk_buff *skb = NULL;
skb = ieee80211_DELBA(ieee, dst, pBA, TxRxSelect, ReasonCode); //construct ACT_ADDBARSP frames
if (skb)
{
softmac_mgmt_xmit(skb, ieee);
//same above
}
else
{
IEEE80211_DEBUG(IEEE80211_DL_ERR, "alloc skb error in function %s()\n", __FUNCTION__);
}
return ;
}
/********************************************************************************************************************
*function: RX ADDBAReq
* input: struct sk_buff * skb //incoming ADDBAReq skb.
* return: 0(pass), other(fail)
* notice: As this function need support of QOS, I comment some code out. And when qos is ready, this code need to be support.
********************************************************************************************************************/
int ieee80211_rx_ADDBAReq( struct ieee80211_device* ieee, struct sk_buff *skb)
{
struct ieee80211_hdr_3addr* req = NULL;
u16 rc = 0;
u8 * dst = NULL, *pDialogToken = NULL, *tag = NULL;
PBA_RECORD pBA = NULL;
PBA_PARAM_SET pBaParamSet = NULL;
u16* pBaTimeoutVal = NULL;
PSEQUENCE_CONTROL pBaStartSeqCtrl = NULL;
PRX_TS_RECORD pTS = NULL;
if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 9)
{
IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BAREQ(%d / %d)\n", skb->len, (sizeof( struct ieee80211_hdr_3addr) + 9));
return -1;
}
IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
req = ( struct ieee80211_hdr_3addr*) skb->data;
tag = (u8*)req;
dst = (u8*)(&req->addr2[0]);
tag += sizeof( struct ieee80211_hdr_3addr);
pDialogToken = tag + 2; //category+action
pBaParamSet = (PBA_PARAM_SET)(tag + 3); //+DialogToken
pBaTimeoutVal = (u16*)(tag + 5);
pBaStartSeqCtrl = (PSEQUENCE_CONTROL)(req + 7);
printk("====================>rx ADDBAREQ from :"MAC_FMT"\n", MAC_ARG(dst));
//some other capability is not ready now.
if( (ieee->current_network.qos_data.active == 0) ||
(ieee->pHTInfo->bCurrentHTSupport == false)) //||
// (ieee->pStaQos->bEnableRxImmBA == false) )
{
rc = ADDBA_STATUS_REFUSED;
IEEE80211_DEBUG(IEEE80211_DL_ERR, "Failed to reply on ADDBA_REQ as some capability is not ready(%d, %d)\n", ieee->current_network.qos_data.active, ieee->pHTInfo->bCurrentHTSupport);
goto OnADDBAReq_Fail;
}
// Search for related traffic stream.
// If there is no matched TS, reject the ADDBA request.
if( !GetTs(
ieee,
(PTS_COMMON_INFO*)(&pTS),
dst,
(u8)(pBaParamSet->field.TID),
RX_DIR,
true) )
{
rc = ADDBA_STATUS_REFUSED;
IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't get TS in %s()\n", __FUNCTION__);
goto OnADDBAReq_Fail;
}
pBA = &pTS->RxAdmittedBARecord;
// To Determine the ADDBA Req content
// We can do much more check here, including BufferSize, AMSDU_Support, Policy, StartSeqCtrl...
// I want to check StartSeqCtrl to make sure when we start aggregation!!!
//
if(pBaParamSet->field.BAPolicy == BA_POLICY_DELAYED)
{
rc = ADDBA_STATUS_INVALID_PARAM;
IEEE80211_DEBUG(IEEE80211_DL_ERR, "BA Policy is not correct in %s()\n", __FUNCTION__);
goto OnADDBAReq_Fail;
}
// Admit the ADDBA Request
//
DeActivateBAEntry(ieee, pBA);
pBA->DialogToken = *pDialogToken;
pBA->BaParamSet = *pBaParamSet;
pBA->BaTimeoutValue = *pBaTimeoutVal;
pBA->BaStartSeqCtrl = *pBaStartSeqCtrl;
//for half N mode we only aggregate 1 frame
if (ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev))
pBA->BaParamSet.field.BufferSize = 1;
else
pBA->BaParamSet.field.BufferSize = 32;
ActivateBAEntry(ieee, pBA, pBA->BaTimeoutValue);
ieee80211_send_ADDBARsp(ieee, dst, pBA, ADDBA_STATUS_SUCCESS);
// End of procedure.
return 0;
OnADDBAReq_Fail:
{
BA_RECORD BA;
BA.BaParamSet = *pBaParamSet;
BA.BaTimeoutValue = *pBaTimeoutVal;
BA.DialogToken = *pDialogToken;
BA.BaParamSet.field.BAPolicy = BA_POLICY_IMMEDIATE;
ieee80211_send_ADDBARsp(ieee, dst, &BA, rc);
return 0; //we send RSP out.
}
}
/********************************************************************************************************************
*function: RX ADDBARSP
* input: struct sk_buff * skb //incoming ADDBAReq skb.
* return: 0(pass), other(fail)
* notice: As this function need support of QOS, I comment some code out. And when qos is ready, this code need to be support.
********************************************************************************************************************/
int ieee80211_rx_ADDBARsp( struct ieee80211_device* ieee, struct sk_buff *skb)
{
struct ieee80211_hdr_3addr* rsp = NULL;
PBA_RECORD pPendingBA, pAdmittedBA;
PTX_TS_RECORD pTS = NULL;
u8* dst = NULL, *pDialogToken = NULL, *tag = NULL;
u16* pStatusCode = NULL, *pBaTimeoutVal = NULL;
PBA_PARAM_SET pBaParamSet = NULL;
u16 ReasonCode;
if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 9)
{
IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BARSP(%d / %d)\n", skb->len, (sizeof( struct ieee80211_hdr_3addr) + 9));
return -1;
}
rsp = ( struct ieee80211_hdr_3addr*)skb->data;
tag = (u8*)rsp;
dst = (u8*)(&rsp->addr2[0]);
tag += sizeof( struct ieee80211_hdr_3addr);
pDialogToken = tag + 2;
pStatusCode = (u16*)(tag + 3);
pBaParamSet = (PBA_PARAM_SET)(tag + 5);
pBaTimeoutVal = (u16*)(tag + 7);
// Check the capability
// Since we can always receive A-MPDU, we just check if it is under HT mode.
if( ieee->current_network.qos_data.active == 0 ||
ieee->pHTInfo->bCurrentHTSupport == false ||
ieee->pHTInfo->bCurrentAMPDUEnable == false )
{
IEEE80211_DEBUG(IEEE80211_DL_ERR, "reject to ADDBA_RSP as some capability is not ready(%d, %d, %d)\n",ieee->current_network.qos_data.active, ieee->pHTInfo->bCurrentHTSupport, ieee->pHTInfo->bCurrentAMPDUEnable);
ReasonCode = DELBA_REASON_UNKNOWN_BA;
goto OnADDBARsp_Reject;
}
//
// Search for related TS.
// If there is no TS found, we wil reject ADDBA Rsp by sending DELBA frame.
//
if (!GetTs(
ieee,
(PTS_COMMON_INFO*)(&pTS),
dst,
(u8)(pBaParamSet->field.TID),
TX_DIR,
false) )
{
IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't get TS in %s()\n", __FUNCTION__);
ReasonCode = DELBA_REASON_UNKNOWN_BA;
goto OnADDBARsp_Reject;
}
pTS->bAddBaReqInProgress = false;
pPendingBA = &pTS->TxPendingBARecord;
pAdmittedBA = &pTS->TxAdmittedBARecord;
//
// Check if related BA is waiting for setup.
// If not, reject by sending DELBA frame.
//
if((pAdmittedBA->bValid==true))
{
// Since BA is already setup, we ignore all other ADDBA Response.
IEEE80211_DEBUG(IEEE80211_DL_BA, "OnADDBARsp(): Recv ADDBA Rsp. Drop because already admit it! \n");
return -1;
}
else if((pPendingBA->bValid == false) ||(*pDialogToken != pPendingBA->DialogToken))
{
IEEE80211_DEBUG(IEEE80211_DL_ERR, "OnADDBARsp(): Recv ADDBA Rsp. BA invalid, DELBA! \n");
ReasonCode = DELBA_REASON_UNKNOWN_BA;
goto OnADDBARsp_Reject;
}
else
{
IEEE80211_DEBUG(IEEE80211_DL_BA, "OnADDBARsp(): Recv ADDBA Rsp. BA is admitted! Status code:%X\n", *pStatusCode);
DeActivateBAEntry(ieee, pPendingBA);
}
if(*pStatusCode == ADDBA_STATUS_SUCCESS)
{
//
// Determine ADDBA Rsp content here.
// We can compare the value of BA parameter set that Peer returned and Self sent.
// If it is OK, then admitted. Or we can send DELBA to cancel BA mechanism.
//
if(pBaParamSet->field.BAPolicy == BA_POLICY_DELAYED)
{
// Since this is a kind of ADDBA failed, we delay next ADDBA process.
pTS->bAddBaReqDelayed = true;
DeActivateBAEntry(ieee, pAdmittedBA);
ReasonCode = DELBA_REASON_END_BA;
goto OnADDBARsp_Reject;
}
//
// Admitted condition
//
pAdmittedBA->DialogToken = *pDialogToken;
pAdmittedBA->BaTimeoutValue = *pBaTimeoutVal;
pAdmittedBA->BaStartSeqCtrl = pPendingBA->BaStartSeqCtrl;
pAdmittedBA->BaParamSet = *pBaParamSet;
DeActivateBAEntry(ieee, pAdmittedBA);
ActivateBAEntry(ieee, pAdmittedBA, *pBaTimeoutVal);
}
else
{
// Delay next ADDBA process.
pTS->bAddBaReqDelayed = true;
}
// End of procedure
return 0;
OnADDBARsp_Reject:
{
BA_RECORD BA;
BA.BaParamSet = *pBaParamSet;
ieee80211_send_DELBA(ieee, dst, &BA, TX_DIR, ReasonCode);
return 0;
}
}
/********************************************************************************************************************
*function: RX DELBA
* input: struct sk_buff * skb //incoming ADDBAReq skb.
* return: 0(pass), other(fail)
* notice: As this function need support of QOS, I comment some code out. And when qos is ready, this code need to be support.
********************************************************************************************************************/
int ieee80211_rx_DELBA(struct ieee80211_device* ieee,struct sk_buff *skb)
{
struct ieee80211_hdr_3addr* delba = NULL;
PDELBA_PARAM_SET pDelBaParamSet = NULL;
u16* pReasonCode = NULL;
u8* dst = NULL;
if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 6)
{
IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in DELBA(%d / %d)\n", skb->len, (sizeof( struct ieee80211_hdr_3addr) + 6));
return -1;
}
if(ieee->current_network.qos_data.active == 0 ||
ieee->pHTInfo->bCurrentHTSupport == false )
{
IEEE80211_DEBUG(IEEE80211_DL_ERR, "received DELBA while QOS or HT is not supported(%d, %d)\n",ieee->current_network.qos_data.active, ieee->pHTInfo->bCurrentHTSupport);
return -1;
}
IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
delba = ( struct ieee80211_hdr_3addr*)skb->data;
dst = (u8*)(&delba->addr2[0]);
delba += sizeof( struct ieee80211_hdr_3addr);
pDelBaParamSet = (PDELBA_PARAM_SET)(delba+2);
pReasonCode = (u16*)(delba+4);
if(pDelBaParamSet->field.Initiator == 1)
{
PRX_TS_RECORD pRxTs;
if( !GetTs(
ieee,
(PTS_COMMON_INFO*)&pRxTs,
dst,
(u8)pDelBaParamSet->field.TID,
RX_DIR,
false) )
{
IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't get TS for RXTS in %s()\n", __FUNCTION__);
return -1;
}
RxTsDeleteBA(ieee, pRxTs);
}
else
{
PTX_TS_RECORD pTxTs;
if(!GetTs(
ieee,
(PTS_COMMON_INFO*)&pTxTs,
dst,
(u8)pDelBaParamSet->field.TID,
TX_DIR,
false) )
{
IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't get TS for TXTS in %s()\n", __FUNCTION__);
return -1;
}
pTxTs->bUsingBa = false;
pTxTs->bAddBaReqInProgress = false;
pTxTs->bAddBaReqDelayed = false;
del_timer_sync(&pTxTs->TsAddBaTimer);
//PlatformCancelTimer(Adapter, &pTxTs->TsAddBaTimer);
TxTsDeleteBA(ieee, pTxTs);
}
return 0;
}
//
// ADDBA initiate. This can only be called by TX side.
//
void
TsInitAddBA(
struct ieee80211_device* ieee,
PTX_TS_RECORD pTS,
u8 Policy,
u8 bOverwritePending
)
{
PBA_RECORD pBA = &pTS->TxPendingBARecord;
if(pBA->bValid==true && bOverwritePending==false)
return;
// Set parameters to "Pending" variable set
DeActivateBAEntry(ieee, pBA);
pBA->DialogToken++; // DialogToken: Only keep the latest dialog token
pBA->BaParamSet.field.AMSDU_Support = 0; // Do not support A-MSDU with A-MPDU now!!
pBA->BaParamSet.field.BAPolicy = Policy; // Policy: Delayed or Immediate
pBA->BaParamSet.field.TID = pTS->TsCommonInfo.TSpec.f.TSInfo.field.ucTSID; // TID
// BufferSize: This need to be set according to A-MPDU vector
pBA->BaParamSet.field.BufferSize = 32; // BufferSize: This need to be set according to A-MPDU vector
pBA->BaTimeoutValue = 0; // Timeout value: Set 0 to disable Timer
pBA->BaStartSeqCtrl.field.SeqNum = (pTS->TxCurSeq + 3) % 4096; // Block Ack will start after 3 packets later.
ActivateBAEntry(ieee, pBA, BA_SETUP_TIMEOUT);
ieee80211_send_ADDBAReq(ieee, pTS->TsCommonInfo.Addr, pBA);
}
void
TsInitDelBA( struct ieee80211_device* ieee, PTS_COMMON_INFO pTsCommonInfo, TR_SELECT TxRxSelect)
{
if(TxRxSelect == TX_DIR)
{
PTX_TS_RECORD pTxTs = (PTX_TS_RECORD)pTsCommonInfo;
if(TxTsDeleteBA(ieee, pTxTs))
ieee80211_send_DELBA(
ieee,
pTsCommonInfo->Addr,
(pTxTs->TxAdmittedBARecord.bValid)?(&pTxTs->TxAdmittedBARecord):(&pTxTs->TxPendingBARecord),
TxRxSelect,
DELBA_REASON_END_BA);
}
else if(TxRxSelect == RX_DIR)
{
PRX_TS_RECORD pRxTs = (PRX_TS_RECORD)pTsCommonInfo;
if(RxTsDeleteBA(ieee, pRxTs))
ieee80211_send_DELBA(
ieee,
pTsCommonInfo->Addr,
&pRxTs->RxAdmittedBARecord,
TxRxSelect,
DELBA_REASON_END_BA );
}
}
/********************************************************************************************************************
*function: BA setup timer
* input: unsigned long data //acturally we send TX_TS_RECORD or RX_TS_RECORD to these timer
* return: NULL
* notice:
********************************************************************************************************************/
void BaSetupTimeOut(unsigned long data)
{
PTX_TS_RECORD pTxTs = (PTX_TS_RECORD)data;
pTxTs->bAddBaReqInProgress = false;
pTxTs->bAddBaReqDelayed = true;
pTxTs->TxPendingBARecord.bValid = false;
}
void TxBaInactTimeout(unsigned long data)
{
PTX_TS_RECORD pTxTs = (PTX_TS_RECORD)data;
struct ieee80211_device *ieee = container_of(pTxTs, struct ieee80211_device, TxTsRecord[pTxTs->num]);
TxTsDeleteBA(ieee, pTxTs);
ieee80211_send_DELBA(
ieee,
pTxTs->TsCommonInfo.Addr,
&pTxTs->TxAdmittedBARecord,
TX_DIR,
DELBA_REASON_TIMEOUT);
}
void RxBaInactTimeout(unsigned long data)
{
PRX_TS_RECORD pRxTs = (PRX_TS_RECORD)data;
struct ieee80211_device *ieee = container_of(pRxTs, struct ieee80211_device, RxTsRecord[pRxTs->num]);
RxTsDeleteBA(ieee, pRxTs);
ieee80211_send_DELBA(
ieee,
pRxTs->TsCommonInfo.Addr,
&pRxTs->RxAdmittedBARecord,
RX_DIR,
DELBA_REASON_TIMEOUT);
return ;
}

View File

@ -0,0 +1,481 @@
#ifndef _RTL819XU_HTTYPE_H_
#define _RTL819XU_HTTYPE_H_
//------------------------------------------------------------
// The HT Capability element is present in beacons, association request,
// reassociation request and probe response frames
//------------------------------------------------------------
//
// Operation mode value
//
#define HT_OPMODE_NO_PROTECT 0
#define HT_OPMODE_OPTIONAL 1
#define HT_OPMODE_40MHZ_PROTECT 2
#define HT_OPMODE_MIXED 3
//
// MIMO Power Save Setings
//
#define MIMO_PS_STATIC 0
#define MIMO_PS_DYNAMIC 1
#define MIMO_PS_NOLIMIT 3
//
// There should be 128 bits to cover all of the MCS rates. However, since
// 8190 does not support too much rates, one integer is quite enough.
//
#define sHTCLng 4
#define HT_SUPPORTED_MCS_1SS_BITMAP 0x000000ff
#define HT_SUPPORTED_MCS_2SS_BITMAP 0x0000ff00
#define HT_SUPPORTED_MCS_1SS_2SS_BITMAP HT_MCS_1SS_BITMAP|HT_MCS_1SS_2SS_BITMAP
typedef enum _HT_MCS_RATE{
HT_MCS0 = 0x00000001,
HT_MCS1 = 0x00000002,
HT_MCS2 = 0x00000004,
HT_MCS3 = 0x00000008,
HT_MCS4 = 0x00000010,
HT_MCS5 = 0x00000020,
HT_MCS6 = 0x00000040,
HT_MCS7 = 0x00000080,
HT_MCS8 = 0x00000100,
HT_MCS9 = 0x00000200,
HT_MCS10 = 0x00000400,
HT_MCS11 = 0x00000800,
HT_MCS12 = 0x00001000,
HT_MCS13 = 0x00002000,
HT_MCS14 = 0x00004000,
HT_MCS15 = 0x00008000,
// Do not define MCS32 here although 8190 support MCS32
}HT_MCS_RATE,*PHT_MCS_RATE;
//
// Represent Channel Width in HT Capabilities
//
typedef enum _HT_CHANNEL_WIDTH{
HT_CHANNEL_WIDTH_20 = 0,
HT_CHANNEL_WIDTH_20_40 = 1,
}HT_CHANNEL_WIDTH, *PHT_CHANNEL_WIDTH;
//
// Represent Extention Channel Offset in HT Capabilities
// This is available only in 40Mhz mode.
//
typedef enum _HT_EXTCHNL_OFFSET{
HT_EXTCHNL_OFFSET_NO_EXT = 0,
HT_EXTCHNL_OFFSET_UPPER = 1,
HT_EXTCHNL_OFFSET_NO_DEF = 2,
HT_EXTCHNL_OFFSET_LOWER = 3,
}HT_EXTCHNL_OFFSET, *PHT_EXTCHNL_OFFSET;
typedef enum _CHNLOP{
CHNLOP_NONE = 0, // No Action now
CHNLOP_SCAN = 1, // Scan in progress
CHNLOP_SWBW = 2, // Bandwidth switching in progress
CHNLOP_SWCHNL = 3, // Software Channel switching in progress
} CHNLOP, *PCHNLOP;
// Determine if the Channel Operation is in progress
#define CHHLOP_IN_PROGRESS(_pHTInfo) \
((_pHTInfo)->ChnlOp > CHNLOP_NONE) ? TRUE : FALSE
/*
typedef union _HT_CAPABILITY{
u16 ShortData;
u8 CharData[2];
struct
{
u16 AdvCoding:1;
u16 ChlWidth:1;
u16 MimoPwrSave:2;
u16 GreenField:1;
u16 ShortGI20Mhz:1;
u16 ShortGI40Mhz:1;
u16 STBC:1;
u16 BeamForm:1;
u16 DelayBA:1;
u16 MaxAMSDUSize:1;
u16 DssCCk:1;
u16 PSMP:1;
u16 Rsvd:3;
}Field;
}HT_CAPABILITY, *PHT_CAPABILITY;
typedef union _HT_CAPABILITY_MACPARA{
u8 ShortData;
u8 CharData[1];
struct
{
u8 MaxRxAMPDU:2;
u8 MPDUDensity:2;
u8 Rsvd:4;
}Field;
}HT_CAPABILITY_MACPARA, *PHT_CAPABILITY_MACPARA;
*/
typedef enum _HT_ACTION{
ACT_RECOMMAND_WIDTH = 0,
ACT_MIMO_PWR_SAVE = 1,
ACT_PSMP = 2,
ACT_SET_PCO_PHASE = 3,
ACT_MIMO_CHL_MEASURE = 4,
ACT_RECIPROCITY_CORRECT = 5,
ACT_MIMO_CSI_MATRICS = 6,
ACT_MIMO_NOCOMPR_STEER = 7,
ACT_MIMO_COMPR_STEER = 8,
ACT_ANTENNA_SELECT = 9,
} HT_ACTION, *PHT_ACTION;
/* 2007/06/07 MH Define sub-carrier mode for 40MHZ. */
typedef enum _HT_Bandwidth_40MHZ_Sub_Carrier{
SC_MODE_DUPLICATE = 0,
SC_MODE_LOWER = 1,
SC_MODE_UPPER = 2,
SC_MODE_FULL40MHZ = 3,
}HT_BW40_SC_E;
typedef struct _HT_CAPABILITY_ELE{
//HT capability info
u8 AdvCoding:1;
u8 ChlWidth:1;
u8 MimoPwrSave:2;
u8 GreenField:1;
u8 ShortGI20Mhz:1;
u8 ShortGI40Mhz:1;
u8 TxSTBC:1;
u8 RxSTBC:2;
u8 DelayBA:1;
u8 MaxAMSDUSize:1;
u8 DssCCk:1;
u8 PSMP:1;
u8 Rsvd1:1;
u8 LSigTxopProtect:1;
//MAC HT parameters info
u8 MaxRxAMPDUFactor:2;
u8 MPDUDensity:3;
u8 Rsvd2:3;
//Supported MCS set
u8 MCS[16];
//Extended HT Capability Info
u16 ExtHTCapInfo;
//TXBF Capabilities
u8 TxBFCap[4];
//Antenna Selection Capabilities
u8 ASCap;
} __attribute__ ((packed)) HT_CAPABILITY_ELE, *PHT_CAPABILITY_ELE;
//------------------------------------------------------------
// The HT Information element is present in beacons
// Only AP is required to include this element
//------------------------------------------------------------
typedef struct _HT_INFORMATION_ELE{
u8 ControlChl;
u8 ExtChlOffset:2;
u8 RecommemdedTxWidth:1;
u8 RIFS:1;
u8 PSMPAccessOnly:1;
u8 SrvIntGranularity:3;
u8 OptMode:2;
u8 NonGFDevPresent:1;
u8 Revd1:5;
u8 Revd2:8;
u8 Rsvd3:6;
u8 DualBeacon:1;
u8 DualCTSProtect:1;
u8 SecondaryBeacon:1;
u8 LSigTxopProtectFull:1;
u8 PcoActive:1;
u8 PcoPhase:1;
u8 Rsvd4:4;
u8 BasicMSC[16];
} __attribute__ ((packed)) HT_INFORMATION_ELE, *PHT_INFORMATION_ELE;
//
// MIMO Power Save control field.
// This is appear in MIMO Power Save Action Frame
//
typedef struct _MIMOPS_CTRL{
u8 MimoPsEnable:1;
u8 MimoPsMode:1;
u8 Reserved:6;
} MIMOPS_CTRL, *PMIMOPS_CTRL;
typedef enum _HT_SPEC_VER{
HT_SPEC_VER_IEEE = 0,
HT_SPEC_VER_EWC = 1,
}HT_SPEC_VER, *PHT_SPEC_VER;
typedef enum _HT_AGGRE_MODE_E{
HT_AGG_AUTO = 0,
HT_AGG_FORCE_ENABLE = 1,
HT_AGG_FORCE_DISABLE = 2,
}HT_AGGRE_MODE_E, *PHT_AGGRE_MODE_E;
//------------------------------------------------------------
// The Data structure is used to keep HT related variables when card is
// configured as non-AP STA mode. **Note** Current_xxx should be set
// to default value in HTInitializeHTInfo()
//------------------------------------------------------------
typedef struct _RT_HIGH_THROUGHPUT{
u8 bEnableHT;
u8 bCurrentHTSupport;
u8 bRegBW40MHz; // Tx 40MHz channel capablity
u8 bCurBW40MHz; // Tx 40MHz channel capability
u8 bRegShortGI40MHz; // Tx Short GI for 40Mhz
u8 bCurShortGI40MHz; // Tx Short GI for 40MHz
u8 bRegShortGI20MHz; // Tx Short GI for 20MHz
u8 bCurShortGI20MHz; // Tx Short GI for 20MHz
u8 bRegSuppCCK; // Tx CCK rate capability
u8 bCurSuppCCK; // Tx CCK rate capability
// 802.11n spec version for "peer"
HT_SPEC_VER ePeerHTSpecVer;
// HT related information for "Self"
HT_CAPABILITY_ELE SelfHTCap; // This is HT cap element sent to peer STA, which also indicate HT Rx capabilities.
HT_INFORMATION_ELE SelfHTInfo; // This is HT info element sent to peer STA, which also indicate HT Rx capabilities.
// HT related information for "Peer"
u8 PeerHTCapBuf[32];
u8 PeerHTInfoBuf[32];
// A-MSDU related
u8 bAMSDU_Support; // This indicates Tx A-MSDU capability
u16 nAMSDU_MaxSize; // This indicates Tx A-MSDU capability
u8 bCurrent_AMSDU_Support; // This indicates Tx A-MSDU capability
u16 nCurrent_AMSDU_MaxSize; // This indicates Tx A-MSDU capability
// AMPDU related <2006.08.10 Emily>
u8 bAMPDUEnable; // This indicate Tx A-MPDU capability
u8 bCurrentAMPDUEnable; // This indicate Tx A-MPDU capability
u8 AMPDU_Factor; // This indicate Tx A-MPDU capability
u8 CurrentAMPDUFactor; // This indicate Tx A-MPDU capability
u8 MPDU_Density; // This indicate Tx A-MPDU capability
u8 CurrentMPDUDensity; // This indicate Tx A-MPDU capability
// Forced A-MPDU enable
HT_AGGRE_MODE_E ForcedAMPDUMode;
u8 ForcedAMPDUFactor;
u8 ForcedMPDUDensity;
// Forced A-MSDU enable
HT_AGGRE_MODE_E ForcedAMSDUMode;
u16 ForcedAMSDUMaxSize;
u8 bForcedShortGI;
u8 CurrentOpMode;
// MIMO PS related
u8 SelfMimoPs;
u8 PeerMimoPs;
// 40MHz Channel Offset settings.
HT_EXTCHNL_OFFSET CurSTAExtChnlOffset;
u8 bCurTxBW40MHz; // If we use 40 MHz to Tx
u8 PeerBandwidth;
// For Bandwidth Switching
u8 bSwBwInProgress;
CHNLOP ChnlOp; // software switching channel in progress. By Bruce, 2008-02-15.
u8 SwBwStep;
//struct timer_list SwBwTimer; //moved to ieee80211_device. as timer_list need include some header file here.
// For Realtek proprietary A-MPDU factor for aggregation
u8 bRegRT2RTAggregation;
u8 bCurrentRT2RTAggregation;
u8 bCurrentRT2RTLongSlotTime;
u8 szRT2RTAggBuffer[10];
// Rx Reorder control
u8 bRegRxReorderEnable;
u8 bCurRxReorderEnable;
u8 RxReorderWinSize;
u8 RxReorderPendingTime;
u16 RxReorderDropCounter;
#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
u8 UsbTxAggrNum;
#endif
#ifdef USB_RX_AGGREGATION_SUPPORT
u8 UsbRxFwAggrEn;
u8 UsbRxFwAggrPageNum;
u8 UsbRxFwAggrPacketNum;
u8 UsbRxFwAggrTimeout;
#endif
// Add for Broadcom(Linksys) IOT. Joseph
u8 bIsPeerBcm;
// For IOT issue.
u8 IOTPeer;
u32 IOTAction;
} __attribute__ ((packed)) RT_HIGH_THROUGHPUT, *PRT_HIGH_THROUGHPUT;
//------------------------------------------------------------
// The Data structure is used to keep HT related variable for "each Sta"
// when card is configured as "AP mode"
//------------------------------------------------------------
typedef struct _RT_HTINFO_STA_ENTRY{
u8 bEnableHT;
u8 bSupportCck;
u16 AMSDU_MaxSize;
u8 AMPDU_Factor;
u8 MPDU_Density;
u8 HTHighestOperaRate;
u8 bBw40MHz;
u8 MimoPs;
u8 McsRateSet[16];
}RT_HTINFO_STA_ENTRY, *PRT_HTINFO_STA_ENTRY;
//------------------------------------------------------------
// The Data structure is used to keep HT related variable for "each AP"
// when card is configured as "STA mode"
//------------------------------------------------------------
typedef struct _BSS_HT{
u8 bdSupportHT;
// HT related elements
u8 bdHTCapBuf[32];
u16 bdHTCapLen;
u8 bdHTInfoBuf[32];
u16 bdHTInfoLen;
HT_SPEC_VER bdHTSpecVer;
//HT_CAPABILITY_ELE bdHTCapEle;
//HT_INFORMATION_ELE bdHTInfoEle;
u8 bdRT2RTAggregation;
u8 bdRT2RTLongSlotTime;
} __attribute__ ((packed)) BSS_HT, *PBSS_HT;
typedef struct _MIMO_RSSI{
u32 EnableAntenna;
u32 AntennaA;
u32 AntennaB;
u32 AntennaC;
u32 AntennaD;
u32 Average;
}MIMO_RSSI, *PMIMO_RSSI;
typedef struct _MIMO_EVM{
u32 EVM1;
u32 EVM2;
}MIMO_EVM, *PMIMO_EVM;
typedef struct _FALSE_ALARM_STATISTICS{
u32 Cnt_Parity_Fail;
u32 Cnt_Rate_Illegal;
u32 Cnt_Crc8_fail;
u32 Cnt_all;
}FALSE_ALARM_STATISTICS, *PFALSE_ALARM_STATISTICS;
extern u8 MCS_FILTER_ALL[16];
extern u8 MCS_FILTER_1SS[16];
/* 2007/07/11 MH Modify the macro. Becaus STA may link with a N-AP. If we set
STA in A/B/G mode and AP is still in N mode. The macro will be wrong. We have
to add a macro to judge wireless mode. */
#define PICK_RATE(_nLegacyRate, _nMcsRate) \
(_nMcsRate==0)?(_nLegacyRate&0x7f):(_nMcsRate)
/* 2007/07/12 MH We only define legacy and HT wireless mode now. */
#define LEGACY_WIRELESS_MODE IEEE_MODE_MASK
#define CURRENT_RATE(WirelessMode, LegacyRate, HTRate) \
((WirelessMode & (LEGACY_WIRELESS_MODE))!=0)?\
(LegacyRate):\
(PICK_RATE(LegacyRate, HTRate))
// MCS Bw 40 {1~7, 12~15,32}
#define RATE_ADPT_1SS_MASK 0xFF
#define RATE_ADPT_2SS_MASK 0xF0 //Skip MCS8~11 because mcs7 > mcs6, 9, 10, 11. 2007.01.16 by Emily
#define RATE_ADPT_MCS32_MASK 0x01
#define IS_11N_MCS_RATE(rate) (rate&0x80)
typedef enum _HT_AGGRE_SIZE{
HT_AGG_SIZE_8K = 0,
HT_AGG_SIZE_16K = 1,
HT_AGG_SIZE_32K = 2,
HT_AGG_SIZE_64K = 3,
}HT_AGGRE_SIZE_E, *PHT_AGGRE_SIZE_E;
/* Indicate different AP vendor for IOT issue */
typedef enum _HT_IOT_PEER
{
HT_IOT_PEER_UNKNOWN = 0,
HT_IOT_PEER_REALTEK = 1,
HT_IOT_PEER_BROADCOM = 2,
HT_IOT_PEER_RALINK = 3,
HT_IOT_PEER_ATHEROS = 4,
HT_IOT_PEER_CISCO= 5,
HT_IOT_PEER_MAX = 6
}HT_IOT_PEER_E, *PHTIOT_PEER_E;
//
// IOT Action for different AP
//
typedef enum _HT_IOT_ACTION{
HT_IOT_ACT_TX_USE_AMSDU_4K = 0x00000001,
HT_IOT_ACT_TX_USE_AMSDU_8K = 0x00000002,
HT_IOT_ACT_DISABLE_MCS14 = 0x00000004,
HT_IOT_ACT_DISABLE_MCS15 = 0x00000008,
HT_IOT_ACT_DISABLE_ALL_2SS = 0x00000010,
HT_IOT_ACT_DISABLE_EDCA_TURBO = 0x00000020,
HT_IOT_ACT_MGNT_USE_CCK_6M = 0x00000040,
HT_IOT_ACT_CDD_FSYNC = 0x00000080,
HT_IOT_ACT_PURE_N_MODE = 0x00000100,
HT_IOT_ACT_FORCED_CTS2SELF = 0x00000200,
}HT_IOT_ACTION_E, *PHT_IOT_ACTION_E;
#endif //_RTL819XU_HTTYPE_H_

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,749 @@
#ifndef __INC_QOS_TYPE_H
#define __INC_QOS_TYPE_H
//#include "EndianFree.h"
#define BIT0 0x00000001
#define BIT1 0x00000002
#define BIT2 0x00000004
#define BIT3 0x00000008
#define BIT4 0x00000010
#define BIT5 0x00000020
#define BIT6 0x00000040
#define BIT7 0x00000080
#define BIT8 0x00000100
#define BIT9 0x00000200
#define BIT10 0x00000400
#define BIT11 0x00000800
#define BIT12 0x00001000
#define BIT13 0x00002000
#define BIT14 0x00004000
#define BIT15 0x00008000
#define BIT16 0x00010000
#define BIT17 0x00020000
#define BIT18 0x00040000
#define BIT19 0x00080000
#define BIT20 0x00100000
#define BIT21 0x00200000
#define BIT22 0x00400000
#define BIT23 0x00800000
#define BIT24 0x01000000
#define BIT25 0x02000000
#define BIT26 0x04000000
#define BIT27 0x08000000
#define BIT28 0x10000000
#define BIT29 0x20000000
#define BIT30 0x40000000
#define BIT31 0x80000000
#define MAX_WMMELE_LENGTH 64
//
// QoS mode.
// enum 0, 1, 2, 4: since we can use the OR(|) operation.
//
// QOS_MODE is redefined for enum can't be ++, | under C++ compiler, 2006.05.17, by rcnjko.
//typedef enum _QOS_MODE{
// QOS_DISABLE = 0,
// QOS_WMM = 1,
// QOS_EDCA = 2,
// QOS_HCCA = 4,
//}QOS_MODE,*PQOS_MODE;
//
typedef u32 QOS_MODE, *PQOS_MODE;
#define QOS_DISABLE 0
#define QOS_WMM 1
#define QOS_WMMSA 2
#define QOS_EDCA 4
#define QOS_HCCA 8
#define QOS_WMM_UAPSD 16 //WMM Power Save, 2006-06-14 Isaiah
#define AC_PARAM_SIZE 4
#define WMM_PARAM_ELE_BODY_LEN 18
//
// QoS ACK Policy Field Values
// Ref: WMM spec 2.1.6: QoS Control Field, p.10.
//
typedef enum _ACK_POLICY{
eAckPlc0_ACK = 0x00,
eAckPlc1_NoACK = 0x01,
}ACK_POLICY,*PACK_POLICY;
#define WMM_PARAM_ELEMENT_SIZE (8+(4*AC_PARAM_SIZE))
#if 0
#define GET_QOS_CTRL(_pStart) ReadEF2Byte((u8 *)(_pStart) + 24)
#define SET_QOS_CTRL(_pStart, _value) WriteEF2Byte((u8 *)(_pStart) + 24, _value)
// WMM control field.
#define GET_QOS_CTRL_WMM_UP(_pStart) ((u8)LE_BITS_TO_2BYTE((u8 *)(_pStart)+24, 0, 3))
#define SET_QOS_CTRL_WMM_UP(_pStart, _value) SET_BITS_TO_LE_2BYTE((u8 *)(_pStart)+24, 0, 3, (u8)(_value))
#define GET_QOS_CTRL_WMM_EOSP(_pStart) ((u8)LE_BITS_TO_2BYTE((u8 *)(_pStart)+24, 4, 1))
#define SET_QOS_CTRL_WMM_EOSP(_pStart, _value) SET_BITS_TO_LE_2BYTE((u8 *)(_pStart)+24, 4, 1, (u8)(_value))
#define GET_QOS_CTRL_WMM_ACK_POLICY(_pStart) ((u8)LE_BITS_TO_2BYTE((u8 *)(_pStart)+24, 5, 2))
#define SET_QOS_CTRL_WMM_ACK_POLICY(_pStart, _value) SET_BITS_TO_LE_2BYTE((u8 *)(_pStart)+24, 5, 2, (u8)(_value))
// 802.11e control field (by STA, data)
#define GET_QOS_CTRL_STA_DATA_TID(_pStart) ((u8)LE_BITS_TO_2BYTE((u8 *)(_pStart)+24, 0, 4))
#define SET_QOS_CTRL_STA_DATA_TID(_pStart, _value) SET_BITS_TO_LE_2BYTE((u8 *)(_pStart)+24, 0, 4, (u8)(_value))
#define GET_QOS_CTRL_STA_DATA_QSIZE_FLAG(_pStart) ((u8)LE_BITS_TO_2BYTE((u8 *)(_pStart)+24, 4, 1))
#define SET_QOS_CTRL_STA_DATA_QSIZE_FLAG(_pStart, _value) SET_BITS_TO_LE_2BYTE((u8 *)(_pStart)+24, 4, 1, (u8)(_value))
#define GET_QOS_CTRL_STA_DATA_ACK_POLICY(_pStart) ((u8)LE_BITS_TO_2BYTE((u8 *)(_pStart)+24, 5, 2))
#define SET_QOS_CTRL_STA_DATA_ACK_POLICY(_pStart, _value) SET_BITS_TO_LE_2BYTE((u8 *)(_pStart)+24, 5, 2, (u8)(_value))
#define GET_QOS_CTRL_STA_DATA_TXOP(_pStart) ((u8)LE_BITS_TO_2BYTE((u8 *)(_pStart)+24, 8, 8))
#define SET_QOS_CTRL_STA_DATA_TXOP(_pStart, _value) SET_BITS_TO_LE_2BYTE((u8 *)(_pStart)+24, 8, 8, (u8)(_value))
#define GET_QOS_CTRL_STA_DATA_QSIZE(_pStart) GET_QOS_CTRL_STA_DATA_TXOP(_pStart)
#define SET_QOS_CTRL_STA_DATA_QSIZE(_pStart, _value) SET_QOS_CTRL_STA_DATA_TXOP(_pStart)
// 802.11e control field (by HC, data)
#define GET_QOS_CTRL_HC_DATA_TID(_pStart) ((u8)LE_BITS_TO_2BYTE((u8 *)(_pStart)+24, 0, 4))
#define SET_QOS_CTRL_HC_DATA_TID(_pStart, _value) SET_BITS_TO_LE_2BYTE((u8 *)(_pStart)+24, 0, 4, (u8)(_value))
#define GET_QOS_CTRL_HC_DATA_EOSP(_pStart) ((u8)LE_BITS_TO_2BYTE((u8 *)(_pStart)+24, 4, 1))
#define SET_QOS_CTRL_HC_DATA_EOSP(_pStart, _value) SET_BITS_TO_LE_2BYTE((u8 *)(_pStart)+24, 4, 1, (u8)(_value))
#define GET_QOS_CTRL_HC_DATA_ACK_POLICY(_pStart) ((u8)LE_BITS_TO_2BYTE((u8 *)(_pStart)+24, 5, 2))
#define SET_QOS_CTRL_HC_DATA_ACK_POLICY(_pStart, _value) SET_BITS_TO_LE_2BYTE((u8 *)(_pStart)+24, 5, 2, (u8)(_value))
#define GET_QOS_CTRL_HC_DATA_PS_BUFSTATE(_pStart) ((u8)LE_BITS_TO_2BYTE((u8 *)(_pStart)+24, 8, 8))
#define SET_QOS_CTRL_HC_DATA_PS_BUFSTATE(_pStart, _value) SET_BITS_TO_LE_2BYTE((u8 *)(_pStart)+24, 8, 8, (u8)(_value))
// 802.11e control field (by HC, CFP)
#define GET_QOS_CTRL_HC_CFP_TID(_pStart) ((u8)LE_BITS_TO_2BYTE((u8 *)(_pStart)+24, 0, 4))
#define SET_QOS_CTRL_HC_CFP_TID(_pStart, _value) SET_BITS_TO_LE_2BYTE((u8 *)(_pStart)+24, 0, 4, (u8)(_value))
#define GET_QOS_CTRL_HC_CFP_EOSP(_pStart) ((u8)LE_BITS_TO_2BYTE((u8 *)(_pStart)+24, 4, 1))
#define SET_QOS_CTRL_HC_CFP_EOSP(_pStart, _value) SET_BITS_TO_LE_2BYTE((u8 *)(_pStart)+24, 4, 1, (u8)(_value))
#define GET_QOS_CTRL_HC_CFP_ACK_POLICY(_pStart) ((u8)LE_BITS_TO_2BYTE((u8 *)(_pStart)+24, 5, 2))
#define SET_QOS_CTRL_HC_CFP_ACK_POLICY(_pStart, _value) SET_BITS_TO_LE_2BYTE((u8 *)(_pStart)+24, 5, 2, (u8)(_value))
#define GET_QOS_CTRL_HC_CFP_TXOP_LIMIT(_pStart) ((u8)LE_BITS_TO_2BYTE((u8 *)(_pStart)+24, 8, 8))
#define SET_QOS_CTRL_HC_CFP_TXOP_LIMIT(_pStart, _value) SET_BITS_TO_LE_2BYTE((u8 *)(_pStart)+24, 8, 8, (u8)(_value))
#define SET_WMM_QOS_INFO_FIELD(_pStart, _val) WriteEF1Byte(_pStart, _val)
#define GET_WMM_QOS_INFO_FIELD_PARAMETERSET_COUNT(_pStart) LE_BITS_TO_1BYTE(_pStart, 0, 4)
#define SET_WMM_QOS_INFO_FIELD_PARAMETERSET_COUNT(_pStart, _val) SET_BITS_TO_LE_1BYTE(_pStart, 0, 4, _val)
#define GET_WMM_QOS_INFO_FIELD_AP_UAPSD(_pStart) LE_BITS_TO_1BYTE(_pStart, 7, 1)
#define SET_WMM_QOS_INFO_FIELD_AP_UAPSD(_pStart, _val) SET_BITS_TO_LE_1BYTE(_pStart, 7, 1, _val)
#define GET_WMM_QOS_INFO_FIELD_STA_AC_VO_UAPSD(_pStart) LE_BITS_TO_1BYTE(_pStart, 0, 1)
#define SET_WMM_QOS_INFO_FIELD_STA_AC_VO_UAPSD(_pStart, _val) SET_BITS_TO_LE_1BYTE(_pStart, 0, 1, _val)
#define GET_WMM_QOS_INFO_FIELD_STA_AC_VI_UAPSD(_pStart) LE_BITS_TO_1BYTE(_pStart, 1, 1)
#define SET_WMM_QOS_INFO_FIELD_STA_AC_VI_UAPSD(_pStart, _val) SET_BITS_TO_LE_1BYTE(_pStart, 1, 1, _val)
#define GET_WMM_QOS_INFO_FIELD_STA_AC_BE_UAPSD(_pStart) LE_BITS_TO_1BYTE(_pStart, 2, 1)
#define SET_WMM_QOS_INFO_FIELD_STA_AC_BE_UAPSD(_pStart, _val) SET_BITS_TO_LE_1BYTE(_pStart, 2, 1, _val)
#define GET_WMM_QOS_INFO_FIELD_STA_AC_BK_UAPSD(_pStart) LE_BITS_TO_1BYTE(_pStart, 3, 1)
#define SET_WMM_QOS_INFO_FIELD_STA_AC_BK_UAPSD(_pStart, _val) SET_BITS_TO_LE_1BYTE(_pStart, 3, 1, _val)
#define GET_WMM_QOS_INFO_FIELD_STA_MAX_SP_LEN(_pStart) LE_BITS_TO_1BYTE(_pStart, 5, 2)
#define SET_WMM_QOS_INFO_FIELD_STA_MAX_SP_LEN(_pStart, _val) SET_BITS_TO_LE_1BYTE(_pStart, 5, 2, _val)
#define WMM_INFO_ELEMENT_SIZE 7
#define GET_WMM_INFO_ELE_OUI(_pStart) ((u8 *)(_pStart))
#define SET_WMM_INFO_ELE_OUI(_pStart, _pVal) PlatformMoveMemory(_pStart, _pVal, 3);
#define GET_WMM_INFO_ELE_OUI_TYPE(_pStart) ( EF1Byte( *((u8 *)(_pStart)+3) ) )
#define SET_WMM_INFO_ELE_OUI_TYPE(_pStart, _val) ( *((u8 *)(_pStart)+3) = EF1Byte(_val) )
#define GET_WMM_INFO_ELE_OUI_SUBTYPE(_pStart) ( EF1Byte( *((u8 *)(_pStart)+4) ) )
#define SET_WMM_INFO_ELE_OUI_SUBTYPE(_pStart, _val) ( *((u8 *)(_pStart)+4) = EF1Byte(_val) )
#define GET_WMM_INFO_ELE_VERSION(_pStart) ( EF1Byte( *((u8 *)(_pStart)+5) ) )
#define SET_WMM_INFO_ELE_VERSION(_pStart, _val) ( *((u8 *)(_pStart)+5) = EF1Byte(_val) )
#define GET_WMM_INFO_ELE_QOS_INFO_FIELD(_pStart) ( EF1Byte( *((u8 *)(_pStart)+6) ) )
#define SET_WMM_INFO_ELE_QOS_INFO_FIELD(_pStart, _val) ( *((u8 *)(_pStart)+6) = EF1Byte(_val) )
#define GET_WMM_AC_PARAM_AIFSN(_pStart) ( (u8)LE_BITS_TO_4BYTE(_pStart, 0, 4) )
#define SET_WMM_AC_PARAM_AIFSN(_pStart, _val) SET_BITS_TO_LE_4BYTE(_pStart, 0, 4, _val)
#define GET_WMM_AC_PARAM_ACM(_pStart) ( (u8)LE_BITS_TO_4BYTE(_pStart, 4, 1) )
#define SET_WMM_AC_PARAM_ACM(_pStart, _val) SET_BITS_TO_LE_4BYTE(_pStart, 4, 1, _val)
#define GET_WMM_AC_PARAM_ACI(_pStart) ( (u8)LE_BITS_TO_4BYTE(_pStart, 5, 2) )
#define SET_WMM_AC_PARAM_ACI(_pStart, _val) SET_BITS_TO_LE_4BYTE(_pStart, 5, 2, _val)
#define GET_WMM_AC_PARAM_ACI_AIFSN(_pStart) ( (u8)LE_BITS_TO_4BYTE(_pStart, 0, 8) )
#define SET_WMM_AC_PARAM_ACI_AIFSN(_pStart, _val) SET_BTIS_TO_LE_4BYTE(_pStart, 0, 8, _val)
#define GET_WMM_AC_PARAM_ECWMIN(_pStart) ( (u8)LE_BITS_TO_4BYTE(_pStart, 8, 4) )
#define SET_WMM_AC_PARAM_ECWMIN(_pStart, _val) SET_BITS_TO_LE_4BYTE(_pStart, 8, 4, _val)
#define GET_WMM_AC_PARAM_ECWMAX(_pStart) ( (u8)LE_BITS_TO_4BYTE(_pStart, 12, 4) )
#define SET_WMM_AC_PARAM_ECWMAX(_pStart, _val) SET_BITS_TO_LE_4BYTE(_pStart, 12, 4, _val)
#define GET_WMM_AC_PARAM_TXOP_LIMIT(_pStart) ( (u16)LE_BITS_TO_4BYTE(_pStart, 16, 16) )
#define SET_WMM_AC_PARAM_TXOP_LIMIT(_pStart, _val) SET_BITS_TO_LE_4BYTE(_pStart, 16, 16, _val)
#define GET_WMM_PARAM_ELE_OUI(_pStart) ((u8 *)(_pStart))
#define SET_WMM_PARAM_ELE_OUI(_pStart, _pVal) PlatformMoveMemory(_pStart, _pVal, 3)
#define GET_WMM_PARAM_ELE_OUI_TYPE(_pStart) ( EF1Byte( *((u8 *)(_pStart)+3) ) )
#define SET_WMM_PARAM_ELE_OUI_TYPE(_pStart, _val) ( *((u8 *)(_pStart)+3) = EF1Byte(_val) )
#define GET_WMM_PARAM_ELE_OUI_SUBTYPE(_pStart) ( EF1Byte( *((u8 *)(_pStart)+4) ) )
#define SET_WMM_PARAM_ELE_OUI_SUBTYPE(_pStart, _val) ( *((u8 *)(_pStart)+4) = EF1Byte(_val) )
#define GET_WMM_PARAM_ELE_VERSION(_pStart) ( EF1Byte( *((u8 *)(_pStart)+5) ) )
#define SET_WMM_PARAM_ELE_VERSION(_pStart, _val) ( *((u8 *)(_pStart)+5) = EF1Byte(_val) )
#define GET_WMM_PARAM_ELE_QOS_INFO_FIELD(_pStart) ( EF1Byte( *((u8 *)(_pStart)+6) ) )
#define SET_WMM_PARAM_ELE_QOS_INFO_FIELD(_pStart, _val) ( *((u8 *)(_pStart)+6) = EF1Byte(_val) )
#define GET_WMM_PARAM_ELE_AC_PARAM(_pStart) ( (u8 *)(_pStart)+8 )
#define SET_WMM_PARAM_ELE_AC_PARAM(_pStart, _pVal) PlatformMoveMemory((_pStart)+8, _pVal, 16)
#endif
//
// QoS Control Field
// Ref:
// 1. WMM spec 2.1.6: QoS Control Field, p.9.
// 2. 802.11e/D13.0 7.1.3.5, p.26.
//
typedef union _QOS_CTRL_FIELD{
u8 charData[2];
u16 shortData;
// WMM spec
struct
{
u8 UP:3;
u8 usRsvd1:1;
u8 EOSP:1;
u8 AckPolicy:2;
u8 usRsvd2:1;
u8 ucRsvdByte;
}WMM;
// 802.11e: QoS data type frame sent by non-AP QSTAs.
struct
{
u8 TID:4;
u8 bIsQsize:1;// 0: BIT[8:15] is TXOP Duration Requested, 1: BIT[8:15] is Queue Size.
u8 AckPolicy:2;
u8 usRsvd:1;
u8 TxopOrQsize; // (BIT4=0)TXOP Duration Requested or (BIT4=1)Queue Size.
}BySta;
// 802.11e: QoS data, QoS Null, and QoS Data+CF-Ack frames sent by HC.
struct
{
u8 TID:4;
u8 EOSP:1;
u8 AckPolicy:2;
u8 usRsvd:1;
u8 PSBufState; // QAP PS Buffer State.
}ByHc_Data;
// 802.11e: QoS (+) CF-Poll frames sent by HC.
struct
{
u8 TID:4;
u8 EOSP:1;
u8 AckPolicy:2;
u8 usRsvd:1;
u8 TxopLimit; // TXOP Limit.
}ByHc_CFP;
}QOS_CTRL_FIELD, *PQOS_CTRL_FIELD;
//
// QoS Info Field
// Ref:
// 1. WMM spec 2.2.1: WME Information Element, p.11.
// 2. 8185 QoS code: QOS_INFO [def. in QoS_mp.h]
//
typedef union _QOS_INFO_FIELD{
u8 charData;
struct
{
u8 ucParameterSetCount:4;
u8 ucReserved:4;
}WMM;
struct
{
//Ref WMM_Specification_1-1.pdf, 2006-06-13 Isaiah
u8 ucAC_VO_UAPSD:1;
u8 ucAC_VI_UAPSD:1;
u8 ucAC_BE_UAPSD:1;
u8 ucAC_BK_UAPSD:1;
u8 ucReserved1:1;
u8 ucMaxSPLen:2;
u8 ucReserved2:1;
}ByWmmPsSta;
struct
{
//Ref WMM_Specification_1-1.pdf, 2006-06-13 Isaiah
u8 ucParameterSetCount:4;
u8 ucReserved:3;
u8 ucApUapsd:1;
}ByWmmPsAp;
struct
{
u8 ucAC3_UAPSD:1;
u8 ucAC2_UAPSD:1;
u8 ucAC1_UAPSD:1;
u8 ucAC0_UAPSD:1;
u8 ucQAck:1;
u8 ucMaxSPLen:2;
u8 ucMoreDataAck:1;
} By11eSta;
struct
{
u8 ucParameterSetCount:4;
u8 ucQAck:1;
u8 ucQueueReq:1;
u8 ucTXOPReq:1;
u8 ucReserved:1;
} By11eAp;
struct
{
u8 ucReserved1:4;
u8 ucQAck:1;
u8 ucReserved2:2;
u8 ucMoreDataAck:1;
} ByWmmsaSta;
struct
{
u8 ucReserved1:4;
u8 ucQAck:1;
u8 ucQueueReq:1;
u8 ucTXOPReq:1;
u8 ucReserved2:1;
} ByWmmsaAp;
struct
{
u8 ucAC3_UAPSD:1;
u8 ucAC2_UAPSD:1;
u8 ucAC1_UAPSD:1;
u8 ucAC0_UAPSD:1;
u8 ucQAck:1;
u8 ucMaxSPLen:2;
u8 ucMoreDataAck:1;
} ByAllSta;
struct
{
u8 ucParameterSetCount:4;
u8 ucQAck:1;
u8 ucQueueReq:1;
u8 ucTXOPReq:1;
u8 ucApUapsd:1;
} ByAllAp;
}QOS_INFO_FIELD, *PQOS_INFO_FIELD;
#if 0
//
// WMM Information Element
// Ref: WMM spec 2.2.1: WME Information Element, p.10.
//
typedef struct _WMM_INFO_ELEMENT{
// u8 ElementID;
// u8 Length;
u8 OUI[3];
u8 OUI_Type;
u8 OUI_SubType;
u8 Version;
QOS_INFO_FIELD QosInfo;
}WMM_INFO_ELEMENT, *PWMM_INFO_ELEMENT;
#endif
//
// ACI to AC coding.
// Ref: WMM spec 2.2.2: WME Parameter Element, p.13.
//
// AC_CODING is redefined for enum can't be ++, | under C++ compiler, 2006.05.17, by rcnjko.
//typedef enum _AC_CODING{
// AC0_BE = 0, // ACI: 0x00 // Best Effort
// AC1_BK = 1, // ACI: 0x01 // Background
// AC2_VI = 2, // ACI: 0x10 // Video
// AC3_VO = 3, // ACI: 0x11 // Voice
// AC_MAX = 4, // Max: define total number; Should not to be used as a real enum.
//}AC_CODING,*PAC_CODING;
//
typedef u32 AC_CODING;
#define AC0_BE 0 // ACI: 0x00 // Best Effort
#define AC1_BK 1 // ACI: 0x01 // Background
#define AC2_VI 2 // ACI: 0x10 // Video
#define AC3_VO 3 // ACI: 0x11 // Voice
#define AC_MAX 4 // Max: define total number; Should not to be used as a real enum.
//
// ACI/AIFSN Field.
// Ref: WMM spec 2.2.2: WME Parameter Element, p.12.
//
typedef union _ACI_AIFSN{
u8 charData;
struct
{
u8 AIFSN:4;
u8 ACM:1;
u8 ACI:2;
u8 Reserved:1;
}f; // Field
}ACI_AIFSN, *PACI_AIFSN;
//
// ECWmin/ECWmax field.
// Ref: WMM spec 2.2.2: WME Parameter Element, p.13.
//
typedef union _ECW{
u8 charData;
struct
{
u8 ECWmin:4;
u8 ECWmax:4;
}f; // Field
}ECW, *PECW;
//
// AC Parameters Record Format.
// Ref: WMM spec 2.2.2: WME Parameter Element, p.12.
//
typedef union _AC_PARAM{
u32 longData;
u8 charData[4];
struct
{
ACI_AIFSN AciAifsn;
ECW Ecw;
u16 TXOPLimit;
}f; // Field
}AC_PARAM, *PAC_PARAM;
//
// QoS element subtype
//
typedef enum _QOS_ELE_SUBTYPE{
QOSELE_TYPE_INFO = 0x00, // 0x00: Information element
QOSELE_TYPE_PARAM = 0x01, // 0x01: parameter element
}QOS_ELE_SUBTYPE,*PQOS_ELE_SUBTYPE;
//
// Direction Field Values.
// Ref: WMM spec 2.2.11: WME TSPEC Element, p.18.
//
typedef enum _DIRECTION_VALUE{
DIR_UP = 0, // 0x00 // UpLink
DIR_DOWN = 1, // 0x01 // DownLink
DIR_DIRECT = 2, // 0x10 // DirectLink
DIR_BI_DIR = 3, // 0x11 // Bi-Direction
}DIRECTION_VALUE,*PDIRECTION_VALUE;
//
// TS Info field in WMM TSPEC Element.
// Ref:
// 1. WMM spec 2.2.11: WME TSPEC Element, p.18.
// 2. 8185 QoS code: QOS_TSINFO [def. in QoS_mp.h]
//
typedef union _QOS_TSINFO{
u8 charData[3];
struct {
u8 ucTrafficType:1; //WMM is reserved
u8 ucTSID:4;
u8 ucDirection:2;
u8 ucAccessPolicy:2; //WMM: bit8=0, bit7=1
u8 ucAggregation:1; //WMM is reserved
u8 ucPSB:1; //WMMSA is APSD
u8 ucUP:3;
u8 ucTSInfoAckPolicy:2; //WMM is reserved
u8 ucSchedule:1; //WMM is reserved
u8 ucReserved:7;
}field;
}QOS_TSINFO, *PQOS_TSINFO;
//
// WMM TSPEC Body.
// Ref: WMM spec 2.2.11: WME TSPEC Element, p.16.
//
typedef union _TSPEC_BODY{
u8 charData[55];
struct
{
QOS_TSINFO TSInfo; //u8 TSInfo[3];
u16 NominalMSDUsize;
u16 MaxMSDUsize;
u32 MinServiceItv;
u32 MaxServiceItv;
u32 InactivityItv;
u32 SuspenItv;
u32 ServiceStartTime;
u32 MinDataRate;
u32 MeanDataRate;
u32 PeakDataRate;
u32 MaxBurstSize;
u32 DelayBound;
u32 MinPhyRate;
u16 SurplusBandwidthAllowance;
u16 MediumTime;
} f; // Field
}TSPEC_BODY, *PTSPEC_BODY;
//
// WMM TSPEC Element.
// Ref: WMM spec 2.2.11: WME TSPEC Element, p.16.
//
typedef struct _WMM_TSPEC{
u8 ID;
u8 Length;
u8 OUI[3];
u8 OUI_Type;
u8 OUI_SubType;
u8 Version;
TSPEC_BODY Body;
} WMM_TSPEC, *PWMM_TSPEC;
//
// ACM implementation method.
// Annie, 2005-12-13.
//
typedef enum _ACM_METHOD{
eAcmWay0_SwAndHw = 0, // By SW and HW.
eAcmWay1_HW = 1, // By HW.
eAcmWay2_SW = 2, // By SW.
}ACM_METHOD,*PACM_METHOD;
typedef struct _ACM{
// u8 RegEnableACM;
u64 UsedTime;
u64 MediumTime;
u8 HwAcmCtl; // TRUE: UsedTime exceed => Do NOT USE this AC. It wll be written to ACM_CONTROL(0xBF BIT 0/1/2 in 8185B).
}ACM, *PACM;
typedef u8 AC_UAPSD, *PAC_UAPSD;
#define GET_VO_UAPSD(_apsd) ((_apsd) & BIT0)
#define SET_VO_UAPSD(_apsd) ((_apsd) |= BIT0)
#define GET_VI_UAPSD(_apsd) ((_apsd) & BIT1)
#define SET_VI_UAPSD(_apsd) ((_apsd) |= BIT1)
#define GET_BK_UAPSD(_apsd) ((_apsd) & BIT2)
#define SET_BK_UAPSD(_apsd) ((_apsd) |= BIT2)
#define GET_BE_UAPSD(_apsd) ((_apsd) & BIT3)
#define SET_BE_UAPSD(_apsd) ((_apsd) |= BIT3)
//typedef struct _TCLASS{
// TODO
//} TCLASS, *PTCLASS;
typedef union _QOS_TCLAS{
struct _TYPE_GENERAL{
u8 Priority;
u8 ClassifierType;
u8 Mask;
} TYPE_GENERAL;
struct _TYPE0_ETH{
u8 Priority;
u8 ClassifierType;
u8 Mask;
u8 SrcAddr[6];
u8 DstAddr[6];
u16 Type;
} TYPE0_ETH;
struct _TYPE1_IPV4{
u8 Priority;
u8 ClassifierType;
u8 Mask;
u8 Version;
u8 SrcIP[4];
u8 DstIP[4];
u16 SrcPort;
u16 DstPort;
u8 DSCP;
u8 Protocol;
u8 Reserved;
} TYPE1_IPV4;
struct _TYPE1_IPV6{
u8 Priority;
u8 ClassifierType;
u8 Mask;
u8 Version;
u8 SrcIP[16];
u8 DstIP[16];
u16 SrcPort;
u16 DstPort;
u8 FlowLabel[3];
} TYPE1_IPV6;
struct _TYPE2_8021Q{
u8 Priority;
u8 ClassifierType;
u8 Mask;
u16 TagType;
} TYPE2_8021Q;
} QOS_TCLAS, *PQOS_TCLAS;
//typedef struct _WMM_TSTREAM{
//
//- TSPEC
//- AC (which to mapping)
//} WMM_TSTREAM, *PWMM_TSTREAM;
typedef struct _QOS_TSTREAM{
u8 AC;
WMM_TSPEC TSpec;
QOS_TCLAS TClass;
} QOS_TSTREAM, *PQOS_TSTREAM;
//typedef struct _U_APSD{
//- TriggerEnable [4]
//- MaxSPLength
//- HighestAcBuffered
//} U_APSD, *PU_APSD;
//joseph TODO:
// UAPSD function should be implemented by 2 data structure
// "Qos control field" and "Qos info field"
//typedef struct _QOS_UAPSD{
// u8 bTriggerEnable[4];
// u8 MaxSPLength;
// u8 HighestBufAC;
//} QOS_UAPSD, *PQOS_APSD;
//----------------------------------------------------------------------------
// 802.11 Management frame Status Code field
//----------------------------------------------------------------------------
typedef struct _OCTET_STRING{
u8 *Octet;
u16 Length;
}OCTET_STRING, *POCTET_STRING;
#if 0
#define FillOctetString(_os,_octet,_len) \
(_os).Octet=(u8 *)(_octet); \
(_os).Length=(_len);
#define WMM_ELEM_HDR_LEN 6
#define WMMElemSkipHdr(_osWMMElem) \
(_osWMMElem).Octet += WMM_ELEM_HDR_LEN; \
(_osWMMElem).Length -= WMM_ELEM_HDR_LEN;
#endif
//
// STA QoS data.
// Ref: DOT11_QOS in 8185 code. [def. in QoS_mp.h]
//
typedef struct _STA_QOS{
//DECLARE_RT_OBJECT(STA_QOS);
u8 WMMIEBuf[MAX_WMMELE_LENGTH];
u8* WMMIE;
// Part 1. Self QoS Mode.
QOS_MODE QosCapability; //QoS Capability, 2006-06-14 Isaiah
QOS_MODE CurrentQosMode;
// For WMM Power Save Mode :
// ACs are trigger/delivery enabled or legacy power save enabled. 2006-06-13 Isaiah
AC_UAPSD b4ac_Uapsd; //VoUapsd(bit0), ViUapsd(bit1), BkUapsd(bit2), BeUapsd(bit3),
AC_UAPSD Curr4acUapsd;
u8 bInServicePeriod;
u8 MaxSPLength;
int NumBcnBeforeTrigger;
// Part 2. EDCA Parameter (perAC)
u8 * pWMMInfoEle;
u8 WMMParamEle[WMM_PARAM_ELEMENT_SIZE];
u8 WMMPELength;
// <Bruce_Note>
//2 ToDo: remove the Qos Info Field and replace it by the above WMM Info element.
// By Bruce, 2008-01-30.
// Part 2. EDCA Parameter (perAC)
QOS_INFO_FIELD QosInfoField_STA; // Maintained by STA
QOS_INFO_FIELD QosInfoField_AP; // Retrieved from AP
AC_PARAM CurAcParameters[4];
// Part 3. ACM
ACM acm[4];
ACM_METHOD AcmMethod;
// Part 4. Per TID (Part 5: TCLASS will be described by TStream)
QOS_TSTREAM TStream[16];
WMM_TSPEC TSpec;
u32 QBssWirelessMode;
// No Ack Setting
u8 bNoAck;
// Enable/Disable Rx immediate BA capability.
u8 bEnableRxImmBA;
}STA_QOS, *PSTA_QOS;
//
// BSS QOS data.
// Ref: BssDscr in 8185 code. [def. in BssDscr.h]
//
typedef struct _BSS_QOS{
QOS_MODE bdQoSMode;
u8 bdWMMIEBuf[MAX_WMMELE_LENGTH];
u8* bdWMMIE;
QOS_ELE_SUBTYPE EleSubType;
u8 * pWMMInfoEle;
u8 * pWMMParamEle;
QOS_INFO_FIELD QosInfoField;
AC_PARAM AcParameter[4];
}BSS_QOS, *PBSS_QOS;
//
// Ref: sQoSCtlLng and QoSCtl definition in 8185 QoS code.
//#define QoSCtl (( (Adapter->bRegQoS) && (Adapter->dot11QoS.QoSMode &(QOS_EDCA|QOS_HCCA)) ) ?sQoSCtlLng:0)
//
#define sQoSCtlLng 2
#define QOS_CTRL_LEN(_QosMode) ((_QosMode > QOS_DISABLE)? sQoSCtlLng : 0)
//Added by joseph
//UP Mapping to AC, using in MgntQuery_SequenceNumber() and maybe for DSCP
//#define UP2AC(up) ((up<3)?((up==0)?1:0):(up>>1))
#define IsACValid(ac) ((ac<=7 )?true:false )
#endif // #ifndef __INC_QOS_TYPE_H

View File

@ -0,0 +1,56 @@
#ifndef _TSTYPE_H_
#define _TSTYPE_H_
#include "rtl819x_Qos.h"
#define TS_SETUP_TIMEOUT 60 // In millisecond
#define TS_INACT_TIMEOUT 60
#define TS_ADDBA_DELAY 60
#define TOTAL_TS_NUM 16
#define TCLAS_NUM 4
// This define the Tx/Rx directions
typedef enum _TR_SELECT {
TX_DIR = 0,
RX_DIR = 1,
} TR_SELECT, *PTR_SELECT;
typedef struct _TS_COMMON_INFO{
struct list_head List;
struct timer_list SetupTimer;
struct timer_list InactTimer;
u8 Addr[6];
TSPEC_BODY TSpec;
QOS_TCLAS TClass[TCLAS_NUM];
u8 TClasProc;
u8 TClasNum;
} TS_COMMON_INFO, *PTS_COMMON_INFO;
typedef struct _TX_TS_RECORD{
TS_COMMON_INFO TsCommonInfo;
u16 TxCurSeq;
BA_RECORD TxPendingBARecord; // For BA Originator
BA_RECORD TxAdmittedBARecord; // For BA Originator
// QOS_DL_RECORD DLRecord;
u8 bAddBaReqInProgress;
u8 bAddBaReqDelayed;
u8 bUsingBa;
struct timer_list TsAddBaTimer;
u8 num;
} TX_TS_RECORD, *PTX_TS_RECORD;
typedef struct _RX_TS_RECORD {
TS_COMMON_INFO TsCommonInfo;
u16 RxIndicateSeq;
u16 RxTimeoutIndicateSeq;
struct list_head RxPendingPktList;
struct timer_list RxPktPendingTimer;
BA_RECORD RxAdmittedBARecord; // For BA Recepient
u16 RxLastSeqNum;
u8 RxLastFragNum;
u8 num;
// QOS_DL_RECORD DLRecord;
} RX_TS_RECORD, *PRX_TS_RECORD;
#endif

View File

@ -0,0 +1,654 @@
#include "ieee80211.h"
#include <linux/etherdevice.h>
#include "rtl819x_TS.h"
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
#define list_for_each_entry_safe(pos, n, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member), \
n = list_entry(pos->member.next, typeof(*pos), member); \
&pos->member != (head); \
pos = n, n = list_entry(n->member.next, typeof(*n), member))
#endif
void TsSetupTimeOut(unsigned long data)
{
// Not implement yet
// This is used for WMMSA and ACM , that would send ADDTSReq frame.
}
void TsInactTimeout(unsigned long data)
{
// Not implement yet
// This is used for WMMSA and ACM.
// This function would be call when TS is no Tx/Rx for some period of time.
}
/********************************************************************************************************************
*function: I still not understand this function, so wait for further implementation
* input: unsigned long data //acturally we send TX_TS_RECORD or RX_TS_RECORD to these timer
* return: NULL
* notice:
********************************************************************************************************************/
#if 1
void RxPktPendingTimeout(unsigned long data)
{
PRX_TS_RECORD pRxTs = (PRX_TS_RECORD)data;
struct ieee80211_device *ieee = container_of(pRxTs, struct ieee80211_device, RxTsRecord[pRxTs->num]);
PRX_REORDER_ENTRY pReorderEntry = NULL;
//u32 flags = 0;
unsigned long flags = 0;
struct ieee80211_rxb *stats_IndicateArray[REORDER_WIN_SIZE];
u8 index = 0;
bool bPktInBuf = false;
spin_lock_irqsave(&(ieee->reorder_spinlock), flags);
//PlatformAcquireSpinLock(Adapter, RT_RX_SPINLOCK);
IEEE80211_DEBUG(IEEE80211_DL_REORDER,"==================>%s()\n",__FUNCTION__);
if(pRxTs->RxTimeoutIndicateSeq != 0xffff)
{
// Indicate the pending packets sequentially according to SeqNum until meet the gap.
while(!list_empty(&pRxTs->RxPendingPktList))
{
pReorderEntry = (PRX_REORDER_ENTRY)list_entry(pRxTs->RxPendingPktList.prev,RX_REORDER_ENTRY,List);
if(index == 0)
pRxTs->RxIndicateSeq = pReorderEntry->SeqNum;
if( SN_LESS(pReorderEntry->SeqNum, pRxTs->RxIndicateSeq) ||
SN_EQUAL(pReorderEntry->SeqNum, pRxTs->RxIndicateSeq) )
{
list_del_init(&pReorderEntry->List);
if(SN_EQUAL(pReorderEntry->SeqNum, pRxTs->RxIndicateSeq))
pRxTs->RxIndicateSeq = (pRxTs->RxIndicateSeq + 1) % 4096;
IEEE80211_DEBUG(IEEE80211_DL_REORDER,"RxPktPendingTimeout(): IndicateSeq: %d\n", pReorderEntry->SeqNum);
stats_IndicateArray[index] = pReorderEntry->prxb;
index++;
list_add_tail(&pReorderEntry->List, &ieee->RxReorder_Unused_List);
}
else
{
bPktInBuf = true;
break;
}
}
}
if(index>0)
{
// Set RxTimeoutIndicateSeq to 0xffff to indicate no pending packets in buffer now.
pRxTs->RxTimeoutIndicateSeq = 0xffff;
// Indicate packets
if(index > REORDER_WIN_SIZE){
IEEE80211_DEBUG(IEEE80211_DL_ERR, "RxReorderIndicatePacket(): Rx Reorer buffer full!! \n");
spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags);
return;
}
ieee80211_indicate_packets(ieee, stats_IndicateArray, index);
}
if(bPktInBuf && (pRxTs->RxTimeoutIndicateSeq==0xffff))
{
pRxTs->RxTimeoutIndicateSeq = pRxTs->RxIndicateSeq;
if(timer_pending(&pRxTs->RxPktPendingTimer))
del_timer_sync(&pRxTs->RxPktPendingTimer);
pRxTs->RxPktPendingTimer.expires = jiffies + ieee->pHTInfo->RxReorderPendingTime;
add_timer(&pRxTs->RxPktPendingTimer);
}
spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags);
//PlatformReleaseSpinLock(Adapter, RT_RX_SPINLOCK);
}
#endif
/********************************************************************************************************************
*function: Add BA timer function
* input: unsigned long data //acturally we send TX_TS_RECORD or RX_TS_RECORD to these timer
* return: NULL
* notice:
********************************************************************************************************************/
void TsAddBaProcess(unsigned long data)
{
PTX_TS_RECORD pTxTs = (PTX_TS_RECORD)data;
u8 num = pTxTs->num;
struct ieee80211_device *ieee = container_of(pTxTs, struct ieee80211_device, TxTsRecord[num]);
TsInitAddBA(ieee, pTxTs, BA_POLICY_IMMEDIATE, false);
IEEE80211_DEBUG(IEEE80211_DL_BA, "TsAddBaProcess(): ADDBA Req is started!! \n");
}
void ResetTsCommonInfo(PTS_COMMON_INFO pTsCommonInfo)
{
memset(pTsCommonInfo->Addr, 0, 6);
memset(&pTsCommonInfo->TSpec, 0, sizeof(TSPEC_BODY));
memset(&pTsCommonInfo->TClass, 0, sizeof(QOS_TCLAS)*TCLAS_NUM);
pTsCommonInfo->TClasProc = 0;
pTsCommonInfo->TClasNum = 0;
}
void ResetTxTsEntry(PTX_TS_RECORD pTS)
{
ResetTsCommonInfo(&pTS->TsCommonInfo);
pTS->TxCurSeq = 0;
pTS->bAddBaReqInProgress = false;
pTS->bAddBaReqDelayed = false;
pTS->bUsingBa = false;
ResetBaEntry(&pTS->TxAdmittedBARecord); //For BA Originator
ResetBaEntry(&pTS->TxPendingBARecord);
}
void ResetRxTsEntry(PRX_TS_RECORD pTS)
{
ResetTsCommonInfo(&pTS->TsCommonInfo);
pTS->RxIndicateSeq = 0xffff; // This indicate the RxIndicateSeq is not used now!!
pTS->RxTimeoutIndicateSeq = 0xffff; // This indicate the RxTimeoutIndicateSeq is not used now!!
ResetBaEntry(&pTS->RxAdmittedBARecord); // For BA Recepient
}
void TSInitialize(struct ieee80211_device *ieee)
{
PTX_TS_RECORD pTxTS = ieee->TxTsRecord;
PRX_TS_RECORD pRxTS = ieee->RxTsRecord;
PRX_REORDER_ENTRY pRxReorderEntry = ieee->RxReorderEntry;
u8 count = 0;
IEEE80211_DEBUG(IEEE80211_DL_TS, "==========>%s()\n", __FUNCTION__);
// Initialize Tx TS related info.
INIT_LIST_HEAD(&ieee->Tx_TS_Admit_List);
INIT_LIST_HEAD(&ieee->Tx_TS_Pending_List);
INIT_LIST_HEAD(&ieee->Tx_TS_Unused_List);
for(count = 0; count < TOTAL_TS_NUM; count++)
{
//
pTxTS->num = count;
// The timers for the operation of Traffic Stream and Block Ack.
// DLS related timer will be add here in the future!!
init_timer(&pTxTS->TsCommonInfo.SetupTimer);
pTxTS->TsCommonInfo.SetupTimer.data = (unsigned long)pTxTS;
pTxTS->TsCommonInfo.SetupTimer.function = TsSetupTimeOut;
init_timer(&pTxTS->TsCommonInfo.InactTimer);
pTxTS->TsCommonInfo.InactTimer.data = (unsigned long)pTxTS;
pTxTS->TsCommonInfo.InactTimer.function = TsInactTimeout;
init_timer(&pTxTS->TsAddBaTimer);
pTxTS->TsAddBaTimer.data = (unsigned long)pTxTS;
pTxTS->TsAddBaTimer.function = TsAddBaProcess;
init_timer(&pTxTS->TxPendingBARecord.Timer);
pTxTS->TxPendingBARecord.Timer.data = (unsigned long)pTxTS;
pTxTS->TxPendingBARecord.Timer.function = BaSetupTimeOut;
init_timer(&pTxTS->TxAdmittedBARecord.Timer);
pTxTS->TxAdmittedBARecord.Timer.data = (unsigned long)pTxTS;
pTxTS->TxAdmittedBARecord.Timer.function = TxBaInactTimeout;
ResetTxTsEntry(pTxTS);
list_add_tail(&pTxTS->TsCommonInfo.List, &ieee->Tx_TS_Unused_List);
pTxTS++;
}
// Initialize Rx TS related info.
INIT_LIST_HEAD(&ieee->Rx_TS_Admit_List);
INIT_LIST_HEAD(&ieee->Rx_TS_Pending_List);
INIT_LIST_HEAD(&ieee->Rx_TS_Unused_List);
for(count = 0; count < TOTAL_TS_NUM; count++)
{
pRxTS->num = count;
INIT_LIST_HEAD(&pRxTS->RxPendingPktList);
init_timer(&pRxTS->TsCommonInfo.SetupTimer);
pRxTS->TsCommonInfo.SetupTimer.data = (unsigned long)pRxTS;
pRxTS->TsCommonInfo.SetupTimer.function = TsSetupTimeOut;
init_timer(&pRxTS->TsCommonInfo.InactTimer);
pRxTS->TsCommonInfo.InactTimer.data = (unsigned long)pRxTS;
pRxTS->TsCommonInfo.InactTimer.function = TsInactTimeout;
init_timer(&pRxTS->RxAdmittedBARecord.Timer);
pRxTS->RxAdmittedBARecord.Timer.data = (unsigned long)pRxTS;
pRxTS->RxAdmittedBARecord.Timer.function = RxBaInactTimeout;
init_timer(&pRxTS->RxPktPendingTimer);
pRxTS->RxPktPendingTimer.data = (unsigned long)pRxTS;
pRxTS->RxPktPendingTimer.function = RxPktPendingTimeout;
ResetRxTsEntry(pRxTS);
list_add_tail(&pRxTS->TsCommonInfo.List, &ieee->Rx_TS_Unused_List);
pRxTS++;
}
// Initialize unused Rx Reorder List.
INIT_LIST_HEAD(&ieee->RxReorder_Unused_List);
//#ifdef TO_DO_LIST
for(count = 0; count < REORDER_ENTRY_NUM; count++)
{
list_add_tail( &pRxReorderEntry->List,&ieee->RxReorder_Unused_List);
if(count == (REORDER_ENTRY_NUM-1))
break;
pRxReorderEntry = &ieee->RxReorderEntry[count+1];
}
//#endif
}
void AdmitTS(struct ieee80211_device *ieee, PTS_COMMON_INFO pTsCommonInfo, u32 InactTime)
{
del_timer_sync(&pTsCommonInfo->SetupTimer);
del_timer_sync(&pTsCommonInfo->InactTimer);
if(InactTime!=0)
mod_timer(&pTsCommonInfo->InactTimer, jiffies + MSECS(InactTime));
}
PTS_COMMON_INFO SearchAdmitTRStream(struct ieee80211_device *ieee, u8* Addr, u8 TID, TR_SELECT TxRxSelect)
{
//DIRECTION_VALUE dir;
u8 dir;
bool search_dir[4] = {0, 0, 0, 0};
struct list_head* psearch_list; //FIXME
PTS_COMMON_INFO pRet = NULL;
if(ieee->iw_mode == IW_MODE_MASTER) //ap mode
{
if(TxRxSelect == TX_DIR)
{
search_dir[DIR_DOWN] = true;
search_dir[DIR_BI_DIR]= true;
}
else
{
search_dir[DIR_UP] = true;
search_dir[DIR_BI_DIR]= true;
}
}
else if(ieee->iw_mode == IW_MODE_ADHOC)
{
if(TxRxSelect == TX_DIR)
search_dir[DIR_UP] = true;
else
search_dir[DIR_DOWN] = true;
}
else
{
if(TxRxSelect == TX_DIR)
{
search_dir[DIR_UP] = true;
search_dir[DIR_BI_DIR]= true;
search_dir[DIR_DIRECT]= true;
}
else
{
search_dir[DIR_DOWN] = true;
search_dir[DIR_BI_DIR]= true;
search_dir[DIR_DIRECT]= true;
}
}
if(TxRxSelect == TX_DIR)
psearch_list = &ieee->Tx_TS_Admit_List;
else
psearch_list = &ieee->Rx_TS_Admit_List;
//for(dir = DIR_UP; dir <= DIR_BI_DIR; dir++)
for(dir = 0; dir <= DIR_BI_DIR; dir++)
{
if(search_dir[dir] ==false )
continue;
list_for_each_entry(pRet, psearch_list, List){
// IEEE80211_DEBUG(IEEE80211_DL_TS, "ADD:"MAC_FMT", TID:%d, dir:%d\n", MAC_ARG(pRet->Addr), pRet->TSpec.f.TSInfo.field.ucTSID, pRet->TSpec.f.TSInfo.field.ucDirection);
if (memcmp(pRet->Addr, Addr, 6) == 0)
if (pRet->TSpec.f.TSInfo.field.ucTSID == TID)
if(pRet->TSpec.f.TSInfo.field.ucDirection == dir)
{
// printk("Bingo! got it\n");
break;
}
}
if(&pRet->List != psearch_list)
break;
}
if(&pRet->List != psearch_list){
return pRet ;
}
else
return NULL;
}
void MakeTSEntry(
PTS_COMMON_INFO pTsCommonInfo,
u8* Addr,
PTSPEC_BODY pTSPEC,
PQOS_TCLAS pTCLAS,
u8 TCLAS_Num,
u8 TCLAS_Proc
)
{
u8 count;
if(pTsCommonInfo == NULL)
return;
memcpy(pTsCommonInfo->Addr, Addr, 6);
if(pTSPEC != NULL)
memcpy((u8*)(&(pTsCommonInfo->TSpec)), (u8*)pTSPEC, sizeof(TSPEC_BODY));
for(count = 0; count < TCLAS_Num; count++)
memcpy((u8*)(&(pTsCommonInfo->TClass[count])), (u8*)pTCLAS, sizeof(QOS_TCLAS));
pTsCommonInfo->TClasProc = TCLAS_Proc;
pTsCommonInfo->TClasNum = TCLAS_Num;
}
bool GetTs(
struct ieee80211_device* ieee,
PTS_COMMON_INFO *ppTS,
u8* Addr,
u8 TID,
TR_SELECT TxRxSelect, //Rx:1, Tx:0
bool bAddNewTs
)
{
u8 UP = 0;
//
// We do not build any TS for Broadcast or Multicast stream.
// So reject these kinds of search here.
//
if(is_broadcast_ether_addr(Addr) || is_multicast_ether_addr(Addr))
{
IEEE80211_DEBUG(IEEE80211_DL_ERR, "get TS for Broadcast or Multicast\n");
return false;
}
#if 0
if(ieee->pStaQos->CurrentQosMode == QOS_DISABLE)
{ UP = 0; } //only use one TS
else if(ieee->pStaQos->CurrentQosMode & QOS_WMM)
{
#else
if (ieee->current_network.qos_data.supported == 0)
UP = 0;
else
{
#endif
// In WMM case: we use 4 TID only
if (!IsACValid(TID))
{
IEEE80211_DEBUG(IEEE80211_DL_ERR, " in %s(), TID(%d) is not valid\n", __FUNCTION__, TID);
return false;
}
switch(TID)
{
case 0:
case 3:
UP = 0;
break;
case 1:
case 2:
UP = 2;
break;
case 4:
case 5:
UP = 5;
break;
case 6:
case 7:
UP = 7;
break;
}
}
*ppTS = SearchAdmitTRStream(
ieee,
Addr,
UP,
TxRxSelect);
if(*ppTS != NULL)
{
return true;
}
else
{
if(bAddNewTs == false)
{
IEEE80211_DEBUG(IEEE80211_DL_TS, "add new TS failed(tid:%d)\n", UP);
return false;
}
else
{
//
// Create a new Traffic stream for current Tx/Rx
// This is for EDCA and WMM to add a new TS.
// For HCCA or WMMSA, TS cannot be addmit without negotiation.
//
TSPEC_BODY TSpec;
PQOS_TSINFO pTSInfo = &TSpec.f.TSInfo;
struct list_head* pUnusedList =
(TxRxSelect == TX_DIR)?
(&ieee->Tx_TS_Unused_List):
(&ieee->Rx_TS_Unused_List);
struct list_head* pAddmitList =
(TxRxSelect == TX_DIR)?
(&ieee->Tx_TS_Admit_List):
(&ieee->Rx_TS_Admit_List);
DIRECTION_VALUE Dir = (ieee->iw_mode == IW_MODE_MASTER)?
((TxRxSelect==TX_DIR)?DIR_DOWN:DIR_UP):
((TxRxSelect==TX_DIR)?DIR_UP:DIR_DOWN);
IEEE80211_DEBUG(IEEE80211_DL_TS, "to add Ts\n");
if(!list_empty(pUnusedList))
{
(*ppTS) = list_entry(pUnusedList->next, TS_COMMON_INFO, List);
list_del_init(&(*ppTS)->List);
if(TxRxSelect==TX_DIR)
{
PTX_TS_RECORD tmp = container_of(*ppTS, TX_TS_RECORD, TsCommonInfo);
ResetTxTsEntry(tmp);
}
else{
PRX_TS_RECORD tmp = container_of(*ppTS, RX_TS_RECORD, TsCommonInfo);
ResetRxTsEntry(tmp);
}
IEEE80211_DEBUG(IEEE80211_DL_TS, "to init current TS, UP:%d, Dir:%d, addr:"MAC_FMT"\n", UP, Dir, MAC_ARG(Addr));
// Prepare TS Info releated field
pTSInfo->field.ucTrafficType = 0; // Traffic type: WMM is reserved in this field
pTSInfo->field.ucTSID = UP; // TSID
pTSInfo->field.ucDirection = Dir; // Direction: if there is DirectLink, this need additional consideration.
pTSInfo->field.ucAccessPolicy = 1; // Access policy
pTSInfo->field.ucAggregation = 0; // Aggregation
pTSInfo->field.ucPSB = 0; // Aggregation
pTSInfo->field.ucUP = UP; // User priority
pTSInfo->field.ucTSInfoAckPolicy = 0; // Ack policy
pTSInfo->field.ucSchedule = 0; // Schedule
MakeTSEntry(*ppTS, Addr, &TSpec, NULL, 0, 0);
AdmitTS(ieee, *ppTS, 0);
list_add_tail(&((*ppTS)->List), pAddmitList);
// if there is DirectLink, we need to do additional operation here!!
return true;
}
else
{
IEEE80211_DEBUG(IEEE80211_DL_ERR, "in function %s() There is not enough TS record to be used!!", __FUNCTION__);
return false;
}
}
}
}
void RemoveTsEntry(
struct ieee80211_device* ieee,
PTS_COMMON_INFO pTs,
TR_SELECT TxRxSelect
)
{
//u32 flags = 0;
unsigned long flags = 0;
del_timer_sync(&pTs->SetupTimer);
del_timer_sync(&pTs->InactTimer);
TsInitDelBA(ieee, pTs, TxRxSelect);
if(TxRxSelect == RX_DIR)
{
//#ifdef TO_DO_LIST
PRX_REORDER_ENTRY pRxReorderEntry;
PRX_TS_RECORD pRxTS = (PRX_TS_RECORD)pTs;
if(timer_pending(&pRxTS->RxPktPendingTimer))
del_timer_sync(&pRxTS->RxPktPendingTimer);
while(!list_empty(&pRxTS->RxPendingPktList))
{
// PlatformAcquireSpinLock(Adapter, RT_RX_SPINLOCK);
spin_lock_irqsave(&(ieee->reorder_spinlock), flags);
//pRxReorderEntry = list_entry(&pRxTS->RxPendingPktList.prev,RX_REORDER_ENTRY,List);
pRxReorderEntry = (PRX_REORDER_ENTRY)list_entry(pRxTS->RxPendingPktList.prev,RX_REORDER_ENTRY,List);
list_del_init(&pRxReorderEntry->List);
{
int i = 0;
struct ieee80211_rxb * prxb = pRxReorderEntry->prxb;
if (unlikely(!prxb))
{
spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags);
return;
}
for(i =0; i < prxb->nr_subframes; i++) {
dev_kfree_skb(prxb->subframes[i]);
}
kfree(prxb);
prxb = NULL;
}
list_add_tail(&pRxReorderEntry->List,&ieee->RxReorder_Unused_List);
//PlatformReleaseSpinLock(Adapter, RT_RX_SPINLOCK);
spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags);
}
//#endif
}
else
{
PTX_TS_RECORD pTxTS = (PTX_TS_RECORD)pTs;
del_timer_sync(&pTxTS->TsAddBaTimer);
}
}
void RemovePeerTS(struct ieee80211_device* ieee, u8* Addr)
{
PTS_COMMON_INFO pTS, pTmpTS;
printk("===========>RemovePeerTS,"MAC_FMT"\n", MAC_ARG(Addr));
#if 1
list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Pending_List, List)
{
if (memcmp(pTS->Addr, Addr, 6) == 0)
{
RemoveTsEntry(ieee, pTS, TX_DIR);
list_del_init(&pTS->List);
list_add_tail(&pTS->List, &ieee->Tx_TS_Unused_List);
}
}
list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Admit_List, List)
{
if (memcmp(pTS->Addr, Addr, 6) == 0)
{
printk("====>remove Tx_TS_admin_list\n");
RemoveTsEntry(ieee, pTS, TX_DIR);
list_del_init(&pTS->List);
list_add_tail(&pTS->List, &ieee->Tx_TS_Unused_List);
}
}
list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Pending_List, List)
{
if (memcmp(pTS->Addr, Addr, 6) == 0)
{
RemoveTsEntry(ieee, pTS, RX_DIR);
list_del_init(&pTS->List);
list_add_tail(&pTS->List, &ieee->Rx_TS_Unused_List);
}
}
list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Admit_List, List)
{
if (memcmp(pTS->Addr, Addr, 6) == 0)
{
RemoveTsEntry(ieee, pTS, RX_DIR);
list_del_init(&pTS->List);
list_add_tail(&pTS->List, &ieee->Rx_TS_Unused_List);
}
}
#endif
}
void RemoveAllTS(struct ieee80211_device* ieee)
{
PTS_COMMON_INFO pTS, pTmpTS;
#if 1
list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Pending_List, List)
{
RemoveTsEntry(ieee, pTS, TX_DIR);
list_del_init(&pTS->List);
list_add_tail(&pTS->List, &ieee->Tx_TS_Unused_List);
}
list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Admit_List, List)
{
RemoveTsEntry(ieee, pTS, TX_DIR);
list_del_init(&pTS->List);
list_add_tail(&pTS->List, &ieee->Tx_TS_Unused_List);
}
list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Pending_List, List)
{
RemoveTsEntry(ieee, pTS, RX_DIR);
list_del_init(&pTS->List);
list_add_tail(&pTS->List, &ieee->Rx_TS_Unused_List);
}
list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Admit_List, List)
{
RemoveTsEntry(ieee, pTS, RX_DIR);
list_del_init(&pTS->List);
list_add_tail(&pTS->List, &ieee->Rx_TS_Unused_List);
}
#endif
}
void TsStartAddBaProcess(struct ieee80211_device* ieee, PTX_TS_RECORD pTxTS)
{
if(pTxTS->bAddBaReqInProgress == false)
{
pTxTS->bAddBaReqInProgress = true;
#if 1
if(pTxTS->bAddBaReqDelayed)
{
IEEE80211_DEBUG(IEEE80211_DL_BA, "TsStartAddBaProcess(): Delayed Start ADDBA after 60 sec!!\n");
mod_timer(&pTxTS->TsAddBaTimer, jiffies + MSECS(TS_ADDBA_DELAY));
}
else
{
IEEE80211_DEBUG(IEEE80211_DL_BA,"TsStartAddBaProcess(): Immediately Start ADDBA now!!\n");
mod_timer(&pTxTS->TsAddBaTimer, jiffies+10); //set 10 ticks
}
#endif
}
else
IEEE80211_DEBUG(IEEE80211_DL_ERR, "%s()==>BA timer is already added\n", __FUNCTION__);
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
EXPORT_SYMBOL_NOVERS(RemovePeerTS);
#else
EXPORT_SYMBOL(RemovePeerTS);
#endif

View File

@ -0,0 +1,399 @@
/*
* Scatterlist Cryptographic API.
*
* Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
* Copyright (c) 2002 David S. Miller (davem@redhat.com)
*
* Portions derived from Cryptoapi, by Alexander Kjeldaas <astor@fast.no>
* and Nettle, by Niels M鰈ler.
*
* 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.
*
*/
#ifndef _LINUX_CRYPTO_H
#define _LINUX_CRYPTO_H
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/list.h>
#include <linux/string.h>
#include <asm/page.h>
#include <asm/errno.h>
#define crypto_register_alg crypto_register_alg_rsl
#define crypto_unregister_alg crypto_unregister_alg_rsl
#define crypto_alloc_tfm crypto_alloc_tfm_rsl
#define crypto_free_tfm crypto_free_tfm_rsl
#define crypto_alg_available crypto_alg_available_rsl
/*
* Algorithm masks and types.
*/
#define CRYPTO_ALG_TYPE_MASK 0x000000ff
#define CRYPTO_ALG_TYPE_CIPHER 0x00000001
#define CRYPTO_ALG_TYPE_DIGEST 0x00000002
#define CRYPTO_ALG_TYPE_COMPRESS 0x00000004
/*
* Transform masks and values (for crt_flags).
*/
#define CRYPTO_TFM_MODE_MASK 0x000000ff
#define CRYPTO_TFM_REQ_MASK 0x000fff00
#define CRYPTO_TFM_RES_MASK 0xfff00000
#define CRYPTO_TFM_MODE_ECB 0x00000001
#define CRYPTO_TFM_MODE_CBC 0x00000002
#define CRYPTO_TFM_MODE_CFB 0x00000004
#define CRYPTO_TFM_MODE_CTR 0x00000008
#define CRYPTO_TFM_REQ_WEAK_KEY 0x00000100
#define CRYPTO_TFM_RES_WEAK_KEY 0x00100000
#define CRYPTO_TFM_RES_BAD_KEY_LEN 0x00200000
#define CRYPTO_TFM_RES_BAD_KEY_SCHED 0x00400000
#define CRYPTO_TFM_RES_BAD_BLOCK_LEN 0x00800000
#define CRYPTO_TFM_RES_BAD_FLAGS 0x01000000
/*
* Miscellaneous stuff.
*/
#define CRYPTO_UNSPEC 0
#define CRYPTO_MAX_ALG_NAME 64
struct scatterlist;
/*
* Algorithms: modular crypto algorithm implementations, managed
* via crypto_register_alg() and crypto_unregister_alg().
*/
struct cipher_alg {
unsigned int cia_min_keysize;
unsigned int cia_max_keysize;
int (*cia_setkey)(void *ctx, const u8 *key,
unsigned int keylen, u32 *flags);
void (*cia_encrypt)(void *ctx, u8 *dst, const u8 *src);
void (*cia_decrypt)(void *ctx, u8 *dst, const u8 *src);
};
struct digest_alg {
unsigned int dia_digestsize;
void (*dia_init)(void *ctx);
void (*dia_update)(void *ctx, const u8 *data, unsigned int len);
void (*dia_final)(void *ctx, u8 *out);
int (*dia_setkey)(void *ctx, const u8 *key,
unsigned int keylen, u32 *flags);
};
struct compress_alg {
int (*coa_init)(void *ctx);
void (*coa_exit)(void *ctx);
int (*coa_compress)(void *ctx, const u8 *src, unsigned int slen,
u8 *dst, unsigned int *dlen);
int (*coa_decompress)(void *ctx, const u8 *src, unsigned int slen,
u8 *dst, unsigned int *dlen);
};
#define cra_cipher cra_u.cipher
#define cra_digest cra_u.digest
#define cra_compress cra_u.compress
struct crypto_alg {
struct list_head cra_list;
u32 cra_flags;
unsigned int cra_blocksize;
unsigned int cra_ctxsize;
const char cra_name[CRYPTO_MAX_ALG_NAME];
union {
struct cipher_alg cipher;
struct digest_alg digest;
struct compress_alg compress;
} cra_u;
struct module *cra_module;
};
/*
* Algorithm registration interface.
*/
int crypto_register_alg(struct crypto_alg *alg);
int crypto_unregister_alg(struct crypto_alg *alg);
/*
* Algorithm query interface.
*/
int crypto_alg_available(const char *name, u32 flags);
/*
* Transforms: user-instantiated objects which encapsulate algorithms
* and core processing logic. Managed via crypto_alloc_tfm() and
* crypto_free_tfm(), as well as the various helpers below.
*/
struct crypto_tfm;
struct cipher_tfm {
void *cit_iv;
unsigned int cit_ivsize;
u32 cit_mode;
int (*cit_setkey)(struct crypto_tfm *tfm,
const u8 *key, unsigned int keylen);
int (*cit_encrypt)(struct crypto_tfm *tfm,
struct scatterlist *dst,
struct scatterlist *src,
unsigned int nbytes);
int (*cit_encrypt_iv)(struct crypto_tfm *tfm,
struct scatterlist *dst,
struct scatterlist *src,
unsigned int nbytes, u8 *iv);
int (*cit_decrypt)(struct crypto_tfm *tfm,
struct scatterlist *dst,
struct scatterlist *src,
unsigned int nbytes);
int (*cit_decrypt_iv)(struct crypto_tfm *tfm,
struct scatterlist *dst,
struct scatterlist *src,
unsigned int nbytes, u8 *iv);
void (*cit_xor_block)(u8 *dst, const u8 *src);
};
struct digest_tfm {
void (*dit_init)(struct crypto_tfm *tfm);
void (*dit_update)(struct crypto_tfm *tfm,
struct scatterlist *sg, unsigned int nsg);
void (*dit_final)(struct crypto_tfm *tfm, u8 *out);
void (*dit_digest)(struct crypto_tfm *tfm, struct scatterlist *sg,
unsigned int nsg, u8 *out);
int (*dit_setkey)(struct crypto_tfm *tfm,
const u8 *key, unsigned int keylen);
#ifdef CONFIG_CRYPTO_HMAC
void *dit_hmac_block;
#endif
};
struct compress_tfm {
int (*cot_compress)(struct crypto_tfm *tfm,
const u8 *src, unsigned int slen,
u8 *dst, unsigned int *dlen);
int (*cot_decompress)(struct crypto_tfm *tfm,
const u8 *src, unsigned int slen,
u8 *dst, unsigned int *dlen);
};
#define crt_cipher crt_u.cipher
#define crt_digest crt_u.digest
#define crt_compress crt_u.compress
struct crypto_tfm {
u32 crt_flags;
union {
struct cipher_tfm cipher;
struct digest_tfm digest;
struct compress_tfm compress;
} crt_u;
struct crypto_alg *__crt_alg;
};
/*
* Transform user interface.
*/
/*
* crypto_alloc_tfm() will first attempt to locate an already loaded algorithm.
* If that fails and the kernel supports dynamically loadable modules, it
* will then attempt to load a module of the same name or alias. A refcount
* is grabbed on the algorithm which is then associated with the new transform.
*
* crypto_free_tfm() frees up the transform and any associated resources,
* then drops the refcount on the associated algorithm.
*/
struct crypto_tfm *crypto_alloc_tfm(const char *alg_name, u32 tfm_flags);
void crypto_free_tfm(struct crypto_tfm *tfm);
/*
* Transform helpers which query the underlying algorithm.
*/
static inline const char *crypto_tfm_alg_name(struct crypto_tfm *tfm)
{
return tfm->__crt_alg->cra_name;
}
static inline const char *crypto_tfm_alg_modname(struct crypto_tfm *tfm)
{
struct crypto_alg *alg = tfm->__crt_alg;
if (alg->cra_module)
return alg->cra_module->name;
else
return NULL;
}
static inline u32 crypto_tfm_alg_type(struct crypto_tfm *tfm)
{
return tfm->__crt_alg->cra_flags & CRYPTO_ALG_TYPE_MASK;
}
static inline unsigned int crypto_tfm_alg_min_keysize(struct crypto_tfm *tfm)
{
BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
return tfm->__crt_alg->cra_cipher.cia_min_keysize;
}
static inline unsigned int crypto_tfm_alg_max_keysize(struct crypto_tfm *tfm)
{
BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
return tfm->__crt_alg->cra_cipher.cia_max_keysize;
}
static inline unsigned int crypto_tfm_alg_ivsize(struct crypto_tfm *tfm)
{
BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
return tfm->crt_cipher.cit_ivsize;
}
static inline unsigned int crypto_tfm_alg_blocksize(struct crypto_tfm *tfm)
{
return tfm->__crt_alg->cra_blocksize;
}
static inline unsigned int crypto_tfm_alg_digestsize(struct crypto_tfm *tfm)
{
BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST);
return tfm->__crt_alg->cra_digest.dia_digestsize;
}
/*
* API wrappers.
*/
static inline void crypto_digest_init(struct crypto_tfm *tfm)
{
BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST);
tfm->crt_digest.dit_init(tfm);
}
static inline void crypto_digest_update(struct crypto_tfm *tfm,
struct scatterlist *sg,
unsigned int nsg)
{
BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST);
tfm->crt_digest.dit_update(tfm, sg, nsg);
}
static inline void crypto_digest_final(struct crypto_tfm *tfm, u8 *out)
{
BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST);
tfm->crt_digest.dit_final(tfm, out);
}
static inline void crypto_digest_digest(struct crypto_tfm *tfm,
struct scatterlist *sg,
unsigned int nsg, u8 *out)
{
BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST);
tfm->crt_digest.dit_digest(tfm, sg, nsg, out);
}
static inline int crypto_digest_setkey(struct crypto_tfm *tfm,
const u8 *key, unsigned int keylen)
{
BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST);
if (tfm->crt_digest.dit_setkey == NULL)
return -ENOSYS;
return tfm->crt_digest.dit_setkey(tfm, key, keylen);
}
static inline int crypto_cipher_setkey(struct crypto_tfm *tfm,
const u8 *key, unsigned int keylen)
{
BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
return tfm->crt_cipher.cit_setkey(tfm, key, keylen);
}
static inline int crypto_cipher_encrypt(struct crypto_tfm *tfm,
struct scatterlist *dst,
struct scatterlist *src,
unsigned int nbytes)
{
BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
return tfm->crt_cipher.cit_encrypt(tfm, dst, src, nbytes);
}
static inline int crypto_cipher_encrypt_iv(struct crypto_tfm *tfm,
struct scatterlist *dst,
struct scatterlist *src,
unsigned int nbytes, u8 *iv)
{
BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
BUG_ON(tfm->crt_cipher.cit_mode == CRYPTO_TFM_MODE_ECB);
return tfm->crt_cipher.cit_encrypt_iv(tfm, dst, src, nbytes, iv);
}
static inline int crypto_cipher_decrypt(struct crypto_tfm *tfm,
struct scatterlist *dst,
struct scatterlist *src,
unsigned int nbytes)
{
BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
return tfm->crt_cipher.cit_decrypt(tfm, dst, src, nbytes);
}
static inline int crypto_cipher_decrypt_iv(struct crypto_tfm *tfm,
struct scatterlist *dst,
struct scatterlist *src,
unsigned int nbytes, u8 *iv)
{
BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
BUG_ON(tfm->crt_cipher.cit_mode == CRYPTO_TFM_MODE_ECB);
return tfm->crt_cipher.cit_decrypt_iv(tfm, dst, src, nbytes, iv);
}
static inline void crypto_cipher_set_iv(struct crypto_tfm *tfm,
const u8 *src, unsigned int len)
{
BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
memcpy(tfm->crt_cipher.cit_iv, src, len);
}
static inline void crypto_cipher_get_iv(struct crypto_tfm *tfm,
u8 *dst, unsigned int len)
{
BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
memcpy(dst, tfm->crt_cipher.cit_iv, len);
}
static inline int crypto_comp_compress(struct crypto_tfm *tfm,
const u8 *src, unsigned int slen,
u8 *dst, unsigned int *dlen)
{
BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_COMPRESS);
return tfm->crt_compress.cot_compress(tfm, src, slen, dst, dlen);
}
static inline int crypto_comp_decompress(struct crypto_tfm *tfm,
const u8 *src, unsigned int slen,
u8 *dst, unsigned int *dlen)
{
BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_COMPRESS);
return tfm->crt_compress.cot_decompress(tfm, src, slen, dst, dlen);
}
/*
* HMAC support.
*/
#ifdef CONFIG_CRYPTO_HMAC
void crypto_hmac_init(struct crypto_tfm *tfm, u8 *key, unsigned int *keylen);
void crypto_hmac_update(struct crypto_tfm *tfm,
struct scatterlist *sg, unsigned int nsg);
void crypto_hmac_final(struct crypto_tfm *tfm, u8 *key,
unsigned int *keylen, u8 *out);
void crypto_hmac(struct crypto_tfm *tfm, u8 *key, unsigned int *keylen,
struct scatterlist *sg, unsigned int nsg, u8 *out);
#endif /* CONFIG_CRYPTO_HMAC */
#endif /* _LINUX_CRYPTO_H */

View File

@ -0,0 +1,126 @@
/*
* Cryptographic API.
*
* Cipher operations.
*
* Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
* 2002 Adam J. Richter <adam@yggdrasil.com>
* 2004 Jean-Luc Cooke <jlcooke@certainkey.com>
*
* 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.
*
*/
#include "kmap_types.h"
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/pagemap.h>
#include <linux/highmem.h>
#include <asm/scatterlist.h>
#include "internal.h"
#include "scatterwalk.h"
enum km_type crypto_km_types[] = {
KM_USER0,
KM_USER1,
KM_SOFTIRQ0,
KM_SOFTIRQ1,
};
void *scatterwalk_whichbuf(struct scatter_walk *walk, unsigned int nbytes, void *scratch)
{
if (nbytes <= walk->len_this_page &&
(((unsigned long)walk->data) & (PAGE_CACHE_SIZE - 1)) + nbytes <=
PAGE_CACHE_SIZE)
return walk->data;
else
return scratch;
}
static void memcpy_dir(void *buf, void *sgdata, size_t nbytes, int out)
{
if (out)
memcpy(sgdata, buf, nbytes);
else
memcpy(buf, sgdata, nbytes);
}
void scatterwalk_start(struct scatter_walk *walk, struct scatterlist *sg)
{
unsigned int rest_of_page;
walk->sg = sg;
walk->page = sg->page;
walk->len_this_segment = sg->length;
rest_of_page = PAGE_CACHE_SIZE - (sg->offset & (PAGE_CACHE_SIZE - 1));
walk->len_this_page = min(sg->length, rest_of_page);
walk->offset = sg->offset;
}
void scatterwalk_map(struct scatter_walk *walk, int out)
{
walk->data = crypto_kmap(walk->page, out) + walk->offset;
}
static void scatterwalk_pagedone(struct scatter_walk *walk, int out,
unsigned int more)
{
/* walk->data may be pointing the first byte of the next page;
however, we know we transfered at least one byte. So,
walk->data - 1 will be a virtual address in the mapped page. */
if (out)
flush_dcache_page(walk->page);
if (more) {
walk->len_this_segment -= walk->len_this_page;
if (walk->len_this_segment) {
walk->page++;
walk->len_this_page = min(walk->len_this_segment,
(unsigned)PAGE_CACHE_SIZE);
walk->offset = 0;
}
else
scatterwalk_start(walk, sg_next(walk->sg));
}
}
void scatterwalk_done(struct scatter_walk *walk, int out, int more)
{
crypto_kunmap(walk->data, out);
if (walk->len_this_page == 0 || !more)
scatterwalk_pagedone(walk, out, more);
}
/*
* Do not call this unless the total length of all of the fragments
* has been verified as multiple of the block size.
*/
int scatterwalk_copychunks(void *buf, struct scatter_walk *walk,
size_t nbytes, int out)
{
if (buf != walk->data) {
while (nbytes > walk->len_this_page) {
memcpy_dir(buf, walk->data, walk->len_this_page, out);
buf += walk->len_this_page;
nbytes -= walk->len_this_page;
crypto_kunmap(walk->data, out);
scatterwalk_pagedone(walk, out, 1);
scatterwalk_map(walk, out);
}
memcpy_dir(buf, walk->data, nbytes, out);
}
walk->offset += nbytes;
walk->len_this_page -= nbytes;
walk->len_this_segment -= nbytes;
return 0;
}

View File

@ -0,0 +1,51 @@
/*
* Cryptographic API.
*
* Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
* Copyright (c) 2002 Adam J. Richter <adam@yggdrasil.com>
* Copyright (c) 2004 Jean-Luc Cooke <jlcooke@certainkey.com>
*
* 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.
*
*/
#ifndef _CRYPTO_SCATTERWALK_H
#define _CRYPTO_SCATTERWALK_H
#include <linux/mm.h>
#include <asm/scatterlist.h>
struct scatter_walk {
struct scatterlist *sg;
struct page *page;
void *data;
unsigned int len_this_page;
unsigned int len_this_segment;
unsigned int offset;
};
/* Define sg_next is an inline routine now in case we want to change
scatterlist to a linked list later. */
static inline struct scatterlist *sg_next(struct scatterlist *sg)
{
return sg + 1;
}
static inline int scatterwalk_samebuf(struct scatter_walk *walk_in,
struct scatter_walk *walk_out,
void *src_p, void *dst_p)
{
return walk_in->page == walk_out->page &&
walk_in->offset == walk_out->offset &&
walk_in->data == src_p && walk_out->data == dst_p;
}
void *scatterwalk_whichbuf(struct scatter_walk *walk, unsigned int nbytes, void *scratch);
void scatterwalk_start(struct scatter_walk *walk, struct scatterlist *sg);
int scatterwalk_copychunks(void *buf, struct scatter_walk *walk, size_t nbytes, int out);
void scatterwalk_map(struct scatter_walk *walk, int out);
void scatterwalk_done(struct scatter_walk *walk, int out, int more);
#endif /* _CRYPTO_SCATTERWALK_H */

View File

@ -0,0 +1,86 @@
/*
* Original code based on Host AP (software wireless LAN access point) driver
* for Intersil Prism2/2.5/3.
*
* Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
* <jkmaline@cc.hut.fi>
* Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
*
* Adaption to a generic IEEE 802.11 stack by James Ketrenos
* <jketreno@linux.intel.com>
*
* Copyright (c) 2004, Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. See README and COPYING for
* more details.
*/
/*
* This file defines the interface to the ieee80211 crypto module.
*/
#ifndef IEEE80211_CRYPT_H
#define IEEE80211_CRYPT_H
#include <linux/skbuff.h>
struct ieee80211_crypto_ops {
const char *name;
/* init new crypto context (e.g., allocate private data space,
* select IV, etc.); returns NULL on failure or pointer to allocated
* private data on success */
void * (*init)(int keyidx);
/* deinitialize crypto context and free allocated private data */
void (*deinit)(void *priv);
/* encrypt/decrypt return < 0 on error or >= 0 on success. The return
* value from decrypt_mpdu is passed as the keyidx value for
* decrypt_msdu. skb must have enough head and tail room for the
* encryption; if not, error will be returned; these functions are
* called for all MPDUs (i.e., fragments).
*/
int (*encrypt_mpdu)(struct sk_buff *skb, int hdr_len, void *priv);
int (*decrypt_mpdu)(struct sk_buff *skb, int hdr_len, void *priv);
/* These functions are called for full MSDUs, i.e. full frames.
* These can be NULL if full MSDU operations are not needed. */
int (*encrypt_msdu)(struct sk_buff *skb, int hdr_len, void *priv);
int (*decrypt_msdu)(struct sk_buff *skb, int keyidx, int hdr_len,
void *priv);
int (*set_key)(void *key, int len, u8 *seq, void *priv);
int (*get_key)(void *key, int len, u8 *seq, void *priv);
/* procfs handler for printing out key information and possible
* statistics */
char * (*print_stats)(char *p, void *priv);
/* maximum number of bytes added by encryption; encrypt buf is
* allocated with extra_prefix_len bytes, copy of in_buf, and
* extra_postfix_len; encrypt need not use all this space, but
* the result must start at the beginning of the buffer and correct
* length must be returned */
int extra_prefix_len, extra_postfix_len;
struct module *owner;
};
struct ieee80211_crypt_data {
struct list_head list; /* delayed deletion list */
struct ieee80211_crypto_ops *ops;
void *priv;
atomic_t refcnt;
};
int ieee80211_register_crypto_ops(struct ieee80211_crypto_ops *ops);
int ieee80211_unregister_crypto_ops(struct ieee80211_crypto_ops *ops);
struct ieee80211_crypto_ops * ieee80211_get_crypto_ops(const char *name);
void ieee80211_crypt_deinit_entries(struct ieee80211_device *, int);
void ieee80211_crypt_deinit_handler(unsigned long);
void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee,
struct ieee80211_crypt_data **crypt);
#endif

View File

@ -0,0 +1,146 @@
/*
This files contains card eeprom (93c46 or 93c56) programming routines,
memory is addressed by 16 bits words.
This is part of rtl8180 OpenSource driver.
Copyright (C) Andrea Merello 2004 <andreamrl@tiscali.it>
Released under the terms of GPL (General Public Licence)
Parts of this driver are based on the GPL part of the
official realtek driver.
Parts of this driver are based on the rtl8180 driver skeleton
from Patric Schenke & Andres Salomon.
Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver.
We want to tanks the Authors of those projects and the Ndiswrapper
project Authors.
*/
#include "r8180_93cx6.h"
void eprom_cs(struct net_device *dev, short bit)
{
if(bit)
write_nic_byte_E(dev, EPROM_CMD,
(1<<EPROM_CS_SHIFT) | \
read_nic_byte_E(dev, EPROM_CMD)); //enable EPROM
else
write_nic_byte_E(dev, EPROM_CMD, read_nic_byte_E(dev, EPROM_CMD)\
&~(1<<EPROM_CS_SHIFT)); //disable EPROM
force_pci_posting(dev);
udelay(EPROM_DELAY);
}
void eprom_ck_cycle(struct net_device *dev)
{
write_nic_byte_E(dev, EPROM_CMD,
(1<<EPROM_CK_SHIFT) | read_nic_byte_E(dev,EPROM_CMD));
force_pci_posting(dev);
udelay(EPROM_DELAY);
write_nic_byte_E(dev, EPROM_CMD,
read_nic_byte_E(dev, EPROM_CMD) &~ (1<<EPROM_CK_SHIFT));
force_pci_posting(dev);
udelay(EPROM_DELAY);
}
void eprom_w(struct net_device *dev,short bit)
{
if(bit)
write_nic_byte_E(dev, EPROM_CMD, (1<<EPROM_W_SHIFT) | \
read_nic_byte_E(dev,EPROM_CMD));
else
write_nic_byte_E(dev, EPROM_CMD, read_nic_byte_E(dev,EPROM_CMD)\
&~(1<<EPROM_W_SHIFT));
force_pci_posting(dev);
udelay(EPROM_DELAY);
}
short eprom_r(struct net_device *dev)
{
short bit;
bit=(read_nic_byte_E(dev, EPROM_CMD) & (1<<EPROM_R_SHIFT) );
udelay(EPROM_DELAY);
if(bit) return 1;
return 0;
}
void eprom_send_bits_string(struct net_device *dev, short b[], int len)
{
int i;
for(i=0; i<len; i++){
eprom_w(dev, b[i]);
eprom_ck_cycle(dev);
}
}
u32 eprom_read(struct net_device *dev, u32 addr)
{
struct r8192_priv *priv = ieee80211_priv(dev);
short read_cmd[]={1,1,0};
short addr_str[8];
int i;
int addr_len;
u32 ret;
ret=0;
//enable EPROM programming
write_nic_byte_E(dev, EPROM_CMD,
(EPROM_CMD_PROGRAM<<EPROM_CMD_OPERATING_MODE_SHIFT));
force_pci_posting(dev);
udelay(EPROM_DELAY);
if (priv->epromtype==EPROM_93c56){
addr_str[7]=addr & 1;
addr_str[6]=addr & (1<<1);
addr_str[5]=addr & (1<<2);
addr_str[4]=addr & (1<<3);
addr_str[3]=addr & (1<<4);
addr_str[2]=addr & (1<<5);
addr_str[1]=addr & (1<<6);
addr_str[0]=addr & (1<<7);
addr_len=8;
}else{
addr_str[5]=addr & 1;
addr_str[4]=addr & (1<<1);
addr_str[3]=addr & (1<<2);
addr_str[2]=addr & (1<<3);
addr_str[1]=addr & (1<<4);
addr_str[0]=addr & (1<<5);
addr_len=6;
}
eprom_cs(dev, 1);
eprom_ck_cycle(dev);
eprom_send_bits_string(dev, read_cmd, 3);
eprom_send_bits_string(dev, addr_str, addr_len);
//keep chip pin D to low state while reading.
//I'm unsure if it is necessary, but anyway shouldn't hurt
eprom_w(dev, 0);
for(i=0;i<16;i++){
//eeprom needs a clk cycle between writing opcode&adr
//and reading data. (eeprom outs a dummy 0)
eprom_ck_cycle(dev);
ret |= (eprom_r(dev)<<(15-i));
}
eprom_cs(dev, 0);
eprom_ck_cycle(dev);
//disable EPROM programming
write_nic_byte_E(dev, EPROM_CMD,
(EPROM_CMD_NORMAL<<EPROM_CMD_OPERATING_MODE_SHIFT));
return ret;
}

View File

@ -0,0 +1,40 @@
/*
This is part of rtl8187 OpenSource driver
Copyright (C) Andrea Merello 2004-2005 <andreamrl@tiscali.it>
Released under the terms of GPL (General Public Licence)
Parts of this driver are based on the GPL part of the official realtek driver
Parts of this driver are based on the rtl8180 driver skeleton from Patric Schenke & Andres Salomon
Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver
We want to tanks the Authors of such projects and the Ndiswrapper project Authors.
*/
/*This files contains card eeprom (93c46 or 93c56) programming routines*/
/*memory is addressed by WORDS*/
#include "r8192U.h"
#include "r8192U_hw.h"
#define EPROM_DELAY 10
#define EPROM_ANAPARAM_ADDRLWORD 0xd
#define EPROM_ANAPARAM_ADDRHWORD 0xe
#define EPROM_RFCHIPID 0x6
#define EPROM_TXPW_BASE 0x05
#define EPROM_RFCHIPID_RTL8225U 5
#define EPROM_RF_PARAM 0x4
#define EPROM_CONFIG2 0xc
#define EPROM_VERSION 0x1E
#define MAC_ADR 0x7
#define CIS 0x18
#define EPROM_TXPW0 0x16
#define EPROM_TXPW2 0x1b
#define EPROM_TXPW1 0x3d
u32 eprom_read(struct net_device *dev,u32 addr); //reads a 16 bits word

View File

@ -0,0 +1,48 @@
/*
Power management interface routines.
Written by Mariusz Matuszek.
This code is currently just a placeholder for later work and
does not do anything useful.
This is part of rtl8180 OpenSource driver.
Copyright (C) Andrea Merello 2004 <andreamrl@tiscali.it>
Released under the terms of GPL (General Public Licence)
*/
#ifdef CONFIG_RTL8180_PM
#include "r8180_hw.h"
#include "r8180_pm.h"
int rtl8180_save_state (struct pci_dev *dev, u32 state)
{
printk(KERN_NOTICE "r8180 save state call (state %u).\n", state);
return(-EAGAIN);
}
int rtl8180_suspend (struct pci_dev *dev, u32 state)
{
printk(KERN_NOTICE "r8180 suspend call (state %u).\n", state);
return(-EAGAIN);
}
int rtl8180_resume (struct pci_dev *dev)
{
printk(KERN_NOTICE "r8180 resume call.\n");
return(-EAGAIN);
}
int rtl8180_enable_wake (struct pci_dev *dev, u32 state, int enable)
{
printk(KERN_NOTICE "r8180 enable wake call (state %u, enable %d).\n",
state, enable);
return(-EAGAIN);
}
#endif //CONFIG_RTL8180_PM

View File

@ -0,0 +1,28 @@
/*
Power management interface routines.
Written by Mariusz Matuszek.
This code is currently just a placeholder for later work and
does not do anything useful.
This is part of rtl8180 OpenSource driver.
Copyright (C) Andrea Merello 2004 <andreamrl@tiscali.it>
Released under the terms of GPL (General Public Licence)
*/
#ifdef CONFIG_RTL8180_PM
#ifndef R8180_PM_H
#define R8180_PM_H
#include <linux/types.h>
#include <linux/pci.h>
int rtl8180_save_state (struct pci_dev *dev, u32 state);
int rtl8180_suspend (struct pci_dev *dev, u32 state);
int rtl8180_resume (struct pci_dev *dev);
int rtl8180_enable_wake (struct pci_dev *dev, u32 state, int enable);
#endif //R8180_PM_H
#endif // CONFIG_RTL8180_PM

View File

@ -0,0 +1,312 @@
/*
This is part of the rtl8192 driver
released under the GPL (See file COPYING for details).
This files contains programming code for the rtl8256
radio frontend.
*Many* thanks to Realtek Corp. for their great support!
*/
#include "r8192U.h"
#include "r8192U_hw.h"
#include "r819xU_phyreg.h"
#include "r819xU_phy.h"
#include "r8190_rtl8256.h"
/*--------------------------------------------------------------------------
* Overview: set RF band width (20M or 40M)
* Input: struct net_device* dev
* WIRELESS_BANDWIDTH_E Bandwidth //20M or 40M
* Output: NONE
* Return: NONE
* Note: 8226 support both 20M and 40 MHz
*---------------------------------------------------------------------------*/
void PHY_SetRF8256Bandwidth(struct net_device* dev , HT_CHANNEL_WIDTH Bandwidth) //20M or 40M
{
u8 eRFPath;
struct r8192_priv *priv = ieee80211_priv(dev);
//for(eRFPath = RF90_PATH_A; eRFPath <pHalData->NumTotalRFPath; eRFPath++)
for(eRFPath = 0; eRFPath <RF90_PATH_MAX; eRFPath++)
{
if (!rtl8192_phy_CheckIsLegalRFPath(dev, eRFPath))
continue;
switch(Bandwidth)
{
case HT_CHANNEL_WIDTH_20:
if(priv->card_8192_version == VERSION_819xU_A || priv->card_8192_version == VERSION_819xU_B)// 8256 D-cut, E-cut, xiong: consider it later!
{
rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, 0x0b, bMask12Bits, 0x100); //phy para:1ba
rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, 0x2c, bMask12Bits, 0x3d7);
rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, 0x0e, bMask12Bits, 0x021);
//cosa add for sd3's request 01/23/2008
rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, 0x14, bMask12Bits, 0x5ab);
}
else
{
RT_TRACE(COMP_ERR, "PHY_SetRF8256Bandwidth(): unknown hardware version\n");
}
break;
case HT_CHANNEL_WIDTH_20_40:
if(priv->card_8192_version == VERSION_819xU_A ||priv->card_8192_version == VERSION_819xU_B)// 8256 D-cut, E-cut, xiong: consider it later!
{
rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, 0x0b, bMask12Bits, 0x300); //phy para:3ba
rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, 0x2c, bMask12Bits, 0x3df);
rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, 0x0e, bMask12Bits, 0x0a1);
//cosa add for sd3's request 01/23/2008
if(priv->chan == 3 || priv->chan == 9) //I need to set priv->chan whenever current channel changes
rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, 0x14, bMask12Bits, 0x59b);
else
rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, 0x14, bMask12Bits, 0x5ab);
}
else
{
RT_TRACE(COMP_ERR, "PHY_SetRF8256Bandwidth(): unknown hardware version\n");
}
break;
default:
RT_TRACE(COMP_ERR, "PHY_SetRF8256Bandwidth(): unknown Bandwidth: %#X\n",Bandwidth );
break;
}
}
return;
}
/*--------------------------------------------------------------------------
* Overview: Interface to config 8256
* Input: struct net_device* dev
* Output: NONE
* Return: NONE
*---------------------------------------------------------------------------*/
void PHY_RF8256_Config(struct net_device* dev)
{
struct r8192_priv *priv = ieee80211_priv(dev);
// Initialize general global value
//
// TODO: Extend RF_PATH_C and RF_PATH_D in the future
priv->NumTotalRFPath = RTL819X_TOTAL_RF_PATH;
// Config BB and RF
phy_RF8256_Config_ParaFile(dev);
return;
}
/*--------------------------------------------------------------------------
* Overview: Interface to config 8256
* Input: struct net_device* dev
* Output: NONE
* Return: NONE
*---------------------------------------------------------------------------*/
void phy_RF8256_Config_ParaFile(struct net_device* dev)
{
u32 u4RegValue = 0;
//static s1Byte szRadioAFile[] = RTL819X_PHY_RADIO_A;
//static s1Byte szRadioBFile[] = RTL819X_PHY_RADIO_B;
//static s1Byte szRadioCFile[] = RTL819X_PHY_RADIO_C;
//static s1Byte szRadioDFile[] = RTL819X_PHY_RADIO_D;
u8 eRFPath;
BB_REGISTER_DEFINITION_T *pPhyReg;
struct r8192_priv *priv = ieee80211_priv(dev);
u32 RegOffSetToBeCheck = 0x3;
u32 RegValueToBeCheck = 0x7f1;
u32 RF3_Final_Value = 0;
u8 ConstRetryTimes = 5, RetryTimes = 5;
u8 ret = 0;
//3//-----------------------------------------------------------------
//3// <2> Initialize RF
//3//-----------------------------------------------------------------
for(eRFPath = (RF90_RADIO_PATH_E)RF90_PATH_A; eRFPath <priv->NumTotalRFPath; eRFPath++)
{
if (!rtl8192_phy_CheckIsLegalRFPath(dev, eRFPath))
continue;
pPhyReg = &priv->PHYRegDef[eRFPath];
// Joseph test for shorten RF config
// pHalData->RfReg0Value[eRFPath] = rtl8192_phy_QueryRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, rGlobalCtrl, bMaskDWord);
/*----Store original RFENV control type----*/
switch(eRFPath)
{
case RF90_PATH_A:
case RF90_PATH_C:
u4RegValue = rtl8192_QueryBBReg(dev, pPhyReg->rfintfs, bRFSI_RFENV);
break;
case RF90_PATH_B :
case RF90_PATH_D:
u4RegValue = rtl8192_QueryBBReg(dev, pPhyReg->rfintfs, bRFSI_RFENV<<16);
break;
}
/*----Set RF_ENV enable----*/
rtl8192_setBBreg(dev, pPhyReg->rfintfe, bRFSI_RFENV<<16, 0x1);
/*----Set RF_ENV output high----*/
rtl8192_setBBreg(dev, pPhyReg->rfintfo, bRFSI_RFENV, 0x1);
/* Set bit number of Address and Data for RF register */
rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2, b3WireAddressLength, 0x0); // Set 0 to 4 bits for Z-serial and set 1 to 6 bits for 8258
rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2, b3WireDataLength, 0x0); // Set 0 to 12 bits for Z-serial and 8258, and set 1 to 14 bits for ???
rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E) eRFPath, 0x0, bMask12Bits, 0xbf);
/*----Check RF block (for FPGA platform only)----*/
// TODO: this function should be removed on ASIC , Emily 2007.2.2
if (rtl8192_phy_checkBBAndRF(dev, HW90_BLOCK_RF, (RF90_RADIO_PATH_E)eRFPath))
{
RT_TRACE(COMP_ERR, "PHY_RF8256_Config():Check Radio[%d] Fail!!\n", eRFPath);
goto phy_RF8256_Config_ParaFile_Fail;
}
RetryTimes = ConstRetryTimes;
RF3_Final_Value = 0;
/*----Initialize RF fom connfiguration file----*/
switch(eRFPath)
{
case RF90_PATH_A:
while(RF3_Final_Value!=RegValueToBeCheck && RetryTimes!=0)
{
ret = rtl8192_phy_ConfigRFWithHeaderFile(dev,(RF90_RADIO_PATH_E)eRFPath);
RF3_Final_Value = rtl8192_phy_QueryRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, RegOffSetToBeCheck, bMask12Bits);
RT_TRACE(COMP_RF, "RF %d %d register final value: %x\n", eRFPath, RegOffSetToBeCheck, RF3_Final_Value);
RetryTimes--;
}
break;
case RF90_PATH_B:
while(RF3_Final_Value!=RegValueToBeCheck && RetryTimes!=0)
{
ret = rtl8192_phy_ConfigRFWithHeaderFile(dev,(RF90_RADIO_PATH_E)eRFPath);
RF3_Final_Value = rtl8192_phy_QueryRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, RegOffSetToBeCheck, bMask12Bits);
RT_TRACE(COMP_RF, "RF %d %d register final value: %x\n", eRFPath, RegOffSetToBeCheck, RF3_Final_Value);
RetryTimes--;
}
break;
case RF90_PATH_C:
while(RF3_Final_Value!=RegValueToBeCheck && RetryTimes!=0)
{
ret = rtl8192_phy_ConfigRFWithHeaderFile(dev,(RF90_RADIO_PATH_E)eRFPath);
RF3_Final_Value = rtl8192_phy_QueryRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, RegOffSetToBeCheck, bMask12Bits);
RT_TRACE(COMP_RF, "RF %d %d register final value: %x\n", eRFPath, RegOffSetToBeCheck, RF3_Final_Value);
RetryTimes--;
}
break;
case RF90_PATH_D:
while(RF3_Final_Value!=RegValueToBeCheck && RetryTimes!=0)
{
ret = rtl8192_phy_ConfigRFWithHeaderFile(dev,(RF90_RADIO_PATH_E)eRFPath);
RF3_Final_Value = rtl8192_phy_QueryRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, RegOffSetToBeCheck, bMask12Bits);
RT_TRACE(COMP_RF, "RF %d %d register final value: %x\n", eRFPath, RegOffSetToBeCheck, RF3_Final_Value);
RetryTimes--;
}
break;
}
/*----Restore RFENV control type----*/;
switch(eRFPath)
{
case RF90_PATH_A:
case RF90_PATH_C:
rtl8192_setBBreg(dev, pPhyReg->rfintfs, bRFSI_RFENV, u4RegValue);
break;
case RF90_PATH_B :
case RF90_PATH_D:
rtl8192_setBBreg(dev, pPhyReg->rfintfs, bRFSI_RFENV<<16, u4RegValue);
break;
}
if(ret){
RT_TRACE(COMP_ERR, "phy_RF8256_Config_ParaFile():Radio[%d] Fail!!", eRFPath);
goto phy_RF8256_Config_ParaFile_Fail;
}
}
RT_TRACE(COMP_PHY, "PHY Initialization Success\n") ;
return ;
phy_RF8256_Config_ParaFile_Fail:
RT_TRACE(COMP_ERR, "PHY Initialization failed\n") ;
return ;
}
void PHY_SetRF8256CCKTxPower(struct net_device* dev, u8 powerlevel)
{
u32 TxAGC=0;
struct r8192_priv *priv = ieee80211_priv(dev);
//modified by vivi, 20080109
TxAGC = powerlevel;
if(priv->bDynamicTxLowPower == TRUE ) //cosa 05/22/2008 for scan
{
if(priv->CustomerID == RT_CID_819x_Netcore)
TxAGC = 0x22;
else
TxAGC += priv->CckPwEnl;
}
if(TxAGC > 0x24)
TxAGC = 0x24;
rtl8192_setBBreg(dev, rTxAGC_CCK_Mcs32, bTxAGCRateCCK, TxAGC);
}
void PHY_SetRF8256OFDMTxPower(struct net_device* dev, u8 powerlevel)
{
struct r8192_priv *priv = ieee80211_priv(dev);
//Joseph TxPower for 8192 testing
u32 writeVal, powerBase0, powerBase1, writeVal_tmp;
u8 index = 0;
u16 RegOffset[6] = {0xe00, 0xe04, 0xe10, 0xe14, 0xe18, 0xe1c};
u8 byte0, byte1, byte2, byte3;
powerBase0 = powerlevel + priv->TxPowerDiff; //OFDM rates
powerBase0 = (powerBase0<<24) | (powerBase0<<16) |(powerBase0<<8) |powerBase0;
powerBase1 = powerlevel; //MCS rates
powerBase1 = (powerBase1<<24) | (powerBase1<<16) |(powerBase1<<8) |powerBase1;
for(index=0; index<6; index++)
{
writeVal = priv->MCSTxPowerLevelOriginalOffset[index] + ((index<2)?powerBase0:powerBase1);
byte0 = (u8)(writeVal & 0x7f);
byte1 = (u8)((writeVal & 0x7f00)>>8);
byte2 = (u8)((writeVal & 0x7f0000)>>16);
byte3 = (u8)((writeVal & 0x7f000000)>>24);
if(byte0 > 0x24) // Max power index = 0x24
byte0 = 0x24;
if(byte1 > 0x24)
byte1 = 0x24;
if(byte2 > 0x24)
byte2 = 0x24;
if(byte3 > 0x24)
byte3 = 0x24;
//for tx power track
if(index == 3)
{
writeVal_tmp = (byte3<<24) | (byte2<<16) |(byte1<<8) |byte0;
priv->Pwr_Track = writeVal_tmp;
}
if(priv->bDynamicTxHighPower == TRUE) //Add by Jacken 2008/03/06
{
// Emily, 20080613. Set low tx power for both MCS and legacy OFDM
writeVal = 0x03030303;
}
else
{
writeVal = (byte3<<24) | (byte2<<16) |(byte1<<8) |byte0;
}
rtl8192_setBBreg(dev, RegOffset[index], 0x7f7f7f7f, writeVal);
}
return;
}

View File

@ -0,0 +1,27 @@
/*
This is part of the rtl8180-sa2400 driver
released under the GPL (See file COPYING for details).
Copyright (c) 2005 Andrea Merello <andreamrl@tiscali.it>
This files contains programming code for the rtl8256
radio frontend.
*Many* thanks to Realtek Corp. for their great support!
*/
#ifndef RTL8225H
#define RTL8225H
#ifdef RTL8190P
#define RTL819X_TOTAL_RF_PATH 4 //for 90P
#else
#define RTL819X_TOTAL_RF_PATH 2 //for 8192U
#endif
extern void PHY_SetRF8256Bandwidth(struct net_device* dev , HT_CHANNEL_WIDTH Bandwidth);
extern void PHY_RF8256_Config(struct net_device* dev);
extern void phy_RF8256_Config_ParaFile(struct net_device* dev);
extern void PHY_SetRF8256CCKTxPower(struct net_device* dev, u8 powerlevel);
extern void PHY_SetRF8256OFDMTxPower(struct net_device* dev, u8 powerlevel);
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,309 @@
/*****************************************************************************
* Copyright(c) 2007, RealTEK Technology Inc. All Right Reserved.
*
* Module: Hal819xUsbDM.h (RTL8192 Header H File)
*
*
* Note: For dynamic control definition constant structure.
*
*
* Export:
*
* Abbrev:
*
* History:
* Data Who Remark
* 10/04/2007 MHC Create initial version.
*
*****************************************************************************/
/* Check to see if the file has been included already. */
#ifndef __R8192UDM_H__
#define __R8192UDM_H__
/*--------------------------Define Parameters-------------------------------*/
#define DM_DIG_THRESH_HIGH 40
#define DM_DIG_THRESH_LOW 35
#define DM_DIG_HIGH_PWR_THRESH_HIGH 75
#define DM_DIG_HIGH_PWR_THRESH_LOW 70
#define BW_AUTO_SWITCH_HIGH_LOW 25
#define BW_AUTO_SWITCH_LOW_HIGH 30
#define DM_check_fsync_time_interval 500
#define DM_DIG_BACKOFF 12
#define DM_DIG_MAX 0x36
#define DM_DIG_MIN 0x1c
#define DM_DIG_MIN_Netcore 0x12
#define RxPathSelection_SS_TH_low 30
#define RxPathSelection_diff_TH 18
#define RateAdaptiveTH_High 50
#define RateAdaptiveTH_Low_20M 30
#define RateAdaptiveTH_Low_40M 10
#define VeryLowRSSI 15
#define CTSToSelfTHVal 30
//defined by vivi, for tx power track
#define E_FOR_TX_POWER_TRACK 300
//Dynamic Tx Power Control Threshold
#define TX_POWER_NEAR_FIELD_THRESH_HIGH 68
#define TX_POWER_NEAR_FIELD_THRESH_LOW 62
//added by amy for atheros AP
#define TX_POWER_ATHEROAP_THRESH_HIGH 78
#define TX_POWER_ATHEROAP_THRESH_LOW 72
//defined by vivi, for showing on UI
#define Current_Tx_Rate_Reg 0x1b8
#define Initial_Tx_Rate_Reg 0x1b9
#define Tx_Retry_Count_Reg 0x1ac
#define RegC38_TH 20
#if 0
//----------------------------------------------------------------------------
// 8190 Rate Adaptive Table Register (offset 0x320, 4 byte)
//----------------------------------------------------------------------------
//CCK
#define RATR_1M 0x00000001
#define RATR_2M 0x00000002
#define RATR_55M 0x00000004
#define RATR_11M 0x00000008
//OFDM
#define RATR_6M 0x00000010
#define RATR_9M 0x00000020
#define RATR_12M 0x00000040
#define RATR_18M 0x00000080
#define RATR_24M 0x00000100
#define RATR_36M 0x00000200
#define RATR_48M 0x00000400
#define RATR_54M 0x00000800
//MCS 1 Spatial Stream
#define RATR_MCS0 0x00001000
#define RATR_MCS1 0x00002000
#define RATR_MCS2 0x00004000
#define RATR_MCS3 0x00008000
#define RATR_MCS4 0x00010000
#define RATR_MCS5 0x00020000
#define RATR_MCS6 0x00040000
#define RATR_MCS7 0x00080000
//MCS 2 Spatial Stream
#define RATR_MCS8 0x00100000
#define RATR_MCS9 0x00200000
#define RATR_MCS10 0x00400000
#define RATR_MCS11 0x00800000
#define RATR_MCS12 0x01000000
#define RATR_MCS13 0x02000000
#define RATR_MCS14 0x04000000
#define RATR_MCS15 0x08000000
// ALL CCK Rate
#define RATE_ALL_CCK RATR_1M|RATR_2M|RATR_55M|RATR_11M
#define RATE_ALL_OFDM_AG RATR_6M|RATR_9M|RATR_12M|RATR_18M|RATR_24M\
|RATR_36M|RATR_48M|RATR_54M
#define RATE_ALL_OFDM_2SS RATR_MCS8|RATR_MCS9 |RATR_MCS10|RATR_MCS11| \
RATR_MCS12|RATR_MCS13|RATR_MCS14|RATR_MCS15
#endif
/*--------------------------Define Parameters-------------------------------*/
/*------------------------------Define structure----------------------------*/
/* 2007/10/04 MH Define upper and lower threshold of DIG enable or disable. */
typedef struct _dynamic_initial_gain_threshold_
{
u8 dig_enable_flag;
u8 dig_algorithm;
u8 dbg_mode;
u8 dig_algorithm_switch;
long rssi_low_thresh;
long rssi_high_thresh;
long rssi_high_power_lowthresh;
long rssi_high_power_highthresh;
u8 dig_state;
u8 dig_highpwr_state;
u8 cur_connect_state;
u8 pre_connect_state;
u8 curpd_thstate;
u8 prepd_thstate;
u8 curcs_ratio_state;
u8 precs_ratio_state;
u32 pre_ig_value;
u32 cur_ig_value;
u8 backoff_val;
u8 rx_gain_range_max;
u8 rx_gain_range_min;
bool initialgain_lowerbound_state;
long rssi_val;
}dig_t;
typedef enum tag_dynamic_init_gain_state_definition
{
DM_STA_DIG_OFF = 0,
DM_STA_DIG_ON,
DM_STA_DIG_MAX
}dm_dig_sta_e;
/* 2007/10/08 MH Define RATR state. */
typedef enum tag_dynamic_ratr_state_definition
{
DM_RATR_STA_HIGH = 0,
DM_RATR_STA_MIDDLE = 1,
DM_RATR_STA_LOW = 2,
DM_RATR_STA_MAX
}dm_ratr_sta_e;
/* 2007/10/11 MH Define DIG operation type. */
typedef enum tag_dynamic_init_gain_operation_type_definition
{
DIG_TYPE_THRESH_HIGH = 0,
DIG_TYPE_THRESH_LOW = 1,
DIG_TYPE_THRESH_HIGHPWR_HIGH = 2,
DIG_TYPE_THRESH_HIGHPWR_LOW = 3,
DIG_TYPE_DBG_MODE = 4,
DIG_TYPE_RSSI = 5,
DIG_TYPE_ALGORITHM = 6,
DIG_TYPE_BACKOFF = 7,
DIG_TYPE_PWDB_FACTOR = 8,
DIG_TYPE_RX_GAIN_MIN = 9,
DIG_TYPE_RX_GAIN_MAX = 10,
DIG_TYPE_ENABLE = 20,
DIG_TYPE_DISABLE = 30,
DIG_OP_TYPE_MAX
}dm_dig_op_e;
typedef enum tag_dig_algorithm_definition
{
DIG_ALGO_BY_FALSE_ALARM = 0,
DIG_ALGO_BY_RSSI = 1,
DIG_ALGO_MAX
}dm_dig_alg_e;
typedef enum tag_dig_dbgmode_definition
{
DIG_DBG_OFF = 0,
DIG_DBG_ON = 1,
DIG_DBG_MAX
}dm_dig_dbg_e;
typedef enum tag_dig_connect_definition
{
DIG_DISCONNECT = 0,
DIG_CONNECT = 1,
DIG_CONNECT_MAX
}dm_dig_connect_e;
typedef enum tag_dig_packetdetection_threshold_definition
{
DIG_PD_AT_LOW_POWER = 0,
DIG_PD_AT_NORMAL_POWER = 1,
DIG_PD_AT_HIGH_POWER = 2,
DIG_PD_MAX
}dm_dig_pd_th_e;
typedef enum tag_dig_cck_cs_ratio_state_definition
{
DIG_CS_RATIO_LOWER = 0,
DIG_CS_RATIO_HIGHER = 1,
DIG_CS_MAX
}dm_dig_cs_ratio_e;
typedef struct _Dynamic_Rx_Path_Selection_
{
u8 Enable;
u8 DbgMode;
u8 cck_method;
u8 cck_Rx_path;
u8 SS_TH_low;
u8 diff_TH;
u8 disabledRF;
u8 reserved;
u8 rf_rssi[4];
u8 rf_enable_rssi_th[4];
long cck_pwdb_sta[4];
}DRxPathSel;
typedef enum tag_CCK_Rx_Path_Method_Definition
{
CCK_Rx_Version_1 = 0,
CCK_Rx_Version_2= 1,
CCK_Rx_Version_MAX
}DM_CCK_Rx_Path_Method;
typedef enum tag_DM_DbgMode_Definition
{
DM_DBG_OFF = 0,
DM_DBG_ON = 1,
DM_DBG_MAX
}DM_DBG_E;
typedef struct tag_Tx_Config_Cmd_Format
{
u32 Op; /* Command packet type. */
u32 Length; /* Command packet length. */
u32 Value;
}DCMD_TXCMD_T, *PDCMD_TXCMD_T;
/*------------------------------Define structure----------------------------*/
/*------------------------Export global variable----------------------------*/
extern dig_t dm_digtable;
extern u8 dm_shadow[16][256];
extern DRxPathSel DM_RxPathSelTable;
/*------------------------Export global variable----------------------------*/
/*------------------------Export Marco Definition---------------------------*/
/*------------------------Export Marco Definition---------------------------*/
/*--------------------------Exported Function prototype---------------------*/
extern void init_hal_dm(struct net_device *dev);
extern void deinit_hal_dm(struct net_device *dev);
extern void hal_dm_watchdog(struct net_device *dev);
extern void init_rate_adaptive(struct net_device *dev);
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
extern void dm_txpower_trackingcallback(struct work_struct *work);
#else
extern void dm_txpower_trackingcallback(struct net_device *dev);
#endif
extern void dm_restore_dynamic_mechanism_state(struct net_device *dev);
extern void dm_backup_dynamic_mechanism_state(struct net_device *dev);
extern void dm_change_dynamic_initgain_thresh(struct net_device *dev,
u32 dm_type, u32 dm_value);
extern void dm_force_tx_fw_info(struct net_device *dev,u32 force_type, u32 force_value);
extern void dm_init_edca_turbo(struct net_device *dev);
extern void dm_rf_operation_test_callback(unsigned long data);
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
extern void dm_rf_pathcheck_workitemcallback(struct work_struct *work);
#else
extern void dm_rf_pathcheck_workitemcallback(struct net_device *dev);
#endif
extern void dm_fsync_timer_callback(unsigned long data);
extern void dm_cck_txpower_adjust(struct net_device *dev,bool binch14);
#if 0
extern char dm_check_lbus_status(IN PADAPTER Adapter);
#endif
extern void dm_shadow_init(struct net_device *dev);
extern void dm_initialize_txpower_tracking(struct net_device *dev);
/*--------------------------Exported Function prototype---------------------*/
#endif /*__R8192UDM_H__ */
/* End of r8192U_dm.h */

View File

@ -0,0 +1,746 @@
/*
This is part of rtl8187 OpenSource driver.
Copyright (C) Andrea Merello 2004-2005 <andreamrl@tiscali.it>
Released under the terms of GPL (General Public Licence)
Parts of this driver are based on the GPL part of the
official Realtek driver.
Parts of this driver are based on the rtl8180 driver skeleton
from Patric Schenke & Andres Salomon.
Parts of this driver are based on the Intel Pro Wireless
2100 GPL driver.
We want to tanks the Authors of those projects
and the Ndiswrapper project Authors.
*/
/* Mariusz Matuszek added full registers definition with Realtek's name */
/* this file contains register definitions for the rtl8187 MAC controller */
#ifndef R8192_HW
#define R8192_HW
typedef enum _VERSION_819xU{
VERSION_819xU_A, // A-cut
VERSION_819xU_B, // B-cut
VERSION_819xU_C,// C-cut
}VERSION_819xU,*PVERSION_819xU;
//added for different RF type
typedef enum _RT_RF_TYPE_DEF
{
RF_1T2R = 0,
RF_2T4R,
RF_819X_MAX_TYPE
}RT_RF_TYPE_DEF;
typedef enum _BaseBand_Config_Type{
BaseBand_Config_PHY_REG = 0, //Radio Path A
BaseBand_Config_AGC_TAB = 1, //Radio Path B
}BaseBand_Config_Type, *PBaseBand_Config_Type;
#if 0
typedef enum _RT_RF_TYPE_819xU{
RF_TYPE_MIN = 0,
RF_8225,
RF_8256,
RF_8258,
RF_PSEUDO_11N = 4,
}RT_RF_TYPE_819xU, *PRT_RF_TYPE_819xU;
#endif
#define RTL8187_REQT_READ 0xc0
#define RTL8187_REQT_WRITE 0x40
#define RTL8187_REQ_GET_REGS 0x05
#define RTL8187_REQ_SET_REGS 0x05
#define MAX_TX_URB 5
#define MAX_RX_URB 16
#define R8180_MAX_RETRY 255
//#define MAX_RX_NORMAL_URB 3
//#define MAX_RX_COMMAND_URB 2
#define RX_URB_SIZE 9100
#define BB_ANTATTEN_CHAN14 0x0c
#define BB_ANTENNA_B 0x40
#define BB_HOST_BANG (1<<30)
#define BB_HOST_BANG_EN (1<<2)
#define BB_HOST_BANG_CLK (1<<1)
#define BB_HOST_BANG_RW (1<<3)
#define BB_HOST_BANG_DATA 1
//#if (RTL819X_FPGA_VER & RTL819X_FPGA_VIVI_070920)
#define AFR 0x010
#define AFR_CardBEn (1<<0)
#define AFR_CLKRUN_SEL (1<<1)
#define AFR_FuncRegEn (1<<2)
#define RTL8190_EEPROM_ID 0x8129
#define EEPROM_VID 0x02
#define EEPROM_PID 0x04
#define EEPROM_NODE_ADDRESS_BYTE_0 0x0C
#define EEPROM_TxPowerDiff 0x1F
#define EEPROM_ThermalMeter 0x20
#define EEPROM_PwDiff 0x21 //0x21
#define EEPROM_CrystalCap 0x22 //0x22
#define EEPROM_TxPwIndex_CCK 0x23 //0x23
#define EEPROM_TxPwIndex_OFDM_24G 0x24 //0x24~0x26
#define EEPROM_TxPwIndex_CCK_V1 0x29 //0x29~0x2B
#define EEPROM_TxPwIndex_OFDM_24G_V1 0x2C //0x2C~0x2E
#define EEPROM_TxPwIndex_Ver 0x27 //0x27
#define EEPROM_Default_TxPowerDiff 0x0
#define EEPROM_Default_ThermalMeter 0x7
#define EEPROM_Default_PwDiff 0x4
#define EEPROM_Default_CrystalCap 0x5
#define EEPROM_Default_TxPower 0x1010
#define EEPROM_Customer_ID 0x7B //0x7B:CustomerID
#define EEPROM_ChannelPlan 0x16 //0x7C
#define EEPROM_IC_VER 0x7d //0x7D
#define EEPROM_CRC 0x7e //0x7E~0x7F
#define EEPROM_CID_DEFAULT 0x0
#define EEPROM_CID_CAMEO 0x1
#define EEPROM_CID_RUNTOP 0x2
#define EEPROM_CID_Senao 0x3
#define EEPROM_CID_TOSHIBA 0x4 // Toshiba setting, Merge by Jacken, 2008/01/31
#define EEPROM_CID_NetCore 0x5
#define EEPROM_CID_Nettronix 0x6
#define EEPROM_CID_Pronet 0x7
#define EEPROM_CID_DLINK 0x8
#define AC_PARAM_TXOP_LIMIT_OFFSET 16
#define AC_PARAM_ECW_MAX_OFFSET 12
#define AC_PARAM_ECW_MIN_OFFSET 8
#define AC_PARAM_AIFS_OFFSET 0
//#endif
enum _RTL8192Usb_HW {
PCIF = 0x009, // PCI Function Register 0x0009h~0x000bh
#define BB_GLOBAL_RESET_BIT 0x1
BB_GLOBAL_RESET = 0x020, // BasebandGlobal Reset Register
BSSIDR = 0x02E, // BSSID Register
CMDR = 0x037, // Command register
#define CR_RST 0x10
#define CR_RE 0x08
#define CR_TE 0x04
#define CR_MulRW 0x01
SIFS = 0x03E, // SIFS register
TCR = 0x040, // Transmit Configuration Register
#define TCR_MXDMA_2048 7
#define TCR_LRL_OFFSET 0
#define TCR_SRL_OFFSET 8
#define TCR_MXDMA_OFFSET 21
#define TCR_SAT BIT24 // Enable Rate depedent ack timeout timer
RCR = 0x044, // Receive Configuration Register
#define MAC_FILTER_MASK ((1<<0) | (1<<1) | (1<<2) | (1<<3) | (1<<5) | \
(1<<12) | (1<<18) | (1<<19) | (1<<20) | (1<<21) | (1<<22) | (1<<23))
#define RX_FIFO_THRESHOLD_MASK ((1<<13) | (1<<14) | (1<<15))
#define RX_FIFO_THRESHOLD_SHIFT 13
#define RX_FIFO_THRESHOLD_128 3
#define RX_FIFO_THRESHOLD_256 4
#define RX_FIFO_THRESHOLD_512 5
#define RX_FIFO_THRESHOLD_1024 6
#define RX_FIFO_THRESHOLD_NONE 7
#define MAX_RX_DMA_MASK ((1<<8) | (1<<9) | (1<<10))
#define RCR_MXDMA_OFFSET 8
#define RCR_FIFO_OFFSET 13
#define RCR_ONLYERLPKT BIT31 // Early Receiving based on Packet Size.
#define RCR_ENCS2 BIT30 // Enable Carrier Sense Detection Method 2
#define RCR_ENCS1 BIT29 // Enable Carrier Sense Detection Method 1
#define RCR_ENMBID BIT27 // Enable Multiple BssId.
#define RCR_ACKTXBW (BIT24|BIT25) // TXBW Setting of ACK frames
#define RCR_CBSSID BIT23 // Accept BSSID match packet
#define RCR_APWRMGT BIT22 // Accept power management packet
#define RCR_ADD3 BIT21 // Accept address 3 match packet
#define RCR_AMF BIT20 // Accept management type frame
#define RCR_ACF BIT19 // Accept control type frame
#define RCR_ADF BIT18 // Accept data type frame
#define RCR_RXFTH BIT13 // Rx FIFO Threshold
#define RCR_AICV BIT12 // Accept ICV error packet
#define RCR_ACRC32 BIT5 // Accept CRC32 error packet
#define RCR_AB BIT3 // Accept broadcast packet
#define RCR_AM BIT2 // Accept multicast packet
#define RCR_APM BIT1 // Accept physical match packet
#define RCR_AAP BIT0 // Accept all unicast packet
SLOT_TIME = 0x049, // Slot Time Register
ACK_TIMEOUT = 0x04c, // Ack Timeout Register
PIFS_TIME = 0x04d, // PIFS time
USTIME = 0x04e, // Microsecond Tuning Register, Sets the microsecond time unit used by MAC clock.
EDCAPARA_BE = 0x050, // EDCA Parameter of AC BE
EDCAPARA_BK = 0x054, // EDCA Parameter of AC BK
EDCAPARA_VO = 0x058, // EDCA Parameter of AC VO
EDCAPARA_VI = 0x05C, // EDCA Parameter of AC VI
RFPC = 0x05F, // Rx FIFO Packet Count
CWRR = 0x060, // Contention Window Report Register
BCN_TCFG = 0x062, // Beacon Time Configuration
#define BCN_TCFG_CW_SHIFT 8
#define BCN_TCFG_IFS 0
BCN_INTERVAL = 0x070, // Beacon Interval (TU)
ATIMWND = 0x072, // ATIM Window Size (TU)
BCN_DRV_EARLY_INT = 0x074, // Driver Early Interrupt Time (TU). Time to send interrupt to notify to change beacon content before TBTT
BCN_DMATIME = 0x076, // Beacon DMA and ATIM interrupt time (US). Indicates the time before TBTT to perform beacon queue DMA
BCN_ERR_THRESH = 0x078, // Beacon Error Threshold
RWCAM = 0x0A0, //IN 8190 Data Sheet is called CAMcmd
WCAMI = 0x0A4, // Software write CAM input content
RCAMO = 0x0A8, // Software read/write CAM config
SECR = 0x0B0, //Security Configuration Register
#define SCR_TxUseDK BIT0 //Force Tx Use Default Key
#define SCR_RxUseDK BIT1 //Force Rx Use Default Key
#define SCR_TxEncEnable BIT2 //Enable Tx Encryption
#define SCR_RxDecEnable BIT3 //Enable Rx Decryption
#define SCR_SKByA2 BIT4 //Search kEY BY A2
#define SCR_NoSKMC BIT5 //No Key Search for Multicast
#define SCR_UseDK 0x01
#define SCR_TxSecEnable 0x02
#define SCR_RxSecEnable 0x04
TPPoll = 0x0fd, // Transmit priority polling register
PSR = 0x0ff, // Page Select Register
#define CPU_CCK_LOOPBACK 0x00030000
#define CPU_GEN_SYSTEM_RESET 0x00000001
#define CPU_GEN_FIRMWARE_RESET 0x00000008
#define CPU_GEN_BOOT_RDY 0x00000010
#define CPU_GEN_FIRM_RDY 0x00000020
#define CPU_GEN_PUT_CODE_OK 0x00000080
#define CPU_GEN_BB_RST 0x00000100
#define CPU_GEN_PWR_STB_CPU 0x00000004
#define CPU_GEN_NO_LOOPBACK_MSK 0xFFF8FFFF // Set bit18,17,16 to 0. Set bit19
#define CPU_GEN_NO_LOOPBACK_SET 0x00080000 // Set BIT19 to 1
//----------------------------------------------------------------------------
// 8190 CPU General Register (offset 0x100, 4 byte)
//----------------------------------------------------------------------------
#define CPU_CCK_LOOPBACK 0x00030000
#define CPU_GEN_SYSTEM_RESET 0x00000001
#define CPU_GEN_FIRMWARE_RESET 0x00000008
#define CPU_GEN_BOOT_RDY 0x00000010
#define CPU_GEN_FIRM_RDY 0x00000020
#define CPU_GEN_PUT_CODE_OK 0x00000080
#define CPU_GEN_BB_RST 0x00000100
#define CPU_GEN_PWR_STB_CPU 0x00000004
#define CPU_GEN_NO_LOOPBACK_MSK 0xFFF8FFFF // Set bit18,17,16 to 0. Set bit19
#define CPU_GEN_NO_LOOPBACK_SET 0x00080000 // Set BIT19 to 1
CPU_GEN = 0x100, // CPU Reset Register
LED1Cfg = 0x154,// LED1 Configuration Register
LED0Cfg = 0x155,// LED0 Configuration Register
AcmAvg = 0x170, // ACM Average Period Register
AcmHwCtrl = 0x171, // ACM Hardware Control Register
//----------------------------------------------------------------------------
////
//// 8190 AcmHwCtrl bits (offset 0x171, 1 byte)
////----------------------------------------------------------------------------
//
#define AcmHw_HwEn BIT0
#define AcmHw_BeqEn BIT1
#define AcmHw_ViqEn BIT2
#define AcmHw_VoqEn BIT3
#define AcmHw_BeqStatus BIT4
#define AcmHw_ViqStatus BIT5
#define AcmHw_VoqStatus BIT6
AcmFwCtrl = 0x172, // ACM Firmware Control Register
AES_11N_FIX = 0x173,
VOAdmTime = 0x174, // VO Queue Admitted Time Register
VIAdmTime = 0x178, // VI Queue Admitted Time Register
BEAdmTime = 0x17C, // BE Queue Admitted Time Register
RQPN1 = 0x180, // Reserved Queue Page Number , Vo Vi, Be, Bk
RQPN2 = 0x184, // Reserved Queue Page Number, HCCA, Cmd, Mgnt, High
RQPN3 = 0x188, // Reserved Queue Page Number, Bcn, Public,
// QPRR = 0x1E0, // Queue Page Report per TID
QPNR = 0x1D0, //0x1F0, // Queue Packet Number report per TID
BQDA = 0x200, // Beacon Queue Descriptor Address
HQDA = 0x204, // High Priority Queue Descriptor Address
CQDA = 0x208, // Command Queue Descriptor Address
MQDA = 0x20C, // Management Queue Descriptor Address
HCCAQDA = 0x210, // HCCA Queue Descriptor Address
VOQDA = 0x214, // VO Queue Descriptor Address
VIQDA = 0x218, // VI Queue Descriptor Address
BEQDA = 0x21C, // BE Queue Descriptor Address
BKQDA = 0x220, // BK Queue Descriptor Address
RCQDA = 0x224, // Receive command Queue Descriptor Address
RDQDA = 0x228, // Receive Queue Descriptor Start Address
MAR0 = 0x240, // Multicast filter.
MAR4 = 0x244,
CCX_PERIOD = 0x250, // CCX Measurement Period Register, in unit of TU.
CLM_RESULT = 0x251, // CCA Busy fraction register.
NHM_PERIOD = 0x252, // NHM Measurement Period register, in unit of TU.
NHM_THRESHOLD0 = 0x253, // Noise Histogram Meashorement0.
NHM_THRESHOLD1 = 0x254, // Noise Histogram Meashorement1.
NHM_THRESHOLD2 = 0x255, // Noise Histogram Meashorement2.
NHM_THRESHOLD3 = 0x256, // Noise Histogram Meashorement3.
NHM_THRESHOLD4 = 0x257, // Noise Histogram Meashorement4.
NHM_THRESHOLD5 = 0x258, // Noise Histogram Meashorement5.
NHM_THRESHOLD6 = 0x259, // Noise Histogram Meashorement6
MCTRL = 0x25A, // Measurement Control
NHM_RPI_COUNTER0 = 0x264, // Noise Histogram RPI counter0, the fraction of signal strength < NHM_THRESHOLD0.
NHM_RPI_COUNTER1 = 0x265, // Noise Histogram RPI counter1, the fraction of signal strength in (NHM_THRESHOLD0, NHM_THRESHOLD1].
NHM_RPI_COUNTER2 = 0x266, // Noise Histogram RPI counter2, the fraction of signal strength in (NHM_THRESHOLD1, NHM_THRESHOLD2].
NHM_RPI_COUNTER3 = 0x267, // Noise Histogram RPI counter3, the fraction of signal strength in (NHM_THRESHOLD2, NHM_THRESHOLD3].
NHM_RPI_COUNTER4 = 0x268, // Noise Histogram RPI counter4, the fraction of signal strength in (NHM_THRESHOLD3, NHM_THRESHOLD4].
NHM_RPI_COUNTER5 = 0x269, // Noise Histogram RPI counter5, the fraction of signal strength in (NHM_THRESHOLD4, NHM_THRESHOLD5].
NHM_RPI_COUNTER6 = 0x26A, // Noise Histogram RPI counter6, the fraction of signal strength in (NHM_THRESHOLD5, NHM_THRESHOLD6].
NHM_RPI_COUNTER7 = 0x26B, // Noise Histogram RPI counter7, the fraction of signal strength in (NHM_THRESHOLD6, NHM_THRESHOLD7].
#define BW_OPMODE_11J BIT0
#define BW_OPMODE_5G BIT1
#define BW_OPMODE_20MHZ BIT2
BW_OPMODE = 0x300, // Bandwidth operation mode
MSR = 0x303, // Media Status register
#define MSR_LINK_MASK ((1<<0)|(1<<1))
#define MSR_LINK_MANAGED 2
#define MSR_LINK_NONE 0
#define MSR_LINK_SHIFT 0
#define MSR_LINK_ADHOC 1
#define MSR_LINK_MASTER 3
#define MSR_LINK_ENEDCA (1<<4)
RETRY_LIMIT = 0x304, // Retry Limit [15:8]-short, [7:0]-long
#define RETRY_LIMIT_SHORT_SHIFT 8
#define RETRY_LIMIT_LONG_SHIFT 0
TSFR = 0x308,
RRSR = 0x310, // Response Rate Set
#define RRSR_RSC_OFFSET 21
#define RRSR_SHORT_OFFSET 23
#define RRSR_RSC_DUPLICATE 0x600000
#define RRSR_RSC_LOWSUBCHNL 0x400000
#define RRSR_RSC_UPSUBCHANL 0x200000
#define RRSR_SHORT 0x800000
#define RRSR_1M BIT0
#define RRSR_2M BIT1
#define RRSR_5_5M BIT2
#define RRSR_11M BIT3
#define RRSR_6M BIT4
#define RRSR_9M BIT5
#define RRSR_12M BIT6
#define RRSR_18M BIT7
#define RRSR_24M BIT8
#define RRSR_36M BIT9
#define RRSR_48M BIT10
#define RRSR_54M BIT11
#define RRSR_MCS0 BIT12
#define RRSR_MCS1 BIT13
#define RRSR_MCS2 BIT14
#define RRSR_MCS3 BIT15
#define RRSR_MCS4 BIT16
#define RRSR_MCS5 BIT17
#define RRSR_MCS6 BIT18
#define RRSR_MCS7 BIT19
#define BRSR_AckShortPmb BIT23 // CCK ACK: use Short Preamble or not.
RATR0 = 0x320, // Rate Adaptive Table register1
UFWP = 0x318,
DRIVER_RSSI = 0x32c, // Driver tell Firmware current RSSI
//----------------------------------------------------------------------------
// 8190 Rate Adaptive Table Register (offset 0x320, 4 byte)
//----------------------------------------------------------------------------
//CCK
#define RATR_1M 0x00000001
#define RATR_2M 0x00000002
#define RATR_55M 0x00000004
#define RATR_11M 0x00000008
//OFDM
#define RATR_6M 0x00000010
#define RATR_9M 0x00000020
#define RATR_12M 0x00000040
#define RATR_18M 0x00000080
#define RATR_24M 0x00000100
#define RATR_36M 0x00000200
#define RATR_48M 0x00000400
#define RATR_54M 0x00000800
//MCS 1 Spatial Stream
#define RATR_MCS0 0x00001000
#define RATR_MCS1 0x00002000
#define RATR_MCS2 0x00004000
#define RATR_MCS3 0x00008000
#define RATR_MCS4 0x00010000
#define RATR_MCS5 0x00020000
#define RATR_MCS6 0x00040000
#define RATR_MCS7 0x00080000
//MCS 2 Spatial Stream
#define RATR_MCS8 0x00100000
#define RATR_MCS9 0x00200000
#define RATR_MCS10 0x00400000
#define RATR_MCS11 0x00800000
#define RATR_MCS12 0x01000000
#define RATR_MCS13 0x02000000
#define RATR_MCS14 0x04000000
#define RATR_MCS15 0x08000000
// ALL CCK Rate
#define RATE_ALL_CCK RATR_1M|RATR_2M|RATR_55M|RATR_11M
#define RATE_ALL_OFDM_AG RATR_6M|RATR_9M|RATR_12M|RATR_18M|RATR_24M\
|RATR_36M|RATR_48M|RATR_54M
#define RATE_ALL_OFDM_1SS RATR_MCS0|RATR_MCS1|RATR_MCS2|RATR_MCS3 | \
RATR_MCS4|RATR_MCS5|RATR_MCS6|RATR_MCS7
#define RATE_ALL_OFDM_2SS RATR_MCS8|RATR_MCS9 |RATR_MCS10|RATR_MCS11| \
RATR_MCS12|RATR_MCS13|RATR_MCS14|RATR_MCS15
MCS_TXAGC = 0x340, // MCS AGC
CCK_TXAGC = 0x348, // CCK AGC
// ISR = 0x350, // Interrupt Status Register
// IMR = 0x354, // Interrupt Mask Register
// IMR_POLL = 0x360,
MacBlkCtrl = 0x403, // Mac block on/off control register
EPROM_CMD = 0xfe58,
#define Cmd9346CR_9356SEL (1<<4)
#define EPROM_CMD_RESERVED_MASK (1<<5)
#define EPROM_CMD_OPERATING_MODE_SHIFT 6
#define EPROM_CMD_OPERATING_MODE_MASK ((1<<7)|(1<<6))
#define EPROM_CMD_CONFIG 0x3
#define EPROM_CMD_NORMAL 0
#define EPROM_CMD_LOAD 1
#define EPROM_CMD_PROGRAM 2
#define EPROM_CS_SHIFT 3
#define EPROM_CK_SHIFT 2
#define EPROM_W_SHIFT 1
#define EPROM_R_SHIFT 0
MAC0 = 0x000,
MAC1 = 0x001,
MAC2 = 0x002,
MAC3 = 0x003,
MAC4 = 0x004,
MAC5 = 0x005,
#if 0
/* 0x0006 - 0x0007 - reserved */
RXFIFOCOUNT = 0x010,
TXFIFOCOUNT = 0x012,
BQREQ = 0x013,
/* 0x0010 - 0x0017 - reserved */
TSFTR = 0x018,
TLPDA = 0x020,
TNPDA = 0x024,
THPDA = 0x028,
BSSID = 0x02E,
RESP_RATE = 0x034,
CMD = 0x037,
#define CMD_RST_SHIFT 4
#define CMD_RESERVED_MASK ((1<<1) | (1<<5) | (1<<6) | (1<<7))
#define CMD_RX_ENABLE_SHIFT 3
#define CMD_TX_ENABLE_SHIFT 2
#define CR_RST ((1<< 4))
#define CR_RE ((1<< 3))
#define CR_TE ((1<< 2))
#define CR_MulRW ((1<< 0))
INTA_MASK = 0x03c,
INTA = 0x03e,
#define INTA_TXOVERFLOW (1<<15)
#define INTA_TIMEOUT (1<<14)
#define INTA_BEACONTIMEOUT (1<<13)
#define INTA_ATIM (1<<12)
#define INTA_BEACONDESCERR (1<<11)
#define INTA_BEACONDESCOK (1<<10)
#define INTA_HIPRIORITYDESCERR (1<<9)
#define INTA_HIPRIORITYDESCOK (1<<8)
#define INTA_NORMPRIORITYDESCERR (1<<7)
#define INTA_NORMPRIORITYDESCOK (1<<6)
#define INTA_RXOVERFLOW (1<<5)
#define INTA_RXDESCERR (1<<4)
#define INTA_LOWPRIORITYDESCERR (1<<3)
#define INTA_LOWPRIORITYDESCOK (1<<2)
#define INTA_RXCRCERR (1<<1)
#define INTA_RXOK (1)
TX_CONF = 0x040,
#define TX_CONF_HEADER_AUTOICREMENT_SHIFT 30
#define TX_LOOPBACK_SHIFT 17
#define TX_LOOPBACK_MAC 1
#define TX_LOOPBACK_BASEBAND 2
#define TX_LOOPBACK_NONE 0
#define TX_LOOPBACK_CONTINUE 3
#define TX_LOOPBACK_MASK ((1<<17)|(1<<18))
#define TX_LRLRETRY_SHIFT 0
#define TX_SRLRETRY_SHIFT 8
#define TX_NOICV_SHIFT 19
#define TX_NOCRC_SHIFT 16
#define TCR_DurProcMode ((1<<30))
#define TCR_DISReqQsize ((1<<28))
#define TCR_HWVERID_MASK ((1<<27)|(1<<26)|(1<<25))
#define TCR_HWVERID_SHIFT 25
#define TCR_SWPLCPLEN ((1<<24))
#define TCR_PLCP_LEN TCR_SAT // rtl8180
#define TCR_MXDMA_MASK ((1<<23)|(1<<22)|(1<<21))
#define TCR_MXDMA_1024 6
#define TCR_MXDMA_2048 7
#define TCR_MXDMA_SHIFT 21
#define TCR_DISCW ((1<<20))
#define TCR_ICV ((1<<19))
#define TCR_LBK ((1<<18)|(1<<17))
#define TCR_LBK1 ((1<<18))
#define TCR_LBK0 ((1<<17))
#define TCR_CRC ((1<<16))
#define TCR_SRL_MASK ((1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(1<<10)|(1<<9)|(1<<8))
#define TCR_LRL_MASK ((1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<7))
#define TCR_PROBE_NOTIMESTAMP_SHIFT 29 //rtl8185
RX_CONF = 0x044,
#define MAC_FILTER_MASK ((1<<0) | (1<<1) | (1<<2) | (1<<3) | (1<<5) | \
(1<<12) | (1<<18) | (1<<19) | (1<<20) | (1<<21) | (1<<22) | (1<<23))
#define RX_CHECK_BSSID_SHIFT 23
#define ACCEPT_PWR_FRAME_SHIFT 22
#define ACCEPT_MNG_FRAME_SHIFT 20
#define ACCEPT_CTL_FRAME_SHIFT 19
#define ACCEPT_DATA_FRAME_SHIFT 18
#define ACCEPT_ICVERR_FRAME_SHIFT 12
#define ACCEPT_CRCERR_FRAME_SHIFT 5
#define ACCEPT_BCAST_FRAME_SHIFT 3
#define ACCEPT_MCAST_FRAME_SHIFT 2
#define ACCEPT_ALLMAC_FRAME_SHIFT 0
#define ACCEPT_NICMAC_FRAME_SHIFT 1
#define RX_FIFO_THRESHOLD_MASK ((1<<13) | (1<<14) | (1<<15))
#define RX_FIFO_THRESHOLD_SHIFT 13
#define RX_FIFO_THRESHOLD_128 3
#define RX_FIFO_THRESHOLD_256 4
#define RX_FIFO_THRESHOLD_512 5
#define RX_FIFO_THRESHOLD_1024 6
#define RX_FIFO_THRESHOLD_NONE 7
#define RX_AUTORESETPHY_SHIFT 28
#define MAX_RX_DMA_MASK ((1<<8) | (1<<9) | (1<<10))
#define MAX_RX_DMA_2048 7
#define MAX_RX_DMA_1024 6
#define MAX_RX_DMA_SHIFT 10
#define RCR_ONLYERLPKT ((1<<31))
#define RCR_CS_SHIFT 29
#define RCR_CS_MASK ((1<<30) | (1<<29))
#define RCR_ENMARP ((1<<28))
#define RCR_CBSSID ((1<<23))
#define RCR_APWRMGT ((1<<22))
#define RCR_ADD3 ((1<<21))
#define RCR_AMF ((1<<20))
#define RCR_ACF ((1<<19))
#define RCR_ADF ((1<<18))
#define RCR_RXFTH ((1<<15)|(1<<14)|(1<<13))
#define RCR_RXFTH2 ((1<<15))
#define RCR_RXFTH1 ((1<<14))
#define RCR_RXFTH0 ((1<<13))
#define RCR_AICV ((1<<12))
#define RCR_MXDMA ((1<<10)|(1<< 9)|(1<< 8))
#define RCR_MXDMA2 ((1<<10))
#define RCR_MXDMA1 ((1<< 9))
#define RCR_MXDMA0 ((1<< 8))
#define RCR_9356SEL ((1<< 6))
#define RCR_ACRC32 ((1<< 5))
#define RCR_AB ((1<< 3))
#define RCR_AM ((1<< 2))
#define RCR_APM ((1<< 1))
#define RCR_AAP ((1<< 0))
INT_TIMEOUT = 0x048,
TX_BEACON_RING_ADDR = 0x04c,
EPROM_CMD = 0x58,
#define EPROM_CMD_RESERVED_MASK ((1<<5)|(1<<4))
#define EPROM_CMD_OPERATING_MODE_SHIFT 6
#define EPROM_CMD_OPERATING_MODE_MASK ((1<<7)|(1<<6))
#define EPROM_CMD_CONFIG 0x3
#define EPROM_CMD_NORMAL 0
#define EPROM_CMD_LOAD 1
#define EPROM_CMD_PROGRAM 2
#define EPROM_CS_SHIFT 3
#define EPROM_CK_SHIFT 2
#define EPROM_W_SHIFT 1
#define EPROM_R_SHIFT 0
CONFIG0 = 0x051,
#define CONFIG0_WEP104 ((1<<6))
#define CONFIG0_LEDGPO_En ((1<<4))
#define CONFIG0_Aux_Status ((1<<3))
#define CONFIG0_GL ((1<<1)|(1<<0))
#define CONFIG0_GL1 ((1<<1))
#define CONFIG0_GL0 ((1<<0))
CONFIG1 = 0x052,
#define CONFIG1_LEDS ((1<<7)|(1<<6))
#define CONFIG1_LEDS1 ((1<<7))
#define CONFIG1_LEDS0 ((1<<6))
#define CONFIG1_LWACT ((1<<4))
#define CONFIG1_MEMMAP ((1<<3))
#define CONFIG1_IOMAP ((1<<2))
#define CONFIG1_VPD ((1<<1))
#define CONFIG1_PMEn ((1<<0))
CONFIG2 = 0x053,
#define CONFIG2_LCK ((1<<7))
#define CONFIG2_ANT ((1<<6))
#define CONFIG2_DPS ((1<<3))
#define CONFIG2_PAPE_sign ((1<<2))
#define CONFIG2_PAPE_time ((1<<1)|(1<<0))
#define CONFIG2_PAPE_time1 ((1<<1))
#define CONFIG2_PAPE_time0 ((1<<0))
ANA_PARAM = 0x054,
CONFIG3 = 0x059,
#define CONFIG3_GNTSel ((1<<7))
#define CONFIG3_PARM_En ((1<<6))
#define CONFIG3_Magic ((1<<5))
#define CONFIG3_CardB_En ((1<<3))
#define CONFIG3_CLKRUN_En ((1<<2))
#define CONFIG3_FuncRegEn ((1<<1))
#define CONFIG3_FBtbEn ((1<<0))
#define CONFIG3_CLKRUN_SHIFT 2
#define CONFIG3_ANAPARAM_W_SHIFT 6
CONFIG4 = 0x05a,
#define CONFIG4_VCOPDN ((1<<7))
#define CONFIG4_PWROFF ((1<<6))
#define CONFIG4_PWRMGT ((1<<5))
#define CONFIG4_LWPME ((1<<4))
#define CONFIG4_LWPTN ((1<<2))
#define CONFIG4_RFTYPE ((1<<1)|(1<<0))
#define CONFIG4_RFTYPE1 ((1<<1))
#define CONFIG4_RFTYPE0 ((1<<0))
TESTR = 0x05b,
#define TFPC_AC 0x05C
#define SCR 0x05F
PGSELECT = 0x05e,
#define PGSELECT_PG_SHIFT 0
SECURITY = 0x05f,
#define SECURITY_WEP_TX_ENABLE_SHIFT 1
#define SECURITY_WEP_RX_ENABLE_SHIFT 0
#define SECURITY_ENCRYP_104 1
#define SECURITY_ENCRYP_SHIFT 4
#define SECURITY_ENCRYP_MASK ((1<<4)|(1<<5))
ANA_PARAM2 = 0x060,
BEACON_INTERVAL = 0x070,
#define BEACON_INTERVAL_MASK ((1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4)|(1<<5)| \
(1<<6)|(1<<7)|(1<<8)|(1<<9))
ATIM_WND = 0x072,
#define ATIM_WND_MASK (0x01FF)
BCN_INTR_ITV = 0x074,
#define BCN_INTR_ITV_MASK (0x01FF)
ATIM_INTR_ITV = 0x076,
#define ATIM_INTR_ITV_MASK (0x01FF)
AckTimeOutReg = 0x079, //ACK timeout register, in unit of 4 us.
PHY_ADR = 0x07c,
PHY_READ = 0x07e,
RFPinsOutput = 0x080,
RFPinsEnable = 0x082,
//Page 0
RFPinsSelect = 0x084,
#define SW_CONTROL_GPIO 0x400
RFPinsInput = 0x086,
RF_PARA = 0x088,
RF_TIMING = 0x08c,
GP_ENABLE = 0x090,
GPIO = 0x091,
TX_AGC_CTL = 0x09c,
#define TX_AGC_CTL_PER_PACKET_TXAGC 0x01
#define TX_AGC_CTL_PERPACKET_GAIN_SHIFT 0
#define TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT 1
#define TX_AGC_CTL_FEEDBACK_ANT 2
#define TXAGC_CTL_PER_PACKET_ANT_SEL 0x02
OFDM_TXAGC = 0x09e,
ANTSEL = 0x09f,
WPA_CONFIG = 0x0b0,
SIFS = 0x0b4,
DIFS = 0x0b5,
SLOT = 0x0b6,
CW_CONF = 0x0bc,
#define CW_CONF_PERPACKET_RETRY_LIMIT 0x02
#define CW_CONF_PERPACKET_CW 0x01
#define CW_CONF_PERPACKET_RETRY_SHIFT 1
#define CW_CONF_PERPACKET_CW_SHIFT 0
CW_VAL = 0x0bd,
RATE_FALLBACK = 0x0be,
#define MAX_RESP_RATE_SHIFT 4
#define MIN_RESP_RATE_SHIFT 0
#define RATE_FALLBACK_CTL_ENABLE 0x80
#define RATE_FALLBACK_CTL_AUTO_STEP0 0x00
ACM_CONTROL = 0x0BF, // ACM Control Registe
//----------------------------------------------------------------------------
// 8187B ACM_CONTROL bits (Offset 0xBF, 1 Byte)
//----------------------------------------------------------------------------
#define VOQ_ACM_EN (0x01 << 7) //BIT7
#define VIQ_ACM_EN (0x01 << 6) //BIT6
#define BEQ_ACM_EN (0x01 << 5) //BIT5
#define ACM_HW_EN (0x01 << 4) //BIT4
#define TXOPSEL (0x01 << 3) //BIT3
#define VOQ_ACM_CTL (0x01 << 2) //BIT2 // Set to 1 when AC_VO used time reaches or exceeds the admitted time
#define VIQ_ACM_CTL (0x01 << 1) //BIT1 // Set to 1 when AC_VI used time reaches or exceeds the admitted time
#define BEQ_ACM_CTL (0x01 << 0) //BIT0 // Set to 1 when AC_BE used time reaches or exceeds the admitted time
CONFIG5 = 0x0D8,
#define CONFIG5_TX_FIFO_OK ((1<<7))
#define CONFIG5_RX_FIFO_OK ((1<<6))
#define CONFIG5_CALON ((1<<5))
#define CONFIG5_EACPI ((1<<2))
#define CONFIG5_LANWake ((1<<1))
#define CONFIG5_PME_STS ((1<<0))
TX_DMA_POLLING = 0x0d9,
#define TX_DMA_POLLING_BEACON_SHIFT 7
#define TX_DMA_POLLING_HIPRIORITY_SHIFT 6
#define TX_DMA_POLLING_NORMPRIORITY_SHIFT 5
#define TX_DMA_POLLING_LOWPRIORITY_SHIFT 4
#define TX_DMA_STOP_BEACON_SHIFT 3
#define TX_DMA_STOP_HIPRIORITY_SHIFT 2
#define TX_DMA_STOP_NORMPRIORITY_SHIFT 1
#define TX_DMA_STOP_LOWPRIORITY_SHIFT 0
CWR = 0x0DC,
RetryCTR = 0x0DE,
INT_MIG = 0x0E2, // Interrupt Migration (0xE2 ~ 0xE3)
TID_AC_MAP = 0x0E8, // TID to AC Mapping Register
ANA_PARAM3 = 0x0EE,
//page 1
Wakeup0 = 0x084,
Wakeup1 = 0x08C,
Wakeup2LD = 0x094,
Wakeup2HD = 0x09C,
Wakeup3LD = 0x0A4,
Wakeup3HD = 0x0AC,
Wakeup4LD = 0x0B4,
Wakeup4HD = 0x0BC,
CRC0 = 0x0C4,
CRC1 = 0x0C6,
CRC2 = 0x0C8,
CRC3 = 0x0CA,
CRC4 = 0x0CC,
/* 0x00CE - 0x00D3 - reserved */
RFSW_CTRL = 0x272, // 0x272-0x273.
//Reg Diff between rtl8187 and rtl8187B
/**************************************************************************/
BRSR_8187 = 0x02C,
BRSR_8187B = 0x034,
#define BRSR_BPLCP ((1<< 8))
#define BRSR_MBR ((1<< 1)|(1<< 0))
#define BRSR_MBR_8185 ((1<< 11)|(1<< 10)|(1<< 9)|(1<< 8)|(1<< 7)|(1<< 6)|(1<< 5)|(1<< 4)|(1<< 3)|(1<< 2)|(1<< 1)|(1<< 0))
#define BRSR_MBR0 ((1<< 0))
#define BRSR_MBR1 ((1<< 1))
/**************************************************************************/
EIFS_8187 = 0x035,
EIFS_8187B = 0x02D,
/**************************************************************************/
FER = 0x0F0,
FEMR = 0x0F4,
FPSR = 0x0F8,
FFER = 0x0FC,
AC_VO_PARAM = 0x0F0, // AC_VO Parameters Record
AC_VI_PARAM = 0x0F4, // AC_VI Parameters Record
AC_BE_PARAM = 0x0F8, // AC_BE Parameters Record
AC_BK_PARAM = 0x0FC, // AC_BK Parameters Record
TALLY_SEL = 0x0fc,
//----------------------------------------------------------------------------
// 8187B AC_XX_PARAM bits
//----------------------------------------------------------------------------
#define AC_PARAM_TXOP_LIMIT_OFFSET 16
#define AC_PARAM_ECW_MAX_OFFSET 12
#define AC_PARAM_ECW_MIN_OFFSET 8
#define AC_PARAM_AIFS_OFFSET 0
#endif
};
//----------------------------------------------------------------------------
// 818xB AnaParm & AnaParm2 Register
//----------------------------------------------------------------------------
//#define ANAPARM_ASIC_ON 0x45090658
//#define ANAPARM2_ASIC_ON 0x727f3f52
#define GPI 0x108
#define GPO 0x109
#define GPE 0x10a
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,23 @@
/*
This is part of rtl8180 OpenSource driver - v 0.3
Copyright (C) Andrea Merello 2004 <andreamrl@tiscali.it>
Released under the terms of GPL (General Public Licence)
Parts of this driver are based on the GPL part of the official realtek driver
Parts of this driver are based on the rtl8180 driver skeleton from Patric Schenke & Andres Salomon
Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver
We want to tanks the Authors of such projects and the Ndiswrapper project Authors.
*/
/* this file (will) contains wireless extension handlers*/
#ifndef R8180_WX_H
#define R8180_WX_H
//#include <linux/wireless.h>
//#include "ieee80211.h"
extern struct iw_handler_def r8192_wx_handlers_def;
/* Enable the rtl819x_core.c to share this function, david 2008.9.22 */
extern struct iw_statistics *r8192_get_wireless_stats(struct net_device *dev);
#endif

View File

@ -0,0 +1,13 @@
//
// IOT Action for different AP
//
typedef enum _HT_IOT_ACTION{
HT_IOT_ACT_TX_USE_AMSDU_4K = 0x00000001,
HT_IOT_ACT_TX_USE_AMSDU_8K = 0x00000002,
HT_IOT_ACT_DECLARE_MCS13 = 0x00000004,
HT_IOT_ACT_DISABLE_EDCA_TURBO = 0x00000008,
HT_IOT_ACT_MGNT_USE_CCK_6M = 0x00000010,
HT_IOT_ACT_CDD_FSYNC = 0x00000020,
HT_IOT_ACT_PURE_N_MODE = 0x00000040,
}HT_IOT_ACTION_E, *PHT_IOT_ACTION_E;

View File

@ -0,0 +1,391 @@
#ifndef _R819XU_HTTYPE_H_
#define _R819XU_HTTYPE_H_
//------------------------------------------------------------
// The HT Capability element is present in beacons, association request,
// reassociation request and probe response frames
//------------------------------------------------------------
//
// Operation mode value
//
#define HT_OPMODE_NO_PROTECT 0
#define HT_OPMODE_OPTIONAL 1
#define HT_OPMODE_40MHZ_PROTECT 2
#define HT_OPMODE_MIXED 3
//
// MIMO Power Save Setings
//
#define MIMO_PS_STATIC 0
#define MIMO_PS_DYNAMIC 1
#define MIMO_PS_NOLIMIT 3
//
// There should be 128 bits to cover all of the MCS rates. However, since
// 8190 does not support too much rates, one integer is quite enough.
//
#define sHTCLng 4
#define HT_SUPPORTED_MCS_1SS_BITMAP 0x000000ff
#define HT_SUPPORTED_MCS_2SS_BITMAP 0x0000ff00
#define HT_SUPPORTED_MCS_1SS_2SS_BITMAP HT_MCS_1SS_BITMAP|HT_MCS_1SS_2SS_BITMAP
typedef enum _HT_MCS_RATE{
HT_MCS0 = 0x00000001,
HT_MCS1 = 0x00000002,
HT_MCS2 = 0x00000004,
HT_MCS3 = 0x00000008,
HT_MCS4 = 0x00000010,
HT_MCS5 = 0x00000020,
HT_MCS6 = 0x00000040,
HT_MCS7 = 0x00000080,
HT_MCS8 = 0x00000100,
HT_MCS9 = 0x00000200,
HT_MCS10 = 0x00000400,
HT_MCS11 = 0x00000800,
HT_MCS12 = 0x00001000,
HT_MCS13 = 0x00002000,
HT_MCS14 = 0x00004000,
HT_MCS15 = 0x00008000,
// Do not define MCS32 here although 8190 support MCS32
}HT_MCS_RATE,*PHT_MCS_RATE;
//
// Represent Channel Width in HT Capabilities
//
typedef enum _HT_CHANNEL_WIDTH{
HT_CHANNEL_WIDTH_20 = 0,
HT_CHANNEL_WIDTH_20_40 = 1,
}HT_CHANNEL_WIDTH, *PHT_CHANNEL_WIDTH;
//
// Represent Extention Channel Offset in HT Capabilities
// This is available only in 40Mhz mode.
//
typedef enum _HT_EXTCHNL_OFFSET{
HT_EXTCHNL_OFFSET_NO_EXT = 0,
HT_EXTCHNL_OFFSET_UPPER = 1,
HT_EXTCHNL_OFFSET_NO_DEF = 2,
HT_EXTCHNL_OFFSET_LOWER = 3,
}HT_EXTCHNL_OFFSET, *PHT_EXTCHNL_OFFSET;
typedef enum _CHNLOP{
CHNLOP_NONE = 0, // No Action now
CHNLOP_SCAN = 1, // Scan in progress
CHNLOP_SWBW = 2, // Bandwidth switching in progress
CHNLOP_SWCHNL = 3, // Software Channel switching in progress
} CHNLOP, *PCHNLOP;
// Determine if the Channel Operation is in progress
#define CHHLOP_IN_PROGRESS(_pHTInfo) \
((_pHTInfo)->ChnlOp > CHNLOP_NONE) ? TRUE : FALSE
typedef enum _HT_ACTION{
ACT_RECOMMAND_WIDTH = 0,
ACT_MIMO_PWR_SAVE = 1,
ACT_PSMP = 2,
ACT_SET_PCO_PHASE = 3,
ACT_MIMO_CHL_MEASURE = 4,
ACT_RECIPROCITY_CORRECT = 5,
ACT_MIMO_CSI_MATRICS = 6,
ACT_MIMO_NOCOMPR_STEER = 7,
ACT_MIMO_COMPR_STEER = 8,
ACT_ANTENNA_SELECT = 9,
} HT_ACTION, *PHT_ACTION;
/* 2007/06/07 MH Define sub-carrier mode for 40MHZ. */
typedef enum _HT_Bandwidth_40MHZ_Sub_Carrier{
SC_MODE_DUPLICATE = 0,
SC_MODE_LOWER = 1,
SC_MODE_UPPER = 2,
SC_MODE_FULL40MHZ = 3,
}HT_BW40_SC_E;
typedef struct _HT_CAPABILITY_ELE{
//HT capability info
u8 AdvCoding:1;
u8 ChlWidth:1;
u8 MimoPwrSave:2;
u8 GreenField:1;
u8 ShortGI20Mhz:1;
u8 ShortGI40Mhz:1;
u8 TxSTBC:1;
u8 RxSTBC:2;
u8 DelayBA:1;
u8 MaxAMSDUSize:1;
u8 DssCCk:1;
u8 PSMP:1;
u8 Rsvd1:1;
u8 LSigTxopProtect:1;
//MAC HT parameters info
u8 MaxRxAMPDUFactor:2;
u8 MPDUDensity:3;
u8 Rsvd2:3;
//Supported MCS set
u8 MCS[16];
//Extended HT Capability Info
u16 ExtHTCapInfo;
//TXBF Capabilities
u8 TxBFCap[4];
//Antenna Selection Capabilities
u8 ASCap;
}__attribute__((packed)) HT_CAPABILITY_ELE, *PHT_CAPABILITY_ELE;
//------------------------------------------------------------
// The HT Information element is present in beacons
// Only AP is required to include this element
//------------------------------------------------------------
typedef struct _HT_INFORMATION_ELE{
u8 ControlChl;
u8 ExtChlOffset:2;
u8 RecommemdedTxWidth:1;
u8 RIFS:1;
u8 PSMPAccessOnly:1;
u8 SrvIntGranularity:3;
u8 OptMode:2;
u8 NonGFDevPresent:1;
u8 Revd1:5;
u8 Revd2:8;
u8 Rsvd3:6;
u8 DualBeacon:1;
u8 DualCTSProtect:1;
u8 SecondaryBeacon:1;
u8 LSigTxopProtectFull:1;
u8 PcoActive:1;
u8 PcoPhase:1;
u8 Rsvd4:4;
u8 BasicMSC[16];
}__attribute__((packed)) HT_INFORMATION_ELE, *PHT_INFORMATION_ELE;
//
// MIMO Power Save control field.
// This is appear in MIMO Power Save Action Frame
//
typedef struct _MIMOPS_CTRL{
u8 MimoPsEnable:1;
u8 MimoPsMode:1;
u8 Reserved:6;
} MIMOPS_CTRL, *PMIMOPS_CTRL;
typedef enum _HT_SPEC_VER{
HT_SPEC_VER_IEEE = 0,
HT_SPEC_VER_EWC = 1,
}HT_SPEC_VER, *PHT_SPEC_VER;
typedef enum _HT_AGGRE_MODE_E{
HT_AGG_AUTO = 0,
HT_AGG_FORCE_ENABLE = 1,
HT_AGG_FORCE_DISABLE = 2,
}HT_AGGRE_MODE_E, *PHT_AGGRE_MODE_E;
//------------------------------------------------------------
// The Data structure is used to keep HT related variables when card is
// configured as non-AP STA mode. **Note** Current_xxx should be set
// to default value in HTInitializeHTInfo()
//------------------------------------------------------------
typedef struct _RT_HIGH_THROUGHPUT{
// DECLARE_RT_OBJECT(_RT_HIGH_THROUGHPUT);
u8 bEnableHT;
u8 bCurrentHTSupport;
u8 bRegBW40MHz; // Tx 40MHz channel capablity
u8 bCurBW40MHz; // Tx 40MHz channel capability
u8 bRegShortGI40MHz; // Tx Short GI for 40Mhz
u8 bCurShortGI40MHz; // Tx Short GI for 40MHz
u8 bRegShortGI20MHz; // Tx Short GI for 20MHz
u8 bCurShortGI20MHz; // Tx Short GI for 20MHz
u8 bRegSuppCCK; // Tx CCK rate capability
u8 bCurSuppCCK; // Tx CCK rate capability
// 802.11n spec version for "peer"
HT_SPEC_VER ePeerHTSpecVer;
// HT related information for "Self"
HT_CAPABILITY_ELE SelfHTCap; // This is HT cap element sent to peer STA, which also indicate HT Rx capabilities.
HT_INFORMATION_ELE SelfHTInfo; // This is HT info element sent to peer STA, which also indicate HT Rx capabilities.
// HT related information for "Peer"
u8 PeerHTCapBuf[32];
u8 PeerHTInfoBuf[32];
// A-MSDU related
u8 bAMSDU_Support; // This indicates Tx A-MSDU capability
u16 nAMSDU_MaxSize; // This indicates Tx A-MSDU capability
u8 bCurrent_AMSDU_Support; // This indicates Tx A-MSDU capability
u16 nCurrent_AMSDU_MaxSize; // This indicates Tx A-MSDU capability
// AMPDU related <2006.08.10 Emily>
u8 bAMPDUEnable; // This indicate Tx A-MPDU capability
u8 bCurrentAMPDUEnable; // This indicate Tx A-MPDU capability
u8 AMPDU_Factor; // This indicate Tx A-MPDU capability
u8 CurrentAMPDUFactor; // This indicate Tx A-MPDU capability
u8 MPDU_Density; // This indicate Tx A-MPDU capability
u8 CurrentMPDUDensity; // This indicate Tx A-MPDU capability
// Forced A-MPDU enable
HT_AGGRE_MODE_E ForcedAMPDUMode;
u8 ForcedAMPDUFactor;
u8 ForcedMPDUDensity;
// Forced A-MSDU enable
HT_AGGRE_MODE_E ForcedAMSDUMode;
u16 ForcedAMSDUMaxSize;
u8 bForcedShortGI;
u8 CurrentOpMode;
// MIMO PS related
u8 SelfMimoPs;
u8 PeerMimoPs;
// 40MHz Channel Offset settings.
HT_EXTCHNL_OFFSET CurSTAExtChnlOffset;
u8 bCurTxBW40MHz; // If we use 40 MHz to Tx
u8 PeerBandwidth;
// For Bandwidth Switching
u8 bSwBwInProgress;
CHNLOP ChnlOp; // software switching channel in progress. By Bruce, 2008-02-15.
u8 SwBwStep;
//RT_TIMER SwBwTimer;
struct timer_list SwBwTimer;
// For Realtek proprietary A-MPDU factor for aggregation
u8 bRegRT2RTAggregation;
u8 bCurrentRT2RTAggregation;
u8 bCurrentRT2RTLongSlotTime;
u8 szRT2RTAggBuffer[10];
// Rx Reorder control
u8 bRegRxReorderEnable;
u8 bCurRxReorderEnable;
u8 RxReorderWinSize;
u8 RxReorderPendingTime;
u16 RxReorderDropCounter;
#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
u8 UsbTxAggrNum;
#endif
#ifdef USB_RX_AGGREGATION_SUPPORT
u8 UsbRxFwAggrEn;
u8 UsbRxFwAggrPageNum;
u8 UsbRxFwAggrPacketNum;
u8 UsbRxFwAggrTimeout;
#endif
// Add for Broadcom(Linksys) IOT. Joseph
u8 bIsPeerBcm;
// For IOT issue.
u32 IOTAction;
}RT_HIGH_THROUGHPUT, *PRT_HIGH_THROUGHPUT;
//------------------------------------------------------------
// The Data structure is used to keep HT related variable for "each Sta"
// when card is configured as "AP mode"
//------------------------------------------------------------
typedef struct _RT_HTINFO_STA_ENTRY{
u8 bEnableHT;
u8 bSupportCck;
u16 AMSDU_MaxSize;
u8 AMPDU_Factor;
u8 MPDU_Density;
u8 HTHighestOperaRate;
u8 bBw40MHz;
u8 MimoPs;
u8 McsRateSet[16];
}RT_HTINFO_STA_ENTRY, *PRT_HTINFO_STA_ENTRY;
//------------------------------------------------------------
// The Data structure is used to keep HT related variable for "each AP"
// when card is configured as "STA mode"
//------------------------------------------------------------
typedef struct _BSS_HT{
u8 bdSupportHT;
// HT related elements
u8 bdHTCapBuf[32];
u16 bdHTCapLen;
u8 bdHTInfoBuf[32];
u16 bdHTInfoLen;
HT_SPEC_VER bdHTSpecVer;
//HT_CAPABILITY_ELE bdHTCapEle;
//HT_INFORMATION_ELE bdHTInfoEle;
u8 bdRT2RTAggregation;
u8 bdRT2RTLongSlotTime;
}BSS_HT, *PBSS_HT;
typedef struct _MIMO_RSSI{
u32 EnableAntenna;
u32 AntennaA;
u32 AntennaB;
u32 AntennaC;
u32 AntennaD;
u32 Average;
}MIMO_RSSI, *PMIMO_RSSI;
typedef struct _MIMO_EVM{
u32 EVM1;
u32 EVM2;
}MIMO_EVM, *PMIMO_EVM;
typedef struct _FALSE_ALARM_STATISTICS{
u32 Cnt_Parity_Fail;
u32 Cnt_Rate_Illegal;
u32 Cnt_Crc8_fail;
u32 Cnt_all;
}FALSE_ALARM_STATISTICS, *PFALSE_ALARM_STATISTICS;
#endif //__INC_HTTYPE_H

View File

@ -0,0 +1,822 @@
/******************************************************************************
(c) Copyright 2008, RealTEK Technologies Inc. All Rights Reserved.
Module: r819xusb_cmdpkt.c (RTL8190 TX/RX command packet handler Source C File)
Note: The module is responsible for handling TX and RX command packet.
1. TX : Send set and query configuration command packet.
2. RX : Receive tx feedback, beacon state, query configuration
command packet.
Function:
Export:
Abbrev:
History:
Data Who Remark
05/06/2008 amy Create initial version porting from windows driver.
******************************************************************************/
#include "r8192U.h"
#include "r819xU_cmdpkt.h"
/*---------------------------Define Local Constant---------------------------*/
/* Debug constant*/
#define CMPK_DEBOUNCE_CNT 1
/* 2007/10/24 MH Add for printing a range of data. */
#define CMPK_PRINT(Address)\
{\
unsigned char i;\
u32 temp[10];\
\
memcpy(temp, Address, 40);\
for (i = 0; i <40; i+=4)\
printk("\r\n %08x", temp[i]);\
}\
/*---------------------------Define functions---------------------------------*/
rt_status
SendTxCommandPacket(
struct net_device *dev,
void* pData,
u32 DataLen
)
{
rt_status rtStatus = RT_STATUS_SUCCESS;
struct r8192_priv *priv = ieee80211_priv(dev);
struct sk_buff *skb;
cb_desc *tcb_desc;
unsigned char *ptr_buf;
//bool bLastInitPacket = false;
//PlatformAcquireSpinLock(Adapter, RT_TX_SPINLOCK);
//Get TCB and local buffer from common pool. (It is shared by CmdQ, MgntQ, and USB coalesce DataQ)
skb = dev_alloc_skb(USB_HWDESC_HEADER_LEN + DataLen + 4);
memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev));
tcb_desc = (cb_desc*)(skb->cb + MAX_DEV_ADDR_SIZE);
tcb_desc->queue_index = TXCMD_QUEUE;
tcb_desc->bCmdOrInit = DESC_PACKET_TYPE_NORMAL;
tcb_desc->bLastIniPkt = 0;
skb_reserve(skb, USB_HWDESC_HEADER_LEN);
ptr_buf = skb_put(skb, DataLen);
memset(ptr_buf,0,DataLen);
memcpy(ptr_buf,pData,DataLen);
tcb_desc->txbuf_size= (u16)DataLen;
if(!priv->ieee80211->check_nic_enough_desc(dev,tcb_desc->queue_index)||
(!skb_queue_empty(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index]))||\
(priv->ieee80211->queue_stop) ) {
RT_TRACE(COMP_FIRMWARE,"===================NULL packet==================================> tx full!\n");
skb_queue_tail(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index], skb);
} else {
priv->ieee80211->softmac_hard_start_xmit(skb,dev);
}
//PlatformReleaseSpinLock(Adapter, RT_TX_SPINLOCK);
return rtStatus;
}
/*-----------------------------------------------------------------------------
* Function: cmpk_message_handle_tx()
*
* Overview: Driver internal module can call the API to send message to
* firmware side. For example, you can send a debug command packet.
* Or you can send a request for FW to modify RLX4181 LBUS HW bank.
* Otherwise, you can change MAC/PHT/RF register by firmware at
* run time. We do not support message more than one segment now.
*
* Input: NONE
*
* Output: NONE
*
* Return: NONE
*
* Revised History:
* When Who Remark
* 05/06/2008 amy porting from windows code.
*
*---------------------------------------------------------------------------*/
extern rt_status cmpk_message_handle_tx(
struct net_device *dev,
u8* codevirtualaddress,
u32 packettype,
u32 buffer_len)
{
bool rt_status = true;
#ifdef RTL8192U
return rt_status;
#else
struct r8192_priv *priv = ieee80211_priv(dev);
u16 frag_threshold;
u16 frag_length, frag_offset = 0;
//u16 total_size;
//int i;
rt_firmware *pfirmware = priv->pFirmware;
struct sk_buff *skb;
unsigned char *seg_ptr;
cb_desc *tcb_desc;
u8 bLastIniPkt;
firmware_init_param(dev);
//Fragmentation might be required
frag_threshold = pfirmware->cmdpacket_frag_thresold;
do {
if((buffer_len - frag_offset) > frag_threshold) {
frag_length = frag_threshold ;
bLastIniPkt = 0;
} else {
frag_length = buffer_len - frag_offset;
bLastIniPkt = 1;
}
/* Allocate skb buffer to contain firmware info and tx descriptor info
* add 4 to avoid packet appending overflow.
* */
#ifdef RTL8192U
skb = dev_alloc_skb(USB_HWDESC_HEADER_LEN + frag_length + 4);
#else
skb = dev_alloc_skb(frag_length + 4);
#endif
memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev));
tcb_desc = (cb_desc*)(skb->cb + MAX_DEV_ADDR_SIZE);
tcb_desc->queue_index = TXCMD_QUEUE;
tcb_desc->bCmdOrInit = packettype;
tcb_desc->bLastIniPkt = bLastIniPkt;
#ifdef RTL8192U
skb_reserve(skb, USB_HWDESC_HEADER_LEN);
#endif
seg_ptr = skb_put(skb, buffer_len);
/*
* Transform from little endian to big endian
* and pending zero
*/
memcpy(seg_ptr,codevirtualaddress,buffer_len);
tcb_desc->txbuf_size= (u16)buffer_len;
if(!priv->ieee80211->check_nic_enough_desc(dev,tcb_desc->queue_index)||
(!skb_queue_empty(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index]))||\
(priv->ieee80211->queue_stop) ) {
RT_TRACE(COMP_FIRMWARE,"=====================================================> tx full!\n");
skb_queue_tail(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index], skb);
} else {
priv->ieee80211->softmac_hard_start_xmit(skb,dev);
}
codevirtualaddress += frag_length;
frag_offset += frag_length;
}while(frag_offset < buffer_len);
return rt_status;
#endif
} /* CMPK_Message_Handle_Tx */
/*-----------------------------------------------------------------------------
* Function: cmpk_counttxstatistic()
*
* Overview:
*
* Input: PADAPTER pAdapter - .
* CMPK_TXFB_T *psTx_FB - .
*
* Output: NONE
*
* Return: NONE
*
* Revised History:
* When Who Remark
* 05/12/2008 amy Create Version 0 porting from windows code.
*
*---------------------------------------------------------------------------*/
static void
cmpk_count_txstatistic(
struct net_device *dev,
cmpk_txfb_t *pstx_fb)
{
struct r8192_priv *priv = ieee80211_priv(dev);
#ifdef ENABLE_PS
RT_RF_POWER_STATE rtState;
pAdapter->HalFunc.GetHwRegHandler(pAdapter, HW_VAR_RF_STATE, (pu1Byte)(&rtState));
// When RF is off, we should not count the packet for hw/sw synchronize
// reason, ie. there may be a duration while sw switch is changed and hw
// switch is being changed. 2006.12.04, by shien chang.
if (rtState == eRfOff)
{
return;
}
#endif
#ifdef TODO
if(pAdapter->bInHctTest)
return;
#endif
/* We can not know the packet length and transmit type: broadcast or uni
or multicast. So the relative statistics must be collected in tx
feedback info. */
if (pstx_fb->tok)
{
priv->stats.txfeedbackok++;
priv->stats.txoktotal++;
priv->stats.txokbytestotal += pstx_fb->pkt_length;
priv->stats.txokinperiod++;
/* We can not make sure broadcast/multicast or unicast mode. */
if (pstx_fb->pkt_type == PACKET_MULTICAST)
{
priv->stats.txmulticast++;
priv->stats.txbytesmulticast += pstx_fb->pkt_length;
}
else if (pstx_fb->pkt_type == PACKET_BROADCAST)
{
priv->stats.txbroadcast++;
priv->stats.txbytesbroadcast += pstx_fb->pkt_length;
}
else
{
priv->stats.txunicast++;
priv->stats.txbytesunicast += pstx_fb->pkt_length;
}
}
else
{
priv->stats.txfeedbackfail++;
priv->stats.txerrtotal++;
priv->stats.txerrbytestotal += pstx_fb->pkt_length;
/* We can not make sure broadcast/multicast or unicast mode. */
if (pstx_fb->pkt_type == PACKET_MULTICAST)
{
priv->stats.txerrmulticast++;
}
else if (pstx_fb->pkt_type == PACKET_BROADCAST)
{
priv->stats.txerrbroadcast++;
}
else
{
priv->stats.txerrunicast++;
}
}
priv->stats.txretrycount += pstx_fb->retry_cnt;
priv->stats.txfeedbackretry += pstx_fb->retry_cnt;
} /* cmpk_CountTxStatistic */
/*-----------------------------------------------------------------------------
* Function: cmpk_handle_tx_feedback()
*
* Overview: The function is responsible for extract the message inside TX
* feedbck message from firmware. It will contain dedicated info in
* ws-06-0063-rtl8190-command-packet-specification. Please
* refer to chapter "TX Feedback Element". We have to read 20 bytes
* in the command packet.
*
* Input: struct net_device * dev
* u8 * pmsg - Msg Ptr of the command packet.
*
* Output: NONE
*
* Return: NONE
*
* Revised History:
* When Who Remark
* 05/08/2008 amy Create Version 0 porting from windows code.
*
*---------------------------------------------------------------------------*/
static void
cmpk_handle_tx_feedback(
struct net_device *dev,
u8 * pmsg)
{
struct r8192_priv *priv = ieee80211_priv(dev);
cmpk_txfb_t rx_tx_fb; /* */
priv->stats.txfeedback++;
/* 0. Display received message. */
//cmpk_Display_Message(CMPK_RX_TX_FB_SIZE, pMsg);
/* 1. Extract TX feedback info from RFD to temp structure buffer. */
/* It seems that FW use big endian(MIPS) and DRV use little endian in
windows OS. So we have to read the content byte by byte or transfer
endian type before copy the message copy. */
#if 0 // The TX FEEDBACK packet element address
//rx_tx_fb.Element_ID = pMsg[0];
//rx_tx_fb.Length = pMsg[1];
rx_tx_fb.TOK = pMsg[2]>>7;
rx_tx_fb.Fail_Reason = (pMsg[2] & 0x70) >> 4;
rx_tx_fb.TID = (pMsg[2] & 0x0F);
rx_tx_fb.Qos_Pkt = pMsg[3] >> 7;
rx_tx_fb.Bandwidth = (pMsg[3] & 0x40) >> 6;
rx_tx_fb.Retry_Cnt = pMsg[5];
rx_tx_fb.Pkt_ID = (pMsg[6] << 8) | pMsg[7];
rx_tx_fb.Seq_Num = (pMsg[8] << 8) | pMsg[9];
rx_tx_fb.S_Rate = pMsg[10];
rx_tx_fb.F_Rate = pMsg[11];
rx_tx_fb.S_RTS_Rate = pMsg[12];
rx_tx_fb.F_RTS_Rate = pMsg[13];
rx_tx_fb.pkt_length = (pMsg[14] << 8) | pMsg[15];
#endif
/* 2007/07/05 MH Use pointer to transfer structure memory. */
//memcpy((UINT8 *)&rx_tx_fb, pMsg, sizeof(CMPK_TXFB_T));
memcpy((u8*)&rx_tx_fb, pmsg, sizeof(cmpk_txfb_t));
/* 2. Use tx feedback info to count TX statistics. */
cmpk_count_txstatistic(dev, &rx_tx_fb);
#if 0
/* 2007/07/11 MH Assign current operate rate. */
if (pAdapter->RegWirelessMode == WIRELESS_MODE_A ||
pAdapter->RegWirelessMode == WIRELESS_MODE_B ||
pAdapter->RegWirelessMode == WIRELESS_MODE_G)
{
pMgntInfo->CurrentOperaRate = (rx_tx_fb.F_Rate & 0x7F);
}
else if (pAdapter->RegWirelessMode == WIRELESS_MODE_N_24G ||
pAdapter->RegWirelessMode == WIRELESS_MODE_N_5G)
{
pMgntInfo->HTCurrentOperaRate = (rx_tx_fb.F_Rate & 0x8F);
}
#endif
/* 2007/01/17 MH Comment previous method for TX statistic function. */
/* Collect info TX feedback packet to fill TCB. */
/* We can not know the packet length and transmit type: broadcast or uni
or multicast. */
//CountTxStatistics( pAdapter, &tcb );
} /* cmpk_Handle_Tx_Feedback */
void
cmdpkt_beacontimerinterrupt_819xusb(
struct net_device *dev
)
{
struct r8192_priv *priv = ieee80211_priv(dev);
u16 tx_rate;
{
//
// 070117, rcnjko: 87B have to S/W beacon for DTM encryption_cmn.
//
if(priv->ieee80211->current_network.mode == IEEE_A ||
priv->ieee80211->current_network.mode == IEEE_N_5G ||
(priv->ieee80211->current_network.mode == IEEE_N_24G && (!priv->ieee80211->pHTInfo->bCurSuppCCK)))
{
tx_rate = 60;
DMESG("send beacon frame tx rate is 6Mbpm\n");
}
else
{
tx_rate =10;
DMESG("send beacon frame tx rate is 1Mbpm\n");
}
rtl819xusb_beacon_tx(dev,tx_rate); // HW Beacon
}
}
/*-----------------------------------------------------------------------------
* Function: cmpk_handle_interrupt_status()
*
* Overview: The function is responsible for extract the message from
* firmware. It will contain dedicated info in
* ws-07-0063-v06-rtl819x-command-packet-specification-070315.doc.
* Please refer to chapter "Interrupt Status Element".
*
* Input: struct net_device *dev,
* u8* pmsg - Message Pointer of the command packet.
*
* Output: NONE
*
* Return: NONE
*
* Revised History:
* When Who Remark
* 05/12/2008 amy Add this for rtl8192 porting from windows code.
*
*---------------------------------------------------------------------------*/
static void
cmpk_handle_interrupt_status(
struct net_device *dev,
u8* pmsg)
{
cmpk_intr_sta_t rx_intr_status; /* */
struct r8192_priv *priv = ieee80211_priv(dev);
DMESG("---> cmpk_Handle_Interrupt_Status()\n");
/* 0. Display received message. */
//cmpk_Display_Message(CMPK_RX_BEACON_STATE_SIZE, pMsg);
/* 1. Extract TX feedback info from RFD to temp structure buffer. */
/* It seems that FW use big endian(MIPS) and DRV use little endian in
windows OS. So we have to read the content byte by byte or transfer
endian type before copy the message copy. */
//rx_bcn_state.Element_ID = pMsg[0];
//rx_bcn_state.Length = pMsg[1];
rx_intr_status.length = pmsg[1];
if (rx_intr_status.length != (sizeof(cmpk_intr_sta_t) - 2))
{
DMESG("cmpk_Handle_Interrupt_Status: wrong length!\n");
return;
}
// Statistics of beacon for ad-hoc mode.
if( priv->ieee80211->iw_mode == IW_MODE_ADHOC)
{
//2 maybe need endian transform?
rx_intr_status.interrupt_status = *((u32 *)(pmsg + 4));
//rx_intr_status.InterruptStatus = N2H4BYTE(*((UINT32 *)(pMsg + 4)));
DMESG("interrupt status = 0x%x\n", rx_intr_status.interrupt_status);
if (rx_intr_status.interrupt_status & ISR_TxBcnOk)
{
priv->ieee80211->bibsscoordinator = true;
priv->stats.txbeaconokint++;
}
else if (rx_intr_status.interrupt_status & ISR_TxBcnErr)
{
priv->ieee80211->bibsscoordinator = false;
priv->stats.txbeaconerr++;
}
if (rx_intr_status.interrupt_status & ISR_BcnTimerIntr)
{
cmdpkt_beacontimerinterrupt_819xusb(dev);
}
}
// Other informations in interrupt status we need?
DMESG("<---- cmpk_handle_interrupt_status()\n");
} /* cmpk_handle_interrupt_status */
/*-----------------------------------------------------------------------------
* Function: cmpk_handle_query_config_rx()
*
* Overview: The function is responsible for extract the message from
* firmware. It will contain dedicated info in
* ws-06-0063-rtl8190-command-packet-specification. Please
* refer to chapter "Beacon State Element".
*
* Input: u8 * pmsg - Message Pointer of the command packet.
*
* Output: NONE
*
* Return: NONE
*
* Revised History:
* When Who Remark
* 05/12/2008 amy Create Version 0 porting from windows code.
*
*---------------------------------------------------------------------------*/
static void
cmpk_handle_query_config_rx(
struct net_device *dev,
u8* pmsg)
{
cmpk_query_cfg_t rx_query_cfg; /* */
/* 0. Display received message. */
//cmpk_Display_Message(CMPK_RX_BEACON_STATE_SIZE, pMsg);
/* 1. Extract TX feedback info from RFD to temp structure buffer. */
/* It seems that FW use big endian(MIPS) and DRV use little endian in
windows OS. So we have to read the content byte by byte or transfer
endian type before copy the message copy. */
//rx_query_cfg.Element_ID = pMsg[0];
//rx_query_cfg.Length = pMsg[1];
rx_query_cfg.cfg_action = (pmsg[4] & 0x80000000)>>31;
rx_query_cfg.cfg_type = (pmsg[4] & 0x60) >> 5;
rx_query_cfg.cfg_size = (pmsg[4] & 0x18) >> 3;
rx_query_cfg.cfg_page = (pmsg[6] & 0x0F) >> 0;
rx_query_cfg.cfg_offset = pmsg[7];
rx_query_cfg.value = (pmsg[8] << 24) | (pmsg[9] << 16) |
(pmsg[10] << 8) | (pmsg[11] << 0);
rx_query_cfg.mask = (pmsg[12] << 24) | (pmsg[13] << 16) |
(pmsg[14] << 8) | (pmsg[15] << 0);
} /* cmpk_Handle_Query_Config_Rx */
/*-----------------------------------------------------------------------------
* Function: cmpk_count_tx_status()
*
* Overview: Count aggregated tx status from firmwar of one type rx command
* packet element id = RX_TX_STATUS.
*
* Input: NONE
*
* Output: NONE
*
* Return: NONE
*
* Revised History:
* When Who Remark
* 05/12/2008 amy Create Version 0 porting from windows code.
*
*---------------------------------------------------------------------------*/
static void cmpk_count_tx_status( struct net_device *dev,
cmpk_tx_status_t *pstx_status)
{
struct r8192_priv *priv = ieee80211_priv(dev);
#ifdef ENABLE_PS
RT_RF_POWER_STATE rtstate;
pAdapter->HalFunc.GetHwRegHandler(pAdapter, HW_VAR_RF_STATE, (pu1Byte)(&rtState));
// When RF is off, we should not count the packet for hw/sw synchronize
// reason, ie. there may be a duration while sw switch is changed and hw
// switch is being changed. 2006.12.04, by shien chang.
if (rtState == eRfOff)
{
return;
}
#endif
priv->stats.txfeedbackok += pstx_status->txok;
priv->stats.txoktotal += pstx_status->txok;
priv->stats.txfeedbackfail += pstx_status->txfail;
priv->stats.txerrtotal += pstx_status->txfail;
priv->stats.txretrycount += pstx_status->txretry;
priv->stats.txfeedbackretry += pstx_status->txretry;
//pAdapter->TxStats.NumTxOkBytesTotal += psTx_FB->pkt_length;
//pAdapter->TxStats.NumTxErrBytesTotal += psTx_FB->pkt_length;
//pAdapter->MgntInfo.LinkDetectInfo.NumTxOkInPeriod++;
priv->stats.txmulticast += pstx_status->txmcok;
priv->stats.txbroadcast += pstx_status->txbcok;
priv->stats.txunicast += pstx_status->txucok;
priv->stats.txerrmulticast += pstx_status->txmcfail;
priv->stats.txerrbroadcast += pstx_status->txbcfail;
priv->stats.txerrunicast += pstx_status->txucfail;
priv->stats.txbytesmulticast += pstx_status->txmclength;
priv->stats.txbytesbroadcast += pstx_status->txbclength;
priv->stats.txbytesunicast += pstx_status->txuclength;
priv->stats.last_packet_rate = pstx_status->rate;
} /* cmpk_CountTxStatus */
/*-----------------------------------------------------------------------------
* Function: cmpk_handle_tx_status()
*
* Overview: Firmware add a new tx feedback status to reduce rx command
* packet buffer operation load.
*
* Input: NONE
*
* Output: NONE
*
* Return: NONE
*
* Revised History:
* When Who Remark
* 05/12/2008 amy Create Version 0 porting from windows code.
*
*---------------------------------------------------------------------------*/
static void
cmpk_handle_tx_status(
struct net_device *dev,
u8* pmsg)
{
cmpk_tx_status_t rx_tx_sts; /* */
memcpy((void*)&rx_tx_sts, (void*)pmsg, sizeof(cmpk_tx_status_t));
/* 2. Use tx feedback info to count TX statistics. */
cmpk_count_tx_status(dev, &rx_tx_sts);
} /* cmpk_Handle_Tx_Status */
/*-----------------------------------------------------------------------------
* Function: cmpk_handle_tx_rate_history()
*
* Overview: Firmware add a new tx rate history
*
* Input: NONE
*
* Output: NONE
*
* Return: NONE
*
* Revised History:
* When Who Remark
* 05/12/2008 amy Create Version 0 porting from windows code.
*
*---------------------------------------------------------------------------*/
static void
cmpk_handle_tx_rate_history(
struct net_device *dev,
u8* pmsg)
{
cmpk_tx_rahis_t *ptxrate;
// RT_RF_POWER_STATE rtState;
u8 i, j;
u16 length = sizeof(cmpk_tx_rahis_t);
u32 *ptemp;
struct r8192_priv *priv = ieee80211_priv(dev);
#ifdef ENABLE_PS
pAdapter->HalFunc.GetHwRegHandler(pAdapter, HW_VAR_RF_STATE, (pu1Byte)(&rtState));
// When RF is off, we should not count the packet for hw/sw synchronize
// reason, ie. there may be a duration while sw switch is changed and hw
// switch is being changed. 2006.12.04, by shien chang.
if (rtState == eRfOff)
{
return;
}
#endif
ptemp = (u32 *)pmsg;
//
// Do endian transfer to word alignment(16 bits) for windows system.
// You must do different endian transfer for linux and MAC OS
//
for (i = 0; i < (length/4); i++)
{
u16 temp1, temp2;
temp1 = ptemp[i]&0x0000FFFF;
temp2 = ptemp[i]>>16;
ptemp[i] = (temp1<<16)|temp2;
}
ptxrate = (cmpk_tx_rahis_t *)pmsg;
if (ptxrate == NULL )
{
return;
}
for (i = 0; i < 16; i++)
{
// Collect CCK rate packet num
if (i < 4)
priv->stats.txrate.cck[i] += ptxrate->cck[i];
// Collect OFDM rate packet num
if (i< 8)
priv->stats.txrate.ofdm[i] += ptxrate->ofdm[i];
for (j = 0; j < 4; j++)
priv->stats.txrate.ht_mcs[j][i] += ptxrate->ht_mcs[j][i];
}
} /* cmpk_Handle_Tx_Rate_History */
/*-----------------------------------------------------------------------------
* Function: cmpk_message_handle_rx()
*
* Overview: In the function, we will capture different RX command packet
* info. Every RX command packet element has different message
* length and meaning in content. We only support three type of RX
* command packet now. Please refer to document
* ws-06-0063-rtl8190-command-packet-specification.
*
* Input: NONE
*
* Output: NONE
*
* Return: NONE
*
* Revised History:
* When Who Remark
* 05/06/2008 amy Create Version 0 porting from windows code.
*
*---------------------------------------------------------------------------*/
extern u32
cmpk_message_handle_rx(
struct net_device *dev,
struct ieee80211_rx_stats *pstats)
{
// u32 debug_level = DBG_LOUD;
struct r8192_priv *priv = ieee80211_priv(dev);
int total_length;
u8 cmd_length, exe_cnt = 0;
u8 element_id;
u8 *pcmd_buff;
/* 0. Check inpt arguments. If is is a command queue message or pointer is
null. */
if (/*(prfd->queue_id != CMPK_RX_QUEUE_ID) || */(pstats== NULL))
{
/* Print error message. */
/*RT_TRACE(COMP_SEND, DebugLevel,
("\n\r[CMPK]-->Err queue id or pointer"));*/
return 0; /* This is not a command packet. */
}
/* 1. Read received command packet message length from RFD. */
total_length = pstats->Length;
/* 2. Read virtual address from RFD. */
pcmd_buff = pstats->virtual_address;
/* 3. Read command pakcet element id and length. */
element_id = pcmd_buff[0];
/*RT_TRACE(COMP_SEND, DebugLevel,
("\n\r[CMPK]-->element ID=%d Len=%d", element_id, total_length));*/
/* 4. Check every received command packet conent according to different
element type. Because FW may aggregate RX command packet to minimize
transmit time between DRV and FW.*/
// Add a counter to prevent to locked in the loop too long
while (total_length > 0 || exe_cnt++ >100)
{
/* 2007/01/17 MH We support aggregation of different cmd in the same packet. */
element_id = pcmd_buff[0];
switch(element_id)
{
case RX_TX_FEEDBACK:
cmpk_handle_tx_feedback (dev, pcmd_buff);
cmd_length = CMPK_RX_TX_FB_SIZE;
break;
case RX_INTERRUPT_STATUS:
cmpk_handle_interrupt_status(dev, pcmd_buff);
cmd_length = sizeof(cmpk_intr_sta_t);
break;
case BOTH_QUERY_CONFIG:
cmpk_handle_query_config_rx(dev, pcmd_buff);
cmd_length = CMPK_BOTH_QUERY_CONFIG_SIZE;
break;
case RX_TX_STATUS:
cmpk_handle_tx_status(dev, pcmd_buff);
cmd_length = CMPK_RX_TX_STS_SIZE;
break;
case RX_TX_PER_PKT_FEEDBACK:
// You must at lease add a switch case element here,
// Otherwise, we will jump to default case.
//DbgPrint("CCX Test\r\n");
cmd_length = CMPK_RX_TX_FB_SIZE;
break;
case RX_TX_RATE_HISTORY:
//DbgPrint(" rx tx rate history\r\n");
cmpk_handle_tx_rate_history(dev, pcmd_buff);
cmd_length = CMPK_TX_RAHIS_SIZE;
break;
default:
RT_TRACE(COMP_ERR, "---->cmpk_message_handle_rx():unknow CMD Element\n");
return 1; /* This is a command packet. */
}
// 2007/01/22 MH Display received rx command packet info.
//cmpk_Display_Message(cmd_length, pcmd_buff);
// 2007/01/22 MH Add to display tx statistic.
//cmpk_DisplayTxStatistic(pAdapter);
/* 2007/03/09 MH Collect sidderent cmd element pkt num. */
priv->stats.rxcmdpkt[element_id]++;
total_length -= cmd_length;
pcmd_buff += cmd_length;
} /* while (total_length > 0) */
return 1; /* This is a command packet. */
} /* CMPK_Message_Handle_Rx */

View File

@ -0,0 +1,217 @@
#ifndef R819XUSB_CMDPKT_H
#define R819XUSB_CMDPKT_H
/* Different command packet have dedicated message length and definition. */
#define CMPK_RX_TX_FB_SIZE sizeof(cmpk_txfb_t) //20
#define CMPK_TX_SET_CONFIG_SIZE sizeof(cmpk_set_cfg_t) //16
#define CMPK_BOTH_QUERY_CONFIG_SIZE sizeof(cmpk_set_cfg_t) //16
#define CMPK_RX_TX_STS_SIZE sizeof(cmpk_tx_status_t)//
#define CMPK_RX_DBG_MSG_SIZE sizeof(cmpk_rx_dbginfo_t)//
#define CMPK_TX_RAHIS_SIZE sizeof(cmpk_tx_rahis_t)
/* 2008/05/08 amy For USB constant. */
#define ISR_TxBcnOk BIT27 // Transmit Beacon OK
#define ISR_TxBcnErr BIT26 // Transmit Beacon Error
#define ISR_BcnTimerIntr BIT13 // Beacon Timer Interrupt
#if 0
/* Define packet type. */
typedef enum tag_packet_type
{
PACKET_BROADCAST,
PACKET_MULTICAST,
PACKET_UNICAST,
PACKET_TYPE_MAX
}cmpk_pkt_type_e;
#endif
/* Define element ID of command packet. */
/*------------------------------Define structure----------------------------*/
/* Define different command packet structure. */
/* 1. RX side: TX feedback packet. */
typedef struct tag_cmd_pkt_tx_feedback
{
// DWORD 0
u8 element_id; /* Command packet type. */
u8 length; /* Command packet length. */
/* 2007/07/05 MH Change tx feedback info field. */
/*------TX Feedback Info Field */
u8 TID:4; /* */
u8 fail_reason:3; /* */
u8 tok:1; /* Transmit ok. */
u8 reserve1:4; /* */
u8 pkt_type:2; /* */
u8 bandwidth:1; /* */
u8 qos_pkt:1; /* */
// DWORD 1
u8 reserve2; /* */
/*------TX Feedback Info Field */
u8 retry_cnt; /* */
u16 pkt_id; /* */
// DWORD 3
u16 seq_num; /* */
u8 s_rate; /* Start rate. */
u8 f_rate; /* Final rate. */
// DWORD 4
u8 s_rts_rate; /* */
u8 f_rts_rate; /* */
u16 pkt_length; /* */
// DWORD 5
u16 reserve3; /* */
u16 duration; /* */
}cmpk_txfb_t;
/* 2. RX side: Interrupt status packet. It includes Beacon State,
Beacon Timer Interrupt and other useful informations in MAC ISR Reg. */
typedef struct tag_cmd_pkt_interrupt_status
{
u8 element_id; /* Command packet type. */
u8 length; /* Command packet length. */
u16 reserve;
u32 interrupt_status; /* Interrupt Status. */
}cmpk_intr_sta_t;
/* 3. TX side: Set configuration packet. */
typedef struct tag_cmd_pkt_set_configuration
{
u8 element_id; /* Command packet type. */
u8 length; /* Command packet length. */
u16 reserve1; /* */
u8 cfg_reserve1:3;
u8 cfg_size:2; /* Configuration info. */
u8 cfg_type:2; /* Configuration info. */
u8 cfg_action:1; /* Configuration info. */
u8 cfg_reserve2; /* Configuration info. */
u8 cfg_page:4; /* Configuration info. */
u8 cfg_reserve3:4; /* Configuration info. */
u8 cfg_offset; /* Configuration info. */
u32 value; /* */
u32 mask; /* */
}cmpk_set_cfg_t;
/* 4. Both side : TX/RX query configuraton packet. The query structure is the
same as set configuration. */
#define cmpk_query_cfg_t cmpk_set_cfg_t
/* 5. Multi packet feedback status. */
typedef struct tag_tx_stats_feedback // PJ quick rxcmd 09042007
{
// For endian transfer --> Driver will not the same as firmware structure.
// DW 0
u16 reserve1;
u8 length; // Command packet length
u8 element_id; // Command packet type
// DW 1
u16 txfail; // Tx Fail count
u16 txok; // Tx ok count
// DW 2
u16 txmcok; // tx multicast
u16 txretry; // Tx Retry count
// DW 3
u16 txucok; // tx unicast
u16 txbcok; // tx broadcast
// DW 4
u16 txbcfail; //
u16 txmcfail; //
// DW 5
u16 reserve2; //
u16 txucfail; //
// DW 6-8
u32 txmclength;
u32 txbclength;
u32 txuclength;
// DW 9
u16 reserve3_23;
u8 reserve3_1;
u8 rate;
}__attribute__((packed)) cmpk_tx_status_t;
/* 6. Debug feedback message. */
/* 2007/10/23 MH Define RX debug message */
typedef struct tag_rx_debug_message_feedback
{
// For endian transfer --> for driver
// DW 0
u16 reserve1;
u8 length; // Command packet length
u8 element_id; // Command packet type
// DW 1-??
// Variable debug message.
}cmpk_rx_dbginfo_t;
/* 2008/03/20 MH Define transmit rate history. For big endian format. */
typedef struct tag_tx_rate_history
{
// For endian transfer --> for driver
// DW 0
u8 element_id; // Command packet type
u8 length; // Command packet length
u16 reserved1;
// DW 1-2 CCK rate counter
u16 cck[4];
// DW 3-6
u16 ofdm[8];
// DW 7-14
//UINT16 MCS_BW0_SG0[16];
// DW 15-22
//UINT16 MCS_BW1_SG0[16];
// DW 23-30
//UINT16 MCS_BW0_SG1[16];
// DW 31-38
//UINT16 MCS_BW1_SG1[16];
// DW 7-14 BW=0 SG=0
// DW 15-22 BW=1 SG=0
// DW 23-30 BW=0 SG=1
// DW 31-38 BW=1 SG=1
u16 ht_mcs[4][16];
}__attribute__((packed)) cmpk_tx_rahis_t;
typedef enum tag_command_packet_directories
{
RX_TX_FEEDBACK = 0,
RX_INTERRUPT_STATUS = 1,
TX_SET_CONFIG = 2,
BOTH_QUERY_CONFIG = 3,
RX_TX_STATUS = 4,
RX_DBGINFO_FEEDBACK = 5,
RX_TX_PER_PKT_FEEDBACK = 6,
RX_TX_RATE_HISTORY = 7,
RX_CMD_ELE_MAX
}cmpk_element_e;
typedef enum _rt_status{
RT_STATUS_SUCCESS,
RT_STATUS_FAILURE,
RT_STATUS_PENDING,
RT_STATUS_RESOURCE
}rt_status,*prt_status;
extern rt_status cmpk_message_handle_tx(struct net_device *dev, u8* codevirtualaddress, u32 packettype, u32 buffer_len);
extern u32 cmpk_message_handle_rx(struct net_device *dev, struct ieee80211_rx_stats * pstats);
extern rt_status SendTxCommandPacket( struct net_device *dev, void* pData, u32 DataLen);
#endif

View File

@ -0,0 +1,700 @@
/**************************************************************************************************
* Procedure: Init boot code/firmware code/data session
*
* Description: This routine will intialize firmware. If any error occurs during the initialization
* process, the routine shall terminate immediately and return fail.
* NIC driver should call NdisOpenFile only from MiniportInitialize.
*
* Arguments: The pointer of the adapter
* Returns:
* NDIS_STATUS_FAILURE - the following initialization process should be terminated
* NDIS_STATUS_SUCCESS - if firmware initialization process success
**************************************************************************************************/
//#include "ieee80211.h"
#include "r8192U.h"
#include "r8192U_hw.h"
#include "r819xU_firmware_img.h"
#include "r819xU_firmware.h"
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
#include <linux/firmware.h>
#endif
void firmware_init_param(struct net_device *dev)
{
struct r8192_priv *priv = ieee80211_priv(dev);
rt_firmware *pfirmware = priv->pFirmware;
pfirmware->cmdpacket_frag_thresold = GET_COMMAND_PACKET_FRAG_THRESHOLD(MAX_TRANSMIT_BUFFER_SIZE);
}
/*
* segment the img and use the ptr and length to remember info on each segment
*
*/
bool fw_download_code(struct net_device *dev, u8 *code_virtual_address, u32 buffer_len)
{
struct r8192_priv *priv = ieee80211_priv(dev);
bool rt_status = true;
u16 frag_threshold;
u16 frag_length, frag_offset = 0;
//u16 total_size;
int i;
rt_firmware *pfirmware = priv->pFirmware;
struct sk_buff *skb;
unsigned char *seg_ptr;
cb_desc *tcb_desc;
u8 bLastIniPkt;
firmware_init_param(dev);
//Fragmentation might be required
frag_threshold = pfirmware->cmdpacket_frag_thresold;
do {
if((buffer_len - frag_offset) > frag_threshold) {
frag_length = frag_threshold ;
bLastIniPkt = 0;
} else {
frag_length = buffer_len - frag_offset;
bLastIniPkt = 1;
}
/* Allocate skb buffer to contain firmware info and tx descriptor info
* add 4 to avoid packet appending overflow.
* */
#ifdef RTL8192U
skb = dev_alloc_skb(USB_HWDESC_HEADER_LEN + frag_length + 4);
#else
skb = dev_alloc_skb(frag_length + 4);
#endif
memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev));
tcb_desc = (cb_desc*)(skb->cb + MAX_DEV_ADDR_SIZE);
tcb_desc->queue_index = TXCMD_QUEUE;
tcb_desc->bCmdOrInit = DESC_PACKET_TYPE_INIT;
tcb_desc->bLastIniPkt = bLastIniPkt;
#ifdef RTL8192U
skb_reserve(skb, USB_HWDESC_HEADER_LEN);
#endif
seg_ptr = skb->data;
/*
* Transform from little endian to big endian
* and pending zero
*/
for(i=0 ; i < frag_length; i+=4) {
*seg_ptr++ = ((i+0)<frag_length)?code_virtual_address[i+3]:0;
*seg_ptr++ = ((i+1)<frag_length)?code_virtual_address[i+2]:0;
*seg_ptr++ = ((i+2)<frag_length)?code_virtual_address[i+1]:0;
*seg_ptr++ = ((i+3)<frag_length)?code_virtual_address[i+0]:0;
}
tcb_desc->txbuf_size= (u16)i;
skb_put(skb, i);
if(!priv->ieee80211->check_nic_enough_desc(dev,tcb_desc->queue_index)||
(!skb_queue_empty(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index]))||\
(priv->ieee80211->queue_stop) ) {
RT_TRACE(COMP_FIRMWARE,"=====================================================> tx full!\n");
skb_queue_tail(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index], skb);
} else {
priv->ieee80211->softmac_hard_start_xmit(skb,dev);
}
code_virtual_address += frag_length;
frag_offset += frag_length;
}while(frag_offset < buffer_len);
return rt_status;
#if 0
cmdsend_downloadcode_fail:
rt_status = false;
RT_TRACE(COMP_ERR, "CmdSendDownloadCode fail !!\n");
return rt_status;
#endif
}
bool
fwSendNullPacket(
struct net_device *dev,
u32 Length
)
{
bool rtStatus = true;
struct r8192_priv *priv = ieee80211_priv(dev);
struct sk_buff *skb;
cb_desc *tcb_desc;
unsigned char *ptr_buf;
bool bLastInitPacket = false;
//PlatformAcquireSpinLock(Adapter, RT_TX_SPINLOCK);
//Get TCB and local buffer from common pool. (It is shared by CmdQ, MgntQ, and USB coalesce DataQ)
skb = dev_alloc_skb(Length+ 4);
memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev));
tcb_desc = (cb_desc*)(skb->cb + MAX_DEV_ADDR_SIZE);
tcb_desc->queue_index = TXCMD_QUEUE;
tcb_desc->bCmdOrInit = DESC_PACKET_TYPE_INIT;
tcb_desc->bLastIniPkt = bLastInitPacket;
ptr_buf = skb_put(skb, Length);
memset(ptr_buf,0,Length);
tcb_desc->txbuf_size= (u16)Length;
if(!priv->ieee80211->check_nic_enough_desc(dev,tcb_desc->queue_index)||
(!skb_queue_empty(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index]))||\
(priv->ieee80211->queue_stop) ) {
RT_TRACE(COMP_FIRMWARE,"===================NULL packet==================================> tx full!\n");
skb_queue_tail(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index], skb);
} else {
priv->ieee80211->softmac_hard_start_xmit(skb,dev);
}
//PlatformReleaseSpinLock(Adapter, RT_TX_SPINLOCK);
return rtStatus;
}
#if 0
/*
* Procedure : Download code into IMEM or DMEM
* Description: This routine will intialize firmware. If any error occurs during the initialization
* process, the routine shall terminate immediately and return fail.
* The routine copy virtual address get from opening of file into shared memory
* allocated during initialization. If code size larger than a conitneous shared
* memory may contain, the code should be divided into several section.
* !!!NOTES This finction should only be called during MPInitialization because
* A NIC driver should call NdisOpenFile only from MiniportInitialize.
* Arguments : The pointer of the adapter
* Code address (Virtual address, should fill descriptor with physical address)
* Code size
* Returns :
* RT_STATUS_FAILURE - the following initialization process should be terminated
* RT_STATUS_SUCCESS - if firmware initialization process success
*/
bool fwsend_download_code(struct net_device *dev)
{
struct r8192_priv *priv = ieee80211_priv(dev);
rt_firmware *pfirmware = (rt_firmware*)(&priv->firmware);
bool rt_status = true;
u16 length = 0;
u16 offset = 0;
u16 frag_threhold;
bool last_init_packet = false;
u32 check_txcmdwait_queueemptytime = 100000;
u16 cmd_buf_len;
u8 *ptr_cmd_buf;
/* reset to 0 for first segment of img download */
pfirmware->firmware_seg_index = 1;
if(pfirmware->firmware_seg_index == pfirmware->firmware_seg_maxnum) {
last_init_packet = 1;
}
cmd_buf_len = pfirmware->firmware_seg_container[pfirmware->firmware_seg_index-1].seg_size;
ptr_cmd_buf = pfirmware->firmware_seg_container[pfirmware->firmware_seg_index-1].seg_ptr;
rtl819xU_tx_cmd(dev, ptr_cmd_buf, cmd_buf_len, last_init_packet, DESC_PACKET_TYPE_INIT);
rt_status = true;
return rt_status;
}
#endif
//-----------------------------------------------------------------------------
// Procedure: Check whether main code is download OK. If OK, turn on CPU
//
// Description: CPU register locates in different page against general register.
// Switch to CPU register in the begin and switch back before return
//
//
// Arguments: The pointer of the adapter
//
// Returns:
// NDIS_STATUS_FAILURE - the following initialization process should be terminated
// NDIS_STATUS_SUCCESS - if firmware initialization process success
//-----------------------------------------------------------------------------
bool CPUcheck_maincodeok_turnonCPU(struct net_device *dev)
{
bool rt_status = true;
int check_putcodeOK_time = 200000, check_bootOk_time = 200000;
u32 CPU_status = 0;
/* Check whether put code OK */
do {
CPU_status = read_nic_dword(dev, CPU_GEN);
if(CPU_status&CPU_GEN_PUT_CODE_OK)
break;
}while(check_putcodeOK_time--);
if(!(CPU_status&CPU_GEN_PUT_CODE_OK)) {
RT_TRACE(COMP_ERR, "Download Firmware: Put code fail!\n");
goto CPUCheckMainCodeOKAndTurnOnCPU_Fail;
} else {
RT_TRACE(COMP_FIRMWARE, "Download Firmware: Put code ok!\n");
}
/* Turn On CPU */
CPU_status = read_nic_dword(dev, CPU_GEN);
write_nic_byte(dev, CPU_GEN, (u8)((CPU_status|CPU_GEN_PWR_STB_CPU)&0xff));
mdelay(1000);
/* Check whether CPU boot OK */
do {
CPU_status = read_nic_dword(dev, CPU_GEN);
if(CPU_status&CPU_GEN_BOOT_RDY)
break;
}while(check_bootOk_time--);
if(!(CPU_status&CPU_GEN_BOOT_RDY)) {
goto CPUCheckMainCodeOKAndTurnOnCPU_Fail;
} else {
RT_TRACE(COMP_FIRMWARE, "Download Firmware: Boot ready!\n");
}
return rt_status;
CPUCheckMainCodeOKAndTurnOnCPU_Fail:
RT_TRACE(COMP_ERR, "ERR in %s()\n", __FUNCTION__);
rt_status = FALSE;
return rt_status;
}
bool CPUcheck_firmware_ready(struct net_device *dev)
{
bool rt_status = true;
int check_time = 200000;
u32 CPU_status = 0;
/* Check Firmware Ready */
do {
CPU_status = read_nic_dword(dev, CPU_GEN);
if(CPU_status&CPU_GEN_FIRM_RDY)
break;
}while(check_time--);
if(!(CPU_status&CPU_GEN_FIRM_RDY))
goto CPUCheckFirmwareReady_Fail;
else
RT_TRACE(COMP_FIRMWARE, "Download Firmware: Firmware ready!\n");
return rt_status;
CPUCheckFirmwareReady_Fail:
RT_TRACE(COMP_ERR, "ERR in %s()\n", __FUNCTION__);
rt_status = false;
return rt_status;
}
bool init_firmware(struct net_device *dev)
{
struct r8192_priv *priv = ieee80211_priv(dev);
bool rt_status = TRUE;
u8 *firmware_img_buf[3] = { &rtl8190_fwboot_array[0],
&rtl8190_fwmain_array[0],
&rtl8190_fwdata_array[0]};
u32 firmware_img_len[3] = { sizeof(rtl8190_fwboot_array),
sizeof(rtl8190_fwmain_array),
sizeof(rtl8190_fwdata_array)};
u32 file_length = 0;
u8 *mapped_file = NULL;
u32 init_step = 0;
opt_rst_type_e rst_opt = OPT_SYSTEM_RESET;
firmware_init_step_e starting_state = FW_INIT_STEP0_BOOT;
rt_firmware *pfirmware = priv->pFirmware;
const struct firmware *fw_entry;
const char *fw_name[3] = { "RTL8192U/boot.img",
"RTL8192U/main.img",
"RTL8192U/data.img"};
int rc;
RT_TRACE(COMP_FIRMWARE, " PlatformInitFirmware()==>\n");
if (pfirmware->firmware_status == FW_STATUS_0_INIT ) {
/* it is called by reset */
rst_opt = OPT_SYSTEM_RESET;
starting_state = FW_INIT_STEP0_BOOT;
// TODO: system reset
}else if(pfirmware->firmware_status == FW_STATUS_5_READY) {
/* it is called by Initialize */
rst_opt = OPT_FIRMWARE_RESET;
starting_state = FW_INIT_STEP2_DATA;
}else {
RT_TRACE(COMP_FIRMWARE, "PlatformInitFirmware: undefined firmware state\n");
}
/*
* Download boot, main, and data image for System reset.
* Download data image for firmware reseta
*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
priv->firmware_source = FW_SOURCE_HEADER_FILE;
#else
priv->firmware_source = FW_SOURCE_IMG_FILE;
#endif
for(init_step = starting_state; init_step <= FW_INIT_STEP2_DATA; init_step++) {
/*
* Open Image file, and map file to contineous memory if open file success.
* or read image file from array. Default load from IMG file
*/
if(rst_opt == OPT_SYSTEM_RESET) {
switch(priv->firmware_source) {
case FW_SOURCE_IMG_FILE:
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
rc = request_firmware(&fw_entry, fw_name[init_step],&priv->udev->dev);
if(rc < 0 ) {
RT_TRACE(COMP_ERR, "request firmware fail!\n");
goto download_firmware_fail;
}
if(fw_entry->size > sizeof(pfirmware->firmware_buf)) {
RT_TRACE(COMP_ERR, "img file size exceed the container buffer fail!\n");
goto download_firmware_fail;
}
if(init_step != FW_INIT_STEP1_MAIN) {
memcpy(pfirmware->firmware_buf,fw_entry->data,fw_entry->size);
mapped_file = pfirmware->firmware_buf;
file_length = fw_entry->size;
} else {
#ifdef RTL8190P
memcpy(pfirmware->firmware_buf,fw_entry->data,fw_entry->size);
mapped_file = pfirmware->firmware_buf;
file_length = fw_entry->size;
#else
memset(pfirmware->firmware_buf,0,128);
memcpy(&pfirmware->firmware_buf[128],fw_entry->data,fw_entry->size);
mapped_file = pfirmware->firmware_buf;
file_length = fw_entry->size + 128;
#endif
}
pfirmware->firmware_buf_size = file_length;
#endif
break;
case FW_SOURCE_HEADER_FILE:
mapped_file = firmware_img_buf[init_step];
file_length = firmware_img_len[init_step];
if(init_step == FW_INIT_STEP2_DATA) {
memcpy(pfirmware->firmware_buf, mapped_file, file_length);
pfirmware->firmware_buf_size = file_length;
}
break;
default:
break;
}
}else if(rst_opt == OPT_FIRMWARE_RESET ) {
/* we only need to download data.img here */
mapped_file = pfirmware->firmware_buf;
file_length = pfirmware->firmware_buf_size;
}
/* Download image file */
/* The firmware download process is just as following,
* 1. that is each packet will be segmented and inserted to the wait queue.
* 2. each packet segment will be put in the skb_buff packet.
* 3. each skb_buff packet data content will already include the firmware info
* and Tx descriptor info
* */
rt_status = fw_download_code(dev,mapped_file,file_length);
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
if(rst_opt == OPT_SYSTEM_RESET) {
release_firmware(fw_entry);
}
#endif
if(rt_status != TRUE) {
goto download_firmware_fail;
}
switch(init_step) {
case FW_INIT_STEP0_BOOT:
/* Download boot
* initialize command descriptor.
* will set polling bit when firmware code is also configured
*/
pfirmware->firmware_status = FW_STATUS_1_MOVE_BOOT_CODE;
#ifdef RTL8190P
// To initialize IMEM, CPU move code from 0x80000080, hence, we send 0x80 byte packet
rt_status = fwSendNullPacket(dev, RTL8190_CPU_START_OFFSET);
if(rt_status != true)
{
RT_TRACE(COMP_INIT, "fwSendNullPacket() fail ! \n");
goto download_firmware_fail;
}
#endif
//mdelay(1000);
/*
* To initialize IMEM, CPU move code from 0x80000080,
* hence, we send 0x80 byte packet
*/
break;
case FW_INIT_STEP1_MAIN:
/* Download firmware code. Wait until Boot Ready and Turn on CPU */
pfirmware->firmware_status = FW_STATUS_2_MOVE_MAIN_CODE;
/* Check Put Code OK and Turn On CPU */
rt_status = CPUcheck_maincodeok_turnonCPU(dev);
if(rt_status != TRUE) {
RT_TRACE(COMP_ERR, "CPUcheck_maincodeok_turnonCPU fail!\n");
goto download_firmware_fail;
}
pfirmware->firmware_status = FW_STATUS_3_TURNON_CPU;
break;
case FW_INIT_STEP2_DATA:
/* download initial data code */
pfirmware->firmware_status = FW_STATUS_4_MOVE_DATA_CODE;
mdelay(1);
rt_status = CPUcheck_firmware_ready(dev);
if(rt_status != TRUE) {
RT_TRACE(COMP_ERR, "CPUcheck_firmware_ready fail(%d)!\n",rt_status);
goto download_firmware_fail;
}
/* wait until data code is initialized ready.*/
pfirmware->firmware_status = FW_STATUS_5_READY;
break;
}
}
RT_TRACE(COMP_FIRMWARE, "Firmware Download Success\n");
//assert(pfirmware->firmware_status == FW_STATUS_5_READY, ("Firmware Download Fail\n"));
return rt_status;
download_firmware_fail:
RT_TRACE(COMP_ERR, "ERR in %s()\n", __FUNCTION__);
rt_status = FALSE;
return rt_status;
}
#if 0
/*
* Procedure: (1) Transform firmware code from little endian to big endian if required.
* (2) Number of bytes in Firmware downloading should be multiple
* of 4 bytes. If length is not multiple of 4 bytes, appending of zeros is required
*
*/
void CmdAppendZeroAndEndianTransform(
u1Byte *pDst,
u1Byte *pSrc,
u2Byte *pLength)
{
u2Byte ulAppendBytes = 0, i;
u2Byte ulLength = *pLength;
//test only
//memset(pDst, 0xcc, 12);
/* Transform from little endian to big endian */
//#if DEV_BUS_TYPE==PCI_INTERFACE
#if 0
for( i=0 ; i<(*pLength) ; i+=4)
{
if((i+3) < (*pLength)) pDst[i+0] = pSrc[i+3];
if((i+2) < (*pLength)) pDst[i+1] = pSrc[i+2];
if((i+1) < (*pLength)) pDst[i+2] = pSrc[i+1];
if((i+0) < (*pLength)) pDst[i+3] = pSrc[i+0];
}
#else
pDst += USB_HWDESC_HEADER_LEN;
ulLength -= USB_HWDESC_HEADER_LEN;
for( i=0 ; i<ulLength ; i+=4) {
if((i+3) < ulLength) pDst[i+0] = pSrc[i+3];
if((i+2) < ulLength) pDst[i+1] = pSrc[i+2];
if((i+1) < ulLength) pDst[i+2] = pSrc[i+1];
if((i+0) < ulLength) pDst[i+3] = pSrc[i+0];
}
#endif
//1(2) Append Zero
if( ((*pLength) % 4) >0)
{
ulAppendBytes = 4-((*pLength) % 4);
for(i=0 ; i<ulAppendBytes; i++)
pDst[ 4*((*pLength)/4) + i ] = 0x0;
*pLength += ulAppendBytes;
}
}
#endif
#if 0
RT_STATUS
CmdSendPacket(
PADAPTER Adapter,
PRT_TCB pTcb,
PRT_TX_LOCAL_BUFFER pBuf,
u4Byte BufferLen,
u4Byte PacketType,
BOOLEAN bLastInitPacket
)
{
s2Byte i;
u1Byte QueueID;
u2Byte firstDesc,curDesc = 0;
u2Byte FragIndex=0, FragBufferIndex=0;
RT_STATUS rtStatus = RT_STATUS_SUCCESS;
CmdInitTCB(Adapter, pTcb, pBuf, BufferLen);
if(CmdCheckFragment(Adapter, pTcb, pBuf))
CmdFragmentTCB(Adapter, pTcb);
else
pTcb->FragLength[0] = (u2Byte)pTcb->BufferList[0].Length;
QueueID=pTcb->SpecifiedQueueID;
#if DEV_BUS_TYPE!=USB_INTERFACE
firstDesc=curDesc=Adapter->NextTxDescToFill[QueueID];
#endif
#if DEV_BUS_TYPE!=USB_INTERFACE
if(VacancyTxDescNum(Adapter, QueueID) > pTcb->BufferCount)
#else
if(PlatformIsTxQueueAvailable(Adapter, QueueID, pTcb->BufferCount) &&
RTIsListEmpty(&Adapter->TcbWaitQueue[QueueID]))
#endif
{
pTcb->nDescUsed=0;
for(i=0 ; i<pTcb->BufferCount ; i++)
{
Adapter->HalFunc.TxFillCmdDescHandler(
Adapter,
pTcb,
QueueID, //QueueIndex
curDesc, //index
FragBufferIndex==0, //bFirstSeg
FragBufferIndex==(pTcb->FragBufCount[FragIndex]-1), //bLastSeg
pTcb->BufferList[i].VirtualAddress, //VirtualAddress
pTcb->BufferList[i].PhysicalAddressLow, //PhyAddressLow
pTcb->BufferList[i].Length, //BufferLen
i!=0, //bSetOwnBit
(i==(pTcb->BufferCount-1)) && bLastInitPacket, //bLastInitPacket
PacketType, //DescPacketType
pTcb->FragLength[FragIndex] //PktLen
);
if(FragBufferIndex==(pTcb->FragBufCount[FragIndex]-1))
{ // Last segment of the fragment.
pTcb->nFragSent++;
}
FragBufferIndex++;
if(FragBufferIndex==pTcb->FragBufCount[FragIndex])
{
FragIndex++;
FragBufferIndex=0;
}
#if DEV_BUS_TYPE!=USB_INTERFACE
curDesc=(curDesc+1)%Adapter->NumTxDesc[QueueID];
#endif
pTcb->nDescUsed++;
}
#if DEV_BUS_TYPE!=USB_INTERFACE
RTInsertTailList(&Adapter->TcbBusyQueue[QueueID], &pTcb->List);
IncrementTxDescToFill(Adapter, QueueID, pTcb->nDescUsed);
Adapter->HalFunc.SetTxDescOWNHandler(Adapter, QueueID, firstDesc);
// TODO: should call poll use QueueID
Adapter->HalFunc.TxPollingHandler(Adapter, TXCMD_QUEUE);
#endif
}
else
#if DEV_BUS_TYPE!=USB_INTERFACE
goto CmdSendPacket_Fail;
#else
{
pTcb->bLastInitPacket = bLastInitPacket;
RTInsertTailList(&Adapter->TcbWaitQueue[pTcb->SpecifiedQueueID], &pTcb->List);
}
#endif
return rtStatus;
#if DEV_BUS_TYPE!=USB_INTERFACE
CmdSendPacket_Fail:
rtStatus = RT_STATUS_FAILURE;
return rtStatus;
#endif
}
#endif
#if 0
RT_STATUS
FWSendNullPacket(
IN PADAPTER Adapter,
IN u4Byte Length
)
{
RT_STATUS rtStatus = RT_STATUS_SUCCESS;
PRT_TCB pTcb;
PRT_TX_LOCAL_BUFFER pBuf;
BOOLEAN bLastInitPacket = FALSE;
PlatformAcquireSpinLock(Adapter, RT_TX_SPINLOCK);
#if DEV_BUS_TYPE==USB_INTERFACE
Length += USB_HWDESC_HEADER_LEN;
#endif
//Get TCB and local buffer from common pool. (It is shared by CmdQ, MgntQ, and USB coalesce DataQ)
if(MgntGetBuffer(Adapter, &pTcb, &pBuf))
{
PlatformZeroMemory(pBuf->Buffer.VirtualAddress, Length);
rtStatus = CmdSendPacket(Adapter, pTcb, pBuf, Length, DESC_PACKET_TYPE_INIT, bLastInitPacket); //0 : always set LastInitPacket to zero
//#if HAL_CODE_BASE != RTL8190HW
// // TODO: for test only
// ReturnTCB(Adapter, pTcb, RT_STATUS_SUCCESS);
//#endif
if(rtStatus == RT_STATUS_FAILURE)
goto CmdSendNullPacket_Fail;
}else
goto CmdSendNullPacket_Fail;
PlatformReleaseSpinLock(Adapter, RT_TX_SPINLOCK);
return rtStatus;
CmdSendNullPacket_Fail:
PlatformReleaseSpinLock(Adapter, RT_TX_SPINLOCK);
rtStatus = RT_STATUS_FAILURE;
RT_ASSERT(rtStatus == RT_STATUS_SUCCESS, ("CmdSendDownloadCode fail !!\n"));
return rtStatus;
}
#endif

View File

@ -0,0 +1,68 @@
#ifndef __INC_FIRMWARE_H
#define __INC_FIRMWARE_H
#define RTL8190_CPU_START_OFFSET 0x80
/* TODO: this definition is TBD */
//#define USB_HWDESC_HEADER_LEN 0
/* It should be double word alignment */
//#if DEV_BUS_TYPE==PCI_INTERFACE
//#define GET_COMMAND_PACKET_FRAG_THRESHOLD(v) 4*(v/4) - 8
//#else
#define GET_COMMAND_PACKET_FRAG_THRESHOLD(v) (4*(v/4) - 8 - USB_HWDESC_HEADER_LEN)
//#endif
typedef enum _firmware_init_step{
FW_INIT_STEP0_BOOT = 0,
FW_INIT_STEP1_MAIN = 1,
FW_INIT_STEP2_DATA = 2,
}firmware_init_step_e;
typedef enum _opt_rst_type{
OPT_SYSTEM_RESET = 0,
OPT_FIRMWARE_RESET = 1,
}opt_rst_type_e;
#if 0
/* CPU related */
RT_STATUS
CPUCheckMainCodeOKAndTurnOnCPU(
IN PADAPTER Adapter
);
RT_STATUS
CPUCheckFirmwareReady(
IN PADAPTER Adapter
);
/* Firmware related */
VOID
FWInitializeParameters(
IN PADAPTER Adapter
);
RT_STATUS
FWSendDownloadCode(
IN PADAPTER Adapter,
IN pu1Byte CodeVirtualAddrress,
IN u4Byte BufferLen
);
RT_STATUS
FWSendNullPacket(
IN PADAPTER Adapter,
IN u4Byte Length
);
RT_STATUS
CmdSendPacket(
PADAPTER Adapter,
PRT_TCB pTcb,
PRT_TX_LOCAL_BUFFER pBuf,
u4Byte BufferLen,
u4Byte PacketType,
BOOLEAN bLastInitPacket
);
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,35 @@
#ifndef IMG_H
#define IMG_H
#define BOOT_ARR_LEN 344
#define MAIN_ARR_LEN 45136
#define DATA_ARR_LEN 796
#define MACPHY_Array_PGLength 30
#define PHY_REG_1T2RArrayLength 296
#define AGCTAB_ArrayLength 384
#define MACPHY_ArrayLength 18
#define RadioA_ArrayLength 246
#define RadioB_ArrayLength 78
#define RadioC_ArrayLength 1
#define RadioD_ArrayLength 1
#define PHY_REGArrayLength 1
extern u8 rtl8190_fwboot_array[BOOT_ARR_LEN];
extern u8 rtl8190_fwmain_array[MAIN_ARR_LEN];
extern u8 rtl8190_fwdata_array[DATA_ARR_LEN];
extern u32 Rtl8192UsbPHY_REGArray[];
extern u32 Rtl8192UsbPHY_REG_1T2RArray[];
extern u32 Rtl8192UsbRadioA_Array[];
extern u32 Rtl8192UsbRadioB_Array[];
extern u32 Rtl8192UsbRadioC_Array[];
extern u32 Rtl8192UsbRadioD_Array[];
extern u32 Rtl8192UsbMACPHY_Array[];
extern u32 Rtl8192UsbMACPHY_Array_PG[];
extern u32 Rtl8192UsbAGCTAB_Array[];
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,94 @@
#ifndef _R819XU_PHY_H
#define _R819XU_PHY_H
/* Channel switch:The size of command tables for switch channel*/
#define MAX_PRECMD_CNT 16
#define MAX_RFDEPENDCMD_CNT 16
#define MAX_POSTCMD_CNT 16
typedef enum _SwChnlCmdID{
CmdID_End,
CmdID_SetTxPowerLevel,
CmdID_BBRegWrite10,
CmdID_WritePortUlong,
CmdID_WritePortUshort,
CmdID_WritePortUchar,
CmdID_RF_WriteReg,
}SwChnlCmdID;
/*--------------------------------Define structure--------------------------------*/
/* 1. Switch channel related */
typedef struct _SwChnlCmd{
SwChnlCmdID CmdID;
u32 Para1;
u32 Para2;
u32 msDelay;
}__attribute__ ((packed)) SwChnlCmd;
extern u32 rtl819XMACPHY_Array_PG[];
extern u32 rtl819XPHY_REG_1T2RArray[];
extern u32 rtl819XAGCTAB_Array[];
extern u32 rtl819XRadioA_Array[];
extern u32 rtl819XRadioB_Array[];
extern u32 rtl819XRadioC_Array[];
extern u32 rtl819XRadioD_Array[];
typedef enum _HW90_BLOCK{
HW90_BLOCK_MAC = 0,
HW90_BLOCK_PHY0 = 1,
HW90_BLOCK_PHY1 = 2,
HW90_BLOCK_RF = 3,
HW90_BLOCK_MAXIMUM = 4, // Never use this
}HW90_BLOCK_E, *PHW90_BLOCK_E;
typedef enum _RF90_RADIO_PATH{
RF90_PATH_A = 0, //Radio Path A
RF90_PATH_B = 1, //Radio Path B
RF90_PATH_C = 2, //Radio Path C
RF90_PATH_D = 3, //Radio Path D
RF90_PATH_MAX //Max RF number 92 support
}RF90_RADIO_PATH_E, *PRF90_RADIO_PATH_E;
#define bMaskByte0 0xff
#define bMaskByte1 0xff00
#define bMaskByte2 0xff0000
#define bMaskByte3 0xff000000
#define bMaskHWord 0xffff0000
#define bMaskLWord 0x0000ffff
#define bMaskDWord 0xffffffff
//extern u32 rtl8192_CalculateBitShift(u32 dwBitMask);
extern u8 rtl8192_phy_CheckIsLegalRFPath(struct net_device* dev, u32 eRFPath);
extern void rtl8192_setBBreg(struct net_device* dev, u32 dwRegAddr, u32 dwBitMask, u32 dwData);
extern u32 rtl8192_QueryBBReg(struct net_device* dev, u32 dwRegAddr, u32 dwBitMask);
//extern u32 rtl8192_phy_RFSerialRead(struct net_device* dev, RF90_RADIO_PATH_E eRFPath, u32 Offset);
//extern void rtl8192_phy_RFSerialWrite(struct net_device* dev, RF90_RADIO_PATH_E eRFPath, u32 Offset, u32 Data);
extern void rtl8192_phy_SetRFReg(struct net_device* dev, RF90_RADIO_PATH_E eRFPath, u32 RegAddr, u32 BitMask, u32 Data);
extern u32 rtl8192_phy_QueryRFReg(struct net_device* dev, RF90_RADIO_PATH_E eRFPath, u32 RegAddr, u32 BitMask);
extern void rtl8192_phy_configmac(struct net_device* dev);
extern void rtl8192_phyConfigBB(struct net_device* dev, u8 ConfigType);
//extern void rtl8192_InitBBRFRegDef(struct net_device* dev);
extern u8 rtl8192_phy_checkBBAndRF(struct net_device* dev, HW90_BLOCK_E CheckBlock, RF90_RADIO_PATH_E eRFPath);
//extern void rtl8192_BB_Config_ParaFile(struct net_device* dev);
extern void rtl8192_BBConfig(struct net_device* dev);
extern void rtl8192_phy_getTxPower(struct net_device* dev);
extern void rtl8192_phy_setTxPower(struct net_device* dev, u8 channel);
extern void rtl8192_phy_RFConfig(struct net_device* dev);
extern void rtl8192_phy_updateInitGain(struct net_device* dev);
extern u8 rtl8192_phy_ConfigRFWithHeaderFile(struct net_device* dev, RF90_RADIO_PATH_E eRFPath);
extern u8 rtl8192_phy_SwChnl(struct net_device* dev, u8 channel);
extern void rtl8192_SetBWMode(struct net_device *dev, HT_CHANNEL_WIDTH Bandwidth, HT_EXTCHNL_OFFSET Offset);
extern void rtl8192_SwChnl_WorkItem(struct net_device *dev);
void rtl8192_SetBWModeWorkItem(struct net_device *dev);
extern bool rtl8192_SetRFPowerState(struct net_device *dev, RT_RF_POWER_STATE eRFPowerState);
//added by amy
extern void InitialGain819xUsb(struct net_device *dev, u8 Operation);
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
extern void InitialGainOperateWorkItemCallBack(struct work_struct *work);
#else
extern void InitialGainOperateWorkItemCallBack(struct net_device *dev);
#endif
#endif

View File

@ -0,0 +1,871 @@
#ifndef _R819XU_PHYREG_H
#define _R819XU_PHYREG_H
#define RF_DATA 0x1d4 // FW will write RF data in the register.
//Register //duplicate register due to connection: RF_Mode, TRxRN, NumOf L-STF
//page 1
#define rPMAC_Reset 0x100
#define rPMAC_TxStart 0x104
#define rPMAC_TxLegacySIG 0x108
#define rPMAC_TxHTSIG1 0x10c
#define rPMAC_TxHTSIG2 0x110
#define rPMAC_PHYDebug 0x114
#define rPMAC_TxPacketNum 0x118
#define rPMAC_TxIdle 0x11c
#define rPMAC_TxMACHeader0 0x120
#define rPMAC_TxMACHeader1 0x124
#define rPMAC_TxMACHeader2 0x128
#define rPMAC_TxMACHeader3 0x12c
#define rPMAC_TxMACHeader4 0x130
#define rPMAC_TxMACHeader5 0x134
#define rPMAC_TxDataType 0x138
#define rPMAC_TxRandomSeed 0x13c
#define rPMAC_CCKPLCPPreamble 0x140
#define rPMAC_CCKPLCPHeader 0x144
#define rPMAC_CCKCRC16 0x148
#define rPMAC_OFDMRxCRC32OK 0x170
#define rPMAC_OFDMRxCRC32Er 0x174
#define rPMAC_OFDMRxParityEr 0x178
#define rPMAC_OFDMRxCRC8Er 0x17c
#define rPMAC_CCKCRxRC16Er 0x180
#define rPMAC_CCKCRxRC32Er 0x184
#define rPMAC_CCKCRxRC32OK 0x188
#define rPMAC_TxStatus 0x18c
//page8
#define rFPGA0_RFMOD 0x800 //RF mode & CCK TxSC
#define rFPGA0_TxInfo 0x804
#define rFPGA0_PSDFunction 0x808
#define rFPGA0_TxGainStage 0x80c
#define rFPGA0_RFTiming1 0x810
#define rFPGA0_RFTiming2 0x814
//#define rFPGA0_XC_RFTiming 0x818
//#define rFPGA0_XD_RFTiming 0x81c
#define rFPGA0_XA_HSSIParameter1 0x820
#define rFPGA0_XA_HSSIParameter2 0x824
#define rFPGA0_XB_HSSIParameter1 0x828
#define rFPGA0_XB_HSSIParameter2 0x82c
#define rFPGA0_XC_HSSIParameter1 0x830
#define rFPGA0_XC_HSSIParameter2 0x834
#define rFPGA0_XD_HSSIParameter1 0x838
#define rFPGA0_XD_HSSIParameter2 0x83c
#define rFPGA0_XA_LSSIParameter 0x840
#define rFPGA0_XB_LSSIParameter 0x844
#define rFPGA0_XC_LSSIParameter 0x848
#define rFPGA0_XD_LSSIParameter 0x84c
#define rFPGA0_RFWakeUpParameter 0x850
#define rFPGA0_RFSleepUpParameter 0x854
#define rFPGA0_XAB_SwitchControl 0x858
#define rFPGA0_XCD_SwitchControl 0x85c
#define rFPGA0_XA_RFInterfaceOE 0x860
#define rFPGA0_XB_RFInterfaceOE 0x864
#define rFPGA0_XC_RFInterfaceOE 0x868
#define rFPGA0_XD_RFInterfaceOE 0x86c
#define rFPGA0_XAB_RFInterfaceSW 0x870
#define rFPGA0_XCD_RFInterfaceSW 0x874
#define rFPGA0_XAB_RFParameter 0x878
#define rFPGA0_XCD_RFParameter 0x87c
#define rFPGA0_AnalogParameter1 0x880
#define rFPGA0_AnalogParameter2 0x884
#define rFPGA0_AnalogParameter3 0x888
#define rFPGA0_AnalogParameter4 0x88c
#define rFPGA0_XA_LSSIReadBack 0x8a0
#define rFPGA0_XB_LSSIReadBack 0x8a4
#define rFPGA0_XC_LSSIReadBack 0x8a8
#define rFPGA0_XD_LSSIReadBack 0x8ac
#define rFPGA0_PSDReport 0x8b4
#define rFPGA0_XAB_RFInterfaceRB 0x8e0
#define rFPGA0_XCD_RFInterfaceRB 0x8e4
//page 9
#define rFPGA1_RFMOD 0x900 //RF mode & OFDM TxSC
#define rFPGA1_TxBlock 0x904
#define rFPGA1_DebugSelect 0x908
#define rFPGA1_TxInfo 0x90c
//page a
#define rCCK0_System 0xa00
#define rCCK0_AFESetting 0xa04
#define rCCK0_CCA 0xa08
#define rCCK0_RxAGC1 0xa0c //AGC default value, saturation level
#define rCCK0_RxAGC2 0xa10 //AGC & DAGC
#define rCCK0_RxHP 0xa14
#define rCCK0_DSPParameter1 0xa18 //Timing recovery & Channel estimation threshold
#define rCCK0_DSPParameter2 0xa1c //SQ threshold
#define rCCK0_TxFilter1 0xa20
#define rCCK0_TxFilter2 0xa24
#define rCCK0_DebugPort 0xa28 //debug port and Tx filter3
#define rCCK0_FalseAlarmReport 0xa2c //0xa2d
#define rCCK0_TRSSIReport 0xa50
#define rCCK0_RxReport 0xa54 //0xa57
#define rCCK0_FACounterLower 0xa5c //0xa5b
#define rCCK0_FACounterUpper 0xa58 //0xa5c
//page c
#define rOFDM0_LSTF 0xc00
#define rOFDM0_TRxPathEnable 0xc04
#define rOFDM0_TRMuxPar 0xc08
#define rOFDM0_TRSWIsolation 0xc0c
#define rOFDM0_XARxAFE 0xc10 //RxIQ DC offset, Rx digital filter, DC notch filter
#define rOFDM0_XARxIQImbalance 0xc14 //RxIQ imblance matrix
#define rOFDM0_XBRxAFE 0xc18
#define rOFDM0_XBRxIQImbalance 0xc1c
#define rOFDM0_XCRxAFE 0xc20
#define rOFDM0_XCRxIQImbalance 0xc24
#define rOFDM0_XDRxAFE 0xc28
#define rOFDM0_XDRxIQImbalance 0xc2c
#define rOFDM0_RxDetector1 0xc30 //PD,BW & SBD
#define rOFDM0_RxDetector2 0xc34 //SBD & Fame Sync.
#define rOFDM0_RxDetector3 0xc38 //Frame Sync.
#define rOFDM0_RxDetector4 0xc3c //PD, SBD, Frame Sync & Short-GI
#define rOFDM0_RxDSP 0xc40 //Rx Sync Path
#define rOFDM0_CFOandDAGC 0xc44 //CFO & DAGC
#define rOFDM0_CCADropThreshold 0xc48 //CCA Drop threshold
#define rOFDM0_ECCAThreshold 0xc4c // energy CCA
#define rOFDM0_XAAGCCore1 0xc50
#define rOFDM0_XAAGCCore2 0xc54
#define rOFDM0_XBAGCCore1 0xc58
#define rOFDM0_XBAGCCore2 0xc5c
#define rOFDM0_XCAGCCore1 0xc60
#define rOFDM0_XCAGCCore2 0xc64
#define rOFDM0_XDAGCCore1 0xc68
#define rOFDM0_XDAGCCore2 0xc6c
#define rOFDM0_AGCParameter1 0xc70
#define rOFDM0_AGCParameter2 0xc74
#define rOFDM0_AGCRSSITable 0xc78
#define rOFDM0_HTSTFAGC 0xc7c
#define rOFDM0_XATxIQImbalance 0xc80
#define rOFDM0_XATxAFE 0xc84
#define rOFDM0_XBTxIQImbalance 0xc88
#define rOFDM0_XBTxAFE 0xc8c
#define rOFDM0_XCTxIQImbalance 0xc90
#define rOFDM0_XCTxAFE 0xc94
#define rOFDM0_XDTxIQImbalance 0xc98
#define rOFDM0_XDTxAFE 0xc9c
#define rOFDM0_RxHPParameter 0xce0
#define rOFDM0_TxPseudoNoiseWgt 0xce4
#define rOFDM0_FrameSync 0xcf0
#define rOFDM0_DFSReport 0xcf4
#define rOFDM0_TxCoeff1 0xca4
#define rOFDM0_TxCoeff2 0xca8
#define rOFDM0_TxCoeff3 0xcac
#define rOFDM0_TxCoeff4 0xcb0
#define rOFDM0_TxCoeff5 0xcb4
#define rOFDM0_TxCoeff6 0xcb8
//page d
#define rOFDM1_LSTF 0xd00
#define rOFDM1_TRxPathEnable 0xd04
#define rOFDM1_CFO 0xd08
#define rOFDM1_CSI1 0xd10
#define rOFDM1_SBD 0xd14
#define rOFDM1_CSI2 0xd18
#define rOFDM1_CFOTracking 0xd2c
#define rOFDM1_TRxMesaure1 0xd34
#define rOFDM1_IntfDet 0xd3c
#define rOFDM1_PseudoNoiseStateAB 0xd50
#define rOFDM1_PseudoNoiseStateCD 0xd54
#define rOFDM1_RxPseudoNoiseWgt 0xd58
#define rOFDM_PHYCounter1 0xda0 //cca, parity fail
#define rOFDM_PHYCounter2 0xda4 //rate illegal, crc8 fail
#define rOFDM_PHYCounter3 0xda8 //MCS not support
#define rOFDM_ShortCFOAB 0xdac
#define rOFDM_ShortCFOCD 0xdb0
#define rOFDM_LongCFOAB 0xdb4
#define rOFDM_LongCFOCD 0xdb8
#define rOFDM_TailCFOAB 0xdbc
#define rOFDM_TailCFOCD 0xdc0
#define rOFDM_PWMeasure1 0xdc4
#define rOFDM_PWMeasure2 0xdc8
#define rOFDM_BWReport 0xdcc
#define rOFDM_AGCReport 0xdd0
#define rOFDM_RxSNR 0xdd4
#define rOFDM_RxEVMCSI 0xdd8
#define rOFDM_SIGReport 0xddc
//page e
#define rTxAGC_Rate18_06 0xe00
#define rTxAGC_Rate54_24 0xe04
#define rTxAGC_CCK_Mcs32 0xe08
#define rTxAGC_Mcs03_Mcs00 0xe10
#define rTxAGC_Mcs07_Mcs04 0xe14
#define rTxAGC_Mcs11_Mcs08 0xe18
#define rTxAGC_Mcs15_Mcs12 0xe1c
//RF
//Zebra1
#define rZebra1_HSSIEnable 0x0
#define rZebra1_TRxEnable1 0x1
#define rZebra1_TRxEnable2 0x2
#define rZebra1_AGC 0x4
#define rZebra1_ChargePump 0x5
#define rZebra1_Channel 0x7
#define rZebra1_TxGain 0x8
#define rZebra1_TxLPF 0x9
#define rZebra1_RxLPF 0xb
#define rZebra1_RxHPFCorner 0xc
//Zebra4
#define rGlobalCtrl 0
#define rRTL8256_TxLPF 19
#define rRTL8256_RxLPF 11
//RTL8258
#define rRTL8258_TxLPF 0x11
#define rRTL8258_RxLPF 0x13
#define rRTL8258_RSSILPF 0xa
//Bit Mask
//page-1
#define bBBResetB 0x100
#define bGlobalResetB 0x200
#define bOFDMTxStart 0x4
#define bCCKTxStart 0x8
#define bCRC32Debug 0x100
#define bPMACLoopback 0x10
#define bTxLSIG 0xffffff
#define bOFDMTxRate 0xf
#define bOFDMTxReserved 0x10
#define bOFDMTxLength 0x1ffe0
#define bOFDMTxParity 0x20000
#define bTxHTSIG1 0xffffff
#define bTxHTMCSRate 0x7f
#define bTxHTBW 0x80
#define bTxHTLength 0xffff00
#define bTxHTSIG2 0xffffff
#define bTxHTSmoothing 0x1
#define bTxHTSounding 0x2
#define bTxHTReserved 0x4
#define bTxHTAggreation 0x8
#define bTxHTSTBC 0x30
#define bTxHTAdvanceCoding 0x40
#define bTxHTShortGI 0x80
#define bTxHTNumberHT_LTF 0x300
#define bTxHTCRC8 0x3fc00
#define bCounterReset 0x10000
#define bNumOfOFDMTx 0xffff
#define bNumOfCCKTx 0xffff0000
#define bTxIdleInterval 0xffff
#define bOFDMService 0xffff0000
#define bTxMACHeader 0xffffffff
#define bTxDataInit 0xff
#define bTxHTMode 0x100
#define bTxDataType 0x30000
#define bTxRandomSeed 0xffffffff
#define bCCKTxPreamble 0x1
#define bCCKTxSFD 0xffff0000
#define bCCKTxSIG 0xff
#define bCCKTxService 0xff00
#define bCCKLengthExt 0x8000
#define bCCKTxLength 0xffff0000
#define bCCKTxCRC16 0xffff
#define bCCKTxStatus 0x1
#define bOFDMTxStatus 0x2
//page-8
#define bRFMOD 0x1
#define bJapanMode 0x2
#define bCCKTxSC 0x30
#define bCCKEn 0x1000000
#define bOFDMEn 0x2000000
#define bOFDMRxADCPhase 0x10000
#define bOFDMTxDACPhase 0x40000
#define bXATxAGC 0x3f
#define bXBTxAGC 0xf00
#define bXCTxAGC 0xf000
#define bXDTxAGC 0xf0000
#define bPAStart 0xf0000000
#define bTRStart 0x00f00000
#define bRFStart 0x0000f000
#define bBBStart 0x000000f0
#define bBBCCKStart 0x0000000f
#define bPAEnd 0xf //Reg0x814
#define bTREnd 0x0f000000
#define bRFEnd 0x000f0000
#define bCCAMask 0x000000f0 //T2R
#define bR2RCCAMask 0x00000f00
#define bHSSI_R2TDelay 0xf8000000
#define bHSSI_T2RDelay 0xf80000
#define bContTxHSSI 0x400 //chane gain at continue Tx
#define bIGFromCCK 0x200
#define bAGCAddress 0x3f
#define bRxHPTx 0x7000
#define bRxHPT2R 0x38000
#define bRxHPCCKIni 0xc0000
#define bAGCTxCode 0xc00000
#define bAGCRxCode 0x300000
#define b3WireDataLength 0x800
#define b3WireAddressLength 0x400
#define b3WireRFPowerDown 0x1
//#define bHWSISelect 0x8
#define b5GPAPEPolarity 0x40000000
#define b2GPAPEPolarity 0x80000000
#define bRFSW_TxDefaultAnt 0x3
#define bRFSW_TxOptionAnt 0x30
#define bRFSW_RxDefaultAnt 0x300
#define bRFSW_RxOptionAnt 0x3000
#define bRFSI_3WireData 0x1
#define bRFSI_3WireClock 0x2
#define bRFSI_3WireLoad 0x4
#define bRFSI_3WireRW 0x8
#define bRFSI_3Wire 0xf //3-wire total control
#define bRFSI_RFENV 0x10
#define bRFSI_TRSW 0x20
#define bRFSI_TRSWB 0x40
#define bRFSI_ANTSW 0x100
#define bRFSI_ANTSWB 0x200
#define bRFSI_PAPE 0x400
#define bRFSI_PAPE5G 0x800
#define bBandSelect 0x1
#define bHTSIG2_GI 0x80
#define bHTSIG2_Smoothing 0x01
#define bHTSIG2_Sounding 0x02
#define bHTSIG2_Aggreaton 0x08
#define bHTSIG2_STBC 0x30
#define bHTSIG2_AdvCoding 0x40
#define bHTSIG2_NumOfHTLTF 0x300
#define bHTSIG2_CRC8 0x3fc
#define bHTSIG1_MCS 0x7f
#define bHTSIG1_BandWidth 0x80
#define bHTSIG1_HTLength 0xffff
#define bLSIG_Rate 0xf
#define bLSIG_Reserved 0x10
#define bLSIG_Length 0x1fffe
#define bLSIG_Parity 0x20
#define bCCKRxPhase 0x4
#define bLSSIReadAddress 0x3f000000 //LSSI "Read" Address
#define bLSSIReadEdge 0x80000000 //LSSI "Read" edge signal
#define bLSSIReadBackData 0xfff
#define bLSSIReadOKFlag 0x1000
#define bCCKSampleRate 0x8 //0: 44MHz, 1:88MHz
#define bRegulator0Standby 0x1
#define bRegulatorPLLStandby 0x2
#define bRegulator1Standby 0x4
#define bPLLPowerUp 0x8
#define bDPLLPowerUp 0x10
#define bDA10PowerUp 0x20
#define bAD7PowerUp 0x200
#define bDA6PowerUp 0x2000
#define bXtalPowerUp 0x4000
#define b40MDClkPowerUP 0x8000
#define bDA6DebugMode 0x20000
#define bDA6Swing 0x380000
#define bADClkPhase 0x4000000
#define b80MClkDelay 0x18000000
#define bAFEWatchDogEnable 0x20000000
#define bXtalCap 0x0f000000
#define bIntDifClkEnable 0x400
#define bExtSigClkEnable 0x800
#define bBandgapMbiasPowerUp 0x10000
#define bAD11SHGain 0xc0000
#define bAD11InputRange 0x700000
#define bAD11OPCurrent 0x3800000
#define bIPathLoopback 0x4000000
#define bQPathLoopback 0x8000000
#define bAFELoopback 0x10000000
#define bDA10Swing 0x7e0
#define bDA10Reverse 0x800
#define bDAClkSource 0x1000
#define bAD7InputRange 0x6000
#define bAD7Gain 0x38000
#define bAD7OutputCMMode 0x40000
#define bAD7InputCMMode 0x380000
#define bAD7Current 0xc00000
#define bRegulatorAdjust 0x7000000
#define bAD11PowerUpAtTx 0x1
#define bDA10PSAtTx 0x10
#define bAD11PowerUpAtRx 0x100
#define bDA10PSAtRx 0x1000
#define bCCKRxAGCFormat 0x200
#define bPSDFFTSamplepPoint 0xc000
#define bPSDAverageNum 0x3000
#define bIQPathControl 0xc00
#define bPSDFreq 0x3ff
#define bPSDAntennaPath 0x30
#define bPSDIQSwitch 0x40
#define bPSDRxTrigger 0x400000
#define bPSDTxTrigger 0x80000000
#define bPSDSineToneScale 0x7f000000
#define bPSDReport 0xffff
//page-9
#define bOFDMTxSC 0x30000000
#define bCCKTxOn 0x1
#define bOFDMTxOn 0x2
#define bDebugPage 0xfff //reset debug page and also HWord, LWord
#define bDebugItem 0xff //reset debug page and LWord
#define bAntL 0x10
#define bAntNonHT 0x100
#define bAntHT1 0x1000
#define bAntHT2 0x10000
#define bAntHT1S1 0x100000
#define bAntNonHTS1 0x1000000
//page-a
#define bCCKBBMode 0x3
#define bCCKTxPowerSaving 0x80
#define bCCKRxPowerSaving 0x40
#define bCCKSideBand 0x10
#define bCCKScramble 0x8
#define bCCKAntDiversity 0x8000
#define bCCKCarrierRecovery 0x4000
#define bCCKTxRate 0x3000
#define bCCKDCCancel 0x0800
#define bCCKISICancel 0x0400
#define bCCKMatchFilter 0x0200
#define bCCKEqualizer 0x0100
#define bCCKPreambleDetect 0x800000
#define bCCKFastFalseCCA 0x400000
#define bCCKChEstStart 0x300000
#define bCCKCCACount 0x080000
#define bCCKcs_lim 0x070000
#define bCCKBistMode 0x80000000
#define bCCKCCAMask 0x40000000
#define bCCKTxDACPhase 0x4
#define bCCKRxADCPhase 0x20000000 //r_rx_clk
#define bCCKr_cp_mode0 0x0100
#define bCCKTxDCOffset 0xf0
#define bCCKRxDCOffset 0xf
#define bCCKCCAMode 0xc000
#define bCCKFalseCS_lim 0x3f00
#define bCCKCS_ratio 0xc00000
#define bCCKCorgBit_sel 0x300000
#define bCCKPD_lim 0x0f0000
#define bCCKNewCCA 0x80000000
#define bCCKRxHPofIG 0x8000
#define bCCKRxIG 0x7f00
#define bCCKLNAPolarity 0x800000
#define bCCKRx1stGain 0x7f0000
#define bCCKRFExtend 0x20000000 //CCK Rx Iinital gain polarity
#define bCCKRxAGCSatLevel 0x1f000000
#define bCCKRxAGCSatCount 0xe0
#define bCCKRxRFSettle 0x1f //AGCsamp_dly
#define bCCKFixedRxAGC 0x8000
//#define bCCKRxAGCFormat 0x4000 //remove to HSSI register 0x824
#define bCCKAntennaPolarity 0x2000
#define bCCKTxFilterType 0x0c00
#define bCCKRxAGCReportType 0x0300
#define bCCKRxDAGCEn 0x80000000
#define bCCKRxDAGCPeriod 0x20000000
#define bCCKRxDAGCSatLevel 0x1f000000
#define bCCKTimingRecovery 0x800000
#define bCCKTxC0 0x3f0000
#define bCCKTxC1 0x3f000000
#define bCCKTxC2 0x3f
#define bCCKTxC3 0x3f00
#define bCCKTxC4 0x3f0000
#define bCCKTxC5 0x3f000000
#define bCCKTxC6 0x3f
#define bCCKTxC7 0x3f00
#define bCCKDebugPort 0xff0000
#define bCCKDACDebug 0x0f000000
#define bCCKFalseAlarmEnable 0x8000
#define bCCKFalseAlarmRead 0x4000
#define bCCKTRSSI 0x7f
#define bCCKRxAGCReport 0xfe
#define bCCKRxReport_AntSel 0x80000000
#define bCCKRxReport_MFOff 0x40000000
#define bCCKRxRxReport_SQLoss 0x20000000
#define bCCKRxReport_Pktloss 0x10000000
#define bCCKRxReport_Lockedbit 0x08000000
#define bCCKRxReport_RateError 0x04000000
#define bCCKRxReport_RxRate 0x03000000
#define bCCKRxFACounterLower 0xff
#define bCCKRxFACounterUpper 0xff000000
#define bCCKRxHPAGCStart 0xe000
#define bCCKRxHPAGCFinal 0x1c00
#define bCCKRxFalseAlarmEnable 0x8000
#define bCCKFACounterFreeze 0x4000
#define bCCKTxPathSel 0x10000000
#define bCCKDefaultRxPath 0xc000000
#define bCCKOptionRxPath 0x3000000
//page c
#define bNumOfSTF 0x3
#define bShift_L 0xc0
#define bGI_TH 0xc
#define bRxPathA 0x1
#define bRxPathB 0x2
#define bRxPathC 0x4
#define bRxPathD 0x8
#define bTxPathA 0x1
#define bTxPathB 0x2
#define bTxPathC 0x4
#define bTxPathD 0x8
#define bTRSSIFreq 0x200
#define bADCBackoff 0x3000
#define bDFIRBackoff 0xc000
#define bTRSSILatchPhase 0x10000
#define bRxIDCOffset 0xff
#define bRxQDCOffset 0xff00
#define bRxDFIRMode 0x1800000
#define bRxDCNFType 0xe000000
#define bRXIQImb_A 0x3ff
#define bRXIQImb_B 0xfc00
#define bRXIQImb_C 0x3f0000
#define bRXIQImb_D 0xffc00000
#define bDC_dc_Notch 0x60000
#define bRxNBINotch 0x1f000000
#define bPD_TH 0xf
#define bPD_TH_Opt2 0xc000
#define bPWED_TH 0x700
#define bIfMF_Win_L 0x800
#define bPD_Option 0x1000
#define bMF_Win_L 0xe000
#define bBW_Search_L 0x30000
#define bwin_enh_L 0xc0000
#define bBW_TH 0x700000
#define bED_TH2 0x3800000
#define bBW_option 0x4000000
#define bRatio_TH 0x18000000
#define bWindow_L 0xe0000000
#define bSBD_Option 0x1
#define bFrame_TH 0x1c
#define bFS_Option 0x60
#define bDC_Slope_check 0x80
#define bFGuard_Counter_DC_L 0xe00
#define bFrame_Weight_Short 0x7000
#define bSub_Tune 0xe00000
#define bFrame_DC_Length 0xe000000
#define bSBD_start_offset 0x30000000
#define bFrame_TH_2 0x7
#define bFrame_GI2_TH 0x38
#define bGI2_Sync_en 0x40
#define bSarch_Short_Early 0x300
#define bSarch_Short_Late 0xc00
#define bSarch_GI2_Late 0x70000
#define bCFOAntSum 0x1
#define bCFOAcc 0x2
#define bCFOStartOffset 0xc
#define bCFOLookBack 0x70
#define bCFOSumWeight 0x80
#define bDAGCEnable 0x10000
#define bTXIQImb_A 0x3ff
#define bTXIQImb_B 0xfc00
#define bTXIQImb_C 0x3f0000
#define bTXIQImb_D 0xffc00000
#define bTxIDCOffset 0xff
#define bTxQDCOffset 0xff00
#define bTxDFIRMode 0x10000
#define bTxPesudoNoiseOn 0x4000000
#define bTxPesudoNoise_A 0xff
#define bTxPesudoNoise_B 0xff00
#define bTxPesudoNoise_C 0xff0000
#define bTxPesudoNoise_D 0xff000000
#define bCCADropOption 0x20000
#define bCCADropThres 0xfff00000
#define bEDCCA_H 0xf
#define bEDCCA_L 0xf0
#define bLambda_ED 0x300
#define bRxInitialGain 0x7f
#define bRxAntDivEn 0x80
#define bRxAGCAddressForLNA 0x7f00
#define bRxHighPowerFlow 0x8000
#define bRxAGCFreezeThres 0xc0000
#define bRxFreezeStep_AGC1 0x300000
#define bRxFreezeStep_AGC2 0xc00000
#define bRxFreezeStep_AGC3 0x3000000
#define bRxFreezeStep_AGC0 0xc000000
#define bRxRssi_Cmp_En 0x10000000
#define bRxQuickAGCEn 0x20000000
#define bRxAGCFreezeThresMode 0x40000000
#define bRxOverFlowCheckType 0x80000000
#define bRxAGCShift 0x7f
#define bTRSW_Tri_Only 0x80
#define bPowerThres 0x300
#define bRxAGCEn 0x1
#define bRxAGCTogetherEn 0x2
#define bRxAGCMin 0x4
#define bRxHP_Ini 0x7
#define bRxHP_TRLNA 0x70
#define bRxHP_RSSI 0x700
#define bRxHP_BBP1 0x7000
#define bRxHP_BBP2 0x70000
#define bRxHP_BBP3 0x700000
#define bRSSI_H 0x7f0000 //the threshold for high power
#define bRSSI_Gen 0x7f000000 //the threshold for ant diversity
#define bRxSettle_TRSW 0x7
#define bRxSettle_LNA 0x38
#define bRxSettle_RSSI 0x1c0
#define bRxSettle_BBP 0xe00
#define bRxSettle_RxHP 0x7000
#define bRxSettle_AntSW_RSSI 0x38000
#define bRxSettle_AntSW 0xc0000
#define bRxProcessTime_DAGC 0x300000
#define bRxSettle_HSSI 0x400000
#define bRxProcessTime_BBPPW 0x800000
#define bRxAntennaPowerShift 0x3000000
#define bRSSITableSelect 0xc000000
#define bRxHP_Final 0x7000000
#define bRxHTSettle_BBP 0x7
#define bRxHTSettle_HSSI 0x8
#define bRxHTSettle_RxHP 0x70
#define bRxHTSettle_BBPPW 0x80
#define bRxHTSettle_Idle 0x300
#define bRxHTSettle_Reserved 0x1c00
#define bRxHTRxHPEn 0x8000
#define bRxHTAGCFreezeThres 0x30000
#define bRxHTAGCTogetherEn 0x40000
#define bRxHTAGCMin 0x80000
#define bRxHTAGCEn 0x100000
#define bRxHTDAGCEn 0x200000
#define bRxHTRxHP_BBP 0x1c00000
#define bRxHTRxHP_Final 0xe0000000
#define bRxPWRatioTH 0x3
#define bRxPWRatioEn 0x4
#define bRxMFHold 0x3800
#define bRxPD_Delay_TH1 0x38
#define bRxPD_Delay_TH2 0x1c0
#define bRxPD_DC_COUNT_MAX 0x600
//#define bRxMF_Hold 0x3800
#define bRxPD_Delay_TH 0x8000
#define bRxProcess_Delay 0xf0000
#define bRxSearchrange_GI2_Early 0x700000
#define bRxFrame_Guard_Counter_L 0x3800000
#define bRxSGI_Guard_L 0xc000000
#define bRxSGI_Search_L 0x30000000
#define bRxSGI_TH 0xc0000000
#define bDFSCnt0 0xff
#define bDFSCnt1 0xff00
#define bDFSFlag 0xf0000
#define bMFWeightSum 0x300000
#define bMinIdxTH 0x7f000000
#define bDAFormat 0x40000
#define bTxChEmuEnable 0x01000000
#define bTRSWIsolation_A 0x7f
#define bTRSWIsolation_B 0x7f00
#define bTRSWIsolation_C 0x7f0000
#define bTRSWIsolation_D 0x7f000000
#define bExtLNAGain 0x7c00
//page d
#define bSTBCEn 0x4
#define bAntennaMapping 0x10
#define bNss 0x20
#define bCFOAntSumD 0x200
#define bPHYCounterReset 0x8000000
#define bCFOReportGet 0x4000000
#define bOFDMContinueTx 0x10000000
#define bOFDMSingleCarrier 0x20000000
#define bOFDMSingleTone 0x40000000
//#define bRxPath1 0x01
//#define bRxPath2 0x02
//#define bRxPath3 0x04
//#define bRxPath4 0x08
//#define bTxPath1 0x10
//#define bTxPath2 0x20
#define bHTDetect 0x100
#define bCFOEn 0x10000
#define bCFOValue 0xfff00000
#define bSigTone_Re 0x3f
#define bSigTone_Im 0x7f00
#define bCounter_CCA 0xffff
#define bCounter_ParityFail 0xffff0000
#define bCounter_RateIllegal 0xffff
#define bCounter_CRC8Fail 0xffff0000
#define bCounter_MCSNoSupport 0xffff
#define bCounter_FastSync 0xffff
#define bShortCFO 0xfff
#define bShortCFOTLength 12 //total
#define bShortCFOFLength 11 //fraction
#define bLongCFO 0x7ff
#define bLongCFOTLength 11
#define bLongCFOFLength 11
#define bTailCFO 0x1fff
#define bTailCFOTLength 13
#define bTailCFOFLength 12
#define bmax_en_pwdB 0xffff
#define bCC_power_dB 0xffff0000
#define bnoise_pwdB 0xffff
#define bPowerMeasTLength 10
#define bPowerMeasFLength 3
#define bRx_HT_BW 0x1
#define bRxSC 0x6
#define bRx_HT 0x8
#define bNB_intf_det_on 0x1
#define bIntf_win_len_cfg 0x30
#define bNB_Intf_TH_cfg 0x1c0
#define bRFGain 0x3f
#define bTableSel 0x40
#define bTRSW 0x80
#define bRxSNR_A 0xff
#define bRxSNR_B 0xff00
#define bRxSNR_C 0xff0000
#define bRxSNR_D 0xff000000
#define bSNREVMTLength 8
#define bSNREVMFLength 1
#define bCSI1st 0xff
#define bCSI2nd 0xff00
#define bRxEVM1st 0xff0000
#define bRxEVM2nd 0xff000000
#define bSIGEVM 0xff
#define bPWDB 0xff00
#define bSGIEN 0x10000
#define bSFactorQAM1 0xf
#define bSFactorQAM2 0xf0
#define bSFactorQAM3 0xf00
#define bSFactorQAM4 0xf000
#define bSFactorQAM5 0xf0000
#define bSFactorQAM6 0xf0000
#define bSFactorQAM7 0xf00000
#define bSFactorQAM8 0xf000000
#define bSFactorQAM9 0xf0000000
#define bCSIScheme 0x100000
#define bNoiseLvlTopSet 0x3
#define bChSmooth 0x4
#define bChSmoothCfg1 0x38
#define bChSmoothCfg2 0x1c0
#define bChSmoothCfg3 0xe00
#define bChSmoothCfg4 0x7000
#define bMRCMode 0x800000
#define bTHEVMCfg 0x7000000
#define bLoopFitType 0x1
#define bUpdCFO 0x40
#define bUpdCFOOffData 0x80
#define bAdvUpdCFO 0x100
#define bAdvTimeCtrl 0x800
#define bUpdClko 0x1000
#define bFC 0x6000
#define bTrackingMode 0x8000
#define bPhCmpEnable 0x10000
#define bUpdClkoLTF 0x20000
#define bComChCFO 0x40000
#define bCSIEstiMode 0x80000
#define bAdvUpdEqz 0x100000
#define bUChCfg 0x7000000
#define bUpdEqz 0x8000000
//page e
#define bTxAGCRate18_06 0x7f7f7f7f
#define bTxAGCRate54_24 0x7f7f7f7f
#define bTxAGCRateMCS32 0x7f
#define bTxAGCRateCCK 0x7f00
#define bTxAGCRateMCS3_MCS0 0x7f7f7f7f
#define bTxAGCRateMCS7_MCS4 0x7f7f7f7f
#define bTxAGCRateMCS11_MCS8 0x7f7f7f7f
#define bTxAGCRateMCS15_MCS12 0x7f7f7f7f
//Rx Pseduo noise
#define bRxPesudoNoiseOn 0x20000000
#define bRxPesudoNoise_A 0xff
#define bRxPesudoNoise_B 0xff00
#define bRxPesudoNoise_C 0xff0000
#define bRxPesudoNoise_D 0xff000000
#define bPesudoNoiseState_A 0xffff
#define bPesudoNoiseState_B 0xffff0000
#define bPesudoNoiseState_C 0xffff
#define bPesudoNoiseState_D 0xffff0000
//RF
//Zebra1
#define bZebra1_HSSIEnable 0x8
#define bZebra1_TRxControl 0xc00
#define bZebra1_TRxGainSetting 0x07f
#define bZebra1_RxCorner 0xc00
#define bZebra1_TxChargePump 0x38
#define bZebra1_RxChargePump 0x7
#define bZebra1_ChannelNum 0xf80
#define bZebra1_TxLPFBW 0x400
#define bZebra1_RxLPFBW 0x600
//Zebra4
#define bRTL8256RegModeCtrl1 0x100
#define bRTL8256RegModeCtrl0 0x40
#define bRTL8256_TxLPFBW 0x18
#define bRTL8256_RxLPFBW 0x600
//RTL8258
#define bRTL8258_TxLPFBW 0xc
#define bRTL8258_RxLPFBW 0xc00
#define bRTL8258_RSSILPFBW 0xc0
//byte endable for sb_write
#define bByte0 0x1
#define bByte1 0x2
#define bByte2 0x4
#define bByte3 0x8
#define bWord0 0x3
#define bWord1 0xc
#define bDWord 0xf
//for PutRegsetting & GetRegSetting BitMask
#define bMaskByte0 0xff
#define bMaskByte1 0xff00
#define bMaskByte2 0xff0000
#define bMaskByte3 0xff000000
#define bMaskHWord 0xffff0000
#define bMaskLWord 0x0000ffff
#define bMaskDWord 0xffffffff
//for PutRFRegsetting & GetRFRegSetting BitMask
#define bMask12Bits 0xfff
#define bEnable 0x1
#define bDisable 0x0
#define LeftAntenna 0x0
#define RightAntenna 0x1
#define tCheckTxStatus 500 //500ms
#define tUpdateRxCounter 100 //100ms
#define rateCCK 0
#define rateOFDM 1
#define rateHT 2
//define Register-End
#define bPMAC_End 0x1ff
#define bFPGAPHY0_End 0x8ff
#define bFPGAPHY1_End 0x9ff
#define bCCKPHY0_End 0xaff
#define bOFDMPHY0_End 0xcff
#define bOFDMPHY1_End 0xdff
//define max debug item in each debug page
//#define bMaxItem_FPGA_PHY0 0x9
//#define bMaxItem_FPGA_PHY1 0x3
//#define bMaxItem_PHY_11B 0x16
//#define bMaxItem_OFDM_PHY0 0x29
//#define bMaxItem_OFDM_PHY1 0x0
#define bPMACControl 0x0
#define bWMACControl 0x1
#define bWNICControl 0x2
#define PathA 0x0
#define PathB 0x1
#define PathC 0x2
#define PathD 0x3
#define rRTL8256RxMixerPole 0xb
#define bZebraRxMixerPole 0x6
#define rRTL8256TxBBOPBias 0x9
#define bRTL8256TxBBOPBias 0x400
#define rRTL8256TxBBBW 19
#define bRTL8256TxBBBW 0x18
#endif //__INC_HAL8190PCIPHYREG_H