mirror of https://github.com/hak5/openwrt.git
Upgrade rt2x00 to a more recent snapshot, master mode now working, thanks to Daniel Gimpelevich
SVN-Revision: 8367lede-17.01
parent
ce173e2094
commit
195c4d9a3d
|
@ -10,8 +10,7 @@ include $(TOPDIR)/rules.mk
|
|||
include $(INCLUDE_DIR)/kernel.mk
|
||||
|
||||
PKG_NAME:=rt2x00
|
||||
#PKG_VERSION:=cvs-20070725
|
||||
PKG_VERSION:=git-200706018
|
||||
PKG_VERSION:=cvs-20070712
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
|
@ -107,18 +106,20 @@ endef
|
|||
define Build/Prepare
|
||||
$(call Build/Prepare/Default)
|
||||
$(CP) -r src/* $(PKG_BUILD_DIR)/
|
||||
sed 's/\$$$$(CONFIG_RT.*)/m\t\t/g' src/Makefile > $(PKG_BUILD_DIR)/Makefile
|
||||
wget -N -P $(DL_DIR) http://www.ralinktech.com.tw/data/RT61_Firmware_V1.2.zip
|
||||
wget -N -P $(DL_DIR) http://www.ralinktech.com.tw/data/RT71W_Firmware_V1.8.zip
|
||||
unzip -jod $(PKG_BUILD_DIR) $(DL_DIR)/RT61_Firmware_V1.2.zip
|
||||
unzip -jod $(PKG_BUILD_DIR) $(DL_DIR)/RT71W_Firmware_V1.8.zip
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
# $(MAKE) -C "$(PKG_BUILD_DIR)" config_header
|
||||
$(MAKE) -C "$(PKG_BUILD_DIR)" config_header
|
||||
$(MAKE) -C "$(LINUX_DIR)" \
|
||||
CROSS_COMPILE="$(TARGET_CROSS)" \
|
||||
ARCH="$(LINUX_KARCH)" V="$(V)" \
|
||||
SUBDIRS="$(PKG_BUILD_DIR)" \
|
||||
KERNELVERSION="$(KERNEL)" \
|
||||
KERNEL_SOURCE="$(LINUX_DIR)" \
|
||||
CFLAGS_MODULE="-DMODULE -include $(PKG_BUILD_DIR)/rt2x00_compat.h" \
|
||||
KDIR="$(LINUX_DIR)"
|
||||
endef
|
||||
|
||||
|
|
|
@ -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.
|
|
@ -1,11 +1,147 @@
|
|||
rt2x00lib-objs := rt2x00dev.o rt2x00mac.o rt2x00firmware.o
|
||||
# Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
|
||||
# <http://rt2x00.serialmonkey.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.
|
||||
#
|
||||
# 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.
|
||||
|
||||
EXTRA_CFLAGS += -DCONFIG_RT2X00_LIB_FIRMWARE
|
||||
# Module: Makefile
|
||||
# Abstract: Makefile for rt2x00 kernel module
|
||||
|
||||
obj-m += rt2x00lib.o rt2x00pci.o rt2x00usb.o
|
||||
#
|
||||
# Set the enviroment variables.
|
||||
#
|
||||
ifndef SUBDIRS
|
||||
SUBDIRS=$(shell pwd)
|
||||
endif
|
||||
|
||||
obj-$(CONFIG_RT2400PCI) += rt2400pci.o
|
||||
obj-$(CONFIG_RT2500PCI) += rt2500pci.o
|
||||
obj-$(CONFIG_RT61PCI) += rt61pci.o
|
||||
obj-$(CONFIG_RT2500USB) += rt2500usb.o
|
||||
obj-$(CONFIG_RT73USB) += rt73usb.o
|
||||
ifdef KERNDIR
|
||||
KERNEL_SOURCES := $(KERNDIR)
|
||||
else
|
||||
KERNEL_SOURCES := /lib/modules/$(shell uname -r)/build
|
||||
endif
|
||||
|
||||
ifdef KERNOUT
|
||||
KERNEL_OUTPUT := KBUILD_OUTPUT=$(KERNOUT)
|
||||
else
|
||||
KERNEL_OUTPUT :=
|
||||
endif
|
||||
|
||||
#
|
||||
# Include kernel and rt2x00 config.
|
||||
#
|
||||
include $(KERNEL_SOURCES)/.config
|
||||
include $(SUBDIRS)/config
|
||||
|
||||
#
|
||||
# Determine if and with what options the rt2x00 drivers should be build
|
||||
#
|
||||
rt2x00lib-objs := rt2x00dev.o rt2x00mac.o
|
||||
|
||||
ifeq ($(CONFIG_RT2X00),y)
|
||||
|
||||
ifeq ($(CONFIG_RT2X00_LIB_DEBUGFS),y)
|
||||
rt2x00lib-objs += rt2x00debug.o
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_RT2400PCI),y)
|
||||
obj-m += rt2400pci.o rt2x00pci.o rt2x00lib.o
|
||||
ifeq ($(CONFIG_RT2400PCI_RFKILL),y)
|
||||
rt2x00lib-objs += rt2x00rfkill.o
|
||||
CFLAGS += -DCONFIG_RT2X00_LIB_RFKILL
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_RT2500PCI),y)
|
||||
obj-m += rt2500pci.o rt2x00pci.o rt2x00lib.o
|
||||
ifeq ($(CONFIG_RT2500PCI_RFKILL),y)
|
||||
rt2x00lib-objs += rt2x00rfkill.o
|
||||
CFLAGS += -DCONFIG_RT2X00_LIB_RFKILL
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_RT2500USB),y)
|
||||
obj-m += rt2500usb.o rt2x00usb.o rt2x00lib.o
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_RT61PCI),y)
|
||||
CFLAGS += -DCONFIG_RT2X00_LIB_FIRMWARE
|
||||
rt2x00lib-objs += rt2x00firmware.o
|
||||
obj-m += rt61pci.o rt2x00pci.o rt2x00lib.o
|
||||
ifeq ($(CONFIG_RT61PCI_RFKILL),y)
|
||||
rt2x00lib-objs += rt2x00rfkill.o
|
||||
CFLAGS += -DCONFIG_RT2X00_LIB_RFKILL
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_RT73USB),y)
|
||||
CFLAGS += -DCONFIG_RT2X00_LIB_FIRMWARE
|
||||
rt2x00lib-objs += rt2x00firmware.o
|
||||
obj-m += rt73usb.o rt2x00usb.o rt2x00lib.o
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
MAKEFLAGS += --no-print-directory
|
||||
CFLAGS := -include $(SUBDIRS)/rt2x00_compat.h $(CFLAGS)
|
||||
|
||||
all: default
|
||||
|
||||
config_header:
|
||||
@if [ ! -f "rt2x00_config.h" ] || [ "rt2x00_config.h" -ot "config" ]; \
|
||||
then \
|
||||
awk -F = > rt2x00_config.h < config '/^CONFIG.*$\/ \
|
||||
{ \
|
||||
if($$2 == "y") { \
|
||||
print "#ifndef " $$1; \
|
||||
print "#define " $$1; \
|
||||
print "#endif"; \
|
||||
print "" \
|
||||
} else { \
|
||||
print "#undef " $$1; \
|
||||
print ""; \
|
||||
} \
|
||||
}'; \
|
||||
fi
|
||||
|
||||
default: config_header
|
||||
@$(MAKE) -C $(KERNEL_SOURCES) SUBDIRS=$(SUBDIRS) $(KERNEL_OUTPUT) \
|
||||
modules
|
||||
|
||||
sparse: config_header
|
||||
@$(MAKE) -C $(KERNEL_SOURCES) SUBDIRS=$(SUBDIRS) $(KERNEL_OUTPUT) \
|
||||
modules C=1 CF=-D__CHECK_ENDIAN__
|
||||
|
||||
install: config_header
|
||||
@$(MAKE) -C $(KERNEL_SOURCES) SUBDIRS=$(SUBDIRS) $(KERNEL_OUTPUT) \
|
||||
INSTALL_MOD_DIR=rt2x00 $(KERNEL_OUTPUT) modules_install
|
||||
/sbin/depmod -a
|
||||
|
||||
clean:
|
||||
@rm -f rt2x00_config.h
|
||||
@rm -f Modules.symvers Module.symvers
|
||||
@for folder in $(EXTMODDIRS); \
|
||||
do \
|
||||
rm -f $${folder}/*.o \
|
||||
rm -f $${folder}/*.ko \
|
||||
rm -f $${folder}/*.s \
|
||||
rm -f $${folder}/*.mod.c \
|
||||
rm -f $${folder}/.*.cmd \
|
||||
rm -f $${folder}/.*.flags \
|
||||
rm -f $${folder}/.*.o.d \
|
||||
rm -f $${folder}/.*.s.d \
|
||||
rm -f $${folder}/.#* \
|
||||
rm -f $${folder}/*~ \
|
||||
rm -fr $${folder}/.tmp_versions; \
|
||||
done
|
||||
|
|
|
@ -0,0 +1,548 @@
|
|||
===============================================================================
|
||||
Installation and configuration instructions for the rt2x00 Modules
|
||||
===============================================================================
|
||||
|
||||
===============================================================================
|
||||
Table of contents:
|
||||
========================
|
||||
|
||||
- 1: Minimal requirements
|
||||
- 1.1: kernel
|
||||
- 1.2: gcc
|
||||
- 1.3: make
|
||||
- 2: Hardware
|
||||
- 2.1: Chipsets
|
||||
- 2.2: RF button
|
||||
- 3: Module building & Installation
|
||||
- 3.1: Introduction
|
||||
- 3.2: Configure
|
||||
- 3.3: Build
|
||||
- 3.4: Installation
|
||||
- 4: Firmware
|
||||
- 4.1: Firmware files
|
||||
- 4.2: Firmware installation
|
||||
- 4.3: Firmware requirements
|
||||
- 5: Module loading
|
||||
- 5.1: Module load order
|
||||
- 5.2: Module load options
|
||||
- 6: Interfaces
|
||||
- 6.1: Wireless interfaces
|
||||
- 6.2: Input interface
|
||||
- 7: Interface configuration
|
||||
- 7.1: Minimal configuration
|
||||
- 7.2: Configuration tools
|
||||
- 8: Distribution specific notes
|
||||
- 8.1: Debian & derivatives
|
||||
- 8.2: Fedora
|
||||
- 8.3: Gentoo
|
||||
- 8.4: Mandriva
|
||||
- 9: Problems & Troubleshooting
|
||||
- 9.1: Debug information
|
||||
- 9.2: Debugfs
|
||||
- 9.3: Bug reporting
|
||||
- 10: Problems & Workarounds
|
||||
- 10.1: udev interface naming
|
||||
- 10.2: BUG - ifdown & ifup radio failure
|
||||
- 11: TODO list
|
||||
- 12: Contact us
|
||||
|
||||
|
||||
===============================================================================
|
||||
1: Minimal requirements:
|
||||
=======================================
|
||||
|
||||
===================
|
||||
1.1: kernel
|
||||
=========
|
||||
|
||||
- The minimal required kernel version is 2.6.22-rc1
|
||||
|
||||
- It is important that the installed kernel sources match
|
||||
the running kernel. Unless you are crosscompiling and you
|
||||
know what you are doing.
|
||||
|
||||
- Depending on what rt2x00 components will be built,
|
||||
some kernel configuration options are mandatory.
|
||||
It does however not matter if these options are compiled
|
||||
into the kernel or compiled as module.
|
||||
|
||||
Kernel config option Required for component
|
||||
------------------------------------------------------------------
|
||||
# CONFIG_NET_RADIO all
|
||||
# CONFIG_MAC80211 all
|
||||
# CONFIG_WLAN_80211 all
|
||||
# CONFIG_PCI rt2400pci, rt2500pci, rt61pci
|
||||
# CONFIG_USB rt2500usb, rt73usb
|
||||
# CONFIG_HOTPLUG rt61pci, rt73usb
|
||||
# CONFIG_FW_LOADER rt61pci, rt73usb
|
||||
# CONFIG_CRC_ITU_T rt61pci, rt73usb
|
||||
# CONFIG_DEBUG_FS rt2x00 (optional, only for debug)
|
||||
# CONFIG_RFKILL rt2400pci, rt2500pci, rt61pci (optional,
|
||||
only for button support)
|
||||
|
||||
===================
|
||||
1.2: GCC
|
||||
=========
|
||||
|
||||
- For building the rt2x00 components the same gcc version is required
|
||||
as was used to build your target kernel.
|
||||
|
||||
===================
|
||||
1.3: make
|
||||
=========
|
||||
|
||||
- The program 'make' needs to be installed on the system. There are no
|
||||
further special requirements for this program.
|
||||
|
||||
===============================================================================
|
||||
2: Hardware
|
||||
=======================================
|
||||
|
||||
===================
|
||||
2.1: Chipsets
|
||||
=========
|
||||
|
||||
Support for each Ralink wireless chipset has been split into separate drivers.
|
||||
|
||||
# rt2400pci
|
||||
- chipset: rt2400
|
||||
- supports: rt2460
|
||||
- bus type: PCI/PCMCIA/miniPCI
|
||||
# rt2500pci
|
||||
- chipset: rt2500
|
||||
- supports: rt2560
|
||||
- bus type: PCI/PCMCIA/miniPCI
|
||||
# rt2500usb
|
||||
- chipset: rt2570
|
||||
- supports: rt2570
|
||||
- bus type: USB
|
||||
# rt61pci
|
||||
- chipset: rt61 (or rt2600)
|
||||
- supports: rt2561, rt2561s, rt2661
|
||||
- bus type: PCI/PCMCIA/miniPCI
|
||||
# rt73usb
|
||||
- chipset: rt73
|
||||
- supports: rt2571(w), rt2573, rt2671
|
||||
- bus type: USB
|
||||
|
||||
===================
|
||||
2.2: RF button
|
||||
=========
|
||||
|
||||
On some occasions the Ralink chipset has been built into a laptop.
|
||||
If that is the case, there usually is a hardware button that controls the
|
||||
radio of the wireless interface.
|
||||
If you have such a hardware device, make sure you enable hardware button
|
||||
support for your device in the configuration before building the rt2x00
|
||||
components.
|
||||
Note: This feature requires the enabling of the rfkill driver in the kernel.
|
||||
|
||||
===============================================================================
|
||||
3: Module building & Installation
|
||||
=======================================
|
||||
|
||||
===================
|
||||
3.1: Introduction
|
||||
=========
|
||||
|
||||
The following steps in this chapter concerning module building and
|
||||
installation need to be performed for each kernel. This means that
|
||||
after each kernel upgrade the modules need to be rebuild and
|
||||
reinstalled in order to make them work with the new kernel.
|
||||
|
||||
===================
|
||||
3.2: Configure
|
||||
=========
|
||||
|
||||
Before starting to build the rt2x00 components it is recommended to look into
|
||||
the 'config' file first. In this file you can configure which components of
|
||||
rt2x00 should be built. And even more importantly, you can configure with
|
||||
what options the components will be built.
|
||||
To build all the rt2x00 drivers (with debug capabilities enabled) no changes
|
||||
in the configuration file are required. For most users this would be
|
||||
sufficient to start working with rt2x00.
|
||||
|
||||
===================
|
||||
3.3: Build
|
||||
=========
|
||||
|
||||
To build all rt2x00 components which were enabled in the configuration file
|
||||
simply run (root privileges not required):
|
||||
|
||||
# $ make
|
||||
|
||||
All modules (.ko files) will be created in the current directory.
|
||||
|
||||
===================
|
||||
3.4: Installation
|
||||
=========
|
||||
|
||||
All rt2x00 modules can be installed by doing (with root privileges):
|
||||
|
||||
# $ make install
|
||||
|
||||
With this command all rt2x00 modules (including rfkill and d80211) will be
|
||||
created in a newly created folder named 'rt2x00' inside the kernel modules
|
||||
directory (usually '/lib/modules/$(uname -r)/').
|
||||
|
||||
|
||||
==============================================================================
|
||||
4: Firmware
|
||||
=======================================
|
||||
|
||||
===================
|
||||
4.1: Firmware files
|
||||
=========
|
||||
|
||||
rt61pci and rt73usb require firmware to be available while loading the module.
|
||||
The following firmware files are available for each driver:
|
||||
|
||||
# rt61pci
|
||||
- rt2561.bin
|
||||
- rt2561s.bin
|
||||
- rt2661.bin
|
||||
|
||||
# rt73usb
|
||||
- rt73.bin
|
||||
|
||||
===================
|
||||
4.2: Firmware installation
|
||||
=========
|
||||
|
||||
The latest firmware files are available in a separate .zip archive and can be
|
||||
downloaded from the support page on the Ralink website at
|
||||
http://www.ralinktech.com.
|
||||
Note that by a high level of logic, Ralink has named their firmware for rt73
|
||||
chipsets "rt71W" with a comment that it is for the rt2571W and rt2671 devices.
|
||||
For rt61pci 3 seperate firmware files are available, which one is used depends
|
||||
on which RT chip is on the device. Usually it is best to install all files.
|
||||
To install the firmware the firmware files need to be manually copied to the
|
||||
systems firmware folder (usually '/lib/firmware/') the exact folder depends
|
||||
on the distribution. When in doubt consult the distributions documentation.
|
||||
|
||||
===================
|
||||
4.3: Firmware requirements
|
||||
=========
|
||||
|
||||
To load firmware when the module is loaded the hotplug daemon should be
|
||||
running. Make sure you either enable hotplugging manually before loading the
|
||||
module, or make sure hotplugging is enabled during the system boot process.
|
||||
|
||||
|
||||
==============================================================================
|
||||
5: Module loading
|
||||
=======================================
|
||||
|
||||
===================
|
||||
5.1: Module load order
|
||||
=========
|
||||
|
||||
When the modules have been properly installed by following the installation
|
||||
instructions from the previous section, the module handlers (i.e. modprobe)
|
||||
will automaticly resolve all module dependencies when loading the device
|
||||
specific driver.
|
||||
|
||||
When loading the modules manually with insmod, you should load them in the
|
||||
following order:
|
||||
|
||||
# eeprom_93cx6.ko (optional, only required for pci devices)
|
||||
# rt2x00lib.ko
|
||||
# rt2x00pci.ko (optional, only required for pci devices)
|
||||
# rt2x00usb.ko (optional, only required for usb devices)
|
||||
# rt2400pci.ko (optional, only required for rt2400 support)
|
||||
# rt2500pci.ko (optional, only required for rt2500 support)
|
||||
# rt2500usb.ko (optional, only required for rt2570 support)
|
||||
# rt61pci.ko (optional, only required for rt61 support)
|
||||
# rt73usb.ko (optional, only required for rt73 support)
|
||||
|
||||
===================
|
||||
5.2: Module load options
|
||||
=========
|
||||
|
||||
None.
|
||||
|
||||
|
||||
==============================================================================
|
||||
6: Interfaces
|
||||
=======================================
|
||||
|
||||
===================
|
||||
6.1: Wireless interfaces
|
||||
=========
|
||||
|
||||
After loading the modules two interfaces will now be visible in ifconfig and
|
||||
iwconfig, namely wmaster0 and wlan0. The first device is the so called master
|
||||
device which is can be used by some userspace tools, but normally can be
|
||||
ignored by the user. The second interface wlan0 is the client interface which
|
||||
the user can configure.
|
||||
With rt2x00 it is possible to run multiple client interfaces with
|
||||
only a single device. 1 client interface can run in adhoc, managed or master
|
||||
mode while a second interface can run in monitor mode at the same time.
|
||||
More client interfaces can be added by issuing the following command
|
||||
(with root privileges):
|
||||
|
||||
# $ echo -n <name> > /sys/class/ieee80211/<dev>/add_iface
|
||||
|
||||
where the variable <name> is the name of the client interface that should be
|
||||
added (i.e. wlan1), and <dev> is the physical device where the new client
|
||||
interface should be attached to (i.e. phy0).
|
||||
|
||||
===================
|
||||
6.2: Input interface
|
||||
=========
|
||||
|
||||
When the rfkill driver is being used a new input device with the name of the
|
||||
device specific module where the button belongs to will have been created.
|
||||
Whenever the user presses the hardware button the rfkill driver will
|
||||
automatically make sure the hardware radio is being disabled or enabled
|
||||
accordingly. When the user has opened the input device the radio will
|
||||
not be automatically controlled, but instead the input device will
|
||||
report all button events (KEY_RFKILL) to userspace where the user
|
||||
could have setup script to do all the work that has to be executed.
|
||||
This means that while the input device is opened, the user is responsible
|
||||
for the correct behaviour.
|
||||
|
||||
|
||||
==============================================================================
|
||||
7: Interface configuration
|
||||
=======================================
|
||||
|
||||
===================
|
||||
7.1: Minimal configuration
|
||||
=========
|
||||
|
||||
- After loading the modules the interface should be configured to start
|
||||
an association or work in monitor mode. The following steps are required
|
||||
for a minimal configuration to associate with a non-encrypted access point.
|
||||
|
||||
- Before bringing the client interface up, the working mode should be set:
|
||||
|
||||
# $ iwconfig wlan0 mode managed
|
||||
|
||||
- Configuration parts like essid and channel can be set before or after the
|
||||
client interface has been brought up.
|
||||
|
||||
- It is usually a good idea to set the essid:
|
||||
|
||||
# $ iwconfig wlan0 essid myessid
|
||||
|
||||
- In some situations the device also requires the channel to be manually set:
|
||||
|
||||
# $ iwconfig wlan0 channel mychannel
|
||||
|
||||
- To bring the client interface up:
|
||||
|
||||
# $ ifconfig wlan0 up
|
||||
|
||||
- After the client interface has been brought up, scanning can be performed
|
||||
to check if the desired AP is being detected.
|
||||
|
||||
# $ iwlist wlan0 scan
|
||||
|
||||
- To start an association attempt, the AP address should be set:
|
||||
|
||||
# $ iwconfig wlan0 ap mybssid
|
||||
|
||||
===================
|
||||
7.2: Configuration tools
|
||||
=========
|
||||
|
||||
To configure the interface several tools are possible, the most basic tools
|
||||
are the wireless-tools that provide the iwconfig, iwpriv and iwlist commands.
|
||||
For WPA connections the wireless-tools are not sufficient, to configure the
|
||||
interface for WPA wireless network wpa_supplicant is required.
|
||||
For master mode functionality it is possible to only use the wireless-tools,
|
||||
but it is recommended to use hostapd instead. This tool offers the best
|
||||
functionality.
|
||||
For all configuration tools (wireless-tools, wpa_supplicant and hostapd) are
|
||||
manuals and howto's present in the manpages or on the internet. It is adviced
|
||||
to have at least read the manpages before using the tools for a better
|
||||
understanding on configuring the interface.
|
||||
|
||||
|
||||
==============================================================================
|
||||
8: Distribution specific notes
|
||||
=======================================
|
||||
|
||||
===================
|
||||
8.1: Debian & derivatives
|
||||
=========
|
||||
|
||||
In some instances installing the rt2x00 drivers on debian will result
|
||||
in the problem that the files are being copied into the wrong folder,
|
||||
which results in the fact that the driver cannot be loaded.
|
||||
Installing the drivers should be done manually in this case,
|
||||
please refer to the distributions documentation regarding the proper
|
||||
location of the kernel modules.
|
||||
|
||||
===================
|
||||
8.2: Fedora
|
||||
=========
|
||||
|
||||
Although rt2x00 contains many backward compatibility fixes to ensure
|
||||
that all rt2x00 components will be able to compile and run on all
|
||||
systems that meet the minimal requirements, this does not work in all
|
||||
situations when the Fedora kernels are being used.
|
||||
The problem lies in the fact that Fedora (like most other distributions)
|
||||
heavily patch their kernel for better stability and more features.
|
||||
Unlike the other distributions however, Fedora does not pay attention to
|
||||
compatibility for external kernel drivers. This means that compiling rt2x00
|
||||
while using a Fedora kernel will result in compile errors regarding unknown
|
||||
fields in structures or problems with function arguments.
|
||||
For rt2x00 it is impossible to make all checks to support all Fedora kernel
|
||||
releases. This means that when rt2x00 compilation is failing while using a
|
||||
Fedora kernel we cannot give support for the compilation steps.
|
||||
We recommend the user to complain to the Fedora developers when this problem
|
||||
occurs.
|
||||
If the user has managed to compile rt2x00 for a Fedora kernel we will
|
||||
give support for possible problems while working with rt2x00. So the only
|
||||
part we do not support is the building of rt2x00.
|
||||
Please note that when you have edited the rt2x00 code to make it compile,
|
||||
it is advised to state those changes in bugreports while reporting other
|
||||
problems with rt2x00.
|
||||
|
||||
===================
|
||||
8.3: Gentoo
|
||||
=========
|
||||
|
||||
rt2x00 can also be found in portage, both the beta releases and the cvs tree.
|
||||
Because rt2x00 is still experimental these ebuild are still masked, this means
|
||||
that before you can emerge them they first have to be unmasked.
|
||||
Gentoo provides various instructions on how this can be done on their website.
|
||||
|
||||
===================
|
||||
8.4: Mandriva
|
||||
=========
|
||||
|
||||
In some instances installing the rt2x00 drivers on Mandriva will result
|
||||
in the problem that the files are being copied into the wrong folder,
|
||||
which results in the fact that the driver cannot be loaded.
|
||||
Installing the drivers should be done manually in this case,
|
||||
please refer to the distributions documentation regarding the proper
|
||||
location of the kernel modules.
|
||||
|
||||
|
||||
==============================================================================
|
||||
9: Problems & Troubleshooting
|
||||
=======================================
|
||||
|
||||
===================
|
||||
9.1: Debug information
|
||||
=========
|
||||
|
||||
When reporting problems make sure the driver has been compiled with debug
|
||||
enabled.
|
||||
If you have done so, the debug output can be found in the output
|
||||
of 'dmesg' and also in /var/log/messages and /var/log/syslog.
|
||||
|
||||
===================
|
||||
9.2: Debugfs
|
||||
=========
|
||||
|
||||
rt2x00 provides several debugfs entries which can be used to help
|
||||
provide more information about the interface.
|
||||
To see the rt2x00 debugfs entries, debugfs should first be mounted,
|
||||
to do this you should issue the following command:
|
||||
|
||||
# $ mount -t debugfs none /debug
|
||||
|
||||
Where /debug is the directy on which the debugfs entries should appear,
|
||||
make sure this directory exists when mounting debugfs.
|
||||
With the debugfs folder, the rt2x00 folder with the rt2x00 debugfs entries
|
||||
will be created. Within the rt2x00 folder, each physical device will be
|
||||
represented by a folder named after the interface which belongs to this
|
||||
device. Within the folder the following files can be found:
|
||||
|
||||
# register
|
||||
- This file contains the register contents of the interface.
|
||||
# eeprom
|
||||
- This file contains the eeprom contents of the interface.
|
||||
|
||||
===================
|
||||
9.3: Bug reporting
|
||||
=========
|
||||
|
||||
When reporting a bug or problem with the rt2x00 module,
|
||||
make sure you report the following information:
|
||||
# How to reproduce
|
||||
# RT2x00 debug output, usually found in /var/log/messages
|
||||
# Module version
|
||||
# Wireless card chipset, model and manufacturer
|
||||
# Kernel version (i.e. 2.6.17)
|
||||
# Hardware architecture (i.e. x86, AMD64, Sparc)
|
||||
# rt2x00 code changes done by the user
|
||||
# Anything else you may think will help us resolve the issue
|
||||
|
||||
|
||||
==============================================================================
|
||||
10: Problems & Workarounds
|
||||
=======================================
|
||||
|
||||
===================
|
||||
10.1: udev interface naming
|
||||
=========
|
||||
|
||||
In some cases when loading the rt2x00 drivers the interface names are
|
||||
different from the names used in this README. This is usually caused by the
|
||||
udev handler who has set some rules regarding the interface. These rules
|
||||
are usually set up by the distribution and have been created especially for
|
||||
for the legacy driver and their strange behavior.
|
||||
To change the rules udev applies to your interface you should edit the udev
|
||||
rules stored in /etc/udev/rules.d/ (exact location might be different
|
||||
depending on distribution).
|
||||
When editing this file, search for the line that contains something like this:
|
||||
|
||||
# ACTION=="add", SUBSYSTEM=="net", DRIVERS=="?*",
|
||||
# SYSFS{address}=="<mac address>", NAME="<interface>"
|
||||
(line has been wrapped due to max line length limit)
|
||||
|
||||
Where <mac address> is the hardware address of your wireless networkcard,
|
||||
and <interface> is the interface name the interface takes as soon as the
|
||||
rt2x00 modules are loaded.
|
||||
This line should be changed to look like:
|
||||
|
||||
# ACTION=="add", SUBSYSTEM=="net", DRIVERS=="?*",
|
||||
# SYSFS{address}=="<mac address>", SYSFS{type}=="801",
|
||||
# NAME="wmaster0"
|
||||
# ACTION=="add", SUBSYSTEM=="net", DRIVERS=="?*",
|
||||
# SYSFS{address}=="<mac address>", NAME="wlan0"
|
||||
(the 2 lines have been wrapped due to max line length limit)
|
||||
|
||||
Where <mac address> is the hardware address of your wireless networkcard,
|
||||
and thus should be the same as on the original line.
|
||||
|
||||
===================
|
||||
10.2: BUG - ifdown & ifup radio failure
|
||||
=========
|
||||
|
||||
It is a known issue (and BUG) that the driver will fail to correctly resume
|
||||
its radio operations after the interface has been brought down and up again.
|
||||
It is still unknown what the cause for this issue could be, besides the fact
|
||||
that for some reason the device's registers have been incorrectly initialized.
|
||||
This issue also has impact on the device status after a suspend/resume
|
||||
operation. There is no known workaround for this yet.
|
||||
|
||||
|
||||
==============================================================================
|
||||
11: TODO list
|
||||
=======================================
|
||||
See http://rt2x00.serialmonkey.com/wiki/index.php/Rt2x00_beta
|
||||
|
||||
==============================================================================
|
||||
12: Contact us
|
||||
=======================================
|
||||
|
||||
- Website
|
||||
# http://rt2x00.serialmonkey.com/
|
||||
# http://rt2x00.serialmonkey.com/wiki/index.php/Rt2x00_beta
|
||||
|
||||
- Forums:
|
||||
# http://rt2x00.serialmonkey.com/phpBB2/
|
||||
|
||||
- Mailing list:
|
||||
# general: rt2400-general@lists.sourceforge.net
|
||||
# developers: rt2400-devel@lists.sourceforge.net
|
||||
|
||||
- Sourceforge:
|
||||
# http://sourceforge.net/projects/rt2400
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
A big thanks to all the developers, testers and supporters of
|
||||
the rt2x00 Linux source code.
|
||||
|
||||
Thanks to the projects main developers:
|
||||
* Mark Wallis - mwallis@serialmonkey.com
|
||||
* Ivo van Doorn - IvDoorn@gmail.com
|
||||
* Luis Correia - lfcorreia@users.sf.net
|
||||
* Robin Cornelius - robin.cornelius@gmail.com
|
||||
* Gertjan van Wingerde - gwingerde@kpnplanet.nl
|
||||
* Romain - spy84464@hotmail.com
|
||||
|
||||
Special thanks to the contributors of this project:
|
||||
* Adisorn Ermongkonchai - moo7822-wlan@yahoo.com
|
||||
* Amir Shalem - amir@boom.org.il
|
||||
* Bernd Petrovitsch - bernd@firmix.at
|
||||
* Bruno - bruno123@users.sf.net
|
||||
* Chris Houston - chris.houston@atterotech.com
|
||||
* Defekt - defekt@liquid-nexus.net
|
||||
* Edvard - eaglenest@users.sourceforge.net
|
||||
* Flavio Stanchina - flavio@stanchina.net
|
||||
* Gregor Glomm - gg@seh.de
|
||||
* Heikki Pernu - heikki.pernu@nekonet.fi
|
||||
* Jerzy Kozera - nordom@tlen.pl
|
||||
* Joachim Gleißner - jg@suse.de
|
||||
* John Coppens - john@jcoppens.com
|
||||
* Jonathan Hudson
|
||||
* KrissN - krissn@op.pl
|
||||
* Luca Tettamanti - kronos.it@gmail.com
|
||||
* Magnus Damm - magnus.damm@gmail.com
|
||||
* Mags
|
||||
* Mathias Klien - ma_klein@gmx.de
|
||||
* Meelis Roos - mroos@linux.ee
|
||||
* Michal Ludvig - michal@logix.cz
|
||||
* Miguel - miguel.marte2@verizon.net
|
||||
* Mike Skinner
|
||||
* Olivier Cornu - o.cornu@gmail.com
|
||||
* Paul Hampson - Paul.Hampson@anu.edu.au
|
||||
* Philippe Rousselot - amazilia@users.sourceforge.net
|
||||
* Remco - remco@d-compu.dyndns.org
|
||||
* Sergey Vlasov - vsu@altlinux.ru
|
||||
* Stephen Warren - SWarren@nvidia.com
|
||||
* Stuart Rackham - srackham@methods.co.nz
|
||||
* Thor Harald Johansen - thorhajo@gmail.com
|
||||
* Tor Petterson - 2r@manowar.dk
|
||||
|
||||
Special thanks:
|
||||
* Ralink - http://www.ralinktech.com.tw
|
||||
For releasing their rt2400/rt2500/rt2570 drivers under the GPL,
|
||||
and their assistance in providing documentation to help development.
|
||||
* Minitar - www.minitar.com
|
||||
For working together with Ralink on releasing the
|
||||
rt2400/rt2500/rt2570 drivers under the GPL.
|
||||
* All the people that have assisted with the rt2400/rt2500/rt2570 source
|
||||
and hence progressed the rt2x00 along the way.
|
|
@ -0,0 +1,41 @@
|
|||
# rt2x00 configuration
|
||||
# All configuration options can be enabled
|
||||
# by setting the value to 'y'. To disable
|
||||
# the option it should be set to 'n'.
|
||||
|
||||
#
|
||||
# RT2X00 generic support
|
||||
#
|
||||
|
||||
# Enable rt2x00 support
|
||||
CONFIG_RT2X00=y
|
||||
# Enable rt2x00 debug output
|
||||
CONFIG_RT2X00_DEBUG=y
|
||||
# Enable rt2x00 debugfs support
|
||||
CONFIG_RT2X00_DEBUGFS=n
|
||||
# Enable rt2x00 asm file creation
|
||||
CONFIG_RT2X00_ASM=n
|
||||
|
||||
#
|
||||
# RT2X00 driver support
|
||||
#
|
||||
# Enable rt2400pci support
|
||||
CONFIG_RT2400PCI=y
|
||||
# Enable rt2400pci hardware button support (requires rfkill)
|
||||
CONFIG_RT2400PCI_BUTTON=n
|
||||
|
||||
# Enable rt2500pci support
|
||||
CONFIG_RT2500PCI=y
|
||||
# Enable rt2500pci hardware button support (requires rfkill)
|
||||
CONFIG_RT2500PCI_BUTTON=n
|
||||
|
||||
# Enable rt2500usb support
|
||||
CONFIG_RT2500USB=y
|
||||
|
||||
# Enable rt61pci support
|
||||
CONFIG_RT61PCI=y
|
||||
# Enable rt61pci hardware button support (requires rfkill)
|
||||
CONFIG_RT61PCI_BUTTON=n
|
||||
|
||||
# Enable rt73usb support
|
||||
CONFIG_RT73USB=y
|
|
@ -42,6 +42,7 @@
|
|||
#include <asm/io.h>
|
||||
|
||||
#include "rt2x00.h"
|
||||
#include "rt2x00lib.h"
|
||||
#include "rt2x00pci.h"
|
||||
#include "rt2400pci.h"
|
||||
|
||||
|
@ -614,7 +615,7 @@ static void rt2400pci_disable_led(struct rt2x00_dev *rt2x00dev)
|
|||
/*
|
||||
* Link tuning
|
||||
*/
|
||||
static void rt2400pci_link_tuner(struct rt2x00_dev *rt2x00dev, int rssi)
|
||||
static void rt2400pci_link_tuner(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
u8 reg;
|
||||
char false_cca_delta;
|
||||
|
@ -623,7 +624,7 @@ static void rt2400pci_link_tuner(struct rt2x00_dev *rt2x00dev, int rssi)
|
|||
* The link tuner should not run longer then 60 seconds,
|
||||
* and should run once every 2 seconds.
|
||||
*/
|
||||
if (rt2x00dev->link.count > 60 || !(rt2x00dev->link.count % 1))
|
||||
if (rt2x00dev->link.count > 60 || !(rt2x00dev->link.count & 1))
|
||||
return;
|
||||
|
||||
/*
|
||||
|
@ -649,6 +650,7 @@ static void rt2400pci_link_tuner(struct rt2x00_dev *rt2x00dev, int rssi)
|
|||
reg += 2;
|
||||
if (reg < 0x20)
|
||||
rt2400pci_bbp_write(rt2x00dev, 13, reg);
|
||||
rt2x00dev->rx_status.noise = reg;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -926,10 +928,34 @@ static void rt2400pci_toggle_rx(struct rt2x00_dev *rt2x00dev,
|
|||
rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
|
||||
}
|
||||
|
||||
static int rt2400pci_enable_radio(struct rt2x00_dev *rt2x00dev)
|
||||
static void rt2400pci_toggle_irq(struct rt2x00_dev *rt2x00dev, int enabled)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
/*
|
||||
* When interrupts are being enabled, the interrupt registers
|
||||
* should clear the register to assure a clean state.
|
||||
*/
|
||||
if (enabled) {
|
||||
rt2x00pci_register_read(rt2x00dev, CSR7, ®);
|
||||
rt2x00pci_register_write(rt2x00dev, CSR7, reg);
|
||||
}
|
||||
|
||||
/*
|
||||
* Only toggle the interrupts bits we are going to use.
|
||||
* Non-checked interrupt bits are disabled by default.
|
||||
*/
|
||||
rt2x00pci_register_read(rt2x00dev, CSR8, ®);
|
||||
rt2x00_set_field32(®, CSR8_TBCN_EXPIRE, !enabled);
|
||||
rt2x00_set_field32(®, CSR8_TXDONE_TXRING, !enabled);
|
||||
rt2x00_set_field32(®, CSR8_TXDONE_ATIMRING, !enabled);
|
||||
rt2x00_set_field32(®, CSR8_TXDONE_PRIORING, !enabled);
|
||||
rt2x00_set_field32(®, CSR8_RXDONE, !enabled);
|
||||
rt2x00pci_register_write(rt2x00dev, CSR8, reg);
|
||||
}
|
||||
|
||||
static int rt2400pci_enable_radio(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
/*
|
||||
* Initialize all registers.
|
||||
*/
|
||||
|
@ -940,22 +966,10 @@ static int rt2400pci_enable_radio(struct rt2x00_dev *rt2x00dev)
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear interrupts.
|
||||
*/
|
||||
rt2x00pci_register_read(rt2x00dev, CSR7, ®);
|
||||
rt2x00pci_register_write(rt2x00dev, CSR7, reg);
|
||||
|
||||
/*
|
||||
* Enable interrupts.
|
||||
*/
|
||||
rt2x00pci_register_read(rt2x00dev, CSR8, ®);
|
||||
rt2x00_set_field32(®, CSR8_TBCN_EXPIRE, 0);
|
||||
rt2x00_set_field32(®, CSR8_TXDONE_TXRING, 0);
|
||||
rt2x00_set_field32(®, CSR8_TXDONE_ATIMRING, 0);
|
||||
rt2x00_set_field32(®, CSR8_TXDONE_PRIORING, 0);
|
||||
rt2x00_set_field32(®, CSR8_RXDONE, 0);
|
||||
rt2x00pci_register_write(rt2x00dev, CSR8, reg);
|
||||
rt2400pci_toggle_irq(rt2x00dev, 1);
|
||||
|
||||
/*
|
||||
* Enable LED
|
||||
|
@ -991,13 +1005,7 @@ static void rt2400pci_disable_radio(struct rt2x00_dev *rt2x00dev)
|
|||
/*
|
||||
* Disable interrupts.
|
||||
*/
|
||||
rt2x00pci_register_read(rt2x00dev, CSR8, ®);
|
||||
rt2x00_set_field32(®, CSR8_TBCN_EXPIRE, 1);
|
||||
rt2x00_set_field32(®, CSR8_TXDONE_TXRING, 1);
|
||||
rt2x00_set_field32(®, CSR8_TXDONE_ATIMRING, 1);
|
||||
rt2x00_set_field32(®, CSR8_TXDONE_PRIORING, 1);
|
||||
rt2x00_set_field32(®, CSR8_RXDONE, 1);
|
||||
rt2x00pci_register_write(rt2x00dev, CSR8, reg);
|
||||
rt2400pci_toggle_irq(rt2x00dev, 0);
|
||||
}
|
||||
|
||||
static int rt2400pci_set_state(struct rt2x00_dev *rt2x00dev,
|
||||
|
@ -1163,59 +1171,40 @@ static void rt2400pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, int queue)
|
|||
}
|
||||
|
||||
/*
|
||||
* Interrupt functions.
|
||||
* RX control handlers
|
||||
*/
|
||||
static void rt2400pci_rxdone(struct rt2x00_dev *rt2x00dev)
|
||||
static int rt2400pci_fill_rxdone(struct data_entry *entry,
|
||||
int *signal, int *rssi, int *ofdm)
|
||||
{
|
||||
struct data_ring *ring = rt2x00dev->rx;
|
||||
struct data_entry *entry;
|
||||
struct data_desc *rxd;
|
||||
struct data_desc *rxd = entry->priv;
|
||||
u32 word0;
|
||||
u32 word2;
|
||||
int signal;
|
||||
int rssi;
|
||||
u16 size;
|
||||
|
||||
while (1) {
|
||||
entry = rt2x00_get_data_entry(ring);
|
||||
rxd = entry->priv;
|
||||
rt2x00_desc_read(rxd, 0, &word0);
|
||||
rt2x00_desc_read(rxd, 2, &word2);
|
||||
|
||||
if (rt2x00_get_field32(word0, RXD_W0_OWNER_NIC))
|
||||
break;
|
||||
|
||||
/*
|
||||
* TODO: Don't we need to keep statistics
|
||||
* updated about events like CRC and physical errors?
|
||||
* updated about these errors?
|
||||
*/
|
||||
if (rt2x00_get_field32(word0, RXD_W0_CRC) ||
|
||||
rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR))
|
||||
goto skip_entry;
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Obtain the status about this packet.
|
||||
*/
|
||||
size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
|
||||
signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL);
|
||||
rssi = rt2x00_get_field32(word2, RXD_W2_RSSI);
|
||||
*signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL);
|
||||
*rssi = rt2x00_get_field32(word2, RXD_W2_RSSI) -
|
||||
entry->ring->rt2x00dev->rssi_offset;
|
||||
*ofdm = 0;
|
||||
|
||||
return rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send the packet to upper layer.
|
||||
* Interrupt functions.
|
||||
*/
|
||||
rt2x00lib_rxdone(entry, entry->data_addr, size,
|
||||
signal, rssi, 0);
|
||||
|
||||
skip_entry:
|
||||
if (test_bit(DEVICE_ENABLED_RADIO, &ring->rt2x00dev->flags)) {
|
||||
rt2x00_set_field32(&word0, RXD_W0_OWNER_NIC, 1);
|
||||
rt2x00_desc_write(rxd, 0, word0);
|
||||
}
|
||||
|
||||
rt2x00_ring_index_inc(ring);
|
||||
}
|
||||
}
|
||||
|
||||
static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev, const int queue)
|
||||
{
|
||||
struct data_ring *ring = rt2x00_get_ring(rt2x00dev, queue);
|
||||
|
@ -1296,7 +1285,7 @@ static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance)
|
|||
* 2 - Rx ring done interrupt.
|
||||
*/
|
||||
if (rt2x00_get_field32(reg, CSR7_RXDONE))
|
||||
rt2400pci_rxdone(rt2x00dev);
|
||||
rt2x00pci_rxdone(rt2x00dev);
|
||||
|
||||
/*
|
||||
* 3 - Atim ring transmit done interrupt.
|
||||
|
@ -1327,6 +1316,7 @@ static int rt2400pci_alloc_eeprom(struct rt2x00_dev *rt2x00dev)
|
|||
struct eeprom_93cx6 eeprom;
|
||||
u32 reg;
|
||||
u16 word;
|
||||
u8 *mac;
|
||||
|
||||
/*
|
||||
* Allocate the eeprom memory, check the eeprom width
|
||||
|
@ -1354,6 +1344,12 @@ static int rt2400pci_alloc_eeprom(struct rt2x00_dev *rt2x00dev)
|
|||
/*
|
||||
* Start validation of the data that has been read.
|
||||
*/
|
||||
mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
|
||||
if (!is_valid_ether_addr(mac)) {
|
||||
random_ether_addr(mac);
|
||||
EEPROM(rt2x00dev, "MAC: " MAC_FMT "\n", MAC_ARG(mac));
|
||||
}
|
||||
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
|
||||
if (word == 0xffff) {
|
||||
ERROR(rt2x00dev, "Invalid EEPROM data detected.\n");
|
||||
|
@ -1440,16 +1436,16 @@ static void rt2400pci_init_hw_mode(struct rt2x00_dev *rt2x00dev)
|
|||
IEEE80211_HW_WEP_INCLUDE_IV |
|
||||
IEEE80211_HW_DATA_NULLFUNC_ACK |
|
||||
IEEE80211_HW_NO_TKIP_WMM_HWACCEL |
|
||||
IEEE80211_HW_MONITOR_DURING_OPER;
|
||||
IEEE80211_HW_MONITOR_DURING_OPER |
|
||||
IEEE80211_HW_NO_PROBE_FILTERING;
|
||||
rt2x00dev->hw->extra_tx_headroom = 0;
|
||||
rt2x00dev->hw->max_rssi = MAX_RX_SSI;
|
||||
rt2x00dev->hw->max_noise = MAX_RX_NOISE;
|
||||
rt2x00dev->hw->queues = 2;
|
||||
|
||||
/*
|
||||
* This device supports ATIM
|
||||
*/
|
||||
__set_bit(DEVICE_SUPPORT_ATIM, &rt2x00dev->flags);
|
||||
SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_pci(rt2x00dev)->dev);
|
||||
SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
|
||||
rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0));
|
||||
|
||||
/*
|
||||
* Set device specific, but channel independent RF values.
|
||||
|
@ -1470,7 +1466,6 @@ static void rt2400pci_init_hw_mode(struct rt2x00_dev *rt2x00dev)
|
|||
/*
|
||||
* Initialize hw_mode information.
|
||||
*/
|
||||
spec->mac_addr = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
|
||||
spec->num_modes = 1;
|
||||
spec->num_rates = 4;
|
||||
spec->num_channels = 14;
|
||||
|
@ -1501,6 +1496,16 @@ static int rt2400pci_init_hw(struct rt2x00_dev *rt2x00dev)
|
|||
*/
|
||||
rt2400pci_init_hw_mode(rt2x00dev);
|
||||
|
||||
/*
|
||||
* This device supports ATIM
|
||||
*/
|
||||
__set_bit(DEVICE_SUPPORT_ATIM, &rt2x00dev->flags);
|
||||
|
||||
/*
|
||||
* Set the rssi offset.
|
||||
*/
|
||||
rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1599,8 +1604,6 @@ static int rt2400pci_tx_last_beacon(struct ieee80211_hw *hw)
|
|||
static const struct ieee80211_ops rt2400pci_mac80211_ops = {
|
||||
.tx = rt2x00lib_tx,
|
||||
.reset = rt2x00lib_reset,
|
||||
.open = rt2x00lib_open,
|
||||
.stop = rt2x00lib_stop,
|
||||
.add_interface = rt2x00lib_add_interface,
|
||||
.remove_interface = rt2x00lib_remove_interface,
|
||||
.config = rt2x00lib_config,
|
||||
|
@ -1629,6 +1632,7 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {
|
|||
.write_tx_desc = rt2400pci_write_tx_desc,
|
||||
.write_tx_data = rt2x00pci_write_tx_data,
|
||||
.kick_tx_queue = rt2400pci_kick_tx_queue,
|
||||
.fill_rxdone = rt2400pci_fill_rxdone,
|
||||
.config_type = rt2400pci_config_type,
|
||||
.config_phymode = rt2400pci_config_phymode,
|
||||
.config_channel = rt2400pci_config_channel,
|
||||
|
@ -1679,14 +1683,11 @@ static struct pci_driver rt2400pci_driver = {
|
|||
|
||||
static int __init rt2400pci_init(void)
|
||||
{
|
||||
printk(KERN_INFO "Loading module: %s - %s by %s.\n",
|
||||
DRV_NAME, DRV_VERSION, DRV_PROJECT);
|
||||
return pci_register_driver(&rt2400pci_driver);
|
||||
}
|
||||
|
||||
static void __exit rt2400pci_exit(void)
|
||||
{
|
||||
printk(KERN_INFO "Unloading module: %s.\n", DRV_NAME);
|
||||
pci_unregister_driver(&rt2400pci_driver);
|
||||
}
|
||||
|
||||
|
|
|
@ -34,10 +34,11 @@
|
|||
#define RF2421 0x0001
|
||||
|
||||
/*
|
||||
* Max RSSI value, required for RSSI <-> dBm conversion.
|
||||
* Signal information.
|
||||
*/
|
||||
#define MAX_RX_SSI 100
|
||||
#define MAX_RX_SSI -1
|
||||
#define MAX_RX_NOISE -110
|
||||
#define DEFAULT_RSSI_OFFSET 100
|
||||
|
||||
/*
|
||||
* Register layout information.
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include <asm/io.h>
|
||||
|
||||
#include "rt2x00.h"
|
||||
#include "rt2x00lib.h"
|
||||
#include "rt2x00pci.h"
|
||||
#include "rt2500pci.h"
|
||||
|
||||
|
@ -368,6 +369,7 @@ static void rt2500pci_config_channel(struct rt2x00_dev *rt2x00dev,
|
|||
u32 rf2 = value;
|
||||
u32 rf3 = rt2x00dev->rf3;
|
||||
u32 rf4 = rt2x00dev->rf4;
|
||||
u8 r70;
|
||||
|
||||
if (rt2x00_rf(&rt2x00dev->chip, RF2525) ||
|
||||
rt2x00_rf(&rt2x00dev->chip, RF2525E))
|
||||
|
@ -435,7 +437,9 @@ static void rt2500pci_config_channel(struct rt2x00_dev *rt2x00dev,
|
|||
/*
|
||||
* Channel 14 requires the Japan filter bit to be set.
|
||||
*/
|
||||
rt2500pci_bbp_write(rt2x00dev, 70, (channel == 14) ? 0x4e : 0x46);
|
||||
r70 = 0x46;
|
||||
rt2x00_set_field8(&r70, BBP_R70_JAPAN_FILTER, channel == 14);
|
||||
rt2500pci_bbp_write(rt2x00dev, 70, r70);
|
||||
|
||||
msleep(1);
|
||||
|
||||
|
@ -692,8 +696,9 @@ static void rt2500pci_disable_led(struct rt2x00_dev *rt2x00dev)
|
|||
/*
|
||||
* Link tuning
|
||||
*/
|
||||
static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev, int rssi)
|
||||
static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
int rssi = rt2x00_get_link_rssi(&rt2x00dev->link);
|
||||
u32 reg;
|
||||
u8 r17;
|
||||
|
||||
|
@ -722,7 +727,7 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev, int rssi)
|
|||
*/
|
||||
if (rssi < -80 && rt2x00dev->link.count > 20) {
|
||||
if (r17 >= 0x41) {
|
||||
r17 = rt2x00dev->link.curr_noise;
|
||||
r17 = rt2x00dev->rx_status.noise;
|
||||
rt2500pci_bbp_write(rt2x00dev, 17, r17);
|
||||
}
|
||||
return;
|
||||
|
@ -751,7 +756,7 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev, int rssi)
|
|||
* to the dynamic tuning range.
|
||||
*/
|
||||
if (r17 >= 0x41) {
|
||||
rt2500pci_bbp_write(rt2x00dev, 17, rt2x00dev->link.curr_noise);
|
||||
rt2500pci_bbp_write(rt2x00dev, 17, rt2x00dev->rx_status.noise);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -766,10 +771,10 @@ dynamic_cca_tune:
|
|||
|
||||
if (rt2x00dev->link.false_cca > 512 && r17 < 0x40) {
|
||||
rt2500pci_bbp_write(rt2x00dev, 17, ++r17);
|
||||
rt2x00dev->link.curr_noise = r17;
|
||||
rt2x00dev->rx_status.noise = r17;
|
||||
} else if (rt2x00dev->link.false_cca < 100 && r17 > 0x32) {
|
||||
rt2500pci_bbp_write(rt2x00dev, 17, --r17);
|
||||
rt2x00dev->link.curr_noise = r17;
|
||||
rt2x00dev->rx_status.noise = r17;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -898,7 +903,16 @@ static int rt2500pci_init_registers(struct rt2x00_dev *rt2x00dev)
|
|||
return -EBUSY;
|
||||
|
||||
rt2x00pci_register_write(rt2x00dev, PWRCSR0, 0x3f3b3100);
|
||||
rt2x00pci_register_write(rt2x00dev, PCICSR, 0x000003b8);
|
||||
|
||||
rt2x00pci_register_read(rt2x00dev, PCICSR, ®);
|
||||
rt2x00_set_field32(®, PCICSR_BIG_ENDIAN, 0);
|
||||
rt2x00_set_field32(®, PCICSR_RX_TRESHOLD, 0);
|
||||
rt2x00_set_field32(®, PCICSR_TX_TRESHOLD, 3);
|
||||
rt2x00_set_field32(®, PCICSR_BURST_LENTH, 1);
|
||||
rt2x00_set_field32(®, PCICSR_ENABLE_CLK, 1);
|
||||
rt2x00_set_field32(®, PCICSR_READ_MULTIPLE, 1);
|
||||
rt2x00_set_field32(®, PCICSR_WRITE_INVALID, 1);
|
||||
rt2x00pci_register_write(rt2x00dev, PCICSR, reg);
|
||||
|
||||
rt2x00pci_register_write(rt2x00dev, PSCSR0, 0x00020002);
|
||||
rt2x00pci_register_write(rt2x00dev, PSCSR1, 0x00000002);
|
||||
|
@ -1079,10 +1093,34 @@ static void rt2500pci_toggle_rx(struct rt2x00_dev *rt2x00dev,
|
|||
rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
|
||||
}
|
||||
|
||||
static int rt2500pci_enable_radio(struct rt2x00_dev *rt2x00dev)
|
||||
static void rt2500pci_toggle_irq(struct rt2x00_dev *rt2x00dev, int enabled)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
/*
|
||||
* When interrupts are being enabled, the interrupt registers
|
||||
* should clear the register to assure a clean state.
|
||||
*/
|
||||
if (enabled) {
|
||||
rt2x00pci_register_read(rt2x00dev, CSR7, ®);
|
||||
rt2x00pci_register_write(rt2x00dev, CSR7, reg);
|
||||
}
|
||||
|
||||
/*
|
||||
* Only toggle the interrupts bits we are going to use.
|
||||
* Non-checked interrupt bits are disabled by default.
|
||||
*/
|
||||
rt2x00pci_register_read(rt2x00dev, CSR8, ®);
|
||||
rt2x00_set_field32(®, CSR8_TBCN_EXPIRE, !enabled);
|
||||
rt2x00_set_field32(®, CSR8_TXDONE_TXRING, !enabled);
|
||||
rt2x00_set_field32(®, CSR8_TXDONE_ATIMRING, !enabled);
|
||||
rt2x00_set_field32(®, CSR8_TXDONE_PRIORING, !enabled);
|
||||
rt2x00_set_field32(®, CSR8_RXDONE, !enabled);
|
||||
rt2x00pci_register_write(rt2x00dev, CSR8, reg);
|
||||
}
|
||||
|
||||
static int rt2500pci_enable_radio(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
/*
|
||||
* Initialize all registers.
|
||||
*/
|
||||
|
@ -1093,22 +1131,10 @@ static int rt2500pci_enable_radio(struct rt2x00_dev *rt2x00dev)
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear interrupts.
|
||||
*/
|
||||
rt2x00pci_register_read(rt2x00dev, CSR7, ®);
|
||||
rt2x00pci_register_write(rt2x00dev, CSR7, reg);
|
||||
|
||||
/*
|
||||
* Enable interrupts.
|
||||
*/
|
||||
rt2x00pci_register_read(rt2x00dev, CSR8, ®);
|
||||
rt2x00_set_field32(®, CSR8_TBCN_EXPIRE, 0);
|
||||
rt2x00_set_field32(®, CSR8_TXDONE_TXRING, 0);
|
||||
rt2x00_set_field32(®, CSR8_TXDONE_ATIMRING, 0);
|
||||
rt2x00_set_field32(®, CSR8_TXDONE_PRIORING, 0);
|
||||
rt2x00_set_field32(®, CSR8_RXDONE, 0);
|
||||
rt2x00pci_register_write(rt2x00dev, CSR8, reg);
|
||||
rt2500pci_toggle_irq(rt2x00dev, 1);
|
||||
|
||||
/*
|
||||
* Enable LED
|
||||
|
@ -1144,13 +1170,7 @@ static void rt2500pci_disable_radio(struct rt2x00_dev *rt2x00dev)
|
|||
/*
|
||||
* Disable interrupts.
|
||||
*/
|
||||
rt2x00pci_register_read(rt2x00dev, CSR8, ®);
|
||||
rt2x00_set_field32(®, CSR8_TBCN_EXPIRE, 1);
|
||||
rt2x00_set_field32(®, CSR8_TXDONE_TXRING, 1);
|
||||
rt2x00_set_field32(®, CSR8_TXDONE_ATIMRING, 1);
|
||||
rt2x00_set_field32(®, CSR8_TXDONE_PRIORING, 1);
|
||||
rt2x00_set_field32(®, CSR8_RXDONE, 1);
|
||||
rt2x00pci_register_write(rt2x00dev, CSR8, reg);
|
||||
rt2500pci_toggle_irq(rt2x00dev, 0);
|
||||
}
|
||||
|
||||
static int rt2500pci_set_state(struct rt2x00_dev *rt2x00dev,
|
||||
|
@ -1300,61 +1320,37 @@ static void rt2500pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, int queue)
|
|||
}
|
||||
|
||||
/*
|
||||
* Interrupt functions.
|
||||
* RX control handlers
|
||||
*/
|
||||
static void rt2500pci_rxdone(struct rt2x00_dev *rt2x00dev)
|
||||
static int rt2500pci_fill_rxdone(struct data_entry *entry,
|
||||
int *signal, int *rssi, int *ofdm)
|
||||
{
|
||||
struct data_ring *ring = rt2x00dev->rx;
|
||||
struct data_entry *entry;
|
||||
struct data_desc *rxd;
|
||||
struct data_desc *rxd = entry->priv;
|
||||
u32 word0;
|
||||
u32 word2;
|
||||
int signal;
|
||||
int rssi;
|
||||
int ofdm;
|
||||
u16 size;
|
||||
|
||||
while (1) {
|
||||
entry = rt2x00_get_data_entry(ring);
|
||||
rxd = entry->priv;
|
||||
rt2x00_desc_read(rxd, 0, &word0);
|
||||
rt2x00_desc_read(rxd, 2, &word2);
|
||||
|
||||
if (rt2x00_get_field32(word0, RXD_W0_OWNER_NIC))
|
||||
break;
|
||||
|
||||
/*
|
||||
* TODO: Don't we need to keep statistics
|
||||
* updated about events like CRC and physical errors?
|
||||
* updated about these errors?
|
||||
*/
|
||||
if (rt2x00_get_field32(word0, RXD_W0_CRC) ||
|
||||
rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR))
|
||||
goto skip_entry;
|
||||
return -EINVAL;
|
||||
|
||||
*signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL);
|
||||
*rssi = rt2x00_get_field32(word2, RXD_W2_RSSI) -
|
||||
entry->ring->rt2x00dev->rssi_offset;
|
||||
*ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM);
|
||||
|
||||
return rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
|
||||
}
|
||||
|
||||
/*
|
||||
* Obtain the status about this packet.
|
||||
* Interrupt functions.
|
||||
*/
|
||||
size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
|
||||
signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL);
|
||||
rssi = rt2x00_get_field32(word2, RXD_W2_RSSI);
|
||||
ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM);
|
||||
|
||||
/*
|
||||
* Send the packet to upper layer.
|
||||
*/
|
||||
rt2x00lib_rxdone(entry, entry->data_addr, size,
|
||||
signal, rssi, ofdm);
|
||||
|
||||
skip_entry:
|
||||
if (test_bit(DEVICE_ENABLED_RADIO, &ring->rt2x00dev->flags)) {
|
||||
rt2x00_set_field32(&word0, RXD_W0_OWNER_NIC, 1);
|
||||
rt2x00_desc_write(rxd, 0, word0);
|
||||
}
|
||||
|
||||
rt2x00_ring_index_inc(ring);
|
||||
}
|
||||
}
|
||||
|
||||
static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev, const int queue)
|
||||
{
|
||||
struct data_ring *ring = rt2x00_get_ring(rt2x00dev, queue);
|
||||
|
@ -1435,7 +1431,7 @@ static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance)
|
|||
* 2 - Rx ring done interrupt.
|
||||
*/
|
||||
if (rt2x00_get_field32(reg, CSR7_RXDONE))
|
||||
rt2500pci_rxdone(rt2x00dev);
|
||||
rt2x00pci_rxdone(rt2x00dev);
|
||||
|
||||
/*
|
||||
* 3 - Atim ring transmit done interrupt.
|
||||
|
@ -1466,6 +1462,7 @@ static int rt2500pci_alloc_eeprom(struct rt2x00_dev *rt2x00dev)
|
|||
struct eeprom_93cx6 eeprom;
|
||||
u32 reg;
|
||||
u16 word;
|
||||
u8 *mac;
|
||||
|
||||
/*
|
||||
* Allocate the eeprom memory, check the eeprom width
|
||||
|
@ -1493,6 +1490,12 @@ static int rt2500pci_alloc_eeprom(struct rt2x00_dev *rt2x00dev)
|
|||
/*
|
||||
* Start validation of the data that has been read.
|
||||
*/
|
||||
mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
|
||||
if (!is_valid_ether_addr(mac)) {
|
||||
random_ether_addr(mac);
|
||||
EEPROM(rt2x00dev, "MAC: " MAC_FMT "\n", MAC_ARG(mac));
|
||||
}
|
||||
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
|
||||
if (word == 0xffff) {
|
||||
rt2x00_set_field16(&word, EEPROM_ANTENNA_NUM, 2);
|
||||
|
@ -1518,7 +1521,7 @@ static int rt2500pci_alloc_eeprom(struct rt2x00_dev *rt2x00dev)
|
|||
rt2x00_eeprom_read(rt2x00dev, EEPROM_CALIBRATE_OFFSET, &word);
|
||||
if (word == 0xffff) {
|
||||
rt2x00_set_field16(&word, EEPROM_CALIBRATE_OFFSET_RSSI,
|
||||
MAX_RX_SSI);
|
||||
DEFAULT_RSSI_OFFSET);
|
||||
rt2x00_eeprom_write(rt2x00dev, EEPROM_CALIBRATE_OFFSET, word);
|
||||
EEPROM(rt2x00dev, "Calibrate offset: 0x%04x\n", word);
|
||||
}
|
||||
|
@ -1586,7 +1589,7 @@ static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
|
|||
* Read the RSSI <-> dBm offset information.
|
||||
*/
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_CALIBRATE_OFFSET, &eeprom);
|
||||
rt2x00dev->hw->max_rssi =
|
||||
rt2x00dev->rssi_offset =
|
||||
rt2x00_get_field16(eeprom, EEPROM_CALIBRATE_OFFSET_RSSI);
|
||||
|
||||
return 0;
|
||||
|
@ -1660,16 +1663,16 @@ static void rt2500pci_init_hw_mode(struct rt2x00_dev *rt2x00dev)
|
|||
IEEE80211_HW_WEP_INCLUDE_IV |
|
||||
IEEE80211_HW_DATA_NULLFUNC_ACK |
|
||||
IEEE80211_HW_NO_TKIP_WMM_HWACCEL |
|
||||
IEEE80211_HW_MONITOR_DURING_OPER;
|
||||
IEEE80211_HW_MONITOR_DURING_OPER |
|
||||
IEEE80211_HW_NO_PROBE_FILTERING;
|
||||
rt2x00dev->hw->extra_tx_headroom = 0;
|
||||
rt2x00dev->hw->max_rssi = MAX_RX_SSI;
|
||||
rt2x00dev->hw->max_noise = MAX_RX_NOISE;
|
||||
rt2x00dev->hw->queues = 2;
|
||||
|
||||
/*
|
||||
* This device supports ATIM
|
||||
*/
|
||||
__set_bit(DEVICE_SUPPORT_ATIM, &rt2x00dev->flags);
|
||||
SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_pci(rt2x00dev)->dev);
|
||||
SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
|
||||
rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0));
|
||||
|
||||
/*
|
||||
* Set device specific, but channel independent RF values.
|
||||
|
@ -1692,7 +1695,6 @@ static void rt2500pci_init_hw_mode(struct rt2x00_dev *rt2x00dev)
|
|||
/*
|
||||
* Initialize hw_mode information.
|
||||
*/
|
||||
spec->mac_addr = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
|
||||
spec->num_modes = 2;
|
||||
spec->num_rates = 12;
|
||||
spec->num_channels = 14;
|
||||
|
@ -1738,6 +1740,11 @@ static int rt2500pci_init_hw(struct rt2x00_dev *rt2x00dev)
|
|||
*/
|
||||
rt2500pci_init_hw_mode(rt2x00dev);
|
||||
|
||||
/*
|
||||
* This device supports ATIM
|
||||
*/
|
||||
__set_bit(DEVICE_SUPPORT_ATIM, &rt2x00dev->flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1812,8 +1819,6 @@ static int rt2500pci_tx_last_beacon(struct ieee80211_hw *hw)
|
|||
static const struct ieee80211_ops rt2500pci_mac80211_ops = {
|
||||
.tx = rt2x00lib_tx,
|
||||
.reset = rt2x00lib_reset,
|
||||
.open = rt2x00lib_open,
|
||||
.stop = rt2x00lib_stop,
|
||||
.add_interface = rt2x00lib_add_interface,
|
||||
.remove_interface = rt2x00lib_remove_interface,
|
||||
.config = rt2x00lib_config,
|
||||
|
@ -1842,6 +1847,7 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {
|
|||
.write_tx_desc = rt2500pci_write_tx_desc,
|
||||
.write_tx_data = rt2x00pci_write_tx_data,
|
||||
.kick_tx_queue = rt2500pci_kick_tx_queue,
|
||||
.fill_rxdone = rt2500pci_fill_rxdone,
|
||||
.config_type = rt2500pci_config_type,
|
||||
.config_phymode = rt2500pci_config_phymode,
|
||||
.config_channel = rt2500pci_config_channel,
|
||||
|
@ -1892,14 +1898,11 @@ static struct pci_driver rt2500pci_driver = {
|
|||
|
||||
static int __init rt2500pci_init(void)
|
||||
{
|
||||
printk(KERN_INFO "Loading module: %s - %s by %s.\n",
|
||||
DRV_NAME, DRV_VERSION, DRV_PROJECT);
|
||||
return pci_register_driver(&rt2500pci_driver);
|
||||
}
|
||||
|
||||
static void __exit rt2500pci_exit(void)
|
||||
{
|
||||
printk(KERN_INFO "Unloading module: %s.\n", DRV_NAME);
|
||||
pci_unregister_driver(&rt2500pci_driver);
|
||||
}
|
||||
|
||||
|
|
|
@ -45,10 +45,11 @@
|
|||
#define RT2560_VERSION_D 4
|
||||
|
||||
/*
|
||||
* Max RSSI value, required for RSSI <-> dBm conversion.
|
||||
* Signal information.
|
||||
*/
|
||||
#define MAX_RX_SSI 121
|
||||
#define MAX_RX_SSI -1
|
||||
#define MAX_RX_NOISE -110
|
||||
#define DEFAULT_RSSI_OFFSET 121
|
||||
|
||||
/*
|
||||
* Register layout information.
|
||||
|
@ -1045,6 +1046,11 @@
|
|||
#define BBP_R14_RX_ANTENNA FIELD8(0x03)
|
||||
#define BBP_R14_RX_IQ_FLIP FIELD8(0x04)
|
||||
|
||||
/*
|
||||
* BBP_R70
|
||||
*/
|
||||
#define BBP_R70_JAPAN_FILTER FIELD8(0x08)
|
||||
|
||||
/*
|
||||
* DMA descriptor defines.
|
||||
*/
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include <linux/etherdevice.h>
|
||||
|
||||
#include "rt2x00.h"
|
||||
#include "rt2x00lib.h"
|
||||
#include "rt2x00usb.h"
|
||||
#include "rt2500usb.h"
|
||||
|
||||
|
@ -638,8 +639,9 @@ static void rt2500usb_disable_led(struct rt2x00_dev *rt2x00dev)
|
|||
/*
|
||||
* Link tuning
|
||||
*/
|
||||
static void rt2500usb_link_tuner(struct rt2x00_dev *rt2x00dev, int rssi)
|
||||
static void rt2500usb_link_tuner(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
int rssi = rt2x00_get_link_rssi(&rt2x00dev->link);
|
||||
u16 bbp_thresh;
|
||||
u16 cca_alarm;
|
||||
u16 vgc_bound;
|
||||
|
@ -734,62 +736,19 @@ static void rt2500usb_link_tuner(struct rt2x00_dev *rt2x00dev, int rssi)
|
|||
|
||||
if (r17 > up_bound) {
|
||||
rt2500usb_bbp_write(rt2x00dev, 17, up_bound);
|
||||
rt2x00dev->link.curr_noise = up_bound;
|
||||
rt2x00dev->rx_status.noise = up_bound;
|
||||
} else if (cca_alarm > 512 && r17 < up_bound) {
|
||||
rt2500usb_bbp_write(rt2x00dev, 17, ++r17);
|
||||
rt2x00dev->link.curr_noise = r17;
|
||||
rt2x00dev->rx_status.noise = r17;
|
||||
} else if (cca_alarm < 100 && r17 > low_bound) {
|
||||
rt2500usb_bbp_write(rt2x00dev, 17, --r17);
|
||||
rt2x00dev->link.curr_noise = r17;
|
||||
rt2x00dev->rx_status.noise = r17;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialization functions.
|
||||
*/
|
||||
static void rt2500usb_init_rxring(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
struct usb_device *usb_dev =
|
||||
interface_to_usbdev(rt2x00dev_usb(rt2x00dev));
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < rt2x00dev->rx->stats.limit; i++) {
|
||||
usb_fill_bulk_urb(
|
||||
rt2x00dev->rx->entry[i].priv,
|
||||
usb_dev,
|
||||
usb_rcvbulkpipe(usb_dev, 1),
|
||||
rt2x00dev->rx->entry[i].skb->data,
|
||||
rt2x00dev->rx->entry[i].skb->len,
|
||||
rt2500usb_interrupt_rxdone,
|
||||
&rt2x00dev->rx->entry[i]);
|
||||
}
|
||||
|
||||
rt2x00_ring_index_clear(rt2x00dev->rx);
|
||||
}
|
||||
|
||||
static void rt2500usb_init_txring(struct rt2x00_dev *rt2x00dev,
|
||||
const int queue)
|
||||
{
|
||||
struct data_ring *ring = rt2x00_get_ring(rt2x00dev, queue);
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ring->stats.limit; i++)
|
||||
ring->entry[i].flags = 0;
|
||||
|
||||
rt2x00_ring_index_clear(ring);
|
||||
}
|
||||
|
||||
static int rt2500usb_init_rings(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
rt2500usb_init_rxring(rt2x00dev);
|
||||
rt2500usb_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_DATA0);
|
||||
rt2500usb_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_DATA1);
|
||||
rt2500usb_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_AFTER_BEACON);
|
||||
rt2500usb_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_BEACON);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rt2500usb_init_registers(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
u16 reg;
|
||||
|
@ -801,7 +760,10 @@ static int rt2500usb_init_registers(struct rt2x00_dev *rt2x00dev)
|
|||
USB_VENDOR_REQUEST_OUT, 0x0308, 0xf0, NULL, 0,
|
||||
REGISTER_TIMEOUT);
|
||||
|
||||
rt2500usb_register_write(rt2x00dev, TXRX_CSR2, 0x0001);
|
||||
rt2500usb_register_read(rt2x00dev, TXRX_CSR2, ®);
|
||||
rt2x00_set_field16(®, TXRX_CSR2_DISABLE_RX, 1);
|
||||
rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg);
|
||||
|
||||
rt2500usb_register_write(rt2x00dev, MAC_CSR13, 0x1111);
|
||||
rt2500usb_register_write(rt2x00dev, MAC_CSR14, 0x1e11);
|
||||
|
||||
|
@ -819,9 +781,7 @@ static int rt2500usb_init_registers(struct rt2x00_dev *rt2x00dev)
|
|||
|
||||
rt2500usb_register_write(rt2x00dev, MAC_CSR1, 0x0004);
|
||||
|
||||
reg = 0;
|
||||
rt2500usb_register_read(rt2x00dev, MAC_CSR0, ®);
|
||||
if (reg >= 0x0003) {
|
||||
if (rt2x00_rev(&rt2x00dev->chip) >= RT2570_VERSION_C) {
|
||||
rt2500usb_register_read(rt2x00dev, PHY_CSR2, ®);
|
||||
reg &= ~0x0002;
|
||||
} else {
|
||||
|
@ -962,8 +922,7 @@ static int rt2500usb_enable_radio(struct rt2x00_dev *rt2x00dev)
|
|||
/*
|
||||
* Initialize all registers.
|
||||
*/
|
||||
if (rt2500usb_init_rings(rt2x00dev) ||
|
||||
rt2500usb_init_registers(rt2x00dev) ||
|
||||
if (rt2500usb_init_registers(rt2x00dev) ||
|
||||
rt2500usb_init_bbp(rt2x00dev)) {
|
||||
ERROR(rt2x00dev, "Register initialization failed.\n");
|
||||
return -EIO;
|
||||
|
@ -1107,7 +1066,7 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
|
|||
rt2x00_set_field32(&word, TXD_W0_OFDM,
|
||||
test_bit(ENTRY_TXD_OFDM_RATE, &entry->flags));
|
||||
rt2x00_set_field32(&word, TXD_W0_NEW_SEQ,
|
||||
test_bit(ENTRY_TXD_NEW_SEQ, &entry->flags));
|
||||
control->flags & IEEE80211_TXCTL_FIRST_FRAGMENT);
|
||||
rt2x00_set_field32(&word, TXD_W0_IFS, desc->ifs);
|
||||
rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, length);
|
||||
rt2x00_set_field32(&word, TXD_W0_CIPHER, CIPHER_NONE);
|
||||
|
@ -1141,74 +1100,40 @@ static void rt2500usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, int queue)
|
|||
}
|
||||
|
||||
/*
|
||||
* Interrupt functions.
|
||||
* RX control handlers
|
||||
*/
|
||||
static void rt2500usb_interrupt_rxdone(struct urb *urb)
|
||||
static int rt2500usb_fill_rxdone(struct data_entry *entry,
|
||||
int *signal, int *rssi, int *ofdm)
|
||||
{
|
||||
struct data_entry *entry = (struct data_entry*)urb->context;
|
||||
struct data_ring *ring = entry->ring;
|
||||
struct rt2x00_dev *rt2x00dev = ring->rt2x00dev;
|
||||
struct data_desc *rxd = (struct data_desc*)
|
||||
(entry->skb->data + urb->actual_length - ring->desc_size);
|
||||
struct urb *urb = entry->priv;
|
||||
struct data_desc *rxd = (struct data_desc*)(entry->skb->data +
|
||||
(urb->actual_length - entry->ring->desc_size));
|
||||
u32 word0;
|
||||
u32 word1;
|
||||
int signal;
|
||||
int rssi;
|
||||
int ofdm;
|
||||
u16 size;
|
||||
|
||||
if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) ||
|
||||
!test_and_clear_bit(ENTRY_OWNER_NIC, &entry->flags))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Check if the received data is simply too small
|
||||
* to be actually valid, or if the urb is signaling
|
||||
* a problem.
|
||||
*/
|
||||
if (urb->actual_length < entry->ring->desc_size || urb->status)
|
||||
goto skip_entry;
|
||||
|
||||
rt2x00_desc_read(rxd, 0, &word0);
|
||||
rt2x00_desc_read(rxd, 1, &word1);
|
||||
|
||||
/*
|
||||
* TODO: Don't we need to keep statistics
|
||||
* updated about events like CRC and physical errors?
|
||||
* updated about these errors?
|
||||
*/
|
||||
if (rt2x00_get_field32(word0, RXD_W0_CRC) ||
|
||||
rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR))
|
||||
goto skip_entry;
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Obtain the status about this packet.
|
||||
*/
|
||||
size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT) - FCS_LEN;
|
||||
signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
|
||||
rssi = rt2x00_get_field32(word1, RXD_W1_RSSI);
|
||||
ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM);
|
||||
*signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
|
||||
*rssi = rt2x00_get_field32(word1, RXD_W1_RSSI) -
|
||||
entry->ring->rt2x00dev->rssi_offset;
|
||||
*ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM);
|
||||
|
||||
/*
|
||||
* Trim the skb_buffer to only contain the valid
|
||||
* frame data (so ignore the device's descriptor).
|
||||
* rt2570 includes the FCS, so fix data length accordingly.
|
||||
*/
|
||||
skb_trim(entry->skb, size);
|
||||
|
||||
/*
|
||||
* Send the packet to upper layer, and update urb.
|
||||
*/
|
||||
rt2x00lib_rxdone(entry, NULL, ring->data_size + ring->desc_size,
|
||||
signal, rssi, ofdm);
|
||||
urb->transfer_buffer = entry->skb->data;
|
||||
urb->transfer_buffer_length = entry->skb->len;
|
||||
|
||||
skip_entry:
|
||||
if (test_bit(DEVICE_ENABLED_RADIO, &ring->rt2x00dev->flags)) {
|
||||
__set_bit(ENTRY_OWNER_NIC, &entry->flags);
|
||||
usb_submit_urb(urb, GFP_ATOMIC);
|
||||
}
|
||||
|
||||
rt2x00_ring_index_inc(ring);
|
||||
return rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT) - FCS_LEN;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1217,6 +1142,7 @@ skip_entry:
|
|||
static int rt2500usb_alloc_eeprom(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
u16 word;
|
||||
u8 *mac;
|
||||
|
||||
/*
|
||||
* Allocate the eeprom memory, check the eeprom width
|
||||
|
@ -1234,6 +1160,12 @@ static int rt2500usb_alloc_eeprom(struct rt2x00_dev *rt2x00dev)
|
|||
/*
|
||||
* Start validation of the data that has been read.
|
||||
*/
|
||||
mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
|
||||
if (!is_valid_ether_addr(mac)) {
|
||||
random_ether_addr(mac);
|
||||
EEPROM(rt2x00dev, "MAC: " MAC_FMT "\n", MAC_ARG(mac));
|
||||
}
|
||||
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
|
||||
if (word == 0xffff) {
|
||||
rt2x00_set_field16(&word, EEPROM_ANTENNA_NUM, 2);
|
||||
|
@ -1259,7 +1191,7 @@ static int rt2500usb_alloc_eeprom(struct rt2x00_dev *rt2x00dev)
|
|||
rt2x00_eeprom_read(rt2x00dev, EEPROM_CALIBRATE_OFFSET, &word);
|
||||
if (word == 0xffff) {
|
||||
rt2x00_set_field16(&word, EEPROM_CALIBRATE_OFFSET_RSSI,
|
||||
MAX_RX_SSI);
|
||||
DEFAULT_RSSI_OFFSET);
|
||||
rt2x00_eeprom_write(rt2x00dev, EEPROM_CALIBRATE_OFFSET, word);
|
||||
EEPROM(rt2x00dev, "Calibrate offset: 0x%04x\n", word);
|
||||
}
|
||||
|
@ -1366,7 +1298,7 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
|
|||
* Read the RSSI <-> dBm offset information.
|
||||
*/
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_CALIBRATE_OFFSET, &eeprom);
|
||||
rt2x00dev->hw->max_rssi =
|
||||
rt2x00dev->rssi_offset =
|
||||
rt2x00_get_field16(eeprom, EEPROM_CALIBRATE_OFFSET_RSSI);
|
||||
|
||||
return 0;
|
||||
|
@ -1443,16 +1375,16 @@ static void rt2500usb_init_hw_mode(struct rt2x00_dev *rt2x00dev)
|
|||
IEEE80211_HW_WEP_INCLUDE_IV |
|
||||
IEEE80211_HW_DATA_NULLFUNC_ACK |
|
||||
IEEE80211_HW_NO_TKIP_WMM_HWACCEL |
|
||||
IEEE80211_HW_MONITOR_DURING_OPER;
|
||||
IEEE80211_HW_MONITOR_DURING_OPER |
|
||||
IEEE80211_HW_NO_PROBE_FILTERING;
|
||||
rt2x00dev->hw->extra_tx_headroom = TXD_DESC_SIZE;
|
||||
rt2x00dev->hw->max_rssi = MAX_RX_SSI;
|
||||
rt2x00dev->hw->max_noise = MAX_RX_NOISE;
|
||||
rt2x00dev->hw->queues = 2;
|
||||
|
||||
/*
|
||||
* This device supports ATIM
|
||||
*/
|
||||
__set_bit(DEVICE_SUPPORT_ATIM, &rt2x00dev->flags);
|
||||
SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_usb(rt2x00dev)->dev);
|
||||
SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
|
||||
rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0));
|
||||
|
||||
/*
|
||||
* Set device specific, but channel independent RF values.
|
||||
|
@ -1475,7 +1407,6 @@ static void rt2500usb_init_hw_mode(struct rt2x00_dev *rt2x00dev)
|
|||
/*
|
||||
* Initialize hw_mode information.
|
||||
*/
|
||||
spec->mac_addr = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
|
||||
spec->num_modes = 2;
|
||||
spec->num_rates = 12;
|
||||
spec->num_channels = 14;
|
||||
|
@ -1522,6 +1453,11 @@ static int rt2500usb_init_hw(struct rt2x00_dev *rt2x00dev)
|
|||
*/
|
||||
rt2500usb_init_hw_mode(rt2x00dev);
|
||||
|
||||
/*
|
||||
* This device supports ATIM
|
||||
*/
|
||||
__set_bit(DEVICE_SUPPORT_ATIM, &rt2x00dev->flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1551,8 +1487,6 @@ static int rt2500usb_get_stats(struct ieee80211_hw *hw,
|
|||
static const struct ieee80211_ops rt2500usb_mac80211_ops = {
|
||||
.tx = rt2x00lib_tx,
|
||||
.reset = rt2x00lib_reset,
|
||||
.open = rt2x00lib_open,
|
||||
.stop = rt2x00lib_stop,
|
||||
.add_interface = rt2x00lib_add_interface,
|
||||
.remove_interface = rt2x00lib_remove_interface,
|
||||
.config = rt2x00lib_config,
|
||||
|
@ -1573,6 +1507,7 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
|
|||
.write_tx_desc = rt2500usb_write_tx_desc,
|
||||
.write_tx_data = rt2x00usb_write_tx_data,
|
||||
.kick_tx_queue = rt2500usb_kick_tx_queue,
|
||||
.fill_rxdone = rt2500usb_fill_rxdone,
|
||||
.config_type = rt2500usb_config_type,
|
||||
.config_phymode = rt2500usb_config_phymode,
|
||||
.config_channel = rt2500usb_config_channel,
|
||||
|
@ -1665,14 +1600,11 @@ static struct usb_driver rt2500usb_driver = {
|
|||
|
||||
static int __init rt2500usb_init(void)
|
||||
{
|
||||
printk(KERN_INFO "Loading module: %s - %s by %s.\n",
|
||||
DRV_NAME, DRV_VERSION, DRV_PROJECT);
|
||||
return usb_register(&rt2500usb_driver);
|
||||
}
|
||||
|
||||
static void __exit rt2500usb_exit(void)
|
||||
{
|
||||
printk(KERN_INFO "Unloading module: %s.\n", DRV_NAME);
|
||||
usb_deregister(&rt2500usb_driver);
|
||||
}
|
||||
|
||||
|
|
|
@ -38,10 +38,18 @@
|
|||
#define RF5222 0x0010
|
||||
|
||||
/*
|
||||
* Max RSSI value, required for RSSI <-> dBm conversion.
|
||||
* RT2570 version
|
||||
*/
|
||||
#define MAX_RX_SSI 120
|
||||
#define RT2570_VERSION_B 2
|
||||
#define RT2570_VERSION_C 3
|
||||
#define RT2570_VERSION_D 4
|
||||
|
||||
/*
|
||||
* Signal information.
|
||||
*/
|
||||
#define MAX_RX_SSI -1
|
||||
#define MAX_RX_NOISE -110
|
||||
#define DEFAULT_RSSI_OFFSET 120
|
||||
|
||||
/*
|
||||
* Register layout information.
|
||||
|
@ -729,9 +737,4 @@
|
|||
(__txpower)); \
|
||||
})
|
||||
|
||||
/*
|
||||
* Interrupt functions.
|
||||
*/
|
||||
static void rt2500usb_interrupt_rxdone(struct urb *urb);
|
||||
|
||||
#endif /* RT2500USB_H */
|
||||
|
|
|
@ -29,21 +29,17 @@
|
|||
#define RT2X00_H
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/prefetch.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
#include <net/mac80211.h>
|
||||
|
||||
#include "rt2x00lib.h"
|
||||
#include "rt2x00debug.h"
|
||||
|
||||
/*
|
||||
* Module information.
|
||||
* DRV_NAME should be set within the individual module source files.
|
||||
*/
|
||||
#ifndef DRV_NAME
|
||||
#define DRV_NAME "rt2x00"
|
||||
#endif /* DRV_NAME */
|
||||
#define DRV_VERSION "2.0.1"
|
||||
#define DRV_VERSION "2.0.2"
|
||||
#define DRV_PROJECT "http://rt2x00.serialmonkey.com"
|
||||
|
||||
/*
|
||||
|
@ -142,7 +138,7 @@
|
|||
/*
|
||||
* Interval defines
|
||||
*/
|
||||
#define LINK_TUNE_INTERVAL ( 1 * HZ )
|
||||
#define LINK_TUNE_INTERVAL ( round_jiffies(HZ) )
|
||||
#define RFKILL_POLL_INTERVAL ( HZ / 4 )
|
||||
|
||||
/*
|
||||
|
@ -392,7 +388,6 @@ struct data_entry {
|
|||
#define ENTRY_TXD_MORE_FRAG 5
|
||||
#define ENTRY_TXD_REQ_TIMESTAMP 6
|
||||
#define ENTRY_TXD_REQ_ACK 7
|
||||
#define ENTRY_TXD_NEW_SEQ 8
|
||||
|
||||
/*
|
||||
* Ring we belong to.
|
||||
|
@ -569,17 +564,26 @@ struct link {
|
|||
*/
|
||||
u32 count;
|
||||
|
||||
/*
|
||||
* RSSI statistics.
|
||||
*/
|
||||
u32 count_rssi;
|
||||
u32 total_rssi;
|
||||
|
||||
/*
|
||||
* Misc statistics.
|
||||
* For the average RSSI value we use the "Walking average" approach.
|
||||
* When adding RSSI to the average value the following calculation
|
||||
* is needed:
|
||||
*
|
||||
* avg_rssi = ((avg_rssi * 7) + rssi) / 8;
|
||||
*
|
||||
* The advantage of this approach is that we only need 1 variable
|
||||
* to store the average in (No need for a count and a total).
|
||||
* But more importantly, normal average values will over time
|
||||
* move less and less towards newly added values.
|
||||
* This means that with link tuning, the device can have a very
|
||||
* good RSSI for a few minutes but when the device is moved away
|
||||
* from the AP the average will not decrease fast enough to
|
||||
* compensate. The walking average compensates this and will
|
||||
* move towards the new values correctly.
|
||||
*/
|
||||
u32 curr_noise;
|
||||
u32 false_cca;
|
||||
int avg_rssi;
|
||||
int false_cca;
|
||||
|
||||
/*
|
||||
* Work structure for scheduling periodic link tuning.
|
||||
|
@ -636,6 +640,33 @@ static inline int is_monitor_present(struct interface *intf)
|
|||
return !!intf->monitor_count;
|
||||
}
|
||||
|
||||
/*
|
||||
* Details about the supported modes, rates and channels
|
||||
* of a particular chipset. This is used by rt2x00lib
|
||||
* to build the ieee80211_hw_mode array for mac80211.
|
||||
*/
|
||||
struct hw_mode_spec {
|
||||
/*
|
||||
* Number of modes, rates and channels.
|
||||
*/
|
||||
int num_modes;
|
||||
int num_rates;
|
||||
int num_channels;
|
||||
|
||||
/*
|
||||
* txpower values.
|
||||
*/
|
||||
const u8 *tx_power_a;
|
||||
const u8 *tx_power_bg;
|
||||
u8 tx_power_default;
|
||||
|
||||
/*
|
||||
* Device/chipset specific value.
|
||||
*/
|
||||
const u32 *chan_val_a;
|
||||
const u32 *chan_val_bg;
|
||||
};
|
||||
|
||||
/*
|
||||
* rt2x00lib callback functions.
|
||||
*/
|
||||
|
@ -665,7 +696,7 @@ struct rt2x00lib_ops {
|
|||
int (*set_device_state)(struct rt2x00_dev *rt2x00dev,
|
||||
enum dev_state state);
|
||||
int (*rfkill_poll)(struct rt2x00_dev *rt2x00dev);
|
||||
void (*link_tuner)(struct rt2x00_dev *rt2x00dev, int rssi);
|
||||
void (*link_tuner)(struct rt2x00_dev *rt2x00dev);
|
||||
|
||||
/*
|
||||
* TX control handlers
|
||||
|
@ -680,6 +711,12 @@ struct rt2x00lib_ops {
|
|||
struct ieee80211_tx_control *control);
|
||||
void (*kick_tx_queue)(struct rt2x00_dev *rt2x00dev, int queue);
|
||||
|
||||
/*
|
||||
* RX control handlers
|
||||
*/
|
||||
int (*fill_rxdone)(struct data_entry *entry,
|
||||
int *signal, int *rssi, int *ofdm);
|
||||
|
||||
/*
|
||||
* Configuration handlers.
|
||||
*/
|
||||
|
@ -723,7 +760,6 @@ struct rt2x00_dev {
|
|||
* macro's should be used for correct typecasting.
|
||||
*/
|
||||
void *dev;
|
||||
struct device *device;
|
||||
#define rt2x00dev_pci(__dev) ( (struct pci_dev*)(__dev)->dev )
|
||||
#define rt2x00dev_usb(__dev) ( (struct usb_interface*)(__dev)->dev )
|
||||
|
||||
|
@ -796,12 +832,9 @@ struct rt2x00_dev {
|
|||
* If enabled, the debugfs interface structures
|
||||
* required for deregistration of debugfs.
|
||||
*/
|
||||
#ifdef CONFIG_RT2X00_LIB_DEBUGFS
|
||||
const struct rt2x00debug_intf *debugfs_intf;
|
||||
|
||||
/*
|
||||
* Queue for deferred work.
|
||||
*/
|
||||
struct workqueue_struct *workqueue;
|
||||
#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
|
||||
|
||||
/*
|
||||
* Interface configuration.
|
||||
|
@ -844,9 +877,9 @@ struct rt2x00_dev {
|
|||
u8 led_mode;
|
||||
|
||||
/*
|
||||
* EEPROM bus width (PCI devices only).
|
||||
* Rssi <-> Dbm offset
|
||||
*/
|
||||
u8 eeprom_width;
|
||||
u8 rssi_offset;
|
||||
|
||||
/*
|
||||
* Frequency offset (for rt61pci & rt73usb).
|
||||
|
@ -907,14 +940,22 @@ static inline struct data_ring* rt2x00_get_ring(
|
|||
* The 1 + Atim check will assure that the address directly after
|
||||
* the ring array is obtained and the for-each loop exits correctly.
|
||||
*/
|
||||
#define ring_end(__dev) \
|
||||
&(__dev)->bcn[1 + test_bit(DEVICE_SUPPORT_ATIM, &rt2x00dev->flags)]
|
||||
|
||||
#define ring_loop(__entry, __start, __end) \
|
||||
for ((__entry) = (__start); \
|
||||
prefetch(&(__entry)[1]), (__entry) != (__end); \
|
||||
(__entry) = &(__entry)[1])
|
||||
|
||||
#define ring_for_each(__dev, __entry) \
|
||||
for ((__entry) = (__dev)->rx; \
|
||||
(__entry) != &(__dev)->bcn[1 + \
|
||||
test_bit(DEVICE_SUPPORT_ATIM, &rt2x00dev->flags)]; \
|
||||
(__entry)++)
|
||||
ring_loop(__entry, (__dev)->rx, ring_end(__dev))
|
||||
|
||||
#define txring_for_each(__dev, __entry) \
|
||||
for ((__entry) = (__dev)->tx; (__entry) != (__dev)->bcn; (__entry)++)
|
||||
ring_loop(__entry, (__dev)->tx, (__dev)->bcn)
|
||||
|
||||
#define txringall_for_each(__dev, __entry) \
|
||||
ring_loop(__entry, (__dev)->tx, ring_end(__dev))
|
||||
|
||||
/*
|
||||
* EEPROM access.
|
||||
|
@ -944,11 +985,10 @@ static inline void rt2x00_eeprom_write(const struct rt2x00_dev *rt2x00dev,
|
|||
static inline void rt2x00_start_link_tune(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
rt2x00dev->link.count = 0;
|
||||
rt2x00dev->link.count_rssi = 0;
|
||||
rt2x00dev->link.total_rssi = 0;
|
||||
rt2x00dev->link.curr_noise = 0;
|
||||
rt2x00dev->link.avg_rssi = 0;
|
||||
rt2x00dev->link.false_cca = 0;
|
||||
|
||||
queue_delayed_work(rt2x00dev->workqueue,
|
||||
queue_delayed_work(rt2x00dev->hw->workqueue,
|
||||
&rt2x00dev->link.work, LINK_TUNE_INTERVAL);
|
||||
}
|
||||
|
||||
|
@ -956,26 +996,20 @@ static inline void rt2x00_stop_link_tune(struct rt2x00_dev *rt2x00dev)
|
|||
{
|
||||
if (work_pending(&rt2x00dev->link.work.work))
|
||||
cancel_rearming_delayed_workqueue(
|
||||
rt2x00dev->workqueue, &rt2x00dev->link.work);
|
||||
rt2x00dev->hw->workqueue, &rt2x00dev->link.work);
|
||||
}
|
||||
|
||||
static inline void rt2x00_update_link_rssi(struct link *link, u32 rssi)
|
||||
static inline void rt2x00_update_link_rssi(struct link *link, int rssi)
|
||||
{
|
||||
link->count_rssi++;
|
||||
link->total_rssi += rssi;
|
||||
if (!link->avg_rssi)
|
||||
link->avg_rssi = rssi;
|
||||
else
|
||||
link->avg_rssi = ((link->avg_rssi * 7) + rssi) / 8;
|
||||
}
|
||||
|
||||
static inline u32 rt2x00_get_link_rssi(struct link *link)
|
||||
static inline int rt2x00_get_link_rssi(struct link *link)
|
||||
{
|
||||
u32 average = 0;
|
||||
|
||||
if (link->count_rssi && link->total_rssi)
|
||||
average = link->total_rssi / link->count_rssi;
|
||||
|
||||
link->count_rssi = 0;
|
||||
link->total_rssi = 0;
|
||||
|
||||
return average;
|
||||
return link->avg_rssi;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -51,6 +51,12 @@
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#if (defined(CONFIG_RT2X00_DEBUGFS))
|
||||
#if (!defined(CONFIG_MAC80211_DEBUGFS) && !defined(CONFIG_MAC80211_DEBUGFS_MODULE))
|
||||
#error mac80211 debugfs support has been disabled in your kernel!
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if (defined(CONFIG_RT2400PCI_BUTTON) || defined(CONFIG_RT2500PCI_BUTTON) || defined(CONFIG_RT61PCI_BUTTON))
|
||||
#if (!defined(CONFIG_RFKILL) && !defined (CONFIG_RFKILL_MODULE))
|
||||
#error RFKILL has been disabled in your kernel!
|
||||
|
|
|
@ -1,44 +0,0 @@
|
|||
#ifndef CONFIG_RT2X00
|
||||
#define CONFIG_RT2X00
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_RT2X00_DEBUG
|
||||
#define CONFIG_RT2X00_DEBUG
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_RT2X00_DEBUGFS
|
||||
#define CONFIG_RT2X00_DEBUGFS
|
||||
#endif
|
||||
|
||||
#undef CONFIG_RT2X00_ASM
|
||||
|
||||
#ifndef CONFIG_RT2X00_LIB_FIRMWARE
|
||||
#define CONFIG_RT2X00_LIB_FIRMWARE
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_RT2400PCI
|
||||
#define CONFIG_RT2400PCI
|
||||
#endif
|
||||
|
||||
#undef CONFIG_RT2400PCI_BUTTON
|
||||
|
||||
#ifndef CONFIG_RT2500PCI
|
||||
#define CONFIG_RT2500PCI
|
||||
#endif
|
||||
|
||||
#undef CONFIG_RT2500PCI_BUTTON
|
||||
|
||||
#ifndef CONFIG_RT2500USB
|
||||
#define CONFIG_RT2500USB
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_RT61PCI
|
||||
#define CONFIG_RT61PCI
|
||||
#endif
|
||||
|
||||
#undef CONFIG_RT61PCI_BUTTON
|
||||
|
||||
#ifndef CONFIG_RT73USB
|
||||
#define CONFIG_RT73USB
|
||||
#endif
|
||||
|
|
@ -30,6 +30,7 @@
|
|||
#include <asm/uaccess.h>
|
||||
|
||||
#include "rt2x00.h"
|
||||
#include "rt2x00debug.h"
|
||||
|
||||
#define PRINT_REG8_STR ( "0x%.2x\n" )
|
||||
#define PRINT_REG16_STR ( "0x%.4x\n" )
|
||||
|
|
|
@ -28,8 +28,6 @@
|
|||
#ifndef RT2X00DEBUG_H
|
||||
#define RT2X00DEBUG_H
|
||||
|
||||
#include <net/wireless.h>
|
||||
|
||||
typedef void (debug_access_t)(struct rt2x00_dev *rt2x00dev,
|
||||
const unsigned long word, void *data);
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include <linux/etherdevice.h>
|
||||
|
||||
#include "rt2x00.h"
|
||||
#include "rt2x00lib.h"
|
||||
#include "rt2x00dev.h"
|
||||
|
||||
/*
|
||||
|
@ -67,6 +68,9 @@ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev)
|
|||
|
||||
ieee80211_start_queues(rt2x00dev->hw);
|
||||
|
||||
if (is_interface_present(&rt2x00dev->interface))
|
||||
rt2x00_start_link_tune(rt2x00dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -75,6 +79,8 @@ void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev)
|
|||
if (!__test_and_clear_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
|
||||
return;
|
||||
|
||||
rt2x00_stop_link_tune(rt2x00dev);
|
||||
|
||||
ieee80211_stop_queues(rt2x00dev->hw);
|
||||
|
||||
rt2x00lib_toggle_rx(rt2x00dev, 0);
|
||||
|
@ -87,7 +93,7 @@ void rt2x00lib_toggle_rx(struct rt2x00_dev *rt2x00dev, int enable)
|
|||
/*
|
||||
* When we are disabling the rx, we should also stop the link tuner.
|
||||
*/
|
||||
if (!enable && work_pending(&rt2x00dev->link.work.work))
|
||||
if (!enable)
|
||||
rt2x00_stop_link_tune(rt2x00dev);
|
||||
|
||||
rt2x00dev->ops->lib->set_device_state(rt2x00dev,
|
||||
|
@ -96,7 +102,7 @@ void rt2x00lib_toggle_rx(struct rt2x00_dev *rt2x00dev, int enable)
|
|||
/*
|
||||
* When we are enabling the rx, we should also start the link tuner.
|
||||
*/
|
||||
if (enable)
|
||||
if (enable && is_interface_present(&rt2x00dev->interface))
|
||||
rt2x00_start_link_tune(rt2x00dev);
|
||||
}
|
||||
|
||||
|
@ -104,7 +110,6 @@ static void rt2x00lib_link_tuner(struct work_struct *work)
|
|||
{
|
||||
struct rt2x00_dev *rt2x00dev =
|
||||
container_of(work, struct rt2x00_dev, link.work.work);
|
||||
int rssi;
|
||||
|
||||
/*
|
||||
* Update promisc mode (this function will first check
|
||||
|
@ -119,20 +124,13 @@ static void rt2x00lib_link_tuner(struct work_struct *work)
|
|||
if (test_bit(CONFIG_DISABLE_LINK_TUNING, &rt2x00dev->flags))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Retrieve link quality.
|
||||
* Also convert rssi to dBm using the max_rssi value.
|
||||
*/
|
||||
rssi = rt2x00_get_link_rssi(&rt2x00dev->link);
|
||||
rssi -= rt2x00dev->hw->max_rssi;
|
||||
|
||||
rt2x00dev->ops->lib->link_tuner(rt2x00dev, rssi);
|
||||
rt2x00dev->ops->lib->link_tuner(rt2x00dev);
|
||||
|
||||
/*
|
||||
* Increase tuner counter, and reschedule the next link tuner run.
|
||||
*/
|
||||
rt2x00dev->link.count++;
|
||||
queue_delayed_work(rt2x00dev->workqueue, &rt2x00dev->link.work,
|
||||
queue_delayed_work(rt2x00dev->hw->workqueue, &rt2x00dev->link.work,
|
||||
LINK_TUNE_INTERVAL);
|
||||
}
|
||||
|
||||
|
@ -422,23 +420,6 @@ static int rt2x00lib_init_hw(struct rt2x00_dev *rt2x00dev)
|
|||
struct hw_mode_spec *spec = &rt2x00dev->spec;
|
||||
int status;
|
||||
|
||||
/*
|
||||
* Initialize device.
|
||||
*/
|
||||
SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->device);
|
||||
|
||||
/*
|
||||
* Initialize MAC address.
|
||||
*/
|
||||
if (!is_valid_ether_addr(spec->mac_addr)) {
|
||||
ERROR(rt2x00dev, "Invalid MAC addr: " MAC_FMT ".\n",
|
||||
MAC_ARG(spec->mac_addr));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rt2x00dev->ops->lib->config_mac_addr(rt2x00dev, spec->mac_addr);
|
||||
SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, spec->mac_addr);
|
||||
|
||||
/*
|
||||
* Initialize HW modes.
|
||||
*/
|
||||
|
@ -463,7 +444,7 @@ static int rt2x00lib_init_hw(struct rt2x00_dev *rt2x00dev)
|
|||
/*
|
||||
* Initialization/uninitialization handlers.
|
||||
*/
|
||||
static int rt2x00lib_alloc_ring(struct data_ring *ring,
|
||||
static int rt2x00lib_alloc_ring_entries(struct data_ring *ring,
|
||||
const u16 max_entries, const u16 data_size, const u16 desc_size)
|
||||
{
|
||||
struct data_entry *entry;
|
||||
|
@ -491,14 +472,14 @@ static int rt2x00lib_alloc_ring(struct data_ring *ring,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int rt2x00lib_allocate_rings(struct rt2x00_dev *rt2x00dev)
|
||||
static int rt2x00lib_allocate_ring_entries(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
struct data_ring *ring;
|
||||
|
||||
/*
|
||||
* Allocate the RX ring.
|
||||
*/
|
||||
if (rt2x00lib_alloc_ring(rt2x00dev->rx,
|
||||
if (rt2x00lib_alloc_ring_entries(rt2x00dev->rx,
|
||||
RX_ENTRIES, DATA_FRAME_SIZE, rt2x00dev->ops->rxd_size))
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -506,7 +487,7 @@ static int rt2x00lib_allocate_rings(struct rt2x00_dev *rt2x00dev)
|
|||
* First allocate the TX rings.
|
||||
*/
|
||||
txring_for_each(rt2x00dev, ring) {
|
||||
if (rt2x00lib_alloc_ring(ring,
|
||||
if (rt2x00lib_alloc_ring_entries(ring,
|
||||
TX_ENTRIES, DATA_FRAME_SIZE, rt2x00dev->ops->txd_size))
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
@ -514,7 +495,7 @@ static int rt2x00lib_allocate_rings(struct rt2x00_dev *rt2x00dev)
|
|||
/*
|
||||
* Allocate the BEACON ring.
|
||||
*/
|
||||
if (rt2x00lib_alloc_ring(&rt2x00dev->bcn[0],
|
||||
if (rt2x00lib_alloc_ring_entries(&rt2x00dev->bcn[0],
|
||||
BEACON_ENTRIES, MGMT_FRAME_SIZE, rt2x00dev->ops->txd_size))
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -522,7 +503,7 @@ static int rt2x00lib_allocate_rings(struct rt2x00_dev *rt2x00dev)
|
|||
* Allocate the Atim ring.
|
||||
*/
|
||||
if (test_bit(DEVICE_SUPPORT_ATIM, &rt2x00dev->flags)) {
|
||||
if (rt2x00lib_alloc_ring(&rt2x00dev->bcn[1],
|
||||
if (rt2x00lib_alloc_ring_entries(&rt2x00dev->bcn[1],
|
||||
ATIM_ENTRIES, DATA_FRAME_SIZE, rt2x00dev->ops->txd_size))
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
@ -530,7 +511,7 @@ static int rt2x00lib_allocate_rings(struct rt2x00_dev *rt2x00dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void rt2x00lib_free_rings(struct rt2x00_dev *rt2x00dev)
|
||||
static void rt2x00lib_free_ring_entries(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
struct data_ring *ring;
|
||||
|
||||
|
@ -550,7 +531,7 @@ int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev)
|
|||
/*
|
||||
* Allocate all data rings.
|
||||
*/
|
||||
status = rt2x00lib_allocate_rings(rt2x00dev);
|
||||
status = rt2x00lib_allocate_ring_entries(rt2x00dev);
|
||||
if (status) {
|
||||
ERROR(rt2x00dev, "DMA allocation failed.\n");
|
||||
return status;
|
||||
|
@ -578,7 +559,7 @@ exit_unitialize:
|
|||
rt2x00lib_uninitialize(rt2x00dev);
|
||||
|
||||
exit:
|
||||
rt2x00lib_free_rings(rt2x00dev);
|
||||
rt2x00lib_free_ring_entries(rt2x00dev);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
@ -588,11 +569,6 @@ void rt2x00lib_uninitialize(struct rt2x00_dev *rt2x00dev)
|
|||
if (!__test_and_clear_bit(DEVICE_INITIALIZED, &rt2x00dev->flags))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Flush out all pending work.
|
||||
*/
|
||||
flush_workqueue(rt2x00dev->workqueue);
|
||||
|
||||
/*
|
||||
* Unregister rfkill.
|
||||
*/
|
||||
|
@ -606,7 +582,7 @@ void rt2x00lib_uninitialize(struct rt2x00_dev *rt2x00dev)
|
|||
/*
|
||||
* Free allocated datarings.
|
||||
*/
|
||||
rt2x00lib_free_rings(rt2x00dev);
|
||||
rt2x00lib_free_ring_entries(rt2x00dev);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -659,13 +635,6 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
|
|||
{
|
||||
int retval = -ENOMEM;
|
||||
|
||||
/*
|
||||
* Create workqueue.
|
||||
*/
|
||||
rt2x00dev->workqueue = create_singlethread_workqueue(DRV_NAME);
|
||||
if (!rt2x00dev->workqueue)
|
||||
goto exit;
|
||||
|
||||
/*
|
||||
* Let the driver probe the device to detect the capabilities.
|
||||
*/
|
||||
|
@ -763,14 +732,6 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev)
|
|||
*/
|
||||
rt2x00lib_deinit_hw(rt2x00dev);
|
||||
|
||||
/*
|
||||
* Free workqueue.
|
||||
*/
|
||||
if (likely(rt2x00dev->workqueue)) {
|
||||
destroy_workqueue(rt2x00dev->workqueue);
|
||||
rt2x00dev->workqueue = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free ring structures.
|
||||
*/
|
||||
|
@ -824,13 +785,6 @@ int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev)
|
|||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set device mode to awake for power management.
|
||||
*/
|
||||
retval = rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2x00lib_resume);
|
||||
|
@ -914,6 +868,7 @@ void rt2x00lib_rxdone(struct data_entry *entry, char *data,
|
|||
*/
|
||||
if (signal & 0x08)
|
||||
val = rate->val2;
|
||||
else
|
||||
val = rate->val;
|
||||
break;
|
||||
}
|
||||
|
@ -921,7 +876,6 @@ void rt2x00lib_rxdone(struct data_entry *entry, char *data,
|
|||
|
||||
rx_status->rate = val;
|
||||
rx_status->ssi = rssi;
|
||||
rx_status->noise = rt2x00dev->link.curr_noise;
|
||||
rt2x00_update_link_rssi(&rt2x00dev->link, rssi);
|
||||
|
||||
/*
|
||||
|
@ -1001,12 +955,6 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev,
|
|||
if (ieee80211_get_morefrag(ieee80211hdr))
|
||||
__set_bit(ENTRY_TXD_MORE_FRAG, &entry->flags);
|
||||
|
||||
/*
|
||||
* Check if this is a new sequence
|
||||
*/
|
||||
if ((seq_ctrl & IEEE80211_SCTL_FRAG) == 0)
|
||||
__set_bit(ENTRY_TXD_NEW_SEQ, &entry->flags);
|
||||
|
||||
/*
|
||||
* Beacons and probe responses require the tsf timestamp
|
||||
* to be inserted into the frame.
|
||||
|
|
|
@ -29,10 +29,12 @@
|
|||
*/
|
||||
#define DRV_NAME "rt2x00lib"
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/crc-itu-t.h>
|
||||
#include <linux/firmware.h>
|
||||
|
||||
#include "rt2x00.h"
|
||||
#include "rt2x00lib.h"
|
||||
#include "rt2x00firmware.h"
|
||||
|
||||
static void rt2x00lib_load_firmware_continued(const struct firmware *fw,
|
||||
|
@ -90,12 +92,17 @@ int rt2x00lib_load_firmware(struct rt2x00_dev *rt2x00dev)
|
|||
* Read correct firmware from harddisk.
|
||||
*/
|
||||
fw_name = rt2x00dev->ops->lib->get_fw_name(rt2x00dev);
|
||||
BUG_ON(fw_name == NULL);
|
||||
if (!fw_name) {
|
||||
ERROR(rt2x00dev,
|
||||
"Invalid firmware filename.\n"
|
||||
"Please file bug report to %s.\n", DRV_PROJECT);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
INFO(rt2x00dev, "Loading firmware file '%s'.\n", fw_name);
|
||||
|
||||
status = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
|
||||
fw_name, rt2x00dev->device, rt2x00dev,
|
||||
fw_name, wiphy_dev(rt2x00dev->hw->wiphy), rt2x00dev,
|
||||
&rt2x00lib_load_firmware_continued);
|
||||
|
||||
if (status)
|
||||
|
|
|
@ -28,43 +28,6 @@
|
|||
#ifndef RT2X00LIB_H
|
||||
#define RT2X00LIB_H
|
||||
|
||||
struct rt2x00_dev;
|
||||
struct data_desc;
|
||||
struct data_entry_desc;
|
||||
struct data_entry;
|
||||
|
||||
/*
|
||||
* Details about the supported modes, rates and channels
|
||||
* of a particular chipset. This is used by rt2x00lib
|
||||
* to build the ieee80211_hw_mode array for mac80211.
|
||||
*/
|
||||
struct hw_mode_spec {
|
||||
/*
|
||||
* Default mac address.
|
||||
*/
|
||||
char *mac_addr;
|
||||
|
||||
/*
|
||||
* Number of modes, rates and channels.
|
||||
*/
|
||||
int num_modes;
|
||||
int num_rates;
|
||||
int num_channels;
|
||||
|
||||
/*
|
||||
* txpower values.
|
||||
*/
|
||||
const u8 *tx_power_a;
|
||||
const u8 *tx_power_bg;
|
||||
u8 tx_power_default;
|
||||
|
||||
/*
|
||||
* Device/chipset specific value.
|
||||
*/
|
||||
const u32 *chan_val_a;
|
||||
const u32 *chan_val_bg;
|
||||
};
|
||||
|
||||
/*
|
||||
* Driver allocation handlers.
|
||||
*/
|
||||
|
@ -99,8 +62,6 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev,
|
|||
int rt2x00lib_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||
struct ieee80211_tx_control *control);
|
||||
int rt2x00lib_reset(struct ieee80211_hw *hw);
|
||||
int rt2x00lib_open(struct ieee80211_hw *hw);
|
||||
int rt2x00lib_stop(struct ieee80211_hw *hw);
|
||||
int rt2x00lib_add_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_if_init_conf *conf);
|
||||
void rt2x00lib_remove_interface(struct ieee80211_hw *hw,
|
||||
|
@ -115,4 +76,6 @@ int rt2x00lib_get_tx_stats(struct ieee80211_hw *hw,
|
|||
int rt2x00lib_conf_tx(struct ieee80211_hw *hw, int queue,
|
||||
const struct ieee80211_tx_queue_params *params);
|
||||
|
||||
#include "rt2x00debug.h"
|
||||
|
||||
#endif /* RT2X00LIB_H */
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include <linux/netdevice.h>
|
||||
|
||||
#include "rt2x00.h"
|
||||
#include "rt2x00lib.h"
|
||||
#include "rt2x00dev.h"
|
||||
|
||||
static int rt2x00_tx_rts_cts(struct rt2x00_dev *rt2x00dev,
|
||||
|
@ -129,60 +130,18 @@ int rt2x00lib_reset(struct ieee80211_hw *hw)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(rt2x00lib_reset);
|
||||
|
||||
int rt2x00lib_open(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rt2x00_dev *rt2x00dev = hw->priv;
|
||||
int status;
|
||||
|
||||
/*
|
||||
* We must wait on the firmware before
|
||||
* we can safely continue.
|
||||
*/
|
||||
status = rt2x00lib_load_firmware_wait(rt2x00dev);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
/*
|
||||
* Initialize the device.
|
||||
*/
|
||||
status = rt2x00lib_initialize(rt2x00dev);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
/*
|
||||
* Enable radio.
|
||||
*/
|
||||
status = rt2x00lib_enable_radio(rt2x00dev);
|
||||
if (status) {
|
||||
rt2x00lib_uninitialize(rt2x00dev);
|
||||
return status;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2x00lib_open);
|
||||
|
||||
int rt2x00lib_stop(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rt2x00_dev *rt2x00dev = hw->priv;
|
||||
|
||||
rt2x00lib_disable_radio(rt2x00dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2x00lib_stop);
|
||||
|
||||
int rt2x00lib_add_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_if_init_conf *conf)
|
||||
{
|
||||
struct rt2x00_dev *rt2x00dev = hw->priv;
|
||||
struct interface *intf = &rt2x00dev->interface;
|
||||
int status;
|
||||
|
||||
/*
|
||||
* We only support 1 non-monitor interface.
|
||||
*/
|
||||
if (conf->type != IEEE80211_IF_TYPE_MNTR &&
|
||||
is_interface_present(&rt2x00dev->interface))
|
||||
is_interface_present(intf))
|
||||
return -ENOBUFS;
|
||||
|
||||
/*
|
||||
|
@ -200,17 +159,39 @@ int rt2x00lib_add_interface(struct ieee80211_hw *hw,
|
|||
}
|
||||
|
||||
/*
|
||||
* If this is the first interface which is being added,
|
||||
* we should write the MAC address to the device.
|
||||
* Initialize interface, and enable the radio when this
|
||||
* is the first interface that is brought up.
|
||||
*/
|
||||
if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
|
||||
rt2x00dev->ops->lib->config_mac_addr(rt2x00dev, conf->mac_addr);
|
||||
if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags)) {
|
||||
/*
|
||||
* We must wait on the firmware before
|
||||
* we can safely continue.
|
||||
*/
|
||||
status = rt2x00lib_load_firmware_wait(rt2x00dev);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
/*
|
||||
* Enable periodic link tuning if this is a non-monitor interface.
|
||||
* Before initialization, the mac address should
|
||||
* be configured.
|
||||
*/
|
||||
if (conf->type != IEEE80211_IF_TYPE_MNTR)
|
||||
rt2x00_start_link_tune(rt2x00dev);
|
||||
rt2x00dev->ops->lib->config_mac_addr(rt2x00dev,
|
||||
conf->mac_addr);
|
||||
|
||||
/*
|
||||
* Initialize the device.
|
||||
*/
|
||||
status = rt2x00lib_initialize(rt2x00dev);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
/*
|
||||
* Enable radio.
|
||||
*/
|
||||
status = rt2x00lib_enable_radio(rt2x00dev);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -226,12 +207,12 @@ void rt2x00lib_remove_interface(struct ieee80211_hw *hw,
|
|||
* We only support 1 non-monitor interface.
|
||||
*/
|
||||
if (conf->type != IEEE80211_IF_TYPE_MNTR &&
|
||||
!is_interface_present(&rt2x00dev->interface))
|
||||
!is_interface_present(intf))
|
||||
return;
|
||||
|
||||
/*
|
||||
* We support muliple monitor mode interfaces.
|
||||
* All we need to do is decrease the monitor_count.
|
||||
* When removing an monitor interface, decrease monitor_count.
|
||||
* For non-monitor interfaces, all interface data needs to be reset.
|
||||
*/
|
||||
if (conf->type == IEEE80211_IF_TYPE_MNTR) {
|
||||
intf->monitor_count--;
|
||||
|
@ -243,33 +224,18 @@ void rt2x00lib_remove_interface(struct ieee80211_hw *hw,
|
|||
}
|
||||
|
||||
/*
|
||||
* When this is a non-monitor mode, stop the periodic link tuning.
|
||||
* If this was the last interface,
|
||||
* this is the time to disable the radio.
|
||||
* If this is not the last interface, then we should
|
||||
* check if we should switch completely to monitor
|
||||
* mode or completely switch to the non-monitor mode.
|
||||
*/
|
||||
if (conf->type != IEEE80211_IF_TYPE_MNTR)
|
||||
rt2x00_stop_link_tune(rt2x00dev);
|
||||
|
||||
/*
|
||||
* Check if we still have 1 non-monitor or a monitor
|
||||
* interface enabled. In that case we should update the
|
||||
* registers.
|
||||
*/
|
||||
if (is_monitor_present(&rt2x00dev->interface) ^
|
||||
is_interface_present(&rt2x00dev->interface)) {
|
||||
if (is_interface_present(&rt2x00dev->interface))
|
||||
if (!is_monitor_present(intf) && !is_interface_present(intf))
|
||||
rt2x00lib_disable_radio(rt2x00dev);
|
||||
else if (is_monitor_present(intf) ^ is_interface_present(intf))
|
||||
rt2x00lib_config_type(rt2x00dev,
|
||||
rt2x00dev->interface.type);
|
||||
else
|
||||
rt2x00lib_config_type(rt2x00dev,
|
||||
IEEE80211_IF_TYPE_MNTR);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check which interfaces have been disabled.
|
||||
*/
|
||||
if (!is_interface_present(&rt2x00dev->interface))
|
||||
__clear_bit(INTERFACE_ENABLED, &rt2x00dev->flags);
|
||||
else if (!is_monitor_present(&rt2x00dev->interface))
|
||||
__clear_bit(INTERFACE_ENABLED_MONITOR, &rt2x00dev->flags);
|
||||
is_interface_present(intf) ?
|
||||
intf->type : IEEE80211_IF_TYPE_MNTR);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2x00lib_remove_interface);
|
||||
|
||||
|
@ -373,10 +339,10 @@ void rt2x00lib_set_multicast_list(struct ieee80211_hw *hw,
|
|||
* Check if the new state is different then the old state.
|
||||
*/
|
||||
if (test_bit(INTERFACE_ENABLED_PROMISC, &rt2x00dev->flags) ==
|
||||
(flags & IFF_PROMISC))
|
||||
!!(flags & IFF_PROMISC))
|
||||
return;
|
||||
|
||||
rt2x00dev->interface.promisc = (flags & IFF_PROMISC);
|
||||
rt2x00dev->interface.promisc = !!(flags & IFF_PROMISC);
|
||||
|
||||
/*
|
||||
* Schedule the link tuner if this does not run
|
||||
|
@ -384,7 +350,7 @@ void rt2x00lib_set_multicast_list(struct ieee80211_hw *hw,
|
|||
* switched off when it is not required.
|
||||
*/
|
||||
if (!work_pending(&rt2x00dev->link.work.work))
|
||||
queue_work(rt2x00dev->workqueue, &rt2x00dev->link.work.work);
|
||||
queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->link.work.work);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2x00lib_set_multicast_list);
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include <linux/pci.h>
|
||||
|
||||
#include "rt2x00.h"
|
||||
#include "rt2x00lib.h"
|
||||
#include "rt2x00pci.h"
|
||||
|
||||
/*
|
||||
|
@ -109,7 +110,8 @@ int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev,
|
|||
|
||||
rt2x00_desc_read(txd, 0, &word);
|
||||
|
||||
if (rt2x00_get_field32(word, TXD_ENTRY_AVAILABLE)) {
|
||||
if (rt2x00_get_field32(word, TXD_ENTRY_OWNER_NIC) ||
|
||||
rt2x00_get_field32(word, TXD_ENTRY_VALID)) {
|
||||
ERROR(rt2x00dev,
|
||||
"Arrived at non-free entry in the non-full queue %d.\n"
|
||||
"Please file bug report to %s.\n",
|
||||
|
@ -118,11 +120,11 @@ int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
entry->skb = skb;
|
||||
memcpy(&entry->tx_status.control, control, sizeof(*control));
|
||||
memcpy(entry->data_addr, skb->data, skb->len);
|
||||
rt2x00lib_write_tx_desc(rt2x00dev, entry, txd, ieee80211hdr,
|
||||
skb->len, control);
|
||||
memcpy(&entry->tx_status.control, control, sizeof(*control));
|
||||
entry->skb = skb;
|
||||
|
||||
rt2x00_ring_index_inc(ring);
|
||||
|
||||
|
@ -133,6 +135,50 @@ int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(rt2x00pci_write_tx_data);
|
||||
|
||||
/*
|
||||
* RX data handlers.
|
||||
*/
|
||||
void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
struct data_ring *ring = rt2x00dev->rx;
|
||||
struct data_entry *entry;
|
||||
struct data_desc *rxd;
|
||||
u32 desc;
|
||||
int signal;
|
||||
int rssi;
|
||||
int ofdm;
|
||||
int size;
|
||||
|
||||
while (1) {
|
||||
entry = rt2x00_get_data_entry(ring);
|
||||
rxd = entry->priv;
|
||||
rt2x00_desc_read(rxd, 0, &desc);
|
||||
|
||||
if (rt2x00_get_field32(desc, RXD_ENTRY_OWNER_NIC))
|
||||
break;
|
||||
|
||||
size = rt2x00dev->ops->lib->fill_rxdone(
|
||||
entry, &signal, &rssi, &ofdm);
|
||||
if (size < 0)
|
||||
goto skip_entry;
|
||||
|
||||
/*
|
||||
* Send the packet to upper layer.
|
||||
*/
|
||||
rt2x00lib_rxdone(entry, entry->data_addr, size,
|
||||
signal, rssi, ofdm);
|
||||
|
||||
skip_entry:
|
||||
if (test_bit(DEVICE_ENABLED_RADIO, &ring->rt2x00dev->flags)) {
|
||||
rt2x00_set_field32(&desc, RXD_ENTRY_OWNER_NIC, 1);
|
||||
rt2x00_desc_write(rxd, 0, desc);
|
||||
}
|
||||
|
||||
rt2x00_ring_index_inc(ring);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2x00pci_rxdone);
|
||||
|
||||
/*
|
||||
* Device initialization handlers.
|
||||
*/
|
||||
|
@ -304,7 +350,6 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
|
|||
|
||||
rt2x00dev = hw->priv;
|
||||
rt2x00dev->dev = pci_dev;
|
||||
rt2x00dev->device = &pci_dev->dev;
|
||||
rt2x00dev->ops = ops;
|
||||
rt2x00dev->hw = hw;
|
||||
|
||||
|
|
|
@ -43,12 +43,13 @@
|
|||
#define REGISTER_BUSY_DELAY 100
|
||||
|
||||
/*
|
||||
* TX descriptor available flag.
|
||||
* This flag is the combination of the TXD_W0_OWNER_NIC
|
||||
* and TXD_W0_VALID flag which have the same value on all
|
||||
* PCI drivers.
|
||||
* Descriptor availability flags.
|
||||
* All PCI device descriptors have these 2 flags
|
||||
* with the exact same definition.
|
||||
*/
|
||||
#define TXD_ENTRY_AVAILABLE FIELD32(0x00000003)
|
||||
#define TXD_ENTRY_OWNER_NIC FIELD32(0x00000001)
|
||||
#define TXD_ENTRY_VALID FIELD32(0x00000002)
|
||||
#define RXD_ENTRY_OWNER_NIC FIELD32(0x00000001)
|
||||
|
||||
/*
|
||||
* Register access.
|
||||
|
@ -93,6 +94,11 @@ int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev,
|
|||
struct data_ring *ring, struct sk_buff *skb,
|
||||
struct ieee80211_tx_control *control);
|
||||
|
||||
/*
|
||||
* RX data handlers.
|
||||
*/
|
||||
void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev);
|
||||
|
||||
/*
|
||||
* Device initialization handlers.
|
||||
*/
|
||||
|
|
|
@ -70,7 +70,7 @@ static void rt2x00lib_rfkill_poll(struct work_struct *work)
|
|||
rfkill_switch_all(rt2x00dev->rfkill->type,
|
||||
rt2x00dev->ops->lib->rfkill_poll(rt2x00dev));
|
||||
|
||||
queue_delayed_work(rt2x00dev->workqueue, &rt2x00dev->rfkill_work,
|
||||
queue_delayed_work(rt2x00dev->hw->workqueue, &rt2x00dev->rfkill_work,
|
||||
RFKILL_POLL_INTERVAL);
|
||||
}
|
||||
|
||||
|
@ -92,7 +92,7 @@ void rt2x00lib_unregister_rfkill(struct rt2x00_dev *rt2x00dev)
|
|||
{
|
||||
if (delayed_work_pending(&rt2x00dev->rfkill_work))
|
||||
cancel_rearming_delayed_workqueue(
|
||||
rt2x00dev->workqueue, &rt2x00dev->rfkill_work);
|
||||
rt2x00dev->hw->workqueue, &rt2x00dev->rfkill_work);
|
||||
|
||||
rfkill_unregister(rt2x00dev->rfkill);
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include <linux/usb.h>
|
||||
|
||||
#include "rt2x00.h"
|
||||
#include "rt2x00lib.h"
|
||||
#include "rt2x00usb.h"
|
||||
|
||||
/*
|
||||
|
@ -62,48 +63,13 @@ int rt2x00usb_vendor_request(const struct rt2x00_dev *rt2x00dev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
ERROR(rt2x00dev, "vendor request error. Request 0x%02x failed "
|
||||
"for offset 0x%04x with error %d.\n", request, offset, status);
|
||||
ERROR(rt2x00dev, "Vendor Request 0x%02x failed for offset 0x%04x"
|
||||
" with error %d.\n", request, offset, status);
|
||||
|
||||
return status;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request);
|
||||
|
||||
/*
|
||||
* Radio handlers
|
||||
*/
|
||||
void rt2x00usb_enable_radio(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
/*
|
||||
* Start the RX ring.
|
||||
*/
|
||||
for (i = 0; i < rt2x00dev->rx->stats.limit; i++) {
|
||||
__set_bit(ENTRY_OWNER_NIC, &rt2x00dev->rx->entry[i].flags);
|
||||
usb_submit_urb(rt2x00dev->rx->entry[i].priv, GFP_ATOMIC);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2x00usb_enable_radio);
|
||||
|
||||
void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
struct data_ring *ring;
|
||||
unsigned int i;
|
||||
|
||||
rt2x00usb_vendor_request(rt2x00dev, USB_RX_CONTROL,
|
||||
USB_VENDOR_REQUEST_OUT, 0x00, 0x00, NULL, 0, REGISTER_TIMEOUT);
|
||||
|
||||
/*
|
||||
* Cancel all rings.
|
||||
*/
|
||||
ring_for_each(rt2x00dev, ring) {
|
||||
for (i = 0; i < ring->stats.limit; i++)
|
||||
usb_kill_urb(ring->entry[i].priv);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2x00usb_disable_radio);
|
||||
|
||||
/*
|
||||
* Beacon handlers.
|
||||
*/
|
||||
|
@ -328,6 +294,120 @@ int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(rt2x00usb_write_tx_data);
|
||||
|
||||
/*
|
||||
* RX data handlers.
|
||||
*/
|
||||
static void rt2x00usb_interrupt_rxdone(struct urb *urb)
|
||||
{
|
||||
struct data_entry *entry = (struct data_entry*)urb->context;
|
||||
struct data_ring *ring = entry->ring;
|
||||
struct rt2x00_dev *rt2x00dev = ring->rt2x00dev;
|
||||
int signal;
|
||||
int rssi;
|
||||
int ofdm;
|
||||
int size;
|
||||
|
||||
if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) ||
|
||||
!test_and_clear_bit(ENTRY_OWNER_NIC, &entry->flags))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Check if the received data is simply too small
|
||||
* to be actually valid, or if the urb is signaling
|
||||
* a problem.
|
||||
*/
|
||||
if (urb->actual_length < entry->ring->desc_size || urb->status)
|
||||
goto skip_entry;
|
||||
|
||||
size = rt2x00dev->ops->lib->fill_rxdone(entry, &signal, &rssi, &ofdm);
|
||||
if (size < 0)
|
||||
goto skip_entry;
|
||||
|
||||
/*
|
||||
* Trim the skb_buffer to only contain the valid
|
||||
* frame data (so ignore the device's descriptor).
|
||||
*/
|
||||
skb_trim(entry->skb, size);
|
||||
|
||||
/*
|
||||
* Send the packet to upper layer, and update urb.
|
||||
*/
|
||||
rt2x00lib_rxdone(entry, NULL, ring->data_size + ring->desc_size,
|
||||
signal, rssi, ofdm);
|
||||
urb->transfer_buffer = entry->skb->data;
|
||||
urb->transfer_buffer_length = entry->skb->len;
|
||||
|
||||
skip_entry:
|
||||
if (test_bit(DEVICE_ENABLED_RADIO, &ring->rt2x00dev->flags)) {
|
||||
__set_bit(ENTRY_OWNER_NIC, &entry->flags);
|
||||
usb_submit_urb(urb, GFP_ATOMIC);
|
||||
}
|
||||
|
||||
rt2x00_ring_index_inc(ring);
|
||||
}
|
||||
|
||||
/*
|
||||
* Radio handlers
|
||||
*/
|
||||
void rt2x00usb_enable_radio(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
struct usb_device *usb_dev =
|
||||
interface_to_usbdev(rt2x00dev_usb(rt2x00dev));
|
||||
struct data_ring *ring;
|
||||
struct data_entry *entry;
|
||||
unsigned int i;
|
||||
|
||||
/*
|
||||
* Initialize the TX rings
|
||||
*/
|
||||
txringall_for_each(rt2x00dev, ring) {
|
||||
for (i = 0; i < ring->stats.limit; i++)
|
||||
ring->entry[i].flags = 0;
|
||||
|
||||
rt2x00_ring_index_clear(ring);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize and start the RX ring.
|
||||
*/
|
||||
rt2x00_ring_index_clear(rt2x00dev->rx);
|
||||
|
||||
for (i = 0; i < rt2x00dev->rx->stats.limit; i++) {
|
||||
entry = &rt2x00dev->rx->entry[i];
|
||||
|
||||
usb_fill_bulk_urb(
|
||||
entry->priv,
|
||||
usb_dev,
|
||||
usb_rcvbulkpipe(usb_dev, 1),
|
||||
entry->skb->data,
|
||||
entry->skb->len,
|
||||
rt2x00usb_interrupt_rxdone,
|
||||
entry);
|
||||
|
||||
__set_bit(ENTRY_OWNER_NIC, &entry->flags);
|
||||
usb_submit_urb(entry->priv, GFP_ATOMIC);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2x00usb_enable_radio);
|
||||
|
||||
void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
struct data_ring *ring;
|
||||
unsigned int i;
|
||||
|
||||
rt2x00usb_vendor_request(rt2x00dev, USB_RX_CONTROL,
|
||||
USB_VENDOR_REQUEST_OUT, 0x00, 0x00, NULL, 0, REGISTER_TIMEOUT);
|
||||
|
||||
/*
|
||||
* Cancel all rings.
|
||||
*/
|
||||
ring_for_each(rt2x00dev, ring) {
|
||||
for (i = 0; i < ring->stats.limit; i++)
|
||||
usb_kill_urb(ring->entry[i].priv);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2x00usb_disable_radio);
|
||||
|
||||
/*
|
||||
* Device initialization handlers.
|
||||
*/
|
||||
|
@ -433,7 +513,6 @@ int rt2x00usb_probe(struct usb_interface *usb_intf,
|
|||
|
||||
rt2x00dev = hw->priv;
|
||||
rt2x00dev->dev = usb_intf;
|
||||
rt2x00dev->device = &usb_intf->dev;
|
||||
rt2x00dev->ops = ops;
|
||||
rt2x00dev->hw = hw;
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include <asm/io.h>
|
||||
|
||||
#include "rt2x00.h"
|
||||
#include "rt2x00lib.h"
|
||||
#include "rt2x00pci.h"
|
||||
#include "rt61pci.h"
|
||||
|
||||
|
@ -891,13 +892,19 @@ static void rt61pci_disable_led(struct rt2x00_dev *rt2x00dev)
|
|||
rt61pci_mcu_request(rt2x00dev, MCU_LED, 0xff, arg0, arg1);
|
||||
}
|
||||
|
||||
static void rt61pci_activity_led(struct rt2x00_dev *rt2x00dev, char rssi)
|
||||
static void rt61pci_activity_led(struct rt2x00_dev *rt2x00dev, int rssi)
|
||||
{
|
||||
u8 led;
|
||||
|
||||
if (rt2x00dev->led_mode != LED_MODE_SIGNAL_STRENGTH)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Led handling requires a positive value for the rssi,
|
||||
* to do that correctly we need to add the correction.
|
||||
*/
|
||||
rssi += rt2x00dev->rssi_offset;
|
||||
|
||||
if (rssi <= 30)
|
||||
led = 0;
|
||||
else if (rssi <= 39)
|
||||
|
@ -917,8 +924,9 @@ static void rt61pci_activity_led(struct rt2x00_dev *rt2x00dev, char rssi)
|
|||
/*
|
||||
* Link tuning
|
||||
*/
|
||||
static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev, int rssi)
|
||||
static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
int rssi = rt2x00_get_link_rssi(&rt2x00dev->link);
|
||||
u32 reg;
|
||||
u8 r17;
|
||||
u8 up_bound;
|
||||
|
@ -1013,10 +1021,12 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev, int rssi)
|
|||
if (++r17 > up_bound)
|
||||
r17 = up_bound;
|
||||
rt61pci_bbp_write(rt2x00dev, 17, r17);
|
||||
rt2x00dev->rx_status.noise = r17;
|
||||
} else if (rt2x00dev->link.false_cca < 100 && r17 > low_bound) {
|
||||
if (--r17 < low_bound)
|
||||
r17 = low_bound;
|
||||
rt61pci_bbp_write(rt2x00dev, 17, r17);
|
||||
rt2x00dev->rx_status.noise = r17;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1279,7 +1289,12 @@ static int rt61pci_init_registers(struct rt2x00_dev *rt2x00dev)
|
|||
|
||||
rt2x00pci_register_write(rt2x00dev, MAC_CSR10, 0x00000718);
|
||||
|
||||
rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, 0x025eb032);
|
||||
rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, ®);
|
||||
rt2x00_set_field32(®, TXRX_CSR0_AUTO_TX_SEQ, 1);
|
||||
rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, 1);
|
||||
rt2x00_set_field32(®, TXRX_CSR0_DROP_ACK_CTS, 1);
|
||||
rt2x00_set_field32(®, TXRX_CSR0_TX_WITHOUT_WAITING, 0);
|
||||
rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg);
|
||||
|
||||
rt2x00pci_register_write(rt2x00dev, TXRX_CSR1, 0x9eb39eb3);
|
||||
rt2x00pci_register_write(rt2x00dev, TXRX_CSR2, 0x8a8b8c8d);
|
||||
|
@ -1312,10 +1327,6 @@ static int rt61pci_init_registers(struct rt2x00_dev *rt2x00dev)
|
|||
rt2x00_set_field32(®, MAC_CSR9_CW_SELECT, 0);
|
||||
rt2x00pci_register_write(rt2x00dev, MAC_CSR9, reg);
|
||||
|
||||
rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, ®);
|
||||
rt2x00_set_field32(®, TXRX_CSR0_AUTO_TX_SEQ, 1);
|
||||
rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg);
|
||||
|
||||
rt2x00pci_register_write(rt2x00dev, PHY_CSR1, 0x000023b0);
|
||||
rt2x00pci_register_write(rt2x00dev, PHY_CSR5, 0x060a100c);
|
||||
rt2x00pci_register_write(rt2x00dev, PHY_CSR6, 0x00080606);
|
||||
|
@ -1432,10 +1443,48 @@ static void rt61pci_toggle_rx(struct rt2x00_dev *rt2x00dev,
|
|||
rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg);
|
||||
}
|
||||
|
||||
static int rt61pci_enable_radio(struct rt2x00_dev *rt2x00dev)
|
||||
static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev, int enabled)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
/*
|
||||
* When interrupts are being enabled, the interrupt registers
|
||||
* should clear the register to assure a clean state.
|
||||
*/
|
||||
if (enabled) {
|
||||
rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, ®);
|
||||
rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
|
||||
|
||||
rt2x00pci_register_read(rt2x00dev, MCU_INT_SOURCE_CSR, ®);
|
||||
rt2x00pci_register_write(rt2x00dev, MCU_INT_SOURCE_CSR, reg);
|
||||
}
|
||||
|
||||
/*
|
||||
* Only toggle the interrupts bits we are going to use.
|
||||
* Non-checked interrupt bits are disabled by default.
|
||||
*/
|
||||
rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, ®);
|
||||
rt2x00_set_field32(®, INT_MASK_CSR_TXDONE, !enabled);
|
||||
rt2x00_set_field32(®, INT_MASK_CSR_RXDONE, !enabled);
|
||||
rt2x00_set_field32(®, INT_MASK_CSR_BEACON_DONE, !enabled);
|
||||
rt2x00_set_field32(®, INT_MASK_CSR_ENABLE_MITIGATION, !enabled);
|
||||
rt2x00_set_field32(®, INT_MASK_CSR_MITIGATION_PERIOD, 0xff);
|
||||
rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg);
|
||||
|
||||
rt2x00pci_register_read(rt2x00dev, MCU_INT_MASK_CSR, ®);
|
||||
rt2x00_set_field32(®, MCU_INT_MASK_CSR_0, !enabled);
|
||||
rt2x00_set_field32(®, MCU_INT_MASK_CSR_1, !enabled);
|
||||
rt2x00_set_field32(®, MCU_INT_MASK_CSR_2, !enabled);
|
||||
rt2x00_set_field32(®, MCU_INT_MASK_CSR_3, !enabled);
|
||||
rt2x00_set_field32(®, MCU_INT_MASK_CSR_4, !enabled);
|
||||
rt2x00_set_field32(®, MCU_INT_MASK_CSR_5, !enabled);
|
||||
rt2x00_set_field32(®, MCU_INT_MASK_CSR_6, !enabled);
|
||||
rt2x00_set_field32(®, MCU_INT_MASK_CSR_7, !enabled);
|
||||
rt2x00pci_register_write(rt2x00dev, MCU_INT_MASK_CSR, reg);
|
||||
}
|
||||
|
||||
static int rt61pci_enable_radio(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
/*
|
||||
* Initialize all registers.
|
||||
*/
|
||||
|
@ -1446,24 +1495,10 @@ static int rt61pci_enable_radio(struct rt2x00_dev *rt2x00dev)
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear interrupts.
|
||||
*/
|
||||
rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, ®);
|
||||
rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
|
||||
|
||||
rt2x00pci_register_read(rt2x00dev, MCU_INT_SOURCE_CSR, ®);
|
||||
rt2x00pci_register_write(rt2x00dev, MCU_INT_SOURCE_CSR, reg);
|
||||
|
||||
/*
|
||||
* Enable interrupts.
|
||||
*/
|
||||
reg = 0;
|
||||
rt2x00_set_field32(®, INT_MASK_CSR_TX_ABORT_DONE, 1);
|
||||
rt2x00_set_field32(®, INT_MASK_CSR_MITIGATION_PERIOD, 0xff);
|
||||
rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg);
|
||||
|
||||
rt2x00pci_register_write(rt2x00dev, MCU_INT_MASK_CSR, 0x00000000);
|
||||
rt61pci_toggle_irq(rt2x00dev, 1);
|
||||
|
||||
/*
|
||||
* Enable RX.
|
||||
|
@ -1508,11 +1543,7 @@ static void rt61pci_disable_radio(struct rt2x00_dev *rt2x00dev)
|
|||
/*
|
||||
* Disable interrupts.
|
||||
*/
|
||||
reg = 0xffffffff;
|
||||
rt2x00_set_field32(®, INT_MASK_CSR_ENABLE_MITIGATION, 0);
|
||||
rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg);
|
||||
|
||||
rt2x00pci_register_write(rt2x00dev, MCU_INT_MASK_CSR, 0xffffffff);
|
||||
rt61pci_toggle_irq(rt2x00dev, 0);
|
||||
}
|
||||
|
||||
static int rt61pci_set_state(struct rt2x00_dev *rt2x00dev,
|
||||
|
@ -1681,60 +1712,80 @@ static void rt61pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, int queue)
|
|||
}
|
||||
|
||||
/*
|
||||
* Interrupt functions.
|
||||
* RX control handlers
|
||||
*/
|
||||
static void rt61pci_rxdone(struct rt2x00_dev *rt2x00dev)
|
||||
static int rt61pci_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1)
|
||||
{
|
||||
struct data_ring *ring = rt2x00dev->rx;
|
||||
struct data_entry *entry;
|
||||
struct data_desc *rxd;
|
||||
u16 eeprom;
|
||||
char offset;
|
||||
char lna;
|
||||
|
||||
lna = rt2x00_get_field32(rxd_w1, RXD_W1_RSSI_LNA);
|
||||
switch (lna) {
|
||||
case 3:
|
||||
offset = 90;
|
||||
break;
|
||||
case 2:
|
||||
offset = 74;
|
||||
break;
|
||||
case 1:
|
||||
offset = 64;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (rt2x00dev->rx_status.phymode == MODE_IEEE80211A) {
|
||||
if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags))
|
||||
offset += 14;
|
||||
|
||||
if (lna == 3 || lna == 2)
|
||||
offset += 10;
|
||||
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A, &eeprom);
|
||||
offset -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_A_1);
|
||||
} else {
|
||||
if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags))
|
||||
offset += 14;
|
||||
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &eeprom);
|
||||
offset -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_BG_1);
|
||||
}
|
||||
|
||||
return rt2x00_get_field32(rxd_w1, RXD_W1_RSSI_AGC) * 2 - offset;
|
||||
}
|
||||
|
||||
static int rt61pci_fill_rxdone(struct data_entry *entry,
|
||||
int *signal, int *rssi, int *ofdm)
|
||||
{
|
||||
struct data_desc *rxd = entry->priv;
|
||||
u32 word0;
|
||||
u32 word1;
|
||||
int signal;
|
||||
int rssi;
|
||||
int ofdm;
|
||||
u16 size;
|
||||
|
||||
while (1) {
|
||||
entry = rt2x00_get_data_entry(ring);
|
||||
rxd = entry->priv;
|
||||
rt2x00_desc_read(rxd, 0, &word0);
|
||||
rt2x00_desc_read(rxd, 1, &word1);
|
||||
|
||||
if (rt2x00_get_field32(word0, RXD_W0_OWNER_NIC))
|
||||
break;
|
||||
|
||||
/*
|
||||
* TODO: Don't we need to keep statistics
|
||||
* updated about events like CRC and physical errors?
|
||||
* updated about these errors?
|
||||
*/
|
||||
if (rt2x00_get_field32(word0, RXD_W0_CRC))
|
||||
goto skip_entry;
|
||||
if (rt2x00_get_field32(word0, RXD_W0_CRC) ||
|
||||
rt2x00_get_field32(word0, RXD_W0_CIPHER_ERROR))
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Obtain the status about this packet.
|
||||
*/
|
||||
size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
|
||||
signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
|
||||
rssi = rt2x00_get_field32(word1, RXD_W1_RSSI);
|
||||
ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM);
|
||||
*signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
|
||||
*rssi = rt61pci_agc_to_rssi(entry->ring->rt2x00dev, word1);
|
||||
*ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM);
|
||||
|
||||
return rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send the packet to upper layer.
|
||||
* Interrupt functions.
|
||||
*/
|
||||
rt2x00lib_rxdone(entry, entry->data_addr, size,
|
||||
signal, rssi, ofdm);
|
||||
|
||||
skip_entry:
|
||||
if (test_bit(DEVICE_ENABLED_RADIO, &ring->rt2x00dev->flags)) {
|
||||
rt2x00_set_field32(&word0, RXD_W0_OWNER_NIC, 1);
|
||||
rt2x00_desc_write(rxd, 0, word0);
|
||||
}
|
||||
|
||||
rt2x00_ring_index_inc(ring);
|
||||
}
|
||||
}
|
||||
|
||||
static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
struct data_ring *ring;
|
||||
|
@ -1840,7 +1891,7 @@ static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance)
|
|||
* 2 - Rx ring done interrupt.
|
||||
*/
|
||||
if (rt2x00_get_field32(reg, INT_SOURCE_CSR_RXDONE))
|
||||
rt61pci_rxdone(rt2x00dev);
|
||||
rt2x00pci_rxdone(rt2x00dev);
|
||||
|
||||
/*
|
||||
* 3 - Tx ring done interrupt.
|
||||
|
@ -1859,6 +1910,8 @@ static int rt61pci_alloc_eeprom(struct rt2x00_dev *rt2x00dev)
|
|||
struct eeprom_93cx6 eeprom;
|
||||
u32 reg;
|
||||
u16 word;
|
||||
u8 *mac;
|
||||
char value;
|
||||
|
||||
/*
|
||||
* Allocate the eeprom memory, check the eeprom width
|
||||
|
@ -1886,6 +1939,12 @@ static int rt61pci_alloc_eeprom(struct rt2x00_dev *rt2x00dev)
|
|||
/*
|
||||
* Start validation of the data that has been read.
|
||||
*/
|
||||
mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
|
||||
if (!is_valid_ether_addr(mac)) {
|
||||
random_ether_addr(mac);
|
||||
EEPROM(rt2x00dev, "MAC: " MAC_FMT "\n", MAC_ARG(mac));
|
||||
}
|
||||
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
|
||||
if (word == 0xffff) {
|
||||
rt2x00_set_field16(&word, EEPROM_ANTENNA_NUM, 2);
|
||||
|
@ -1927,6 +1986,38 @@ static int rt61pci_alloc_eeprom(struct rt2x00_dev *rt2x00dev)
|
|||
EEPROM(rt2x00dev, "Freq: 0x%04x\n", word);
|
||||
}
|
||||
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &word);
|
||||
if (word == 0xffff) {
|
||||
rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_1, 0);
|
||||
rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_2, 0);
|
||||
rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_BG, word);
|
||||
EEPROM(rt2x00dev, "RSSI OFFSET BG: 0x%04x\n", word);
|
||||
} else {
|
||||
value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_BG_1);
|
||||
if (value < -10 || value > 10)
|
||||
rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_1, 0);
|
||||
value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_BG_2);
|
||||
if (value < -10 || value > 10)
|
||||
rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_2, 0);
|
||||
rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_BG, word);
|
||||
}
|
||||
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A, &word);
|
||||
if (word == 0xffff) {
|
||||
rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_1, 0);
|
||||
rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_2, 0);
|
||||
rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_A, word);
|
||||
EEPROM(rt2x00dev, "RSSI OFFSET BG: 0x%04x\n", word);
|
||||
} else {
|
||||
value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_A_1);
|
||||
if (value < -10 || value > 10)
|
||||
rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_1, 0);
|
||||
value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_A_2);
|
||||
if (value < -10 || value > 10)
|
||||
rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_2, 0);
|
||||
rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_A, word);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2086,12 +2177,17 @@ static void rt61pci_init_hw_mode(struct rt2x00_dev *rt2x00dev)
|
|||
IEEE80211_HW_WEP_INCLUDE_IV |
|
||||
IEEE80211_HW_DATA_NULLFUNC_ACK |
|
||||
IEEE80211_HW_NO_TKIP_WMM_HWACCEL |
|
||||
IEEE80211_HW_MONITOR_DURING_OPER;
|
||||
IEEE80211_HW_MONITOR_DURING_OPER |
|
||||
IEEE80211_HW_NO_PROBE_FILTERING;
|
||||
rt2x00dev->hw->extra_tx_headroom = 0;
|
||||
rt2x00dev->hw->max_rssi = MAX_RX_SSI;
|
||||
rt2x00dev->hw->max_noise = MAX_RX_NOISE;
|
||||
rt2x00dev->hw->queues = 5;
|
||||
|
||||
SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_pci(rt2x00dev)->dev);
|
||||
SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
|
||||
rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0));
|
||||
|
||||
/*
|
||||
* Convert tx_power array in eeprom.
|
||||
*/
|
||||
|
@ -2102,7 +2198,6 @@ static void rt61pci_init_hw_mode(struct rt2x00_dev *rt2x00dev)
|
|||
/*
|
||||
* Initialize hw_mode information.
|
||||
*/
|
||||
spec->mac_addr = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
|
||||
spec->num_modes = 2;
|
||||
spec->num_rates = 12;
|
||||
spec->num_channels = 14;
|
||||
|
@ -2150,10 +2245,15 @@ static int rt61pci_init_hw(struct rt2x00_dev *rt2x00dev)
|
|||
rt61pci_init_hw_mode(rt2x00dev);
|
||||
|
||||
/*
|
||||
* rt61pci requires firmware
|
||||
* This device requires firmware
|
||||
*/
|
||||
__set_bit(FIRMWARE_REQUIRED, &rt2x00dev->flags);
|
||||
|
||||
/*
|
||||
* Set the rssi offset.
|
||||
*/
|
||||
rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2219,8 +2319,6 @@ static void rt61pci_reset_tsf(struct ieee80211_hw *hw)
|
|||
static const struct ieee80211_ops rt61pci_mac80211_ops = {
|
||||
.tx = rt2x00lib_tx,
|
||||
.reset = rt2x00lib_reset,
|
||||
.open = rt2x00lib_open,
|
||||
.stop = rt2x00lib_stop,
|
||||
.add_interface = rt2x00lib_add_interface,
|
||||
.remove_interface = rt2x00lib_remove_interface,
|
||||
.config = rt2x00lib_config,
|
||||
|
@ -2250,6 +2348,7 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {
|
|||
.write_tx_desc = rt61pci_write_tx_desc,
|
||||
.write_tx_data = rt2x00pci_write_tx_data,
|
||||
.kick_tx_queue = rt61pci_kick_tx_queue,
|
||||
.fill_rxdone = rt61pci_fill_rxdone,
|
||||
.config_type = rt61pci_config_type,
|
||||
.config_phymode = rt61pci_config_phymode,
|
||||
.config_channel = rt61pci_config_channel,
|
||||
|
@ -2309,14 +2408,11 @@ static struct pci_driver rt61pci_driver = {
|
|||
|
||||
static int __init rt61pci_init(void)
|
||||
{
|
||||
printk(KERN_INFO "Loading module: %s - %s by %s.\n",
|
||||
DRV_NAME, DRV_VERSION, DRV_PROJECT);
|
||||
return pci_register_driver(&rt61pci_driver);
|
||||
}
|
||||
|
||||
static void __exit rt61pci_exit(void)
|
||||
{
|
||||
printk(KERN_INFO "Unloading module: %s.\n", DRV_NAME);
|
||||
pci_unregister_driver(&rt61pci_driver);
|
||||
}
|
||||
|
||||
|
|
|
@ -36,10 +36,11 @@
|
|||
#define RF2529 0x0004
|
||||
|
||||
/*
|
||||
* Max RSSI value, required for RSSI <-> dBm conversion.
|
||||
* Signal information.
|
||||
*/
|
||||
#define MAX_RX_SSI 120
|
||||
#define MAX_RX_SSI -1
|
||||
#define MAX_RX_NOISE -110
|
||||
#define DEFAULT_RSSI_OFFSET 120
|
||||
|
||||
/*
|
||||
* Register layout information.
|
||||
|
@ -1102,6 +1103,20 @@ struct hw_pairwise_ta_entry {
|
|||
#define EEPROM_TXPOWER_A_1 FIELD16(0x00ff)
|
||||
#define EEPROM_TXPOWER_A_2 FIELD16(0xff00)
|
||||
|
||||
/*
|
||||
* EEPROM RSSI offset 802.11BG
|
||||
*/
|
||||
#define EEPROM_RSSI_OFFSET_BG 0x004d
|
||||
#define EEPROM_RSSI_OFFSET_BG_1 FIELD16(0x00ff)
|
||||
#define EEPROM_RSSI_OFFSET_BG_2 FIELD16(0xff00)
|
||||
|
||||
/*
|
||||
* EEPROM RSSI offset 802.11A
|
||||
*/
|
||||
#define EEPROM_RSSI_OFFSET_A 0x004e
|
||||
#define EEPROM_RSSI_OFFSET_A_1 FIELD16(0x00ff)
|
||||
#define EEPROM_RSSI_OFFSET_A_2 FIELD16(0xff00)
|
||||
|
||||
/*
|
||||
* BBP content.
|
||||
* The wordsize of the BBP is 8 bits.
|
||||
|
@ -1285,10 +1300,10 @@ struct hw_pairwise_ta_entry {
|
|||
/*
|
||||
* Word1
|
||||
* SIGNAL: RX raw data rate reported by BBP.
|
||||
* RSSI: RSSI reported by BBP.
|
||||
*/
|
||||
#define RXD_W1_SIGNAL FIELD32(0x000000ff)
|
||||
#define RXD_W1_RSSI FIELD32(0x0000ff00)
|
||||
#define RXD_W1_RSSI_AGC FIELD32(0x00001f00)
|
||||
#define RXD_W1_RSSI_LNA FIELD32(0x00006000)
|
||||
#define RXD_W1_FRAME_OFFSET FIELD32(0x7f000000)
|
||||
|
||||
/*
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include <linux/etherdevice.h>
|
||||
|
||||
#include "rt2x00.h"
|
||||
#include "rt2x00lib.h"
|
||||
#include "rt2x00usb.h"
|
||||
#include "rt73usb.h"
|
||||
|
||||
|
@ -745,13 +746,19 @@ static void rt73usb_disable_led(struct rt2x00_dev *rt2x00dev)
|
|||
0x00, rt2x00dev->led_reg, NULL, 0, REGISTER_TIMEOUT);
|
||||
}
|
||||
|
||||
static void rt73usb_activity_led(struct rt2x00_dev *rt2x00dev, char rssi)
|
||||
static void rt73usb_activity_led(struct rt2x00_dev *rt2x00dev, int rssi)
|
||||
{
|
||||
u32 led;
|
||||
|
||||
if (rt2x00dev->led_mode != LED_MODE_SIGNAL_STRENGTH)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Led handling requires a positive value for the rssi,
|
||||
* to do that correctly we need to add the correction.
|
||||
*/
|
||||
rssi += rt2x00dev->rssi_offset;
|
||||
|
||||
if (rssi <= 30)
|
||||
led = 0;
|
||||
else if (rssi <= 39)
|
||||
|
@ -773,8 +780,9 @@ static void rt73usb_activity_led(struct rt2x00_dev *rt2x00dev, char rssi)
|
|||
/*
|
||||
* Link tuning
|
||||
*/
|
||||
static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev, int rssi)
|
||||
static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
int rssi = rt2x00_get_link_rssi(&rt2x00dev->link);
|
||||
u32 reg;
|
||||
u8 r17;
|
||||
u8 up_bound;
|
||||
|
@ -880,11 +888,13 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev, int rssi)
|
|||
if (r17 > up_bound)
|
||||
r17 = up_bound;
|
||||
rt73usb_bbp_write(rt2x00dev, 17, r17);
|
||||
rt2x00dev->rx_status.noise = r17;
|
||||
} else if (rt2x00dev->link.false_cca < 100 && r17 > low_bound) {
|
||||
r17 -= 4;
|
||||
if (r17 < low_bound)
|
||||
r17 = low_bound;
|
||||
rt73usb_bbp_write(rt2x00dev, 17, r17);
|
||||
rt2x00dev->rx_status.noise = r17;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -952,51 +962,6 @@ static int rt73usb_load_firmware(struct rt2x00_dev *rt2x00dev, void *data,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void rt73usb_init_rxring(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
struct usb_device *usb_dev =
|
||||
interface_to_usbdev(rt2x00dev_usb(rt2x00dev));
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < rt2x00dev->rx->stats.limit; i++) {
|
||||
usb_fill_bulk_urb(
|
||||
rt2x00dev->rx->entry[i].priv,
|
||||
usb_dev,
|
||||
usb_rcvbulkpipe(usb_dev, 1),
|
||||
rt2x00dev->rx->entry[i].skb->data,
|
||||
rt2x00dev->rx->entry[i].skb->len,
|
||||
rt73usb_interrupt_rxdone,
|
||||
&rt2x00dev->rx->entry[i]);
|
||||
}
|
||||
|
||||
rt2x00_ring_index_clear(rt2x00dev->rx);
|
||||
}
|
||||
|
||||
static void rt73usb_init_txring(struct rt2x00_dev *rt2x00dev,
|
||||
const int queue)
|
||||
{
|
||||
struct data_ring *ring = rt2x00_get_ring(rt2x00dev, queue);
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ring->stats.limit; i++)
|
||||
ring->entry[i].flags = 0;
|
||||
|
||||
rt2x00_ring_index_clear(ring);
|
||||
}
|
||||
|
||||
static int rt73usb_init_rings(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
rt73usb_init_rxring(rt2x00dev);
|
||||
rt73usb_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_DATA0);
|
||||
rt73usb_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_DATA1);
|
||||
rt73usb_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_DATA2);
|
||||
rt73usb_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_DATA3);
|
||||
rt73usb_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_DATA4);
|
||||
rt73usb_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_BEACON);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
u32 reg;
|
||||
|
@ -1006,7 +971,12 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev)
|
|||
|
||||
rt73usb_register_write(rt2x00dev, MAC_CSR10, 0x00000718);
|
||||
|
||||
rt73usb_register_write(rt2x00dev, TXRX_CSR0, 0x025eb032);
|
||||
rt73usb_register_read(rt2x00dev, TXRX_CSR0, ®);
|
||||
rt2x00_set_field32(®, TXRX_CSR0_AUTO_TX_SEQ, 1);
|
||||
rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, 1);
|
||||
rt2x00_set_field32(®, TXRX_CSR0_DROP_ACK_CTS, 1);
|
||||
rt2x00_set_field32(®, TXRX_CSR0_TX_WITHOUT_WAITING, 0);
|
||||
rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg);
|
||||
|
||||
rt73usb_register_write(rt2x00dev, TXRX_CSR1, 0x9eaa9eaf);
|
||||
rt73usb_register_write(rt2x00dev, TXRX_CSR2, 0x8a8b8c8d);
|
||||
|
@ -1049,10 +1019,6 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev)
|
|||
rt2x00_set_field32(®, MAC_CSR9_CW_SELECT, 0);
|
||||
rt73usb_register_write(rt2x00dev, MAC_CSR9, reg);
|
||||
|
||||
rt73usb_register_read(rt2x00dev, TXRX_CSR0, ®);
|
||||
rt2x00_set_field32(®, TXRX_CSR0_AUTO_TX_SEQ, 1);
|
||||
rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg);
|
||||
|
||||
/*
|
||||
* We must clear the error counters.
|
||||
* These registers are cleared on read,
|
||||
|
@ -1164,8 +1130,7 @@ static int rt73usb_enable_radio(struct rt2x00_dev *rt2x00dev)
|
|||
/*
|
||||
* Initialize all registers.
|
||||
*/
|
||||
if (rt73usb_init_rings(rt2x00dev) ||
|
||||
rt73usb_init_registers(rt2x00dev) ||
|
||||
if (rt73usb_init_registers(rt2x00dev) ||
|
||||
rt73usb_init_bbp(rt2x00dev)) {
|
||||
ERROR(rt2x00dev, "Register initialization failed.\n");
|
||||
return -EIO;
|
||||
|
@ -1344,74 +1309,84 @@ static void rt73usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, int queue)
|
|||
}
|
||||
|
||||
/*
|
||||
* Interrupt functions.
|
||||
* RX control handlers
|
||||
*/
|
||||
static void rt73usb_interrupt_rxdone(struct urb *urb)
|
||||
static int rt73usb_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1)
|
||||
{
|
||||
u16 eeprom;
|
||||
char offset;
|
||||
char lna;
|
||||
|
||||
lna = rt2x00_get_field32(rxd_w1, RXD_W1_RSSI_LNA);
|
||||
switch (lna) {
|
||||
case 3:
|
||||
offset = 90;
|
||||
break;
|
||||
case 2:
|
||||
offset = 74;
|
||||
break;
|
||||
case 1:
|
||||
offset = 64;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (rt2x00dev->rx_status.phymode == MODE_IEEE80211A) {
|
||||
if (test_bit(CONFIG_EXTERNAL_LNA, &rt2x00dev->flags)) {
|
||||
if (lna == 3 || lna == 2)
|
||||
offset += 10;
|
||||
} else {
|
||||
if (lna == 3)
|
||||
offset += 6;
|
||||
else if (lna == 2)
|
||||
offset += 8;
|
||||
}
|
||||
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A, &eeprom);
|
||||
offset -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_A_1);
|
||||
} else {
|
||||
if (test_bit(CONFIG_EXTERNAL_LNA, &rt2x00dev->flags))
|
||||
offset += 14;
|
||||
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &eeprom);
|
||||
offset -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_BG_1);
|
||||
}
|
||||
|
||||
return rt2x00_get_field32(rxd_w1, RXD_W1_RSSI_AGC) * 2 - offset;
|
||||
}
|
||||
|
||||
static int rt73usb_fill_rxdone(struct data_entry *entry,
|
||||
int *signal, int *rssi, int *ofdm)
|
||||
{
|
||||
struct data_entry *entry = (struct data_entry*)urb->context;
|
||||
struct data_ring *ring = entry->ring;
|
||||
struct rt2x00_dev *rt2x00dev = ring->rt2x00dev;
|
||||
struct data_desc *rxd = (struct data_desc*)entry->skb->data;
|
||||
u32 word0;
|
||||
u32 word1;
|
||||
int signal;
|
||||
int rssi;
|
||||
int ofdm;
|
||||
u16 size;
|
||||
|
||||
if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) ||
|
||||
!__test_and_clear_bit(ENTRY_OWNER_NIC, &entry->flags))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Check if the received data is simply too small
|
||||
* to be actually valid, or if the urb is signaling
|
||||
* a problem.
|
||||
*/
|
||||
if (urb->actual_length < entry->ring->desc_size || urb->status)
|
||||
goto skip_entry;
|
||||
|
||||
rt2x00_desc_read(rxd, 0, &word0);
|
||||
rt2x00_desc_read(rxd, 1, &word1);
|
||||
|
||||
/*
|
||||
* TODO: Don't we need to keep statistics
|
||||
* updated about events like CRC and physical errors?
|
||||
* updated about these errors?
|
||||
*/
|
||||
if (rt2x00_get_field32(word0, RXD_W0_CRC) ||
|
||||
rt2x00_get_field32(word0, RXD_W0_CIPHER_ERROR))
|
||||
goto skip_entry;
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Obtain the status about this packet.
|
||||
*/
|
||||
size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
|
||||
signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
|
||||
rssi = rt2x00_get_field32(word1, RXD_W1_RSSI);
|
||||
ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM);
|
||||
*signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
|
||||
*rssi = rt73usb_agc_to_rssi(entry->ring->rt2x00dev, word1);
|
||||
*ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM);
|
||||
|
||||
/*
|
||||
* Trim the skb_buffer to only contain the valid
|
||||
* frame data (so ignore the device's descriptor).
|
||||
* Pull the skb to clear the descriptor area.
|
||||
*/
|
||||
skb_pull(entry->skb, ring->desc_size);
|
||||
skb_trim(entry->skb, size);
|
||||
skb_pull(entry->skb, entry->ring->desc_size);
|
||||
|
||||
/*
|
||||
* Send the packet to upper layer, and update urb.
|
||||
*/
|
||||
rt2x00lib_rxdone(entry, NULL, ring->data_size + ring->desc_size,
|
||||
signal, rssi, ofdm);
|
||||
urb->transfer_buffer = entry->skb->data;
|
||||
urb->transfer_buffer_length = entry->skb->len;
|
||||
|
||||
skip_entry:
|
||||
if (test_bit(DEVICE_ENABLED_RADIO, &ring->rt2x00dev->flags)) {
|
||||
__set_bit(ENTRY_OWNER_NIC, &entry->flags);
|
||||
usb_submit_urb(urb, GFP_ATOMIC);
|
||||
}
|
||||
|
||||
rt2x00_ring_index_inc(ring);
|
||||
return rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1420,6 +1395,8 @@ skip_entry:
|
|||
static int rt73usb_alloc_eeprom(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
u16 word;
|
||||
u8 *mac;
|
||||
char value;
|
||||
|
||||
/*
|
||||
* Allocate the eeprom memory, check the eeprom width
|
||||
|
@ -1437,6 +1414,12 @@ static int rt73usb_alloc_eeprom(struct rt2x00_dev *rt2x00dev)
|
|||
/*
|
||||
* Start validation of the data that has been read.
|
||||
*/
|
||||
mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
|
||||
if (!is_valid_ether_addr(mac)) {
|
||||
random_ether_addr(mac);
|
||||
EEPROM(rt2x00dev, "MAC: " MAC_FMT "\n", MAC_ARG(mac));
|
||||
}
|
||||
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
|
||||
if (word == 0xffff) {
|
||||
rt2x00_set_field16(&word, EEPROM_ANTENNA_NUM, 2);
|
||||
|
@ -1481,6 +1464,38 @@ static int rt73usb_alloc_eeprom(struct rt2x00_dev *rt2x00dev)
|
|||
EEPROM(rt2x00dev, "Freq: 0x%04x\n", word);
|
||||
}
|
||||
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &word);
|
||||
if (word == 0xffff) {
|
||||
rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_1, 0);
|
||||
rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_2, 0);
|
||||
rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_BG, word);
|
||||
EEPROM(rt2x00dev, "RSSI OFFSET BG: 0x%04x\n", word);
|
||||
} else {
|
||||
value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_BG_1);
|
||||
if (value < -10 || value > 10)
|
||||
rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_1, 0);
|
||||
value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_BG_2);
|
||||
if (value < -10 || value > 10)
|
||||
rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_2, 0);
|
||||
rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_BG, word);
|
||||
}
|
||||
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A, &word);
|
||||
if (word == 0xffff) {
|
||||
rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_1, 0);
|
||||
rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_2, 0);
|
||||
rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_A, word);
|
||||
EEPROM(rt2x00dev, "RSSI OFFSET BG: 0x%04x\n", word);
|
||||
} else {
|
||||
value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_A_1);
|
||||
if (value < -10 || value > 10)
|
||||
rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_1, 0);
|
||||
value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_A_2);
|
||||
if (value < -10 || value > 10)
|
||||
rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_2, 0);
|
||||
rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_A, word);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1612,12 +1627,17 @@ static void rt73usb_init_hw_mode(struct rt2x00_dev *rt2x00dev)
|
|||
IEEE80211_HW_WEP_INCLUDE_IV |
|
||||
IEEE80211_HW_DATA_NULLFUNC_ACK |
|
||||
IEEE80211_HW_NO_TKIP_WMM_HWACCEL |
|
||||
IEEE80211_HW_MONITOR_DURING_OPER;
|
||||
IEEE80211_HW_MONITOR_DURING_OPER |
|
||||
IEEE80211_HW_NO_PROBE_FILTERING;
|
||||
rt2x00dev->hw->extra_tx_headroom = TXD_DESC_SIZE;
|
||||
rt2x00dev->hw->max_rssi = MAX_RX_SSI;
|
||||
rt2x00dev->hw->max_noise = MAX_RX_NOISE;
|
||||
rt2x00dev->hw->queues = 5;
|
||||
|
||||
SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_usb(rt2x00dev)->dev);
|
||||
SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
|
||||
rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0));
|
||||
|
||||
/*
|
||||
* Set device specific, but channel independent RF values.
|
||||
*/
|
||||
|
@ -1638,7 +1658,6 @@ static void rt73usb_init_hw_mode(struct rt2x00_dev *rt2x00dev)
|
|||
/*
|
||||
* Initialize hw_mode information.
|
||||
*/
|
||||
spec->mac_addr = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
|
||||
spec->num_modes = 2;
|
||||
spec->num_rates = 12;
|
||||
spec->num_channels = 14;
|
||||
|
@ -1683,10 +1702,15 @@ static int rt73usb_init_hw(struct rt2x00_dev *rt2x00dev)
|
|||
rt73usb_init_hw_mode(rt2x00dev);
|
||||
|
||||
/*
|
||||
* rt73usb requires firmware
|
||||
* This device requires firmware
|
||||
*/
|
||||
__set_bit(FIRMWARE_REQUIRED, &rt2x00dev->flags);
|
||||
|
||||
/*
|
||||
* Set the rssi offset.
|
||||
*/
|
||||
rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1752,8 +1776,6 @@ static void rt73usb_reset_tsf(struct ieee80211_hw *hw)
|
|||
static const struct ieee80211_ops rt73usb_mac80211_ops = {
|
||||
.tx = rt2x00lib_tx,
|
||||
.reset = rt2x00lib_reset,
|
||||
.open = rt2x00lib_open,
|
||||
.stop = rt2x00lib_stop,
|
||||
.add_interface = rt2x00lib_add_interface,
|
||||
.remove_interface = rt2x00lib_remove_interface,
|
||||
.config = rt2x00lib_config,
|
||||
|
@ -1779,6 +1801,7 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = {
|
|||
.write_tx_desc = rt73usb_write_tx_desc,
|
||||
.write_tx_data = rt2x00usb_write_tx_data,
|
||||
.kick_tx_queue = rt73usb_kick_tx_queue,
|
||||
.fill_rxdone = rt73usb_fill_rxdone,
|
||||
.config_type = rt73usb_config_type,
|
||||
.config_phymode = rt73usb_config_phymode,
|
||||
.config_channel = rt73usb_config_channel,
|
||||
|
@ -1881,14 +1904,11 @@ static struct usb_driver rt73usb_driver = {
|
|||
|
||||
static int __init rt73usb_init(void)
|
||||
{
|
||||
printk(KERN_INFO "Loading module: %s - %s by %s.\n",
|
||||
DRV_NAME, DRV_VERSION, DRV_PROJECT);
|
||||
return usb_register(&rt73usb_driver);
|
||||
}
|
||||
|
||||
static void __exit rt73usb_exit(void)
|
||||
{
|
||||
printk(KERN_INFO "Unloading module: %s.\n", DRV_NAME);
|
||||
usb_deregister(&rt73usb_driver);
|
||||
}
|
||||
|
||||
|
|
|
@ -36,10 +36,11 @@
|
|||
#define RF2527 0x0004
|
||||
|
||||
/*
|
||||
* Max RSSI value, required for RSSI <-> dBm conversion.
|
||||
* Signal information.
|
||||
*/
|
||||
#define MAX_RX_SSI 120
|
||||
#define MAX_RX_SSI -1
|
||||
#define MAX_RX_NOISE -110
|
||||
#define DEFAULT_RSSI_OFFSET 120
|
||||
|
||||
/*
|
||||
* Register layout information.
|
||||
|
@ -748,6 +749,20 @@ struct hw_pairwise_ta_entry {
|
|||
#define EEPROM_TXPOWER_A_1 FIELD16(0x00ff)
|
||||
#define EEPROM_TXPOWER_A_2 FIELD16(0xff00)
|
||||
|
||||
/*
|
||||
* EEPROM RSSI offset 802.11BG
|
||||
*/
|
||||
#define EEPROM_RSSI_OFFSET_BG 0x004d
|
||||
#define EEPROM_RSSI_OFFSET_BG_1 FIELD16(0x00ff)
|
||||
#define EEPROM_RSSI_OFFSET_BG_2 FIELD16(0xff00)
|
||||
|
||||
/*
|
||||
* EEPROM RSSI offset 802.11A
|
||||
*/
|
||||
#define EEPROM_RSSI_OFFSET_A 0x004e
|
||||
#define EEPROM_RSSI_OFFSET_A_1 FIELD16(0x00ff)
|
||||
#define EEPROM_RSSI_OFFSET_A_2 FIELD16(0xff00)
|
||||
|
||||
/*
|
||||
* BBP content.
|
||||
* The wordsize of the BBP is 8 bits.
|
||||
|
@ -886,7 +901,8 @@ struct hw_pairwise_ta_entry {
|
|||
* RSSI: RSSI reported by BBP.
|
||||
*/
|
||||
#define RXD_W1_SIGNAL FIELD32(0x000000ff)
|
||||
#define RXD_W1_RSSI FIELD32(0x0000ff00)
|
||||
#define RXD_W1_RSSI_AGC FIELD32(0x00001f00)
|
||||
#define RXD_W1_RSSI_LNA FIELD32(0x00006000)
|
||||
#define RXD_W1_FRAME_OFFSET FIELD32(0x7f000000)
|
||||
|
||||
/*
|
||||
|
@ -939,9 +955,4 @@ struct hw_pairwise_ta_entry {
|
|||
(__txpower)); \
|
||||
})
|
||||
|
||||
/*
|
||||
* Interrupt functions.
|
||||
*/
|
||||
static void rt73usb_interrupt_rxdone(struct urb *urb);
|
||||
|
||||
#endif /* RT73USB_H */
|
||||
|
|
Loading…
Reference in New Issue