17467 lines
552 KiB
Diff
17467 lines
552 KiB
Diff
commit a09d1e8fd6aaea60578d2cee852ec476da3e6b66
|
|
Author: Nick Kossifidis <mick@madwifi.org>
|
|
Date: Sun Dec 16 03:11:48 2007 +0200
|
|
|
|
ath5k: Minor cleanups
|
|
|
|
* Call set_txpower_limit directly
|
|
* Remove "partialy supported" mesage
|
|
|
|
Changes-licensed-under: ISC
|
|
Signed-off-by: Nick Kossifidis <mickflemm@gmail.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit b46b4130750fd0e37c677a12382ec679845b07ff
|
|
Author: Nick Kossifidis <mick@madwifi.org>
|
|
Date: Sun Dec 16 03:10:27 2007 +0200
|
|
|
|
ath5k: Update initvals.c from recent regdumps
|
|
|
|
* Update initvals.c from recent regdumps.
|
|
* RF5413 and later have a different base address for pcdac table so update reg.h.
|
|
* Remove static pcdac tables, we'll come up with a better solution (works for me).
|
|
|
|
Changes-licensed-under: ISC
|
|
Signed-off-by: Nick Kossifidis <mickflemm@gmail.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 8d91d68029b494bbcc242633e5ce3fcfbcf10f0a
|
|
Author: Nick Kossifidis <mick@madwifi.org>
|
|
Date: Sun Dec 16 03:07:33 2007 +0200
|
|
|
|
ath5k: Fix support for RF2112A based b/g only cards
|
|
|
|
* Fix support for 2112A based b/g only cards (turbog needs review).
|
|
* Enable a part of rf5112_rfregs code that commits x_gain for testing.
|
|
|
|
Thanx to John who gave me his b/g card ;-)
|
|
|
|
Changes-licensed-under: ISC
|
|
Signed-off-by: Nick Kossifidis <mickflemm@gmail.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 3077d9ecc53b14d946cedd87317a5163e2a66dc9
|
|
Author: Nick Kossifidis <mick@madwifi.org>
|
|
Date: Sun Dec 16 03:03:01 2007 +0200
|
|
|
|
ath5k: Skip non-data queues for 5210 for now
|
|
|
|
* Skip non-data tx queues on 5210, don't return -EINVAL since it breaks ifup. This is a temp mesure until we review tx queues etc in base.c. Note that 5210 will wake up and may even scan but needs some more work.
|
|
|
|
Changes-licensed-under: ISC
|
|
Signed-off-by: Nick Kossifidis <mickflemm@gmail.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 528f1b9fa5d46d35ee076ec41860a74fb4d0a801
|
|
Author: Nick Kossifidis <mick@madwifi.org>
|
|
Date: Sun Dec 16 03:01:04 2007 +0200
|
|
|
|
ath5k: Reorder reset function to match regdumps
|
|
|
|
* Modify reset function to match regdumps, we still have some things to fix.
|
|
|
|
Changes-licensed-under: ISC
|
|
Signed-off-by: Nick Kossifidis <mickflemm@gmail.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 41cb0aa95ce0fcade56d267f3804284092360d24
|
|
Author: Nick Kossifidis <mick@madwifi.org>
|
|
Date: Sun Dec 16 02:58:57 2007 +0200
|
|
|
|
ath5k: Implement per-queue interrupts
|
|
|
|
* Implement per-queue interrupt handling. For now treat TXDESC and TXEOL as INT_TX so we can handle them in base.c.
|
|
|
|
Changes-licensed-under: ISC
|
|
Signed-off-by: Nick Kossifidis <mickflemm@gmail.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 8fb46b91e6ed72ccfefa6c3f4850b9b58c1463d1
|
|
Author: Nick Kossifidis <mick@madwifi.org>
|
|
Date: Sun Dec 16 02:55:52 2007 +0200
|
|
|
|
ath5k: Fix diversity
|
|
|
|
* Fix diversity support
|
|
|
|
We have to write all antenna information on AR5K_PHY_ANT_SWITCH_TABLE if antenna mode is not fixed.
|
|
|
|
Changes-licensed-under: ISC
|
|
Signed-off-by: Nick Kossifidis <mickflemm@gmail.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit b6aa459673f61c1288acebec013905a7256f3a5a
|
|
Author: Nick Kossifidis <mick@madwifi.org>
|
|
Date: Sun Dec 16 02:53:18 2007 +0200
|
|
|
|
ath5k: Fix nic_wakeup for 5210
|
|
|
|
* Reset PCI after chip reset for 5210 at nic_wakeup. This fixes the system hang during 5210 attach.
|
|
|
|
Changes-licensed-under: ISC
|
|
Signed-off-by: Nick Kossifidis <mickflemm@gmail.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit a7da8f9d4b256c6014edfe63079c4220e9430e68
|
|
Author: Nick Kossifidis <mick@madwifi.org>
|
|
Date: Sun Dec 16 02:47:55 2007 +0200
|
|
|
|
ath5k: Minor fixes inside base.c
|
|
|
|
* Reorder some inline functions to silence compiler
|
|
* Stop passing 0xff.. for txpower during tx descriptor setup. Txpower is written in hw in 0.5dbm steps.
|
|
|
|
Changes-licensed-under: 3-clause-BSD
|
|
Signed-off-by: Nick Kossifidis <mickflemm@gmail.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 8e685b758aea2c0e82f41813690e229543af9622
|
|
Author: Bruno Randolf <bruno@thinktube.com>
|
|
Date: Fri Dec 14 18:48:57 2007 +0900
|
|
|
|
ath5k: avoid zero rates
|
|
|
|
setting up tx descriptors with a rate of zero will put the HW into a mode where
|
|
it continously sends noise on the channel, thus blocking the whole channel.
|
|
since it is important to avoid this situation, add a WARN_ON in these cases,
|
|
even if we hope to never get bad rates from the rate control module.
|
|
|
|
Changes-licensed-under: ISC
|
|
Signed-off-by: Bruno Randolf <bruno@thinktube.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit fc0374171b9f750790b88b795aac3becf4524a92
|
|
Author: Bruno Randolf <bruno@thinktube.com>
|
|
Date: Mon Dec 10 19:21:17 2007 +0900
|
|
|
|
ath5k: add debugfs entries for registers, tsf, beacon, reset
|
|
|
|
i resend this patch to address jiris comments and with some small improvements.
|
|
this hopefully last version now returns NULL instead of 0 in reg_start() and
|
|
reg_next().
|
|
|
|
'registers' prints the name and value of some registers. this should be adapted
|
|
to what we actually need later and is supposed to replace the hwdump facility i
|
|
removed in my earlier debugging changes.
|
|
|
|
'tsf' prints the current HW TSF. writing "reset" into the file will reset the
|
|
TSF.
|
|
|
|
'beacon' shows beacon relevant registers. it is good for watching the beacon
|
|
timers with something like "watch -n0 cat /dbg/ath5k/phy0/beacon". writing
|
|
"enable" into the file will try to enable beacons by setting the flag
|
|
AR5K_BEACON_ENABLE, "disable" will disable that bit.
|
|
|
|
'reset' can be used to trigger a HW reset, by writing "reset" into it.
|
|
|
|
Changes-licensed-under: GPL
|
|
|
|
Signed-off-by: Bruno Randolf <bruno@thinktube.com>
|
|
Acked-by: Luis R. Rodriguez <mgrof@winlab.rutgers.edu>
|
|
Acked-by: Jiri Slaby <jirislaby@gmail.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 73a8222564a86bf9e38470dbfe44a4826c5d3a0a
|
|
Author: Dave Young <hidave.darkstar@gmail.com>
|
|
Date: Fri Dec 7 10:12:58 2007 +0800
|
|
|
|
ath5k: fix 'static inline' build issues
|
|
|
|
2.6.24-rc4-mm1 build failed at drivers/net/wireless/ath5k/base.c for some inline functions like this:
|
|
drivers/net/wireless/ath5k/base.c:292: sorry, unimplemented: inlining failed in call to 'ath5k_extend_tsf': function body not available
|
|
|
|
fix it with adjust the order of inline function body.
|
|
|
|
Signed-off-by: Dave Young <hidave.darkstar@gmail.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 1a54daf7f3963bd1c04cc28500f48280d6c8dcf3
|
|
Author: Francesco Gringoli <francesco.gringoli@ing.unibs.it>
|
|
Date: Thu Nov 29 21:39:51 2007 +0100
|
|
|
|
ath5k: fix rx filters set up
|
|
|
|
Hello,
|
|
|
|
This simple patch adds pcap compatibility to ath5k code. In base.c
|
|
rx_filters are never refreshed when the state of the interface
|
|
changes. Now tcpdump captures everything in monitor mode when iface
|
|
is set to promisc.
|
|
|
|
Signed-off-by: Francesco Gringoli <francesco.gringoli@ing.unibs.it>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 04f840943842a4870fd1ddd735140dd0ba73f984
|
|
Author: Bruno Randolf <bruno@thinktube.com>
|
|
Date: Fri Nov 30 11:26:37 2007 +0900
|
|
|
|
ath5k: export signal quality values
|
|
|
|
store the last noise floor in ath5k_hw and report signal, noise and link
|
|
quality values to mac80211, which in turn makes them show up in iwconfig.
|
|
|
|
ath5k.h, phy.c:
|
|
Changes-licensed-under: ISC
|
|
|
|
base.c:
|
|
Changes-licensed-under: 3-clause-BSD
|
|
|
|
Signed-off-by: Bruno Randolf <bruno@thinktube.com>
|
|
Acked-by: Nick Kossifidis <mickflemm@gmail.com>
|
|
Acked-by: Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 8003ffec8e1dca7224fd9e2a8adf8e887197c32c
|
|
Author: Bruno Randolf <bruno@thinktube.com>
|
|
Date: Fri Nov 30 11:26:36 2007 +0900
|
|
|
|
ath5k: full noise calibration also for rf511x
|
|
|
|
also perform full noise calibration in ath5k_hw_rf511x_calibrate() instead of
|
|
just writing the bit.
|
|
|
|
Changes-licensed-under: ISC
|
|
Signed-off-by: Bruno Randolf <bruno@thinktube.com>
|
|
Acked-by: Nick Kossifidis <mickflemm@gmail.com>
|
|
Acked-by: Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 335223282459681668ebb0247530020e777d84f5
|
|
Author: Bruno Randolf <bruno@thinktube.com>
|
|
Date: Fri Nov 30 11:26:35 2007 +0900
|
|
|
|
ath5k: fix noise floor calibration
|
|
|
|
fix noise floor calibration by applying AR5K_PHY_NF_AVAL after
|
|
AR5K_PHY_NF_RVAL. that way the XORed mask and value have the same length and
|
|
we get a reasonable noise value in -dBm.
|
|
|
|
move duplicate noise floor calibration code from two different places into one
|
|
function ath5k_hw_noise_floor_calibration().
|
|
|
|
the check for accepted noise_floor values (<= AR5K_TUNE_NOISE_FLOOR) should
|
|
only happen when we have an active reading and a converted value, so move it up
|
|
into the first if.
|
|
|
|
Changes-licensed-under: ISC
|
|
Signed-off-by: Bruno Randolf <bruno@thinktube.com>
|
|
Acked-by: Nick Kossifidis <mickflemm@gmail.com>
|
|
Acked-by: Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 93be8761d08247a45a095b4d9ebdf16ba0c66b68
|
|
Author: Bruno Randolf <bruno@thinktube.com>
|
|
Date: Fri Nov 30 11:26:34 2007 +0900
|
|
|
|
ath5k: more consistent debugging
|
|
|
|
* move all debugging functions to new files debug.c and debug.h.
|
|
|
|
* consistently use ATH5K_DEBUG instead of AR_DEBUG and AR5K_DEBUG defines.
|
|
ATH5K_DEBUG can be set from outside the Makefile via KCFLAGS.
|
|
|
|
* rename DPRINTF to ATH5K_DBG to be consistent with the other logging
|
|
functions. ATH5K_DBG honors the debug level set on module load or by debugfs
|
|
and is limited by net_ratelimit(). another define ATH5K_DBG_UNLIMIT can be
|
|
used specifically when we do not want the output to be rate limited.
|
|
|
|
* move all instances where the debugging output was controlled by additional
|
|
defines (ATH_DEBUG_MODES, ATH_DUMP_SKB) to use the debug level too.
|
|
|
|
* make ATH5K_TRACE honor the debug level as well.
|
|
|
|
* remove ath5k_hw_dump_state().
|
|
|
|
* rename all debugging functions to ath5k_debug_xxx. these are static inline {}
|
|
when ATH5K_DEBUG is 0.
|
|
|
|
* make ath5k_debug_dump_skb distinguish between RX and TX, so we can choose
|
|
wether we want to see RX or TX packets. also prepend the "phyX" name.
|
|
|
|
* added debugfs entry (ath5k/phyX/debug) to control the debug level for each
|
|
device.
|
|
|
|
* add kerneldoc for debugging levels.
|
|
|
|
base.[ch]:
|
|
Changes-licensed-under: 3-clause-BSD
|
|
|
|
hw.c, ath5k.h, phy.c:
|
|
Changes-licensed-under: ISC
|
|
|
|
debug.[ch]:
|
|
Changes-licensed-under: GPL
|
|
|
|
Signed-off-by: Bruno Randolf <bruno@thinktube.com>
|
|
Acked-by: Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
|
|
Acked-by: Nick Kossifidis <mickflemm@gmail.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 07700ba6c1fe652f0c0b9ad5b9d6525664740cf4
|
|
Author: Bruno Randolf <bruno@thinktube.com>
|
|
Date: Fri Nov 30 11:26:33 2007 +0900
|
|
|
|
ath5k: more consistent info and error logging
|
|
|
|
added new macros ATH5K_INFO, ATH5K_WARN and ATH5K_ERR for more consistent
|
|
logging inside ath5k. they prepend "ath5k phyX:" to all lines so we can
|
|
distinguish between different cards in multi-card setups. ATH5K_WARN and
|
|
ATH5K_ERR use net_ratelimit(), so they can be used anywhere without having to
|
|
check net_ratelimit() seperately.
|
|
|
|
the macros get a reference to sc, so we can automatically add additional
|
|
information: right now it is used to get the phy name, but having this in one
|
|
central place gived us the flexibility to switch to dev_info/warn/... or others
|
|
instead too. i think using "phyX" makes the output most readable and easier to
|
|
match with the output from mac80211. in cases where we don't have sc available
|
|
we still use ATH5K_PRINTF.
|
|
|
|
changed all printk, most dev_info and most AR5K_PRINTF lines to use these
|
|
macros instead. deleted AR5K_PRINT because it's easy to use ATH5K_PRINTF
|
|
instead.
|
|
|
|
for base.c
|
|
Changes-licensed-under: 3-clause-BSD
|
|
|
|
for all others...
|
|
Changes-licensed-under: ISC
|
|
|
|
Signed-off-by: Bruno Randolf <bruno@thinktube.com>
|
|
Acked-by: Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
|
|
Acked-by: Nick Kossifidis <mickflemm@gmail.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit fd5be00a58244ffd045c5b5fa1eb4e2279d8c5b3
|
|
Author: Nick Kossifidis <mick@madwifi.org>
|
|
Date: Wed Nov 14 19:49:49 2007 +0200
|
|
|
|
ath5k: Add myself to MAINTAINERS and rewrite module description on Kconfig
|
|
|
|
*Add better description in Kconfig
|
|
*Add myself to MAINTAINERS
|
|
|
|
Signed-off-by: Nick Kossifidis <mickflemm@gmail.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit e856715ffedc6b73c546d5f472e4cd876703091d
|
|
Author: Nick Kossifidis <mick@madwifi.org>
|
|
Date: Wed Nov 14 18:23:59 2007 +0200
|
|
|
|
ath5k: Fix calinterval and add more RF5413/5414 inivals
|
|
|
|
*Fix calinterval to be 10secs for now.
|
|
*Add some more initial settings i got for RF5413/5414
|
|
|
|
Still no fix for poor 802.11a performance (probably tx power related) ;-(
|
|
Leave it as "partialy supported" until this issue is resolved...
|
|
|
|
for base.c
|
|
Changes-licensed-under: 3-clause-BSD
|
|
|
|
for all others...
|
|
Changes-licensed-under: ISC
|
|
|
|
Signed-off-by: Nick Kossifidis <mickflemm@gmail.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 838904d60eeab7d4206451a5503d80a0ef8a2884
|
|
Author: Nick Kossifidis <mick@madwifi.org>
|
|
Date: Wed Nov 14 18:17:37 2007 +0200
|
|
|
|
ath5k: Add RF5413/5414 support
|
|
|
|
*Add support for RF5413/5414 single-chip solutions
|
|
|
|
This needs testing (also on 5424/2424) before we declare that's fully supported.
|
|
It works for me and the RF5413 i got ;-)
|
|
|
|
Changes-licensed-under: ISC
|
|
Signed-Off-by: Nick Kossifidis <mickflemm@gmail.com>
|
|
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 93e5669cf00f5323f65303c4ef096e0c8919d292
|
|
Author: Nick Kossifidis <mick@madwifi.org>
|
|
Date: Wed Nov 14 18:14:40 2007 +0200
|
|
|
|
ath5k: Fix device info reporting
|
|
|
|
*Fix device info code
|
|
|
|
Changes-licensed-under: 3-clause-BSD
|
|
Signed-Off-by: Nick Kossifidis <mickflemm@gmail.com>
|
|
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 41bf49ef5be651dfe06e597389a0237ce5298d20
|
|
Author: Nick Kossifidis <mick@madwifi.org>
|
|
Date: Wed Nov 14 18:11:40 2007 +0200
|
|
|
|
ath5k: Fix another faulty channel flag check
|
|
|
|
*Fix another faulty channel flags check
|
|
|
|
Don't check channel->val against CHANNEL_A/B/G flags because they have common flags set
|
|
eg. doing AND between CHANNEL_A and CHANNEL_G always returns true because they have
|
|
CHANNEL_OFDM, same goes for CHANNEL_B and CHANNEL_G that have CHANNEL_2GHZ in common.
|
|
|
|
Instead check against CHANNEL_CCK/OFDM/2GHZ/5GHZ...
|
|
|
|
Changes-licensed-under: ISC
|
|
Signed-off-by: Nick Kossifidis <mickflemm@gmail.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 1ce29f8277f8d9e44995f81e5986361fbdd87615
|
|
Author: Luis R. Rodriguez <mcgrof@gmail.com>
|
|
Date: Fri Nov 2 16:46:38 2007 -0400
|
|
|
|
ath5k: Set ACK to user lower bit rates
|
|
|
|
Sorry, forgot this last hunk in my patch series... This applies on top
|
|
of my series.
|
|
|
|
This sets the ACK bitrate to the lower rates. Without this I get
|
|
about 70% packet loss when using the 11M rate. Not sure exactly what rates
|
|
this is setting the HW to send the ACKs in but it sure does help.
|
|
|
|
I'll be poking more with this and trying to fix rates for g. We'll figure
|
|
this out ;)
|
|
|
|
Note: our higher rates are still pretty unusable, something is still
|
|
wrong with those.
|
|
|
|
Changes to base.c
|
|
Changes-licensed-under: 3-clause-BSD
|
|
|
|
Changes to ath5k.h, hw.c
|
|
Changes-licensed-under: ISC
|
|
|
|
Signed-off-by: Luis R. Rodriguez <mcgrof@gmail.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 01584d2b0e88eea833c378d4da292f8a7e2a4a49
|
|
Author: Luis R. Rodriguez <mcgrof@gmail.com>
|
|
Date: Thu Nov 1 23:11:31 2007 -0400
|
|
|
|
ath5k: Add documentation for struct ath5k_rate
|
|
|
|
This adds documentation for struct ath5k_rate. This also removes
|
|
some unused variables, lp_ack_duration and sp_ack_duration which
|
|
are simply unnecessary.
|
|
|
|
We're now just missing information about rate hw values:
|
|
|
|
3-5
|
|
16
|
|
17-23
|
|
28-32
|
|
|
|
If anyone knows what those are, please let us know.
|
|
|
|
Changes to ath5k.h
|
|
Changes-licensed-under: ISC
|
|
|
|
Signed-off-by: Luis R. Rodriguez <mcgrof@gmail.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 2e046652afab548b98ceee3043173e17cf7f7145
|
|
Author: Luis R. Rodriguez <mcgrof@gmail.com>
|
|
Date: Thu Nov 1 17:55:53 2007 -0400
|
|
|
|
ath5k: Clear up settings of AR5K_RSSI_THR register settings
|
|
|
|
Clear up settings of AR5K_RSSI_THR register settings. These are split between
|
|
AR5K_TUNE_BMISS_THRES and AR5K_TUNE_RSSI_THRES.
|
|
|
|
Changes to ath5k.h, hw.c
|
|
Changes-licensed-under: ISC
|
|
|
|
Signed-off-by: Luis R. Rodriguez <mcgrof@gmail.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 9b83892f2c0a16f087dc45d7b8a6353c69c0fcfb
|
|
Author: Luis R. Rodriguez <mcgrof@gmail.com>
|
|
Date: Thu Nov 1 17:53:18 2007 -0400
|
|
|
|
ath5k: Move OFDM timings into a helper routine
|
|
|
|
This move the OFDM timings on ath5k_hw_reset() onto a helper,
|
|
ath5k_hw_write_ofdm_timings() to make code cleaner.
|
|
|
|
Changes to ath5k.h, hw.c
|
|
Changes-licensed-under: ISC
|
|
|
|
Signed-off-by: Luis R. Rodriguez <mcgrof@gmail.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit f75a5a95a1fc5287143afbeb99c0e238ef4cbd79
|
|
Author: Luis R. Rodriguez <mcgrof@gmail.com>
|
|
Date: Thu Nov 1 00:38:16 2007 -0400
|
|
|
|
ath5k: Fix clock on OFDM timing computation
|
|
|
|
We were setting the clock to the turbo sampling rate always, lets fix this
|
|
for plain OFDM sampling rate at 40 MHz. I believe this tunes the PLL to
|
|
the desired frequency, by setting the mantissa and the exponent.
|
|
|
|
Changes to hw.c
|
|
Changes-licensed-under: ISC
|
|
|
|
Signed-off-by: Luis R. Rodriguez <mcgrof@gmail.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 6f95039ebee8f0d79b940f06bcde1e0711334a83
|
|
Author: Luis R. Rodriguez <mcgrof@gmail.com>
|
|
Date: Thu Nov 1 17:50:30 2007 -0400
|
|
|
|
ath5k: Clean up ath5k rate duration settings
|
|
|
|
Replace ath5k's rate duration computations for one using
|
|
mac80211's internals. Another consideration here is to simply
|
|
remove these and put them into initval values. They seem to be
|
|
static values based only on mode. We can do this later though once
|
|
we can physically confirm by trial and error these are indeed just
|
|
used for ACK timeout. The next puzzle is figuring out which registers
|
|
are actually setting the control rates.
|
|
|
|
Changes to ath5k.h, hw.c
|
|
Changes-licensed-under: ISC
|
|
|
|
Signed-off-by: Luis R. Rodriguez <mcgrof@gmail.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 012198ddffdb66120528823c73318379b6a59a77
|
|
Author: Luis R. Rodriguez <mcgrof@gmail.com>
|
|
Date: Thu Nov 1 00:35:20 2007 -0400
|
|
|
|
ath5k: Remove opaque pointers from ath5k_hw_attach()
|
|
|
|
Since we don't have a HAL anymore there is no point to use opaque pointers
|
|
in ath5k_hw_attach(). This will also give hw.c access to ath5k_softc
|
|
structure now when needed. While we're at it, lets also give some ah_sh
|
|
a reasonable name, ah_sh --> ah_iobase.
|
|
|
|
Changes to base.c
|
|
Changes-licensed-under: 3-clause-BSD
|
|
|
|
Changes to ath5k.h, hw.c
|
|
Changes-licensed-under: ISC
|
|
|
|
Signed-off-by: Luis R. Rodriguez <mcgrof@gmail.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit e23be3f08baf10d7ded7eab076b68dc6696d230e
|
|
Author: Luis R. Rodriguez <mcgrof@gmail.com>
|
|
Date: Thu Nov 1 00:34:24 2007 -0400
|
|
|
|
ath5k: Fix initval/eeprom/IQ calibration for G mode
|
|
|
|
ath5k_hw_reset() was always setting initval and eeprom settings for B mode
|
|
when using G mode. This is because a B channel was being picked up first. We
|
|
should first instead check for G channel. This patch also introduces a
|
|
driver_mode variable which should be used instead for determing
|
|
more reliably the mode we're in.
|
|
|
|
This fixing another bug where IQ calibration was not being run for
|
|
G mode as CHANNEL_B was always being picked up first. We now instead
|
|
check for driver_mode.
|
|
|
|
Similar problem was occurring in ath5k_hw_rf5112_rfregs(), we fix this
|
|
there too.
|
|
|
|
Changes to phy.c, hw.c
|
|
Changes-licensed-under: ISC
|
|
|
|
Signed-off-by: Luis R. Rodriguez <mcgrof@gmail.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 45cededd2df27b8c2a4b7c37a02c7f3830d1d243
|
|
Author: Ulrich Meis <meis@nets.rwth-aachen.de>
|
|
Date: Tue Oct 30 22:20:56 2007 +0100
|
|
|
|
ath5k: 4word tx descriptor setup doesn't set BUF_LEN
|
|
|
|
This line got lost when the descriptor setup and fill functions were
|
|
merged. Applies ontop of Nick's patches.
|
|
|
|
Changes-licensed-under: ISC
|
|
Signed-off-by: Ulrich Meis <meis@nets.rwth-aachen.de>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 168048516dbf42ca2deb3cd36101f9b76ecdb030
|
|
Author: Nick Kossifidis <mick@madwifi.org>
|
|
Date: Sun Oct 28 02:58:27 2007 +0300
|
|
|
|
ath5k: Remove fill_tx_desc
|
|
|
|
fill_tx_desc is used for fast frames operation, since
|
|
we don't support fast frames (and since fill_tx_desc
|
|
had a bug -thanx to Ulrich Meis for finding that out-)
|
|
these functions are not needed (+ they are misleading
|
|
because they don't "fill" any tx descriptor).
|
|
|
|
I couldn't test this patch much so plz someone ACK it...
|
|
|
|
It applies on top of my previous patches (i just thought
|
|
that [PATCH 8/7] won't look nice ;-) ).
|
|
|
|
Changes-licensed-under: ISC
|
|
Signed-off-by: Ulrich Meis <meis@nets.rwth-aachen.de>
|
|
Signed-Off-by: Nick Kossifidis <mickflemm@gmail.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 7ed69f54e345a9897b0b4617311858303e781aff
|
|
Author: Nick Kossifidis <mick@madwifi.org>
|
|
Date: Sun Oct 28 02:44:18 2007 +0300
|
|
|
|
ath5k: Warn on partially supported chips
|
|
|
|
*Warn on partially supported chips (eg. 5414/5424)
|
|
|
|
These chips need work on PHY part, recently Reyk posted
|
|
a workaround so that they can work on 2GHz but i believe
|
|
that the problem is related to PHY initialization. Plz
|
|
we need help with these...
|
|
|
|
I did some tests on a 5414 at 5GHz and it seemed to work
|
|
but i didn't test it at 2GHz.
|
|
|
|
I'll try to find one of these and play with.
|
|
|
|
Changes-licensed-under: ISC
|
|
Signed-Off-by: Nick Kossifidis <mickflemm@gmail.com>
|
|
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 24d2eab68057de8e63d262e84c0ba3a12a69f0c1
|
|
Author: Nick Kossifidis <mick@madwifi.org>
|
|
Date: Sun Oct 28 02:31:13 2007 +0300
|
|
|
|
ath5k: Add PCI IDs for newer chips
|
|
|
|
*Add PCI IDs for 5416/5418.
|
|
|
|
*Print a message during attach that
|
|
these chips are not yet supported.
|
|
|
|
for base.c
|
|
Changes-licensed-under: 3-clause-BSD
|
|
|
|
for ath5k.h
|
|
Changes-licensed-under: ISC
|
|
|
|
Signed-Off-by: Nick Kossifidis <mickflemm@gmail.com>
|
|
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit d17a1cea1bfc35c735f3ebcf1ef823f06389748d
|
|
Author: Nick Kossifidis <mick@madwifi.org>
|
|
Date: Sun Oct 28 02:24:59 2007 +0300
|
|
|
|
athk: Use SREV to identify single-chip solutions
|
|
|
|
Use SREV instead of pci id to identify single chip solutions.
|
|
|
|
Srev is more accurate info to identify the chip + this makes
|
|
it possible to identify some 5424 chips found on thinkpads with
|
|
faulty 5212 pci id.
|
|
|
|
Changes-licensed-under: ISC
|
|
Signed-Off-by: Nick Kossifidis <mickflemm@gmail.com>
|
|
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 85364fdd0649d1590e9ae18d1961c6861b7b9288
|
|
Author: Nick Kossifidis <mick@madwifi.org>
|
|
Date: Sun Oct 28 02:20:33 2007 +0300
|
|
|
|
ath5k: Add SREV values for newer chips
|
|
|
|
* Add new Silicon Revision values (hex values written on chip) to be able to identify them.
|
|
|
|
* Give more infos about mac/phy/radio revision during attach.
|
|
|
|
for ath5k.h
|
|
Changes-licensed-under: ISC
|
|
|
|
for base.c
|
|
Changes-licensed-under: 3-clause-BSD
|
|
|
|
Signed-Off-by: Nick Kossifidis <mickflemm@gmail.com>
|
|
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 73a0794c3746635652f10bcfe99821b3526163b5
|
|
Author: Nick Kossifidis <mick@madwifi.org>
|
|
Date: Sun Oct 28 02:13:32 2007 +0300
|
|
|
|
ath5k: Remove obsolete sysctl stuff
|
|
|
|
Remove sysctl tables.
|
|
|
|
We shouldn't use /proc to configure things.
|
|
|
|
Changes-licensed-under: 3-clause-BSD
|
|
Signed-Off-by: Nick Kossifidis <mickflemm@gmail.com>
|
|
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit e05ef94a6f9a5b2c485f552e46e334a2a4d17d85
|
|
Author: Nick Kossifidis <mick@madwifi.org>
|
|
Date: Sun Oct 28 02:06:42 2007 +0300
|
|
|
|
ath5k: Rename some functions
|
|
|
|
I've renamed some functions for better maintainability...
|
|
|
|
ath5k_mode_init -> ath5k_mode_setup
|
|
ath5k_rxbuf_init -> ath5k_rxbuf_setup
|
|
Because it's not just initialization + we use
|
|
"setup" on the rest of the code (eg. beacon_setup).
|
|
|
|
ath5k_tx_bf -> ath5k_txbuf_setup
|
|
Obvious
|
|
|
|
ath5k_cleanup_txbuf -> ath5k_txbuf_free
|
|
Previous name is misleading because someone might
|
|
think that it cleans all tx buffers, we use "free"
|
|
to declare that it only cleans one given buffer.
|
|
|
|
ath5k_tx_draintxq -> ath5k_txq_drainq
|
|
ath5k_draintxq -> ath5k_txq_cleanup
|
|
Same here ath5k_draintxq seems to refer to only
|
|
one queue when in fact it drains all queues, so
|
|
we use "cleanup" as above.
|
|
|
|
ath5k_tx_cleanup -> ath5k_txq_release
|
|
This one doesn't do any cleanup, it just calls
|
|
hw_release for each queue.
|
|
|
|
ath5k_startrecv -> ath5k_rx_start
|
|
ath5k_stoprecv -> ath5k_rx_stop
|
|
As above i try to maintain a naming scheme that links
|
|
with the sorting i've done. Eg. ath5k_desc for descriptor
|
|
related funcions, ath5k_rx/tx for general rx/tx functions,
|
|
ath5k_txq for tx queues, ath5k_hw (inside hw.c and rest) for
|
|
hw related functions and so on. This helps us track down things
|
|
more easily.
|
|
|
|
Changes-licensed-under: 3-clause-BSD
|
|
Signed-Off-by: Nick Kossifidis <mickflemm@gmail.com>
|
|
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 4528852951e6ad64171f584f6b685eb802f6293f
|
|
Author: Nick Kossifidis <mick@madwifi.org>
|
|
Date: Sun Oct 28 02:04:25 2007 +0300
|
|
|
|
ath5k: Maintain coding style
|
|
|
|
* Sort functions in segments like we do on the rest of the code (eg.
|
|
hw.c). This improves readability and maintainability.
|
|
|
|
* Add myself as module author (a patch for this was submited some time
|
|
ago as part of SFLC's changes but wasn't applied)
|
|
|
|
* Declare that this driver is or 5xxx chipset series only in
|
|
MODULE_SUPPORTED_DEVICE and MODULE_DESCRIPTION.
|
|
|
|
Changes-licensed-under: 3-clause-BSD
|
|
Signed-Off-by: Nick Kossifidis <mickflemm@gmail.com>
|
|
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 1f480e2920877d373e2a547cf53509fc513e02a9
|
|
Author: Jiri Slaby <jirislaby@gmail.com>
|
|
Date: Fri Oct 19 18:57:13 2007 -0400
|
|
|
|
[PATCH] Net: ath5k, minor fixes
|
|
|
|
ath5k, minor fixes
|
|
|
|
- some -W compiler warnings fixes (signedness)
|
|
- make ath_stop static
|
|
- add BUG to ath5k_register_mode when passing supported but not filled mode
|
|
and move the supported modes check into this function to simplify the
|
|
macro
|
|
|
|
Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 96a596f082e92fcdf6308b6224104f93e8916394
|
|
Author: John W. Linville <linville@tuxdriver.com>
|
|
Date: Tue Oct 23 13:41:37 2007 -0400
|
|
|
|
[PATCH] ath5k: undo overzealous hunk of "ath5k: avoid oops when..."
|
|
|
|
The first hunk of "ath5k: avoid oops when ah_capabilities.cap_mode not
|
|
set" was ill-advised. It can cause its loop to abort prematurely.
|
|
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 05a920250b6385c7eb23a94f0532f94dbd4b6160
|
|
Author: Bruno Randolf <bruno@thinktube.com>
|
|
Date: Fri Oct 19 23:57:27 2007 +0900
|
|
|
|
[PATCH] ath5k: mac revision fixes
|
|
|
|
this are two small fixes:
|
|
|
|
1) actually print the mac revision when we say so
|
|
|
|
2) better check for mac revisions when putting device to sleep: this is
|
|
important with newer mac revisions (>=7.8) which will freeze the whole system
|
|
when put to sleep
|
|
|
|
Signed-off-by: Bruno Randolf <bruno@thinktube.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 14ca910b99e3dc5a1082e7e7b13a2957ffe44fe0
|
|
Author: Nick Kossifidis <mick@madwifi.org>
|
|
Date: Fri Oct 19 13:56:19 2007 +0000
|
|
|
|
[PATCH] ath5k: Maintain naming scheme
|
|
|
|
Use "ath5k_" instead of "ath_" and "ah" instead of "hal"
|
|
|
|
Changes to base.c, base.h
|
|
Changes-licensed-under: 3-clause-BSD
|
|
|
|
Changes to ath5k.h, hw.c, hw.h, reg.h
|
|
Changes-licensed-under: ISC
|
|
|
|
Signed-Off-by: Nick Kossifidis <mickflemm@gmail.com>
|
|
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 34edd82ca97a76b921ac52c99f07dbfe324feaae
|
|
Author: mick@ics.forth.gr <mick@ics.forth.gr>
|
|
Date: Thu Oct 18 00:18:43 2007 +0300
|
|
|
|
[PATCH] ath5k: Clean up unused definitions in base.h
|
|
|
|
Get rid of some definitions that are not used anywhere...
|
|
|
|
Changes-licensed-under: 3-clause-BSD
|
|
|
|
Signed-Off-by: Nick Kossifidis <mickflemm@gmail.com>
|
|
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 4c367a11d4502a6e54fa64514cee61c67be9b411
|
|
Author: mick@ics.forth.gr <mick@ics.forth.gr>
|
|
Date: Thu Oct 18 00:17:12 2007 +0300
|
|
|
|
[PATCH] ath5k: Only one tx descriptor per buffer, no need for ATH_TXDESC
|
|
|
|
Since we don't (and probably won't) support fast frames we'll have
|
|
only one descriptor for each buffer so there is no need for
|
|
ATH_TXDESC.
|
|
|
|
Changes-licensed-under: 3-clause-BSD
|
|
|
|
Signed-Off-by: Nick Kossifidis <mickflemm@gmail.com>
|
|
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 4472d002f92b4365184acd6d38e4e417afd5b857
|
|
Author: mick@ics.forth.gr <mick@ics.forth.gr>
|
|
Date: Thu Oct 18 00:13:26 2007 +0300
|
|
|
|
[PATCH] ath5k: Get rid of unused channel list parameters used in binary HAL
|
|
|
|
There are some parameters left in the code that were used by binary
|
|
HAL to generate the channel list. Since we don't use binary HAL and
|
|
channel list is handled differently, they are out.
|
|
|
|
Changes to base.c
|
|
Changes-licensed-under: 3-clause-BSD
|
|
|
|
Changes to ath5k.h, hw.c
|
|
Changes-licensed-under: ISC
|
|
|
|
Signed-off-by: Nick Kossifidis <mickflemm@gmail.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 9d0d2389d863cc3ef433e5103bd6d37f7a5bc983
|
|
Author: John W. Linville <linville@tuxdriver.com>
|
|
Date: Wed Oct 17 15:01:48 2007 -0400
|
|
|
|
[PATCH] ath5k: avoid oops when ah_capabilities.cap_mode not set
|
|
|
|
ah_capabilities.cap_mode doesn't get set for some cards, causing the
|
|
kernel to oops when these unknown/unsupported cards are inserted.
|
|
Add some NULL checks to avoid this.
|
|
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 4cdfeb9398897c3969f89a8d32ad7632ead0fc6a
|
|
Author: Bruno Randolf <bruno@thinktube.com>
|
|
Date: Tue Oct 16 22:20:37 2007 +0900
|
|
|
|
[PATCH] ath5k: better readability for skb dumps
|
|
|
|
print "RX " and "TX " in front of hexdump
|
|
|
|
Signed-off-by: Bruno Randolf <bruno@thinktube.com>
|
|
Acked-by: Luis R. Rodriguez <mcgrof@gmail.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 75b99ae66c33cfd5664102c2588ebd505577fc7e
|
|
Author: Jiri Slaby <jirislaby@gmail.com>
|
|
Date: Sun Oct 14 10:45:54 2007 -0400
|
|
|
|
[PATCH] Net: ath5k, change set_bit to nonatomic __set_bit
|
|
|
|
ath5k, change set_bit to nonatomic __set_bit
|
|
|
|
We don't need to have atomic set_bit function, so use __set_bit instead.
|
|
|
|
Changes-licensed-under: ISC
|
|
Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 2ad8cab5071e6059c7333cac965f2b7e7a3342a5
|
|
Author: Luis R. Rodriguez <mcgrof@gmail.com>
|
|
Date: Sat Oct 13 16:08:29 2007 -0400
|
|
|
|
[PATCH] ath5k: Fix and clean mode initialization, prefer G for AR5212
|
|
|
|
Currently you get locked on B mode with AR5212s. This could be partly
|
|
mac80211's fault with a recent regression introduced but ath5k mode
|
|
initialization right now is pretty sloppy. For AR5212s we also currently
|
|
start scanning in 5GHz. I've made the mode initialization on ath5k a bit
|
|
clearer and only am registering G mode now instead of both B and G for
|
|
AR5212s. We now also check eeprom reading for capabilities before registering
|
|
a specific mode. For AR5212 I get reliable rates only up to 18Mbps for a
|
|
throughput of up to 5 Mbits/sec. At least now we can work and test the
|
|
other rates again.
|
|
|
|
Also use a static driver specific NUM_DRIVER_MODES instead of mac80211's
|
|
NUM_IEEE80211_MODES.
|
|
|
|
This patch has been tested on AR5210, AR5211 and AR5212.
|
|
|
|
Note: mac80211 simple rate algo throws us to 1Mbps after assoc, this is by
|
|
design. I recommend users to set rate to 11M for now after assoc.
|
|
|
|
Changes to base.[ch]
|
|
Changes-licensed-under: 3-clause-BSD
|
|
|
|
Changes to ath5k.h
|
|
Changes-licensed-under: ISC
|
|
|
|
Signed-off-by: Luis R. Rodriguez <mcgrof@gmail.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 33e9ca7f21695f2f285833cd296f70a2cd345730
|
|
Author: Luis R. Rodriguez <mcgrof@gmail.com>
|
|
Date: Fri Oct 12 11:07:09 2007 -0400
|
|
|
|
[PATCH] Add extensive documenation for the atheros bssid_mask
|
|
|
|
Add extensive documenation for the atheros bssid_mask.
|
|
Credit to David Kimdon for figuring this out. I am
|
|
just documenting it.
|
|
|
|
No need to check for ath5k_hw_hasbssidmask() as
|
|
ath5k_hw_set_bssid_mask() will do the check itself.
|
|
|
|
Also add link to Atheros patent 6677779 B1 about buffer
|
|
registers and control registers. Hope this helps.
|
|
|
|
Changes to base.c
|
|
Changes-licensed-under: 3-clause-BSD
|
|
|
|
Changes to hw.c, reg.h
|
|
Changes-licensed-under: ISC
|
|
|
|
Signed-off-by: Luis R. Rodriguez <mcgrof@gmail.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 953389189d1790b4346a43309719893400a31fc5
|
|
Author: Luis R. Rodriguez <mcgrof@gmail.com>
|
|
Date: Fri Oct 12 11:05:43 2007 -0400
|
|
|
|
[PATCH] Don't read AR5K_RAC_PISR on AR5210, document ath5k_int
|
|
|
|
AR5210 does not have AR5K_RAC_PISR so do not read it. Also lets start
|
|
trying to document all hardware interrupts.
|
|
|
|
Changes-licensed-under: ISC
|
|
Signed-off-by: Luis R. Rodriguez <mcgrof@gmail.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 8462b5d694f20a522ba4dfbb153648ba332b5627
|
|
Author: Luis R. Rodriguez <mcgrof@gmail.com>
|
|
Date: Fri Oct 12 11:04:38 2007 -0400
|
|
|
|
[PATCH] Add proper support for multicast
|
|
|
|
There seems to be several ways to enable multicast. We choose right now
|
|
MadWifi's old implementation. We can later try
|
|
ath5k_hw_set_mcast_filterindex() as well.
|
|
|
|
ath5k_hw_get_rx_filter() may enable AR5K_RX_FILTER_RADARERR or
|
|
AR5K_RX_FILTER_PHYERR. We choose to respect only AR5K_RX_FILTER_PHYERR
|
|
for now because:
|
|
|
|
a. Most radars don't seem to work on 5GHz band now
|
|
b. Some have reported a lot of unnecessary noise is captured
|
|
when trying to filter for radar
|
|
c. When and if someone wants to work on DFS for ath5k later
|
|
this can be enabled then
|
|
|
|
Changes-licensed-under: 3-clause-BSD
|
|
Signed-off-by: Luis R. Rodriguez <mcgrof@gmail.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit ad134b6e277058f4ce929fb4903bac8f2ffa2565
|
|
Author: Luis R. Rodriguez <mcgrof@gmail.com>
|
|
Date: Fri Oct 12 11:03:49 2007 -0400
|
|
|
|
[PATCH] ath5k: Fix a bug which pushed us to enable promiscuous
|
|
|
|
Fix a bug which pushed us to enable the promiscuous filter
|
|
all the time during normal operation. The real problem was caused
|
|
becuase we were reseting the bssid to the broadcast during
|
|
ath5k_hw_reset(). We now cache the bssid value and set the
|
|
bssid again during resets. This gives the driver considerably
|
|
more stability.
|
|
|
|
Known issue: if your DHCP server doesn't ACK your IP via the broadcast but
|
|
instead sends it to the IP it gives you (Cisco seems to do this) you
|
|
may not get the reply. Work is in progress to figure this issue out.
|
|
This issue was present before this patch.
|
|
|
|
Changes to base.c
|
|
Changes-licensed-under: 3-clause-BSD
|
|
|
|
Changes to ath5k.h, hw.c
|
|
Changes-licensed-under: ISC
|
|
|
|
Signed-off-by: Luis R. Rodriguez <mcgrof@gmail.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit cc79ada2dc67857c1fd922e16ca3769a302f0b06
|
|
Author: Bruno Randolf <bruno@thinktube.com>
|
|
Date: Mon Oct 15 21:30:38 2007 +0900
|
|
|
|
[PATCH] ath5k: atheros hardware needs header padding
|
|
|
|
handle padding between header and data
|
|
|
|
Atheros hardware requires the header to be padded to 4 byte (32 bit)
|
|
boundaries. It expects the payload data to start at multiples of 4 byte for TX
|
|
frames and will add the padding for received frames. For most headers there is
|
|
no need for padding, since they are multiples of 4 already - except QoS and 4
|
|
address headers.
|
|
|
|
Changes-licensed-under: 3-clause-BSD
|
|
Signed-off-by: Bruno Randolf <bruno@thinktube.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 1c4a64df662171bf85081aea39d155c683966a56
|
|
Author: John W. Linville <linville@tuxdriver.com>
|
|
Date: Tue Oct 2 19:56:29 2007 -0400
|
|
|
|
[PATCH] ath5k: remove reference to ALG_NONE
|
|
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit ac82c3d69dca0977ad408153109311faabaa73d3
|
|
Author: Luis R. Rodriguez <mcgrof@gmail.com>
|
|
Date: Fri Sep 28 11:26:16 2007 -0400
|
|
|
|
[PATCH] ath5k: Fix a few typos in copyright
|
|
|
|
This patch fixes a few typos overseen by the introduction of
|
|
two new files, intvals.c and phy.c. It also adds the missing
|
|
warranty on base.c and removes the the last CVS tag from base.h
|
|
|
|
Changes to base.[ch]
|
|
Changes-licensed-under: 3-clause-BSD
|
|
|
|
Changes to phy.c, initvals.c
|
|
Changes-licensed-under: ISC
|
|
|
|
Signed-off-by: Luis R. Rodriguez <mcgrof@gmail.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit a1f0e21e5ba549ae9208faf9076b0c807adca7c6
|
|
Author: Luis R. Rodriguez <mcgrof@gmail.com>
|
|
Date: Thu Sep 27 21:04:19 2007 -0400
|
|
|
|
[PATCH] ath5k: add new configure_filter, compile fix on wireless-2.6
|
|
|
|
This patch:
|
|
|
|
* removes the old ath_calcrxfilter() and ath_set_multicast_list()
|
|
* adds new required required configure_filter() ops, this one
|
|
just stores the filter value in cache for later use.
|
|
* introduces a cached sc->filter_flags for hw filter flags
|
|
* moves the driver to mac80211's new required start()/stop()
|
|
* initializes at add_interface() sc->bintval to a common value,
|
|
this will later be updated as per mac80211's preference.
|
|
* Fix compile bug on ath_set_key() (adds enum for set_key_cmd)
|
|
|
|
We'll later port some driver-specific filter stuff onto mac80211.
|
|
|
|
This has been tested. This patch applies to the wireless-2.6 everything branch,
|
|
after the new ath5k directory move and file renames.
|
|
|
|
Changes-licensed-under: 3-clause-BSD
|
|
Signed-off-by: Luis R. Rodriguez <mcgrof@gmail.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 6a0f742dac6bd0c396eb24c021c6c048f496af6e
|
|
Author: Bradley M. Kuhn <bkuhn@softwarefreedom.org>
|
|
Date: Thu Sep 27 18:58:24 2007 -0400
|
|
|
|
[PATCH] ath5k: final correction of copyright notices
|
|
|
|
The patch below is for application to the wireless-2.6 ath5k branch, and
|
|
takes into account the latest driver directory move and file renames. I
|
|
believe this patch handles all copyright notice issues that SFLC is
|
|
currently aware of. Based on our extensive research (which is summarized
|
|
in http://www.softwarefreedom.org/resources/2007/ath5k-code-analysis.html)
|
|
we found that the copyright holders below also have a copyright on some
|
|
files; the patch below adds their copyright notices.
|
|
|
|
We encourage future patchers to add their copyright notice (and any
|
|
appropriate additional licensing notices as needed) into the files when
|
|
they make patches. We also refer developers to our paper at
|
|
http://www.softwarefreedom.org/resources/2007/gpl-non-gpl-collaboration.html
|
|
that recommends ways to incorporate permissive-licensed code like this in
|
|
a GPL-licensed project like Linux.
|
|
|
|
We at SFLC were all very happy to do this work for the Linux Wireless team
|
|
and are glad that a favorable outcome for all was reached.
|
|
|
|
I believe I've used all the patch-submission tags correctly based on
|
|
previous discussions and email exchanges with everyone involved, but I
|
|
obviously don't patch the kernel often (er, at all :), so if I've made a
|
|
mistake, please let me know.
|
|
|
|
Changes-licensed-under: ISC
|
|
Signed-off-by: Richard Fontana <fontana@softwarefreedom.org>
|
|
Signed-off-by: Bradley M. Kuhn <bkuhn@softwarefreedom.org>
|
|
Signed-off-by: Matt Norwood <norwood@softwarefreedom.org>
|
|
Signed-off-by: Karen Sandler <karen@softwarefreedom.org>
|
|
Acked-by: Matthew W. S. Bell <mentor@madwifi.org>
|
|
Acked-by: Pavel Roskin <proski@gnu.org>
|
|
Acked-by: Nick Kossifidis <mickflemm@gmail.com>
|
|
Acked-by: Jiri Slaby <jirislaby@gmail.com>
|
|
Acked-by: Luis Rodriguez <mcgrof@winlab.rutgers.edu>
|
|
Acked-by: Michael Taylor <mike.taylor@apprion.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 4adaee6d7ab1bfd4d9709495a2cb97df4b5afed8
|
|
Author: Andrew Morton <akpm@linux-foundation.org>
|
|
Date: Thu Sep 20 14:02:31 2007 -0700
|
|
|
|
[PATCH] ath5k: Remove pointless empty CVS ID string.
|
|
|
|
Cc: Jeff Garzik <jeff@garzik.org>
|
|
Cc: Jiri Slaby <jirislaby@gmail.com>
|
|
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 260dea31422e4c97b88b2f26474eac3b20ee76a4
|
|
Author: Stephen Hemminger <shemminger@linux-foundation.org>
|
|
Date: Tue Sep 18 10:06:47 2007 -0700
|
|
|
|
[PATCH] ath5k: msi support
|
|
|
|
The atheros on my Fujitsu b6210 supports MSI.
|
|
|
|
Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 6ebc3f5df03a301a173e10dd72b513fe23ecbbce
|
|
Author: Luis R. Rodriguez <mcgrof@gmail.com>
|
|
Date: Thu Sep 20 17:13:26 2007 -0400
|
|
|
|
[PATCH] ath5k - Fix filters for AR5212, correct return values for WEP
|
|
|
|
I was not get getting DHCP replies back with ath5k on a AR5212. Turns
|
|
out out of all filter flags if I enable AR5K_RX_FILTER_PROM I get my
|
|
replies back. I've tested enabling AR5K_RX_FILTER_BCAST and
|
|
AR5K_RX_FILTER_MCAST but AR5K_RX_FILTER_PROM only does the trick. This
|
|
may fix this for other cards if you are not getting DHCP replies
|
|
please let us know. For now we can enable AR5K_RX_FILTER_PROM on STA
|
|
and Ad-hoc only for AR5212 until we sort out the filter flags
|
|
properly. This patch also takes into account new changes to mac80211
|
|
for ieee80211_ops's set_key().
|
|
|
|
Filter API changes to come soon.
|
|
|
|
In summary this patch has these changes:
|
|
|
|
* AR5212 now receives broadcasts (DHCP works now)
|
|
* ath5k_hw_set_key() was checking against key table size against
|
|
key->keyid -- this can only be 0, 1, 2 or 3. Check against key->keylen
|
|
and divide the table size by 8.
|
|
* return proper values for WEP setting as per mac80211 documenation
|
|
|
|
This patch applies to the ath5k branch of wireless-dev.
|
|
|
|
Changes to ath5k_base.c
|
|
Changes-licensed-under: 3-clause-BSD
|
|
|
|
Changes to ath5k_hw.c, ath5k_reg.h
|
|
Changes-licensed-under: ISC
|
|
|
|
Signed-off-by: Luis R. Rodriguez <mcgrof@gmail.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit eae99b799ce2aff97ad9016cac834405678c3d6b
|
|
Author: Jiri Slaby <jirislaby@gmail.com>
|
|
Date: Wed Sep 26 14:04:10 2007 -0400
|
|
|
|
[PATCH] Net: ath5k, remove unused/dead code
|
|
|
|
ath5k, remove unused/dead code
|
|
|
|
Remove ifdeffed code, which is currently (and might not be in the future too)
|
|
unused. If it was ever really needed, it could be easily ported back from the
|
|
madwifi-old-openhal repository.
|
|
|
|
Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
|
|
Cc: Luis R. Rodriguez <mcgrof@gmail.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 9ab409d9f834472b2fdf9705cde52f8b4bc2436e
|
|
Author: Jiri Slaby <jirislaby@gmail.com>
|
|
Date: Wed Sep 26 14:03:27 2007 -0400
|
|
|
|
[PATCH] Net: ath5k, use int as retval
|
|
|
|
ath5k, use int as retval
|
|
|
|
Changes-licensed-under: ISC
|
|
Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
|
|
Cc: Luis R. Rodriguez <mcgrof@gmail.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 5034f1e5e0610667a77e8ac991255162e5fe9982
|
|
Author: Nick Kossifidis <mickflemm@gmail.com>
|
|
Date: Wed Sep 26 14:02:50 2007 -0400
|
|
|
|
[PATCH] Net: ath5k, split hw into hw, phy and initvals
|
|
|
|
ath5k, split hw into hw, phy and initvals
|
|
|
|
Separate the hw code into logical pieces hw, phy and initvals for better
|
|
readability and maintainability.
|
|
|
|
This includes suggested file renames (_hw removal).
|
|
|
|
Changes-licensed-under: ISC
|
|
Signed-off-by: Nick Kossifidis <mickflemm@gmail.com>
|
|
Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
|
|
Cc: Luis R. Rodriguez <mcgrof@gmail.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit c0a7d16f73da9c33bd71ec8b303bc735f604350c
|
|
Author: Jiri Slaby <jirislaby@gmail.com>
|
|
Date: Wed Sep 26 14:02:11 2007 -0400
|
|
|
|
[PATCH] Net: ath5k, make its own directory
|
|
|
|
ath5k, make its own directory
|
|
|
|
also remove ath5_ prefix from the filenames
|
|
|
|
Changes-licensed-under: ISC
|
|
Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
|
|
Cc: Luis R. Rodriguez <mcgrof@gmail.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 71b0b4547745b849f1a2535d37e02cff91cb83ad
|
|
Author: Luis R. Rodriguez <mcgrof@gmail.com>
|
|
Date: Mon Sep 17 17:31:51 2007 -0400
|
|
|
|
[PATCH] ath5k: Internalize Atheros Turbo modes
|
|
|
|
This patch:
|
|
|
|
* Internalizes Atheros Turbo modes (MODE_ATHEROS_TURBO,
|
|
MODE_ATHEROS_TURBOG)
|
|
|
|
* Internatizes Turbo modulation (MODULATION_TURBO)
|
|
|
|
* Adds documention for Atheros Turbo modes (MODE_ATHEROS_TURBO,
|
|
MODE_ATHEROS_TURBOG), Turbo modulation (MODULATION_TURBO) and XR
|
|
modulation (MODULATION_XR)
|
|
|
|
Changes-licensed-under: BSD
|
|
Signed-off-by: Luis R. Rodriguez <mcgrof@gmail.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit aa03e9134b6aca4522e8f0a772f4509a5cfe4b13
|
|
Author: John W. Linville <linville@tuxdriver.com>
|
|
Date: Mon Sep 17 17:11:29 2007 -0400
|
|
|
|
[PATCH] ath5k: remove HW_KEY_IDX_INVALID
|
|
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit a05767ddbfb1138042b5f08c822a54610bd7d437
|
|
Author: Luis R. Rodriguez <mcgrof@gmail.com>
|
|
Date: Mon Sep 17 00:48:27 2007 -0400
|
|
|
|
[PATCH] Correct ath5k Kconfig depends
|
|
|
|
This patch correct's ath5k's Kconfig depends line by making it depend
|
|
on WLAN_80211 and also for now marks it EXPERIMENTAL. This patch
|
|
applies to the ath5k branch of wireless-dev.
|
|
|
|
Signed-off-by: Luis R. Rodriguez <mcgrof@gmail.com
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit fb31173e6ccfbcadd9d7645a384c9add3ce7be4f
|
|
Author: Luis R. Rodriguez <mcgrof@gmail.com>
|
|
Date: Mon Sep 17 00:01:09 2007 -0400
|
|
|
|
[PATCH] Add Luis to MAINTAINERS for ath5k
|
|
|
|
This patch adds me to the MAINTAINERS entry for ath5k. It applies to
|
|
the ath5k branch on wireless-dev.
|
|
|
|
Signed-off-by: Luis R. Rodriguez <mcgrof@gmail.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 5bc68c49c1bdbb92cfcbbea4a57a77b7067350fb
|
|
Author: Krzysztof Halasa <khc@pm.waw.pl>
|
|
Date: Mon Sep 3 20:35:52 2007 +0200
|
|
|
|
[PATCH] Ath5k panic fix
|
|
|
|
Ath5k panics on ath_open() because sc->pdev is never set, fixed.
|
|
|
|
Signed-off-by: Krzysztof Halasa <khc@pm.waw.pl>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 967ee4db879de997e8aadb397317c691480cc9d9
|
|
Author: John W. Linville <linville@tuxdriver.com>
|
|
Date: Sat Sep 15 11:05:32 2007 -0400
|
|
|
|
[PATCH] ath5k: remove use of IEEE80211_HW_WEP_INCLUDE_IV
|
|
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 847a9375af07c677f74934e24f779d90bcc9a7c7
|
|
Author: Luis R. Rodriguez <mcgrof@gmail.com>
|
|
Date: Mon Sep 10 16:00:38 2007 -0400
|
|
|
|
[PATCH] ath5k: more license corrections (ath5k_reg.h)
|
|
|
|
This patch corrects the copyright and license on ath5k_reg.h.
|
|
|
|
Specifically, this patch:
|
|
|
|
* Removes the GPL license and restores the ISC license from
|
|
ath5k_reg.h as Nick indicated.
|
|
|
|
* Adds Reyk's Copyright to ath5k_reg.h
|
|
|
|
Changes-licensed-under: ISC
|
|
Signed-off-by: Luis R. Rodriguez <mcgrof@gmail.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 4ac1d5eb15b9f5a31568d06d38326059bacee642
|
|
Author: Luis R. Rodriguez <mcgrof@gmail.com>
|
|
Date: Thu Sep 6 10:18:22 2007 -0400
|
|
|
|
[PATCH] ath5k: correct some license damage
|
|
|
|
The attached patch fixes copyright notice for 3 files which need to be
|
|
corrected regardless of the outcome of the license of the other files.
|
|
|
|
This patch:
|
|
|
|
* Adds warranty notices back to ath5k_regdom.[ch]
|
|
|
|
* Adds Devicescape Copyright to ath5k_base.c
|
|
|
|
Signed-off-by: Luis R. Rodriguez <mcgrof@gmail.com>
|
|
Changes-licensed-under: ISC
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 82f2f4094eddd1993b9f2bc0d53f26def57c3fae
|
|
Author: Jiri Slaby <jirislaby@gmail.com>
|
|
Date: Tue Aug 28 11:59:54 2007 -0400
|
|
|
|
[PATCH] Net: ath5k, switch to ioread/iowrite
|
|
|
|
ath5k, switch to ioread/iowrite
|
|
|
|
Do not use readl/writel, since iomap retval is platform dependent and
|
|
needn't be virtual address awaited by readl/writel.
|
|
|
|
Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit c2877048ec6f854d417e9141bb18cf4ae15f7b33
|
|
Author: Jiri Slaby <jirislaby@gmail.com>
|
|
Date: Sat Aug 25 03:59:28 2007 -0400
|
|
|
|
[PATCH] Net: ath5k, remove some ieee80211 re-defines
|
|
|
|
ath5k, remove some ieee80211 re-defines
|
|
|
|
use mac80211 defines directly instead. this means MODULATION_* to
|
|
IEEE80211_RATE_* switch.
|
|
|
|
Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
|
|
Cc: <linville@tuxdriver.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 9d6c3cef55cbbd6f4358d9bd7a59a2b7655eaaa3
|
|
Author: Jiri Slaby <jirislaby@gmail.com>
|
|
Date: Sat Aug 25 03:58:47 2007 -0400
|
|
|
|
[PATCH] Net: ath5k, use short preamble for some rates
|
|
|
|
ath5k, use short preamble for some rates
|
|
|
|
2, 5.5 and 11 in b/g are now in short preamble mode
|
|
|
|
Jiri Slaby wrote:
|
|
> Johannes Berg wrote:
|
|
> > umm, mac80211 needs to be able to choose depending on the network.
|
|
|
|
Hmm, misleading log comment. It should be 'can now be in SP mode'.
|
|
|
|
Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
|
|
Cc: <linville@tuxdriver.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 8695faaeffc78924829afb21fd7602dc3a4d81b9
|
|
Author: Jiri Slaby <jirislaby@gmail.com>
|
|
Date: Sat Aug 25 03:51:51 2007 -0400
|
|
|
|
[PATCH] Net: ath5k, initial write cleanup
|
|
|
|
ath5k, initial write cleanup
|
|
|
|
The final step of initial writing cleanup. ar5211_rf is going away.
|
|
|
|
Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
|
|
Cc: <linville@tuxdriver.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 5f56d31da11ddf176e313828d168365662ee7b19
|
|
Author: Jiri Slaby <jirislaby@gmail.com>
|
|
Date: Sat Aug 25 03:57:26 2007 -0400
|
|
|
|
[PATCH] Net: ath5k, comment some EEPROM registers
|
|
|
|
ath5k, comment some EEPROM registers
|
|
|
|
make some registers meaning clear
|
|
|
|
Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
|
|
Cc: <linville@tuxdriver.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit f2854f11abaef57d219103380ab8410eda6a4c83
|
|
Author: John W. Linville <linville@tuxdriver.com>
|
|
Date: Thu Aug 23 15:23:30 2007 -0400
|
|
|
|
[PATCH] ath5k: fix build breakage from recent mac80211 changes
|
|
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 042c3bcd643fc46949ddd1e71d16ec1dcc0dcf18
|
|
Author: Jiri Slaby <jirislaby@gmail.com>
|
|
Date: Wed Aug 22 22:54:07 2007 +0200
|
|
|
|
[PATCH] Net: ath5k, remove sysctls
|
|
|
|
ath5k, remove sysctls
|
|
|
|
Syscalls were buggy and defunct in later kernels (due to sysctl check).
|
|
|
|
Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 1fea1eeb34e4092d45e94e6c3e9f2c93b3bc268a
|
|
Author: Jiri Slaby <jirislaby@gmail.com>
|
|
Date: Wed Aug 22 22:53:25 2007 +0200
|
|
|
|
[PATCH] Net: ath5k, no printk after STA->IBSS switch
|
|
|
|
ath5k, no printk after STA->IBSS switch
|
|
|
|
If STA->IBSS switch was done, but beacon_update weas not called so far, do
|
|
not emit a warning about non-existent skbuf.
|
|
|
|
Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 88ee097caeeb0561c293296c03da47d3b6e688fb
|
|
Author: akpm@linux-foundation.org <akpm@linux-foundation.org>
|
|
Date: Tue Aug 21 16:53:53 2007 -0700
|
|
|
|
[PATCH] ath5k: needs PCI
|
|
|
|
drivers/net/wireless/ath5k_base.c: In function `ath_pci_probe':
|
|
drivers/net/wireless/ath5k_base.c:2279: error: implicit declaration of function `pci_request_region'
|
|
drivers/net/wireless/ath5k_base.c:2359: error: implicit declaration of function `pci_release_region'
|
|
|
|
Cc: Jiri Slaby <jirislaby@gmail.com>
|
|
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit 8ddf75b76f0b704971cb0df635557b5cad84ed7d
|
|
Author: akpm@linux-foundation.org <akpm@linux-foundation.org>
|
|
Date: Tue Aug 21 00:51:20 2007 -0700
|
|
|
|
[PATCH] ath5k: kconfig fix
|
|
|
|
It needs stuff from net/mac80211/ieee80211.c
|
|
|
|
Cc: Jiri Slaby <jirislaby@gmail.com>
|
|
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit cd59338a9249ea6f216ba291167fa9728f8bc1ce
|
|
Author: akpm@linux-foundation.org <akpm@linux-foundation.org>
|
|
Date: Tue Aug 21 00:42:32 2007 -0700
|
|
|
|
[PATCH] ath5k: printk fix
|
|
|
|
drivers/net/wireless/ath5k_base.c: In function 'ath_txq_setup':
|
|
drivers/net/wireless/ath5k_base.c:2033: warning: format '%u' expects type 'unsigned int', but argument 3 has type 'long unsigned int'
|
|
|
|
Cc: Jiri Slaby <jirislaby@gmail.com>
|
|
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
commit d58bf444cd868ce93b29501c013b2c057007eed5
|
|
Author: Jiri Slaby <jirislaby@gmail.com>
|
|
Date: Sun Aug 12 17:33:16 2007 +0200
|
|
|
|
[PATCH] Net: add ath5k wireless driver
|
|
|
|
add ath5k wireless driver
|
|
|
|
Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
|
|
diff -up linux-2.6.23.noarch/MAINTAINERS.orig linux-2.6.23.noarch/MAINTAINERS
|
|
--- linux-2.6.23.noarch/MAINTAINERS.orig 2007-12-21 12:15:17.000000000 -0500
|
|
+++ linux-2.6.23.noarch/MAINTAINERS 2007-12-21 12:18:50.000000000 -0500
|
|
@@ -646,6 +646,17 @@ M: ecashin@coraid.com
|
|
W: http://www.coraid.com/support/linux
|
|
S: Supported
|
|
|
|
+ATHEROS ATH5K WIRELESS DRIVER
|
|
+P: Jiri Slaby
|
|
+M: jirislaby@gmail.com
|
|
+P: Nick Kossifidis
|
|
+M: mickflemm@gmail.com
|
|
+P: Luis R. Rodriguez
|
|
+M: mcgrof@gmail.com
|
|
+L: linux-wireless@vger.kernel.org
|
|
+L: ath5k-devel@lists.ath5k.org
|
|
+S: Maintained
|
|
+
|
|
ATL1 ETHERNET DRIVER
|
|
P: Jay Cliburn
|
|
M: jcliburn@gmail.com
|
|
diff -up linux-2.6.23.noarch/drivers/net/wireless/Makefile.orig linux-2.6.23.noarch/drivers/net/wireless/Makefile
|
|
--- linux-2.6.23.noarch/drivers/net/wireless/Makefile.orig 2007-12-21 12:15:17.000000000 -0500
|
|
+++ linux-2.6.23.noarch/drivers/net/wireless/Makefile 2007-12-21 12:18:50.000000000 -0500
|
|
@@ -61,3 +61,5 @@ obj-$(CONFIG_RT2X00) += rt2x00/
|
|
obj-$(CONFIG_P54_COMMON) += p54common.o
|
|
obj-$(CONFIG_P54_USB) += p54usb.o
|
|
obj-$(CONFIG_P54_PCI) += p54pci.o
|
|
+
|
|
+obj-$(CONFIG_ATH5K) += ath5k/
|
|
diff -up linux-2.6.23.noarch/drivers/net/wireless/Kconfig.orig linux-2.6.23.noarch/drivers/net/wireless/Kconfig
|
|
--- linux-2.6.23.noarch/drivers/net/wireless/Kconfig.orig 2007-12-21 12:15:17.000000000 -0500
|
|
+++ linux-2.6.23.noarch/drivers/net/wireless/Kconfig 2007-12-21 12:18:50.000000000 -0500
|
|
@@ -656,6 +656,24 @@ config P54_PCI
|
|
tristate "Prism54 PCI support"
|
|
depends on P54_COMMON && PCI
|
|
|
|
+config ATH5K
|
|
+ tristate "Atheros 5xxx wireless cards support"
|
|
+ depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL
|
|
+ default m
|
|
+ ---help---
|
|
+ This module adds support for wireless adapters based on
|
|
+ Atheros 5xxx chipset.
|
|
+
|
|
+ Currently the following chip versions are supported:
|
|
+
|
|
+ MAC: AR5211 AR5212
|
|
+ PHY: RF5111/2111 RF5112/2112 RF5413/2413
|
|
+
|
|
+ This driver uses the kernel's mac80211 subsystem.
|
|
+
|
|
+ If you choose to build a module, it'll be called ath5k. Say M if
|
|
+ unsure.
|
|
+
|
|
source "drivers/net/wireless/iwlwifi/Kconfig"
|
|
source "drivers/net/wireless/hostap/Kconfig"
|
|
source "drivers/net/wireless/bcm43xx/Kconfig"
|
|
diff -up /dev/null linux-2.6.23.noarch/drivers/net/wireless/ath5k/phy.c
|
|
--- /dev/null 2007-12-21 08:33:07.834165456 -0500
|
|
+++ linux-2.6.23.noarch/drivers/net/wireless/ath5k/phy.c 2007-12-21 12:18:50.000000000 -0500
|
|
@@ -0,0 +1,2071 @@
|
|
+/*
|
|
+ * PHY functions
|
|
+ *
|
|
+ * Copyright (c) 2004, 2005, 2006, 2007 Reyk Floeter <reyk@openbsd.org>
|
|
+ * Copyright (c) 2006, 2007 Nick Kossifidis <mickflemm@gmail.com>
|
|
+ * Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com>
|
|
+ *
|
|
+ * Permission to use, copy, modify, and distribute this software for any
|
|
+ * purpose with or without fee is hereby granted, provided that the above
|
|
+ * copyright notice and this permission notice appear in all copies.
|
|
+ *
|
|
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
+ *
|
|
+ */
|
|
+
|
|
+#include <linux/delay.h>
|
|
+
|
|
+#include "ath5k.h"
|
|
+#include "reg.h"
|
|
+#include "base.h"
|
|
+
|
|
+/* Struct to hold initial RF register values (RF Banks) */
|
|
+struct ath5k_ini_rf {
|
|
+ u8 rf_bank; /* check out ath5k_reg.h */
|
|
+ u16 rf_register; /* register address */
|
|
+ u32 rf_value[5]; /* register value for different modes (above) */
|
|
+};
|
|
+
|
|
+/*
|
|
+ * Mode-specific RF Gain table (64bytes) for RF5111/5112
|
|
+ * (RF5110 only comes with AR5210 and only supports a/turbo a mode so initial
|
|
+ * RF Gain values are included in AR5K_AR5210_INI)
|
|
+ */
|
|
+struct ath5k_ini_rfgain {
|
|
+ u16 rfg_register; /* RF Gain register address */
|
|
+ u32 rfg_value[2]; /* [freq (see below)] */
|
|
+};
|
|
+
|
|
+struct ath5k_gain_opt {
|
|
+ u32 go_default;
|
|
+ u32 go_steps_count;
|
|
+ const struct ath5k_gain_opt_step go_step[AR5K_GAIN_STEP_COUNT];
|
|
+};
|
|
+
|
|
+/* RF5111 mode-specific init registers */
|
|
+static const struct ath5k_ini_rf rfregs_5111[] = {
|
|
+ { 0, 0x989c,
|
|
+ /* mode a/XR mode aTurbo mode b mode g mode gTurbo */
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 0, 0x989c,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 0, 0x989c,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 0, 0x989c,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 0, 0x989c,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 0, 0x989c,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 0, 0x989c,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 0, 0x989c,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 0, 0x989c,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 0, 0x989c,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 0, 0x989c,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 0, 0x989c,
|
|
+ { 0x00380000, 0x00380000, 0x00380000, 0x00380000, 0x00380000 } },
|
|
+ { 0, 0x989c,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 0, 0x989c,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 0, 0x989c,
|
|
+ { 0x00000000, 0x00000000, 0x000000c0, 0x00000080, 0x00000080 } },
|
|
+ { 0, 0x989c,
|
|
+ { 0x000400f9, 0x000400f9, 0x000400ff, 0x000400fd, 0x000400fd } },
|
|
+ { 0, 0x98d4,
|
|
+ { 0x00000000, 0x00000000, 0x00000004, 0x00000004, 0x00000004 } },
|
|
+ { 1, 0x98d4,
|
|
+ { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
|
|
+ { 2, 0x98d4,
|
|
+ { 0x00000010, 0x00000014, 0x00000010, 0x00000010, 0x00000014 } },
|
|
+ { 3, 0x98d8,
|
|
+ { 0x00601068, 0x00601068, 0x00601068, 0x00601068, 0x00601068 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00000000, 0x00000000, 0x0a000000, 0x00000000, 0x00000000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x003800c0, 0x00380080, 0x023800c0, 0x003800c0, 0x003800c0 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00020006, 0x00020006, 0x00000006, 0x00020006, 0x00020006 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00000089, 0x00000089, 0x00000089, 0x00000089, 0x00000089 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x000000a0, 0x000000a0, 0x000000a0, 0x000000a0, 0x000000a0 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00040007, 0x00040007, 0x00040007, 0x00040007, 0x00040007 } },
|
|
+ { 6, 0x98d4,
|
|
+ { 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a } },
|
|
+ { 7, 0x989c,
|
|
+ { 0x00000040, 0x00000048, 0x00000040, 0x00000040, 0x00000040 } },
|
|
+ { 7, 0x989c,
|
|
+ { 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 } },
|
|
+ { 7, 0x989c,
|
|
+ { 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008 } },
|
|
+ { 7, 0x989c,
|
|
+ { 0x0000004f, 0x0000004f, 0x0000004f, 0x0000004f, 0x0000004f } },
|
|
+ { 7, 0x989c,
|
|
+ { 0x000000f1, 0x000000f1, 0x00000061, 0x000000f1, 0x000000f1 } },
|
|
+ { 7, 0x989c,
|
|
+ { 0x0000904f, 0x0000904f, 0x0000904c, 0x0000904f, 0x0000904f } },
|
|
+ { 7, 0x989c,
|
|
+ { 0x0000125a, 0x0000125a, 0x0000129a, 0x0000125a, 0x0000125a } },
|
|
+ { 7, 0x98cc,
|
|
+ { 0x0000000e, 0x0000000e, 0x0000000f, 0x0000000e, 0x0000000e } },
|
|
+};
|
|
+
|
|
+/* Initial RF Gain settings for RF5111 */
|
|
+static const struct ath5k_ini_rfgain rfgain_5111[] = {
|
|
+ /* 5Ghz 2Ghz */
|
|
+ { AR5K_RF_GAIN(0), { 0x000001a9, 0x00000000 } },
|
|
+ { AR5K_RF_GAIN(1), { 0x000001e9, 0x00000040 } },
|
|
+ { AR5K_RF_GAIN(2), { 0x00000029, 0x00000080 } },
|
|
+ { AR5K_RF_GAIN(3), { 0x00000069, 0x00000150 } },
|
|
+ { AR5K_RF_GAIN(4), { 0x00000199, 0x00000190 } },
|
|
+ { AR5K_RF_GAIN(5), { 0x000001d9, 0x000001d0 } },
|
|
+ { AR5K_RF_GAIN(6), { 0x00000019, 0x00000010 } },
|
|
+ { AR5K_RF_GAIN(7), { 0x00000059, 0x00000044 } },
|
|
+ { AR5K_RF_GAIN(8), { 0x00000099, 0x00000084 } },
|
|
+ { AR5K_RF_GAIN(9), { 0x000001a5, 0x00000148 } },
|
|
+ { AR5K_RF_GAIN(10), { 0x000001e5, 0x00000188 } },
|
|
+ { AR5K_RF_GAIN(11), { 0x00000025, 0x000001c8 } },
|
|
+ { AR5K_RF_GAIN(12), { 0x000001c8, 0x00000014 } },
|
|
+ { AR5K_RF_GAIN(13), { 0x00000008, 0x00000042 } },
|
|
+ { AR5K_RF_GAIN(14), { 0x00000048, 0x00000082 } },
|
|
+ { AR5K_RF_GAIN(15), { 0x00000088, 0x00000178 } },
|
|
+ { AR5K_RF_GAIN(16), { 0x00000198, 0x000001b8 } },
|
|
+ { AR5K_RF_GAIN(17), { 0x000001d8, 0x000001f8 } },
|
|
+ { AR5K_RF_GAIN(18), { 0x00000018, 0x00000012 } },
|
|
+ { AR5K_RF_GAIN(19), { 0x00000058, 0x00000052 } },
|
|
+ { AR5K_RF_GAIN(20), { 0x00000098, 0x00000092 } },
|
|
+ { AR5K_RF_GAIN(21), { 0x000001a4, 0x0000017c } },
|
|
+ { AR5K_RF_GAIN(22), { 0x000001e4, 0x000001bc } },
|
|
+ { AR5K_RF_GAIN(23), { 0x00000024, 0x000001fc } },
|
|
+ { AR5K_RF_GAIN(24), { 0x00000064, 0x0000000a } },
|
|
+ { AR5K_RF_GAIN(25), { 0x000000a4, 0x0000004a } },
|
|
+ { AR5K_RF_GAIN(26), { 0x000000e4, 0x0000008a } },
|
|
+ { AR5K_RF_GAIN(27), { 0x0000010a, 0x0000015a } },
|
|
+ { AR5K_RF_GAIN(28), { 0x0000014a, 0x0000019a } },
|
|
+ { AR5K_RF_GAIN(29), { 0x0000018a, 0x000001da } },
|
|
+ { AR5K_RF_GAIN(30), { 0x000001ca, 0x0000000e } },
|
|
+ { AR5K_RF_GAIN(31), { 0x0000000a, 0x0000004e } },
|
|
+ { AR5K_RF_GAIN(32), { 0x0000004a, 0x0000008e } },
|
|
+ { AR5K_RF_GAIN(33), { 0x0000008a, 0x0000015e } },
|
|
+ { AR5K_RF_GAIN(34), { 0x000001ba, 0x0000019e } },
|
|
+ { AR5K_RF_GAIN(35), { 0x000001fa, 0x000001de } },
|
|
+ { AR5K_RF_GAIN(36), { 0x0000003a, 0x00000009 } },
|
|
+ { AR5K_RF_GAIN(37), { 0x0000007a, 0x00000049 } },
|
|
+ { AR5K_RF_GAIN(38), { 0x00000186, 0x00000089 } },
|
|
+ { AR5K_RF_GAIN(39), { 0x000001c6, 0x00000179 } },
|
|
+ { AR5K_RF_GAIN(40), { 0x00000006, 0x000001b9 } },
|
|
+ { AR5K_RF_GAIN(41), { 0x00000046, 0x000001f9 } },
|
|
+ { AR5K_RF_GAIN(42), { 0x00000086, 0x00000039 } },
|
|
+ { AR5K_RF_GAIN(43), { 0x000000c6, 0x00000079 } },
|
|
+ { AR5K_RF_GAIN(44), { 0x000000c6, 0x000000b9 } },
|
|
+ { AR5K_RF_GAIN(45), { 0x000000c6, 0x000001bd } },
|
|
+ { AR5K_RF_GAIN(46), { 0x000000c6, 0x000001fd } },
|
|
+ { AR5K_RF_GAIN(47), { 0x000000c6, 0x0000003d } },
|
|
+ { AR5K_RF_GAIN(48), { 0x000000c6, 0x0000007d } },
|
|
+ { AR5K_RF_GAIN(49), { 0x000000c6, 0x000000bd } },
|
|
+ { AR5K_RF_GAIN(50), { 0x000000c6, 0x000000fd } },
|
|
+ { AR5K_RF_GAIN(51), { 0x000000c6, 0x000000fd } },
|
|
+ { AR5K_RF_GAIN(52), { 0x000000c6, 0x000000fd } },
|
|
+ { AR5K_RF_GAIN(53), { 0x000000c6, 0x000000fd } },
|
|
+ { AR5K_RF_GAIN(54), { 0x000000c6, 0x000000fd } },
|
|
+ { AR5K_RF_GAIN(55), { 0x000000c6, 0x000000fd } },
|
|
+ { AR5K_RF_GAIN(56), { 0x000000c6, 0x000000fd } },
|
|
+ { AR5K_RF_GAIN(57), { 0x000000c6, 0x000000fd } },
|
|
+ { AR5K_RF_GAIN(58), { 0x000000c6, 0x000000fd } },
|
|
+ { AR5K_RF_GAIN(59), { 0x000000c6, 0x000000fd } },
|
|
+ { AR5K_RF_GAIN(60), { 0x000000c6, 0x000000fd } },
|
|
+ { AR5K_RF_GAIN(61), { 0x000000c6, 0x000000fd } },
|
|
+ { AR5K_RF_GAIN(62), { 0x000000c6, 0x000000fd } },
|
|
+ { AR5K_RF_GAIN(63), { 0x000000c6, 0x000000fd } },
|
|
+};
|
|
+
|
|
+static const struct ath5k_gain_opt rfgain_opt_5111 = {
|
|
+ 4,
|
|
+ 9,
|
|
+ {
|
|
+ { { 4, 1, 1, 1 }, 6 },
|
|
+ { { 4, 0, 1, 1 }, 4 },
|
|
+ { { 3, 1, 1, 1 }, 3 },
|
|
+ { { 4, 0, 0, 1 }, 1 },
|
|
+ { { 4, 1, 1, 0 }, 0 },
|
|
+ { { 4, 0, 1, 0 }, -2 },
|
|
+ { { 3, 1, 1, 0 }, -3 },
|
|
+ { { 4, 0, 0, 0 }, -4 },
|
|
+ { { 2, 1, 1, 0 }, -6 }
|
|
+ }
|
|
+};
|
|
+
|
|
+/* RF5112 mode-specific init registers */
|
|
+static const struct ath5k_ini_rf rfregs_5112[] = {
|
|
+ { 1, 0x98d4,
|
|
+ /* mode a/XR mode aTurbo mode b mode g mode gTurbo */
|
|
+ { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
|
|
+ { 2, 0x98d0,
|
|
+ { 0x03060408, 0x03070408, 0x03060408, 0x03060408, 0x03070408 } },
|
|
+ { 3, 0x98dc,
|
|
+ { 0x00a0c0c0, 0x00a0c0c0, 0x00e0c0c0, 0x00e0c0c0, 0x00e0c0c0 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00a00000, 0x00a00000, 0x00a00000, 0x00a00000, 0x00a00000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00660000, 0x00660000, 0x00660000, 0x00660000, 0x00660000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00db0000, 0x00db0000, 0x00db0000, 0x00db0000, 0x00db0000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00f10000, 0x00f10000, 0x00f10000, 0x00f10000, 0x00f10000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00120000, 0x00120000, 0x00120000, 0x00120000, 0x00120000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00120000, 0x00120000, 0x00120000, 0x00120000, 0x00120000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x008b0000, 0x008b0000, 0x008b0000, 0x008b0000, 0x008b0000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00600000, 0x00600000, 0x00600000, 0x00600000, 0x00600000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00840000, 0x00840000, 0x00840000, 0x00840000, 0x00840000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00640000, 0x00640000, 0x00640000, 0x00640000, 0x00640000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00200000, 0x00200000, 0x00200000, 0x00200000, 0x00200000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00240000, 0x00240000, 0x00240000, 0x00240000, 0x00240000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00250000, 0x00250000, 0x00250000, 0x00250000, 0x00250000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00110000, 0x00110000, 0x00110000, 0x00110000, 0x00110000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00110000, 0x00110000, 0x00110000, 0x00110000, 0x00110000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00510000, 0x00510000, 0x00510000, 0x00510000, 0x00510000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x1c040000, 0x1c040000, 0x1c040000, 0x1c040000, 0x1c040000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00a10000, 0x00a10000, 0x00a10000, 0x00a10000, 0x00a10000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00400000, 0x00400000, 0x00400000, 0x00400000, 0x00400000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x03090000, 0x03090000, 0x03090000, 0x03090000, 0x03090000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x06000000, 0x06000000, 0x06000000, 0x06000000, 0x06000000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x000000b0, 0x000000b0, 0x000000a8, 0x000000a8, 0x000000a8 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x0000002e, 0x0000002e, 0x0000002e, 0x0000002e, 0x0000002e } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x006c4a41, 0x006c4a41, 0x006c4af1, 0x006c4a61, 0x006c4a61 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x0050892a, 0x0050892a, 0x0050892b, 0x0050892b, 0x0050892b } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00842400, 0x00842400, 0x00842400, 0x00842400, 0x00842400 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00c69200, 0x00c69200, 0x00c69200, 0x00c69200, 0x00c69200 } },
|
|
+ { 6, 0x98d0,
|
|
+ { 0x0002000c, 0x0002000c, 0x0002000c, 0x0002000c, 0x0002000c } },
|
|
+ { 7, 0x989c,
|
|
+ { 0x00000094, 0x00000094, 0x00000094, 0x00000094, 0x00000094 } },
|
|
+ { 7, 0x989c,
|
|
+ { 0x00000091, 0x00000091, 0x00000091, 0x00000091, 0x00000091 } },
|
|
+ { 7, 0x989c,
|
|
+ { 0x0000000a, 0x0000000a, 0x00000012, 0x00000012, 0x00000012 } },
|
|
+ { 7, 0x989c,
|
|
+ { 0x00000080, 0x00000080, 0x00000080, 0x00000080, 0x00000080 } },
|
|
+ { 7, 0x989c,
|
|
+ { 0x000000c1, 0x000000c1, 0x000000c1, 0x000000c1, 0x000000c1 } },
|
|
+ { 7, 0x989c,
|
|
+ { 0x00000060, 0x00000060, 0x00000060, 0x00000060, 0x00000060 } },
|
|
+ { 7, 0x989c,
|
|
+ { 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0 } },
|
|
+ { 7, 0x989c,
|
|
+ { 0x00000022, 0x00000022, 0x00000022, 0x00000022, 0x00000022 } },
|
|
+ { 7, 0x989c,
|
|
+ { 0x00000092, 0x00000092, 0x00000092, 0x00000092, 0x00000092 } },
|
|
+ { 7, 0x989c,
|
|
+ { 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4 } },
|
|
+ { 7, 0x989c,
|
|
+ { 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc } },
|
|
+ { 7, 0x989c,
|
|
+ { 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c } },
|
|
+ { 7, 0x98c4,
|
|
+ { 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003 } },
|
|
+};
|
|
+
|
|
+/* RF5112A mode-specific init registers */
|
|
+static const struct ath5k_ini_rf rfregs_5112a[] = {
|
|
+ { 1, 0x98d4,
|
|
+ /* mode a/XR mode aTurbo mode b mode g mode gTurbo */
|
|
+ { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
|
|
+ { 2, 0x98d0,
|
|
+ { 0x03060408, 0x03070408, 0x03060408, 0x03060408, 0x03070408 } },
|
|
+ { 3, 0x98dc,
|
|
+ { 0x00a0c0c0, 0x00a0c0c0, 0x00e0c0c0, 0x00e0c0c0, 0x00e0c0c0 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00800000, 0x00800000, 0x00800000, 0x00800000, 0x00800000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00010000, 0x00010000, 0x00010000, 0x00010000, 0x00010000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00180000, 0x00180000, 0x00180000, 0x00180000, 0x00180000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00600000, 0x00600000, 0x006e0000, 0x006e0000, 0x006e0000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00c70000, 0x00c70000, 0x00c70000, 0x00c70000, 0x00c70000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x004b0000, 0x004b0000, 0x004b0000, 0x004b0000, 0x004b0000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x04480000, 0x04480000, 0x04480000, 0x04480000, 0x04480000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00220000, 0x00220000, 0x00220000, 0x00220000, 0x00220000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00e40000, 0x00e40000, 0x00e40000, 0x00e40000, 0x00e40000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00fc0000, 0x00fc0000, 0x00fc0000, 0x00fc0000, 0x00fc0000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x043f0000, 0x043f0000, 0x043f0000, 0x043f0000, 0x043f0000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00190000, 0x00190000, 0x00190000, 0x00190000, 0x00190000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00240000, 0x00240000, 0x00240000, 0x00240000, 0x00240000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00b40000, 0x00b40000, 0x00b40000, 0x00b40000, 0x00b40000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00990000, 0x00990000, 0x00990000, 0x00990000, 0x00990000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00500000, 0x00500000, 0x00500000, 0x00500000, 0x00500000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00120000, 0x00120000, 0x00120000, 0x00120000, 0x00120000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0xc0320000, 0xc0320000, 0xc0320000, 0xc0320000, 0xc0320000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x01740000, 0x01740000, 0x01740000, 0x01740000, 0x01740000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00110000, 0x00110000, 0x00110000, 0x00110000, 0x00110000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x86280000, 0x86280000, 0x86280000, 0x86280000, 0x86280000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x31840000, 0x31840000, 0x31840000, 0x31840000, 0x31840000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00020080, 0x00020080, 0x00020080, 0x00020080, 0x00020080 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00080009, 0x00080009, 0x00080009, 0x00080009, 0x00080009 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x000000b2, 0x000000b2, 0x000000b2, 0x000000b2, 0x000000b2 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00b02084, 0x00b02084, 0x00b02084, 0x00b02084, 0x00b02084 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x004125a4, 0x004125a4, 0x004125a4, 0x004125a4, 0x004125a4 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00119220, 0x00119220, 0x00119220, 0x00119220, 0x00119220 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x001a4800, 0x001a4800, 0x001a4800, 0x001a4800, 0x001a4800 } },
|
|
+ { 6, 0x98d8,
|
|
+ { 0x000b0230, 0x000b0230, 0x000b0230, 0x000b0230, 0x000b0230 } },
|
|
+ { 7, 0x989c,
|
|
+ { 0x00000094, 0x00000094, 0x00000094, 0x00000094, 0x00000094 } },
|
|
+ { 7, 0x989c,
|
|
+ { 0x00000091, 0x00000091, 0x00000091, 0x00000091, 0x00000091 } },
|
|
+ { 7, 0x989c,
|
|
+ { 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012 } },
|
|
+ { 7, 0x989c,
|
|
+ { 0x00000080, 0x00000080, 0x00000080, 0x00000080, 0x00000080 } },
|
|
+ { 7, 0x989c,
|
|
+ { 0x000000d9, 0x000000d9, 0x000000d9, 0x000000d9, 0x000000d9 } },
|
|
+ { 7, 0x989c,
|
|
+ { 0x00000060, 0x00000060, 0x00000060, 0x00000060, 0x00000060 } },
|
|
+ { 7, 0x989c,
|
|
+ { 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0 } },
|
|
+ { 7, 0x989c,
|
|
+ { 0x000000a2, 0x000000a2, 0x000000a2, 0x000000a2, 0x000000a2 } },
|
|
+ { 7, 0x989c,
|
|
+ { 0x00000052, 0x00000052, 0x00000052, 0x00000052, 0x00000052 } },
|
|
+ { 7, 0x989c,
|
|
+ { 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4 } },
|
|
+ { 7, 0x989c,
|
|
+ { 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc } },
|
|
+ { 7, 0x989c,
|
|
+ { 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c } },
|
|
+ { 7, 0x98c4,
|
|
+ { 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003 } },
|
|
+};
|
|
+
|
|
+
|
|
+static const struct ath5k_ini_rf rfregs_2112a[] = {
|
|
+ { 1, AR5K_RF_BUFFER_CONTROL_4,
|
|
+ /* mode b mode g mode gTurbo */
|
|
+ { 0x00000020, 0x00000020, 0x00000020 } },
|
|
+ { 2, AR5K_RF_BUFFER_CONTROL_3,
|
|
+ { 0x03060408, 0x03060408, 0x03070408 } },
|
|
+ { 3, AR5K_RF_BUFFER_CONTROL_6,
|
|
+ { 0x00e020c0, 0x00e020c0, 0x00e020c0 } },
|
|
+ { 6, AR5K_RF_BUFFER,
|
|
+ { 0x0a000000, 0x0a000000, 0x0a000000 } },
|
|
+ { 6, AR5K_RF_BUFFER,
|
|
+ { 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 6, AR5K_RF_BUFFER,
|
|
+ { 0x00800000, 0x00800000, 0x00800000 } },
|
|
+ { 6, AR5K_RF_BUFFER,
|
|
+ { 0x002a0000, 0x002a0000, 0x002a0000 } },
|
|
+ { 6, AR5K_RF_BUFFER,
|
|
+ { 0x00010000, 0x00010000, 0x00010000 } },
|
|
+ { 6, AR5K_RF_BUFFER,
|
|
+ { 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 6, AR5K_RF_BUFFER,
|
|
+ { 0x00180000, 0x00180000, 0x00180000 } },
|
|
+ { 6, AR5K_RF_BUFFER,
|
|
+ { 0x006e0000, 0x006e0000, 0x006e0000 } },
|
|
+ { 6, AR5K_RF_BUFFER,
|
|
+ { 0x00c70000, 0x00c70000, 0x00c70000 } },
|
|
+ { 6, AR5K_RF_BUFFER,
|
|
+ { 0x004b0000, 0x004b0000, 0x004b0000 } },
|
|
+ { 6, AR5K_RF_BUFFER,
|
|
+ { 0x04480000, 0x04480000, 0x04480000 } },
|
|
+ { 6, AR5K_RF_BUFFER,
|
|
+ { 0x002a0000, 0x002a0000, 0x002a0000 } },
|
|
+ { 6, AR5K_RF_BUFFER,
|
|
+ { 0x00e40000, 0x00e40000, 0x00e40000 } },
|
|
+ { 6, AR5K_RF_BUFFER,
|
|
+ { 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 6, AR5K_RF_BUFFER,
|
|
+ { 0x00fc0000, 0x00fc0000, 0x00fc0000 } },
|
|
+ { 6, AR5K_RF_BUFFER,
|
|
+ { 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
|
|
+ { 6, AR5K_RF_BUFFER,
|
|
+ { 0x043f0000, 0x043f0000, 0x043f0000 } },
|
|
+ { 6, AR5K_RF_BUFFER,
|
|
+ { 0x0c0c0000, 0x0c0c0000, 0x0c0c0000 } },
|
|
+ { 6, AR5K_RF_BUFFER,
|
|
+ { 0x02190000, 0x02190000, 0x02190000 } },
|
|
+ { 6, AR5K_RF_BUFFER,
|
|
+ { 0x00240000, 0x00240000, 0x00240000 } },
|
|
+ { 6, AR5K_RF_BUFFER,
|
|
+ { 0x00b40000, 0x00b40000, 0x00b40000 } },
|
|
+ { 6, AR5K_RF_BUFFER,
|
|
+ { 0x00990000, 0x00990000, 0x00990000 } },
|
|
+ { 6, AR5K_RF_BUFFER,
|
|
+ { 0x00500000, 0x00500000, 0x00500000 } },
|
|
+ { 6, AR5K_RF_BUFFER,
|
|
+ { 0x002a0000, 0x002a0000, 0x002a0000 } },
|
|
+ { 6, AR5K_RF_BUFFER,
|
|
+ { 0x00120000, 0x00120000, 0x00120000 } },
|
|
+ { 6, AR5K_RF_BUFFER,
|
|
+ { 0xc0320000, 0xc0320000, 0xc0320000 } },
|
|
+ { 6, AR5K_RF_BUFFER,
|
|
+ { 0x01740000, 0x01740000, 0x01740000 } },
|
|
+ { 6, AR5K_RF_BUFFER,
|
|
+ { 0x00110000, 0x00110000, 0x00110000 } },
|
|
+ { 6, AR5K_RF_BUFFER,
|
|
+ { 0x86280000, 0x86280000, 0x86280000 } },
|
|
+ { 6, AR5K_RF_BUFFER,
|
|
+ { 0x31840000, 0x31840000, 0x31840000 } },
|
|
+ { 6, AR5K_RF_BUFFER,
|
|
+ { 0x00f20080, 0x00f20080, 0x00f20080 } },
|
|
+ { 6, AR5K_RF_BUFFER,
|
|
+ { 0x00070019, 0x00070019, 0x00070019 } },
|
|
+ { 6, AR5K_RF_BUFFER,
|
|
+ { 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 6, AR5K_RF_BUFFER,
|
|
+ { 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 6, AR5K_RF_BUFFER,
|
|
+ { 0x000000b2, 0x000000b2, 0x000000b2 } },
|
|
+ { 6, AR5K_RF_BUFFER,
|
|
+ { 0x00b02184, 0x00b02184, 0x00b02184 } },
|
|
+ { 6, AR5K_RF_BUFFER,
|
|
+ { 0x004125a4, 0x004125a4, 0x004125a4 } },
|
|
+ { 6, AR5K_RF_BUFFER,
|
|
+ { 0x00119220, 0x00119220, 0x00119220 } },
|
|
+ { 6, AR5K_RF_BUFFER,
|
|
+ { 0x001a4800, 0x001a4800, 0x001a4800 } },
|
|
+ { 6, AR5K_RF_BUFFER_CONTROL_5,
|
|
+ { 0x000b0230, 0x000b0230, 0x000b0230 } },
|
|
+ { 7, AR5K_RF_BUFFER,
|
|
+ { 0x00000094, 0x00000094, 0x00000094 } },
|
|
+ { 7, AR5K_RF_BUFFER,
|
|
+ { 0x00000091, 0x00000091, 0x00000091 } },
|
|
+ { 7, AR5K_RF_BUFFER,
|
|
+ { 0x00000012, 0x00000012, 0x00000012 } },
|
|
+ { 7, AR5K_RF_BUFFER,
|
|
+ { 0x00000080, 0x00000080, 0x00000080 } },
|
|
+ { 7, AR5K_RF_BUFFER,
|
|
+ { 0x000000d9, 0x000000d9, 0x000000d9 } },
|
|
+ { 7, AR5K_RF_BUFFER,
|
|
+ { 0x00000060, 0x00000060, 0x00000060 } },
|
|
+ { 7, AR5K_RF_BUFFER,
|
|
+ { 0x000000f0, 0x000000f0, 0x000000f0 } },
|
|
+ { 7, AR5K_RF_BUFFER,
|
|
+ { 0x000000a2, 0x000000a2, 0x000000a2 } },
|
|
+ { 7, AR5K_RF_BUFFER,
|
|
+ { 0x00000052, 0x00000052, 0x00000052 } },
|
|
+ { 7, AR5K_RF_BUFFER,
|
|
+ { 0x000000d4, 0x000000d4, 0x000000d4 } },
|
|
+ { 7, AR5K_RF_BUFFER,
|
|
+ { 0x000014cc, 0x000014cc, 0x000014cc } },
|
|
+ { 7, AR5K_RF_BUFFER,
|
|
+ { 0x0000048c, 0x0000048c, 0x0000048c } },
|
|
+ { 7, AR5K_RF_BUFFER_CONTROL_1,
|
|
+ { 0x00000003, 0x00000003, 0x00000003 } },
|
|
+};
|
|
+
|
|
+/* RF5413/5414 mode-specific init registers */
|
|
+static const struct ath5k_ini_rf rfregs_5413[] = {
|
|
+ { 1, 0x98d4,
|
|
+ /* mode a/XR mode aTurbo mode b mode g mode gTurbo */
|
|
+ { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
|
|
+ { 2, 0x98d0,
|
|
+ { 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008 } },
|
|
+ { 3, 0x98dc,
|
|
+ { 0x00a000c0, 0x00a000c0, 0x00e000c0, 0x00e000c0, 0x00e000c0 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x33000000, 0x33000000, 0x33000000, 0x33000000, 0x33000000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x01000000, 0x01000000, 0x01000000, 0x01000000, 0x01000000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x1f000000, 0x1f000000, 0x1f000000, 0x1f000000, 0x1f000000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00b80000, 0x00b80000, 0x00b80000, 0x00b80000, 0x00b80000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00b70000, 0x00b70000, 0x00b70000, 0x00b70000, 0x00b70000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00840000, 0x00840000, 0x00840000, 0x00840000, 0x00840000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00980000, 0x00980000, 0x00980000, 0x00980000, 0x00980000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00c00000, 0x00c00000, 0x00c00000, 0x00c00000, 0x00c00000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00d70000, 0x00d70000, 0x00d70000, 0x00d70000, 0x00d70000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00610000, 0x00610000, 0x00610000, 0x00610000, 0x00610000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00fe0000, 0x00fe0000, 0x00fe0000, 0x00fe0000, 0x00fe0000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00de0000, 0x00de0000, 0x00de0000, 0x00de0000, 0x00de0000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x007f0000, 0x007f0000, 0x007f0000, 0x007f0000, 0x007f0000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x043d0000, 0x043d0000, 0x043d0000, 0x043d0000, 0x043d0000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00770000, 0x00770000, 0x00770000, 0x00770000, 0x00770000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00440000, 0x00440000, 0x00440000, 0x00440000, 0x00440000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00980000, 0x00980000, 0x00980000, 0x00980000, 0x00980000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00100080, 0x00100080, 0x00100080, 0x00100080, 0x00100080 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x0005c034, 0x0005c034, 0x0005c034, 0x0005c034, 0x0005c034 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x003100f0, 0x003100f0, 0x003100f0, 0x003100f0, 0x003100f0 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x000c011f, 0x000c011f, 0x000c011f, 0x000c011f, 0x000c011f } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00510040, 0x00510040, 0x005100a0, 0x005100a0, 0x005100a0 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x0050006a, 0x0050006a, 0x005000dd, 0x005000dd, 0x005000dd } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00000001, 0x00000001, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00004044, 0x00004044, 0x00004044, 0x00004044, 0x00004044 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x000060c0, 0x000060c0, 0x000060c0, 0x000060c0, 0x000060c0 } },
|
|
+ { 6, 0x989c,
|
|
+ { 0x00002c00, 0x00002c00, 0x00003600, 0x00003600, 0x00003600 } },
|
|
+ { 6, 0x98c8,
|
|
+ { 0x00000403, 0x00000403, 0x00040403, 0x00040403, 0x00040403 } },
|
|
+ { 7, 0x989c,
|
|
+ { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } },
|
|
+ { 7, 0x989c,
|
|
+ { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } },
|
|
+ { 7, 0x98cc,
|
|
+ { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } },
|
|
+};
|
|
+
|
|
+
|
|
+/* Initial RF Gain settings for RF5112 */
|
|
+static const struct ath5k_ini_rfgain rfgain_5112[] = {
|
|
+ /* 5Ghz 2Ghz */
|
|
+ { AR5K_RF_GAIN(0), { 0x00000007, 0x00000007 } },
|
|
+ { AR5K_RF_GAIN(1), { 0x00000047, 0x00000047 } },
|
|
+ { AR5K_RF_GAIN(2), { 0x00000087, 0x00000087 } },
|
|
+ { AR5K_RF_GAIN(3), { 0x000001a0, 0x000001a0 } },
|
|
+ { AR5K_RF_GAIN(4), { 0x000001e0, 0x000001e0 } },
|
|
+ { AR5K_RF_GAIN(5), { 0x00000020, 0x00000020 } },
|
|
+ { AR5K_RF_GAIN(6), { 0x00000060, 0x00000060 } },
|
|
+ { AR5K_RF_GAIN(7), { 0x000001a1, 0x000001a1 } },
|
|
+ { AR5K_RF_GAIN(8), { 0x000001e1, 0x000001e1 } },
|
|
+ { AR5K_RF_GAIN(9), { 0x00000021, 0x00000021 } },
|
|
+ { AR5K_RF_GAIN(10), { 0x00000061, 0x00000061 } },
|
|
+ { AR5K_RF_GAIN(11), { 0x00000162, 0x00000162 } },
|
|
+ { AR5K_RF_GAIN(12), { 0x000001a2, 0x000001a2 } },
|
|
+ { AR5K_RF_GAIN(13), { 0x000001e2, 0x000001e2 } },
|
|
+ { AR5K_RF_GAIN(14), { 0x00000022, 0x00000022 } },
|
|
+ { AR5K_RF_GAIN(15), { 0x00000062, 0x00000062 } },
|
|
+ { AR5K_RF_GAIN(16), { 0x00000163, 0x00000163 } },
|
|
+ { AR5K_RF_GAIN(17), { 0x000001a3, 0x000001a3 } },
|
|
+ { AR5K_RF_GAIN(18), { 0x000001e3, 0x000001e3 } },
|
|
+ { AR5K_RF_GAIN(19), { 0x00000023, 0x00000023 } },
|
|
+ { AR5K_RF_GAIN(20), { 0x00000063, 0x00000063 } },
|
|
+ { AR5K_RF_GAIN(21), { 0x00000184, 0x00000184 } },
|
|
+ { AR5K_RF_GAIN(22), { 0x000001c4, 0x000001c4 } },
|
|
+ { AR5K_RF_GAIN(23), { 0x00000004, 0x00000004 } },
|
|
+ { AR5K_RF_GAIN(24), { 0x000001ea, 0x0000000b } },
|
|
+ { AR5K_RF_GAIN(25), { 0x0000002a, 0x0000004b } },
|
|
+ { AR5K_RF_GAIN(26), { 0x0000006a, 0x0000008b } },
|
|
+ { AR5K_RF_GAIN(27), { 0x000000aa, 0x000001ac } },
|
|
+ { AR5K_RF_GAIN(28), { 0x000001ab, 0x000001ec } },
|
|
+ { AR5K_RF_GAIN(29), { 0x000001eb, 0x0000002c } },
|
|
+ { AR5K_RF_GAIN(30), { 0x0000002b, 0x00000012 } },
|
|
+ { AR5K_RF_GAIN(31), { 0x0000006b, 0x00000052 } },
|
|
+ { AR5K_RF_GAIN(32), { 0x000000ab, 0x00000092 } },
|
|
+ { AR5K_RF_GAIN(33), { 0x000001ac, 0x00000193 } },
|
|
+ { AR5K_RF_GAIN(34), { 0x000001ec, 0x000001d3 } },
|
|
+ { AR5K_RF_GAIN(35), { 0x0000002c, 0x00000013 } },
|
|
+ { AR5K_RF_GAIN(36), { 0x0000003a, 0x00000053 } },
|
|
+ { AR5K_RF_GAIN(37), { 0x0000007a, 0x00000093 } },
|
|
+ { AR5K_RF_GAIN(38), { 0x000000ba, 0x00000194 } },
|
|
+ { AR5K_RF_GAIN(39), { 0x000001bb, 0x000001d4 } },
|
|
+ { AR5K_RF_GAIN(40), { 0x000001fb, 0x00000014 } },
|
|
+ { AR5K_RF_GAIN(41), { 0x0000003b, 0x0000003a } },
|
|
+ { AR5K_RF_GAIN(42), { 0x0000007b, 0x0000007a } },
|
|
+ { AR5K_RF_GAIN(43), { 0x000000bb, 0x000000ba } },
|
|
+ { AR5K_RF_GAIN(44), { 0x000001bc, 0x000001bb } },
|
|
+ { AR5K_RF_GAIN(45), { 0x000001fc, 0x000001fb } },
|
|
+ { AR5K_RF_GAIN(46), { 0x0000003c, 0x0000003b } },
|
|
+ { AR5K_RF_GAIN(47), { 0x0000007c, 0x0000007b } },
|
|
+ { AR5K_RF_GAIN(48), { 0x000000bc, 0x000000bb } },
|
|
+ { AR5K_RF_GAIN(49), { 0x000000fc, 0x000001bc } },
|
|
+ { AR5K_RF_GAIN(50), { 0x000000fc, 0x000001fc } },
|
|
+ { AR5K_RF_GAIN(51), { 0x000000fc, 0x0000003c } },
|
|
+ { AR5K_RF_GAIN(52), { 0x000000fc, 0x0000007c } },
|
|
+ { AR5K_RF_GAIN(53), { 0x000000fc, 0x000000bc } },
|
|
+ { AR5K_RF_GAIN(54), { 0x000000fc, 0x000000fc } },
|
|
+ { AR5K_RF_GAIN(55), { 0x000000fc, 0x000000fc } },
|
|
+ { AR5K_RF_GAIN(56), { 0x000000fc, 0x000000fc } },
|
|
+ { AR5K_RF_GAIN(57), { 0x000000fc, 0x000000fc } },
|
|
+ { AR5K_RF_GAIN(58), { 0x000000fc, 0x000000fc } },
|
|
+ { AR5K_RF_GAIN(59), { 0x000000fc, 0x000000fc } },
|
|
+ { AR5K_RF_GAIN(60), { 0x000000fc, 0x000000fc } },
|
|
+ { AR5K_RF_GAIN(61), { 0x000000fc, 0x000000fc } },
|
|
+ { AR5K_RF_GAIN(62), { 0x000000fc, 0x000000fc } },
|
|
+ { AR5K_RF_GAIN(63), { 0x000000fc, 0x000000fc } },
|
|
+};
|
|
+
|
|
+/* Initial RF Gain settings for RF5413 */
|
|
+static const struct ath5k_ini_rfgain rfgain_5413[] = {
|
|
+ /* 5Ghz 2Ghz */
|
|
+ { AR5K_RF_GAIN(0), { 0x00000000, 0x00000000 } },
|
|
+ { AR5K_RF_GAIN(1), { 0x00000040, 0x00000040 } },
|
|
+ { AR5K_RF_GAIN(2), { 0x00000080, 0x00000080 } },
|
|
+ { AR5K_RF_GAIN(3), { 0x000001a1, 0x00000161 } },
|
|
+ { AR5K_RF_GAIN(4), { 0x000001e1, 0x000001a1 } },
|
|
+ { AR5K_RF_GAIN(5), { 0x00000021, 0x000001e1 } },
|
|
+ { AR5K_RF_GAIN(6), { 0x00000061, 0x00000021 } },
|
|
+ { AR5K_RF_GAIN(7), { 0x00000188, 0x00000061 } },
|
|
+ { AR5K_RF_GAIN(8), { 0x000001c8, 0x00000188 } },
|
|
+ { AR5K_RF_GAIN(9), { 0x00000008, 0x000001c8 } },
|
|
+ { AR5K_RF_GAIN(10), { 0x00000048, 0x00000008 } },
|
|
+ { AR5K_RF_GAIN(11), { 0x00000088, 0x00000048 } },
|
|
+ { AR5K_RF_GAIN(12), { 0x000001a9, 0x00000088 } },
|
|
+ { AR5K_RF_GAIN(13), { 0x000001e9, 0x00000169 } },
|
|
+ { AR5K_RF_GAIN(14), { 0x00000029, 0x000001a9 } },
|
|
+ { AR5K_RF_GAIN(15), { 0x00000069, 0x000001e9 } },
|
|
+ { AR5K_RF_GAIN(16), { 0x000001d0, 0x00000029 } },
|
|
+ { AR5K_RF_GAIN(17), { 0x00000010, 0x00000069 } },
|
|
+ { AR5K_RF_GAIN(18), { 0x00000050, 0x00000190 } },
|
|
+ { AR5K_RF_GAIN(19), { 0x00000090, 0x000001d0 } },
|
|
+ { AR5K_RF_GAIN(20), { 0x000001b1, 0x00000010 } },
|
|
+ { AR5K_RF_GAIN(21), { 0x000001f1, 0x00000050 } },
|
|
+ { AR5K_RF_GAIN(22), { 0x00000031, 0x00000090 } },
|
|
+ { AR5K_RF_GAIN(23), { 0x00000071, 0x00000171 } },
|
|
+ { AR5K_RF_GAIN(24), { 0x000001b8, 0x000001b1 } },
|
|
+ { AR5K_RF_GAIN(25), { 0x000001f8, 0x000001f1 } },
|
|
+ { AR5K_RF_GAIN(26), { 0x00000038, 0x00000031 } },
|
|
+ { AR5K_RF_GAIN(27), { 0x00000078, 0x00000071 } },
|
|
+ { AR5K_RF_GAIN(28), { 0x00000199, 0x00000198 } },
|
|
+ { AR5K_RF_GAIN(29), { 0x000001d9, 0x000001d8 } },
|
|
+ { AR5K_RF_GAIN(30), { 0x00000019, 0x00000018 } },
|
|
+ { AR5K_RF_GAIN(31), { 0x00000059, 0x00000058 } },
|
|
+ { AR5K_RF_GAIN(32), { 0x00000099, 0x00000098 } },
|
|
+ { AR5K_RF_GAIN(33), { 0x000000d9, 0x00000179 } },
|
|
+ { AR5K_RF_GAIN(34), { 0x000000f9, 0x000001b9 } },
|
|
+ { AR5K_RF_GAIN(35), { 0x000000f9, 0x000001f9 } },
|
|
+ { AR5K_RF_GAIN(36), { 0x000000f9, 0x00000039 } },
|
|
+ { AR5K_RF_GAIN(37), { 0x000000f9, 0x00000079 } },
|
|
+ { AR5K_RF_GAIN(38), { 0x000000f9, 0x000000b9 } },
|
|
+ { AR5K_RF_GAIN(39), { 0x000000f9, 0x000000f9 } },
|
|
+ { AR5K_RF_GAIN(40), { 0x000000f9, 0x000000f9 } },
|
|
+ { AR5K_RF_GAIN(41), { 0x000000f9, 0x000000f9 } },
|
|
+ { AR5K_RF_GAIN(42), { 0x000000f9, 0x000000f9 } },
|
|
+ { AR5K_RF_GAIN(43), { 0x000000f9, 0x000000f9 } },
|
|
+ { AR5K_RF_GAIN(44), { 0x000000f9, 0x000000f9 } },
|
|
+ { AR5K_RF_GAIN(45), { 0x000000f9, 0x000000f9 } },
|
|
+ { AR5K_RF_GAIN(46), { 0x000000f9, 0x000000f9 } },
|
|
+ { AR5K_RF_GAIN(47), { 0x000000f9, 0x000000f9 } },
|
|
+ { AR5K_RF_GAIN(48), { 0x000000f9, 0x000000f9 } },
|
|
+ { AR5K_RF_GAIN(49), { 0x000000f9, 0x000000f9 } },
|
|
+ { AR5K_RF_GAIN(50), { 0x000000f9, 0x000000f9 } },
|
|
+ { AR5K_RF_GAIN(51), { 0x000000f9, 0x000000f9 } },
|
|
+ { AR5K_RF_GAIN(52), { 0x000000f9, 0x000000f9 } },
|
|
+ { AR5K_RF_GAIN(53), { 0x000000f9, 0x000000f9 } },
|
|
+ { AR5K_RF_GAIN(54), { 0x000000f9, 0x000000f9 } },
|
|
+ { AR5K_RF_GAIN(55), { 0x000000f9, 0x000000f9 } },
|
|
+ { AR5K_RF_GAIN(56), { 0x000000f9, 0x000000f9 } },
|
|
+ { AR5K_RF_GAIN(57), { 0x000000f9, 0x000000f9 } },
|
|
+ { AR5K_RF_GAIN(58), { 0x000000f9, 0x000000f9 } },
|
|
+ { AR5K_RF_GAIN(59), { 0x000000f9, 0x000000f9 } },
|
|
+ { AR5K_RF_GAIN(60), { 0x000000f9, 0x000000f9 } },
|
|
+ { AR5K_RF_GAIN(61), { 0x000000f9, 0x000000f9 } },
|
|
+ { AR5K_RF_GAIN(62), { 0x000000f9, 0x000000f9 } },
|
|
+ { AR5K_RF_GAIN(63), { 0x000000f9, 0x000000f9 } },
|
|
+};
|
|
+
|
|
+static const struct ath5k_gain_opt rfgain_opt_5112 = {
|
|
+ 1,
|
|
+ 8,
|
|
+ {
|
|
+ { { 3, 0, 0, 0, 0, 0, 0 }, 6 },
|
|
+ { { 2, 0, 0, 0, 0, 0, 0 }, 0 },
|
|
+ { { 1, 0, 0, 0, 0, 0, 0 }, -3 },
|
|
+ { { 0, 0, 0, 0, 0, 0, 0 }, -6 },
|
|
+ { { 0, 1, 1, 0, 0, 0, 0 }, -8 },
|
|
+ { { 0, 1, 1, 0, 1, 1, 0 }, -10 },
|
|
+ { { 0, 1, 0, 1, 1, 1, 0 }, -13 },
|
|
+ { { 0, 1, 0, 1, 1, 0, 1 }, -16 },
|
|
+ }
|
|
+};
|
|
+
|
|
+/*
|
|
+ * Used to modify RF Banks before writing them to AR5K_RF_BUFFER
|
|
+ */
|
|
+static unsigned int ath5k_hw_rfregs_op(u32 *rf, u32 offset, u32 reg, u32 bits,
|
|
+ u32 first, u32 col, bool set)
|
|
+{
|
|
+ u32 mask, entry, last, data, shift, position;
|
|
+ s32 left;
|
|
+ int i;
|
|
+
|
|
+ data = 0;
|
|
+
|
|
+ if (rf == NULL)
|
|
+ /* should not happen */
|
|
+ return 0;
|
|
+
|
|
+ if (!(col <= 3 && bits <= 32 && first + bits <= 319)) {
|
|
+ ATH5K_PRINTF("invalid values at offset %u\n", offset);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ entry = ((first - 1) / 8) + offset;
|
|
+ position = (first - 1) % 8;
|
|
+
|
|
+ if (set == true)
|
|
+ data = ath5k_hw_bitswap(reg, bits);
|
|
+
|
|
+ for (i = shift = 0, left = bits; left > 0; position = 0, entry++, i++) {
|
|
+ last = (position + left > 8) ? 8 : position + left;
|
|
+ mask = (((1 << last) - 1) ^ ((1 << position) - 1)) << (col * 8);
|
|
+
|
|
+ if (set == true) {
|
|
+ rf[entry] &= ~mask;
|
|
+ rf[entry] |= ((data << position) << (col * 8)) & mask;
|
|
+ data >>= (8 - position);
|
|
+ } else {
|
|
+ data = (((rf[entry] & mask) >> (col * 8)) >> position)
|
|
+ << shift;
|
|
+ shift += last - position;
|
|
+ }
|
|
+
|
|
+ left -= 8 - position;
|
|
+ }
|
|
+
|
|
+ data = set == true ? 1 : ath5k_hw_bitswap(data, bits);
|
|
+
|
|
+ return data;
|
|
+}
|
|
+
|
|
+static u32 ath5k_hw_rfregs_gainf_corr(struct ath5k_hw *ah)
|
|
+{
|
|
+ u32 mix, step;
|
|
+ u32 *rf;
|
|
+
|
|
+ if (ah->ah_rf_banks == NULL)
|
|
+ return 0;
|
|
+
|
|
+ rf = ah->ah_rf_banks;
|
|
+ ah->ah_gain.g_f_corr = 0;
|
|
+
|
|
+ if (ath5k_hw_rfregs_op(rf, ah->ah_offset[7], 0, 1, 36, 0, false) != 1)
|
|
+ return 0;
|
|
+
|
|
+ step = ath5k_hw_rfregs_op(rf, ah->ah_offset[7], 0, 4, 32, 0, false);
|
|
+ mix = ah->ah_gain.g_step->gos_param[0];
|
|
+
|
|
+ switch (mix) {
|
|
+ case 3:
|
|
+ ah->ah_gain.g_f_corr = step * 2;
|
|
+ break;
|
|
+ case 2:
|
|
+ ah->ah_gain.g_f_corr = (step - 5) * 2;
|
|
+ break;
|
|
+ case 1:
|
|
+ ah->ah_gain.g_f_corr = step;
|
|
+ break;
|
|
+ default:
|
|
+ ah->ah_gain.g_f_corr = 0;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ return ah->ah_gain.g_f_corr;
|
|
+}
|
|
+
|
|
+static bool ath5k_hw_rfregs_gain_readback(struct ath5k_hw *ah)
|
|
+{
|
|
+ u32 step, mix, level[4];
|
|
+ u32 *rf;
|
|
+
|
|
+ if (ah->ah_rf_banks == NULL)
|
|
+ return false;
|
|
+
|
|
+ rf = ah->ah_rf_banks;
|
|
+
|
|
+ if (ah->ah_radio == AR5K_RF5111) {
|
|
+ step = ath5k_hw_rfregs_op(rf, ah->ah_offset[7], 0, 6, 37, 0,
|
|
+ false);
|
|
+ level[0] = 0;
|
|
+ level[1] = (step == 0x3f) ? 0x32 : step + 4;
|
|
+ level[2] = (step != 0x3f) ? 0x40 : level[0];
|
|
+ level[3] = level[2] + 0x32;
|
|
+
|
|
+ ah->ah_gain.g_high = level[3] -
|
|
+ (step == 0x3f ? AR5K_GAIN_DYN_ADJUST_HI_MARGIN : -5);
|
|
+ ah->ah_gain.g_low = level[0] +
|
|
+ (step == 0x3f ? AR5K_GAIN_DYN_ADJUST_LO_MARGIN : 0);
|
|
+ } else {
|
|
+ mix = ath5k_hw_rfregs_op(rf, ah->ah_offset[7], 0, 1, 36, 0,
|
|
+ false);
|
|
+ level[0] = level[2] = 0;
|
|
+
|
|
+ if (mix == 1) {
|
|
+ level[1] = level[3] = 83;
|
|
+ } else {
|
|
+ level[1] = level[3] = 107;
|
|
+ ah->ah_gain.g_high = 55;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return (ah->ah_gain.g_current >= level[0] &&
|
|
+ ah->ah_gain.g_current <= level[1]) ||
|
|
+ (ah->ah_gain.g_current >= level[2] &&
|
|
+ ah->ah_gain.g_current <= level[3]);
|
|
+}
|
|
+
|
|
+static s32 ath5k_hw_rfregs_gain_adjust(struct ath5k_hw *ah)
|
|
+{
|
|
+ const struct ath5k_gain_opt *go;
|
|
+ int ret = 0;
|
|
+
|
|
+ switch (ah->ah_radio) {
|
|
+ case AR5K_RF5111:
|
|
+ go = &rfgain_opt_5111;
|
|
+ break;
|
|
+ case AR5K_RF5112:
|
|
+ case AR5K_RF5413: /* ??? */
|
|
+ go = &rfgain_opt_5112;
|
|
+ break;
|
|
+ default:
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ ah->ah_gain.g_step = &go->go_step[ah->ah_gain.g_step_idx];
|
|
+
|
|
+ if (ah->ah_gain.g_current >= ah->ah_gain.g_high) {
|
|
+ if (ah->ah_gain.g_step_idx == 0)
|
|
+ return -1;
|
|
+ for (ah->ah_gain.g_target = ah->ah_gain.g_current;
|
|
+ ah->ah_gain.g_target >= ah->ah_gain.g_high &&
|
|
+ ah->ah_gain.g_step_idx > 0;
|
|
+ ah->ah_gain.g_step =
|
|
+ &go->go_step[ah->ah_gain.g_step_idx])
|
|
+ ah->ah_gain.g_target -= 2 *
|
|
+ (go->go_step[--(ah->ah_gain.g_step_idx)].gos_gain -
|
|
+ ah->ah_gain.g_step->gos_gain);
|
|
+
|
|
+ ret = 1;
|
|
+ goto done;
|
|
+ }
|
|
+
|
|
+ if (ah->ah_gain.g_current <= ah->ah_gain.g_low) {
|
|
+ if (ah->ah_gain.g_step_idx == (go->go_steps_count - 1))
|
|
+ return -2;
|
|
+ for (ah->ah_gain.g_target = ah->ah_gain.g_current;
|
|
+ ah->ah_gain.g_target <= ah->ah_gain.g_low &&
|
|
+ ah->ah_gain.g_step_idx < go->go_steps_count-1;
|
|
+ ah->ah_gain.g_step =
|
|
+ &go->go_step[ah->ah_gain.g_step_idx])
|
|
+ ah->ah_gain.g_target -= 2 *
|
|
+ (go->go_step[++ah->ah_gain.g_step_idx].gos_gain -
|
|
+ ah->ah_gain.g_step->gos_gain);
|
|
+
|
|
+ ret = 2;
|
|
+ goto done;
|
|
+ }
|
|
+
|
|
+done:
|
|
+ ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE,
|
|
+ "ret %d, gain step %u, current gain %u, target gain %u\n",
|
|
+ ret, ah->ah_gain.g_step_idx, ah->ah_gain.g_current,
|
|
+ ah->ah_gain.g_target);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Read EEPROM Calibration data, modify RF Banks and Initialize RF5111
|
|
+ */
|
|
+static int ath5k_hw_rf5111_rfregs(struct ath5k_hw *ah,
|
|
+ struct ieee80211_channel *channel, unsigned int mode)
|
|
+{
|
|
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
|
|
+ u32 *rf;
|
|
+ const unsigned int rf_size = ARRAY_SIZE(rfregs_5111);
|
|
+ unsigned int i;
|
|
+ int obdb = -1, bank = -1;
|
|
+ u32 ee_mode;
|
|
+
|
|
+ AR5K_ASSERT_ENTRY(mode, AR5K_INI_VAL_MAX);
|
|
+
|
|
+ rf = ah->ah_rf_banks;
|
|
+
|
|
+ /* Copy values to modify them */
|
|
+ for (i = 0; i < rf_size; i++) {
|
|
+ if (rfregs_5111[i].rf_bank >= AR5K_RF5111_INI_RF_MAX_BANKS) {
|
|
+ ATH5K_ERR(ah->ah_sc, "invalid bank\n");
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ if (bank != rfregs_5111[i].rf_bank) {
|
|
+ bank = rfregs_5111[i].rf_bank;
|
|
+ ah->ah_offset[bank] = i;
|
|
+ }
|
|
+
|
|
+ rf[i] = rfregs_5111[i].rf_value[mode];
|
|
+ }
|
|
+
|
|
+ /* Modify bank 0 */
|
|
+ if (channel->val & CHANNEL_2GHZ) {
|
|
+ if (channel->val & CHANNEL_CCK)
|
|
+ ee_mode = AR5K_EEPROM_MODE_11B;
|
|
+ else
|
|
+ ee_mode = AR5K_EEPROM_MODE_11G;
|
|
+ obdb = 0;
|
|
+
|
|
+ if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[0],
|
|
+ ee->ee_ob[ee_mode][obdb], 3, 119, 0, true))
|
|
+ return -EINVAL;
|
|
+
|
|
+ if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[0],
|
|
+ ee->ee_ob[ee_mode][obdb], 3, 122, 0, true))
|
|
+ return -EINVAL;
|
|
+
|
|
+ obdb = 1;
|
|
+ /* Modify bank 6 */
|
|
+ } else {
|
|
+ /* For 11a, Turbo and XR */
|
|
+ ee_mode = AR5K_EEPROM_MODE_11A;
|
|
+ obdb = channel->freq >= 5725 ? 3 :
|
|
+ (channel->freq >= 5500 ? 2 :
|
|
+ (channel->freq >= 5260 ? 1 :
|
|
+ (channel->freq > 4000 ? 0 : -1)));
|
|
+
|
|
+ if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6],
|
|
+ ee->ee_pwd_84, 1, 51, 3, true))
|
|
+ return -EINVAL;
|
|
+
|
|
+ if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6],
|
|
+ ee->ee_pwd_90, 1, 45, 3, true))
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6],
|
|
+ !ee->ee_xpd[ee_mode], 1, 95, 0, true))
|
|
+ return -EINVAL;
|
|
+
|
|
+ if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6],
|
|
+ ee->ee_x_gain[ee_mode], 4, 96, 0, true))
|
|
+ return -EINVAL;
|
|
+
|
|
+ if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6], obdb >= 0 ?
|
|
+ ee->ee_ob[ee_mode][obdb] : 0, 3, 104, 0, true))
|
|
+ return -EINVAL;
|
|
+
|
|
+ if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6], obdb >= 0 ?
|
|
+ ee->ee_db[ee_mode][obdb] : 0, 3, 107, 0, true))
|
|
+ return -EINVAL;
|
|
+
|
|
+ /* Modify bank 7 */
|
|
+ if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[7],
|
|
+ ee->ee_i_gain[ee_mode], 6, 29, 0, true))
|
|
+ return -EINVAL;
|
|
+
|
|
+ if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[7],
|
|
+ ee->ee_xpd[ee_mode], 1, 4, 0, true))
|
|
+ return -EINVAL;
|
|
+
|
|
+ /* Write RF values */
|
|
+ for (i = 0; i < rf_size; i++) {
|
|
+ AR5K_REG_WAIT(i);
|
|
+ ath5k_hw_reg_write(ah, rf[i], rfregs_5111[i].rf_register);
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Read EEPROM Calibration data, modify RF Banks and Initialize RF5112
|
|
+ */
|
|
+static int ath5k_hw_rf5112_rfregs(struct ath5k_hw *ah,
|
|
+ struct ieee80211_channel *channel, unsigned int mode)
|
|
+{
|
|
+ const struct ath5k_ini_rf *rf_ini;
|
|
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
|
|
+ u32 *rf;
|
|
+ unsigned int rf_size, i;
|
|
+ int obdb = -1, bank = -1;
|
|
+ u32 ee_mode;
|
|
+
|
|
+ AR5K_ASSERT_ENTRY(mode, AR5K_INI_VAL_MAX);
|
|
+
|
|
+ rf = ah->ah_rf_banks;
|
|
+
|
|
+ if (ah->ah_radio_5ghz_revision >= AR5K_SREV_RAD_2112A
|
|
+ && !test_bit(MODE_IEEE80211A, ah->ah_capabilities.cap_mode)){
|
|
+ rf_ini = rfregs_2112a;
|
|
+ rf_size = ARRAY_SIZE(rfregs_5112a);
|
|
+ if (mode < 2) {
|
|
+ ATH5K_ERR(ah->ah_sc,"invalid channel mode: %i\n",mode);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+ mode = mode - 2; /*no a/turboa modes for 2112*/
|
|
+ } else if (ah->ah_radio_5ghz_revision >= AR5K_SREV_RAD_5112A) {
|
|
+ rf_ini = rfregs_5112a;
|
|
+ rf_size = ARRAY_SIZE(rfregs_5112a);
|
|
+ } else {
|
|
+ rf_ini = rfregs_5112;
|
|
+ rf_size = ARRAY_SIZE(rfregs_5112);
|
|
+ }
|
|
+
|
|
+ /* Copy values to modify them */
|
|
+ for (i = 0; i < rf_size; i++) {
|
|
+ if (rf_ini[i].rf_bank >= AR5K_RF5112_INI_RF_MAX_BANKS) {
|
|
+ ATH5K_ERR(ah->ah_sc, "invalid bank\n");
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ if (bank != rf_ini[i].rf_bank) {
|
|
+ bank = rf_ini[i].rf_bank;
|
|
+ ah->ah_offset[bank] = i;
|
|
+ }
|
|
+
|
|
+ rf[i] = rf_ini[i].rf_value[mode];
|
|
+ }
|
|
+
|
|
+ /* Modify bank 6 */
|
|
+ if (channel->val & CHANNEL_2GHZ) {
|
|
+ if (channel->val & CHANNEL_OFDM)
|
|
+ ee_mode = AR5K_EEPROM_MODE_11G;
|
|
+ else
|
|
+ ee_mode = AR5K_EEPROM_MODE_11B;
|
|
+ obdb = 0;
|
|
+
|
|
+ if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6],
|
|
+ ee->ee_ob[ee_mode][obdb], 3, 287, 0, true))
|
|
+ return -EINVAL;
|
|
+
|
|
+ if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6],
|
|
+ ee->ee_ob[ee_mode][obdb], 3, 290, 0, true))
|
|
+ return -EINVAL;
|
|
+ } else {
|
|
+ /* For 11a, Turbo and XR */
|
|
+ ee_mode = AR5K_EEPROM_MODE_11A;
|
|
+ obdb = channel->freq >= 5725 ? 3 :
|
|
+ (channel->freq >= 5500 ? 2 :
|
|
+ (channel->freq >= 5260 ? 1 :
|
|
+ (channel->freq > 4000 ? 0 : -1)));
|
|
+
|
|
+ if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6],
|
|
+ ee->ee_ob[ee_mode][obdb], 3, 279, 0, true))
|
|
+ return -EINVAL;
|
|
+
|
|
+ if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6],
|
|
+ ee->ee_ob[ee_mode][obdb], 3, 282, 0, true))
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ ath5k_hw_rfregs_op(rf, ah->ah_offset[6],
|
|
+ ee->ee_x_gain[ee_mode], 2, 270, 0, true);
|
|
+ ath5k_hw_rfregs_op(rf, ah->ah_offset[6],
|
|
+ ee->ee_x_gain[ee_mode], 2, 257, 0, true);
|
|
+
|
|
+ if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6],
|
|
+ ee->ee_xpd[ee_mode], 1, 302, 0, true))
|
|
+ return -EINVAL;
|
|
+
|
|
+ /* Modify bank 7 */
|
|
+ if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[7],
|
|
+ ee->ee_i_gain[ee_mode], 6, 14, 0, true))
|
|
+ return -EINVAL;
|
|
+
|
|
+ /* Write RF values */
|
|
+ for (i = 0; i < rf_size; i++)
|
|
+ ath5k_hw_reg_write(ah, rf[i], rf_ini[i].rf_register);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Initialize RF5413/5414
|
|
+ */
|
|
+static int ath5k_hw_rf5413_rfregs(struct ath5k_hw *ah,
|
|
+ struct ieee80211_channel *channel, unsigned int mode)
|
|
+{
|
|
+ const struct ath5k_ini_rf *rf_ini;
|
|
+ u32 *rf;
|
|
+ unsigned int rf_size, i;
|
|
+ int bank = -1;
|
|
+
|
|
+ AR5K_ASSERT_ENTRY(mode, AR5K_INI_VAL_MAX);
|
|
+
|
|
+ rf = ah->ah_rf_banks;
|
|
+
|
|
+ rf_ini = rfregs_5413;
|
|
+ rf_size = ARRAY_SIZE(rfregs_5413);
|
|
+
|
|
+ /* Copy values to modify them */
|
|
+ for (i = 0; i < rf_size; i++) {
|
|
+ if (rf_ini[i].rf_bank >= AR5K_RF5112_INI_RF_MAX_BANKS) {
|
|
+ ATH5K_ERR(ah->ah_sc, "invalid bank\n");
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ if (bank != rf_ini[i].rf_bank) {
|
|
+ bank = rf_ini[i].rf_bank;
|
|
+ ah->ah_offset[bank] = i;
|
|
+ }
|
|
+
|
|
+ rf[i] = rf_ini[i].rf_value[mode];
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * After compairing dumps from different cards
|
|
+ * we get the same RF_BUFFER settings (diff returns
|
|
+ * 0 lines). It seems that RF_BUFFER settings are static
|
|
+ * and are written unmodified (no EEPROM stuff
|
|
+ * is used because calibration data would be
|
|
+ * different between different cards and would result
|
|
+ * different RF_BUFFER settings)
|
|
+ */
|
|
+
|
|
+ /* Write RF values */
|
|
+ for (i = 0; i < rf_size; i++)
|
|
+ ath5k_hw_reg_write(ah, rf[i], rf_ini[i].rf_register);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Initialize RF
|
|
+ */
|
|
+int ath5k_hw_rfregs(struct ath5k_hw *ah, struct ieee80211_channel *channel,
|
|
+ unsigned int mode)
|
|
+{
|
|
+ int (*func)(struct ath5k_hw *, struct ieee80211_channel *, unsigned int);
|
|
+ int ret;
|
|
+
|
|
+ switch (ah->ah_radio) {
|
|
+ case AR5K_RF5111:
|
|
+ ah->ah_rf_banks_size = sizeof(rfregs_5111);
|
|
+ func = ath5k_hw_rf5111_rfregs;
|
|
+ break;
|
|
+ case AR5K_RF5112:
|
|
+ if (ah->ah_radio_5ghz_revision >= AR5K_SREV_RAD_5112A)
|
|
+ ah->ah_rf_banks_size = sizeof(rfregs_5112a);
|
|
+ else
|
|
+ ah->ah_rf_banks_size = sizeof(rfregs_5112);
|
|
+ func = ath5k_hw_rf5112_rfregs;
|
|
+ break;
|
|
+ case AR5K_RF5413:
|
|
+ ah->ah_rf_banks_size = sizeof(rfregs_5413);
|
|
+ func = ath5k_hw_rf5413_rfregs;
|
|
+ break;
|
|
+ default:
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ if (ah->ah_rf_banks == NULL) {
|
|
+ /* XXX do extra checks? */
|
|
+ ah->ah_rf_banks = kmalloc(ah->ah_rf_banks_size, GFP_KERNEL);
|
|
+ if (ah->ah_rf_banks == NULL) {
|
|
+ ATH5K_ERR(ah->ah_sc, "out of memory\n");
|
|
+ return -ENOMEM;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ ret = func(ah, channel, mode);
|
|
+ if (!ret)
|
|
+ ah->ah_rf_gain = AR5K_RFGAIN_INACTIVE;
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+int ath5k_hw_rfgain(struct ath5k_hw *ah, unsigned int freq)
|
|
+{
|
|
+ const struct ath5k_ini_rfgain *ath5k_rfg;
|
|
+ unsigned int i, size;
|
|
+
|
|
+ switch (ah->ah_radio) {
|
|
+ case AR5K_RF5111:
|
|
+ ath5k_rfg = rfgain_5111;
|
|
+ size = ARRAY_SIZE(rfgain_5111);
|
|
+ break;
|
|
+ case AR5K_RF5112:
|
|
+ ath5k_rfg = rfgain_5112;
|
|
+ size = ARRAY_SIZE(rfgain_5112);
|
|
+ break;
|
|
+ case AR5K_RF5413:
|
|
+ ath5k_rfg = rfgain_5413;
|
|
+ size = ARRAY_SIZE(rfgain_5413);
|
|
+ break;
|
|
+ default:
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ switch (freq) {
|
|
+ case AR5K_INI_RFGAIN_2GHZ:
|
|
+ case AR5K_INI_RFGAIN_5GHZ:
|
|
+ break;
|
|
+ default:
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ for (i = 0; i < size; i++) {
|
|
+ AR5K_REG_WAIT(i);
|
|
+ ath5k_hw_reg_write(ah, ath5k_rfg[i].rfg_value[freq],
|
|
+ (u32)ath5k_rfg[i].rfg_register);
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+enum ath5k_rfgain ath5k_hw_get_rf_gain(struct ath5k_hw *ah)
|
|
+{
|
|
+ u32 data, type;
|
|
+
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+
|
|
+ if (ah->ah_rf_banks == NULL || !ah->ah_gain.g_active ||
|
|
+ ah->ah_version <= AR5K_AR5211)
|
|
+ return AR5K_RFGAIN_INACTIVE;
|
|
+
|
|
+ if (ah->ah_rf_gain != AR5K_RFGAIN_READ_REQUESTED)
|
|
+ goto done;
|
|
+
|
|
+ data = ath5k_hw_reg_read(ah, AR5K_PHY_PAPD_PROBE);
|
|
+
|
|
+ if (!(data & AR5K_PHY_PAPD_PROBE_TX_NEXT)) {
|
|
+ ah->ah_gain.g_current = data >> AR5K_PHY_PAPD_PROBE_GAINF_S;
|
|
+ type = AR5K_REG_MS(data, AR5K_PHY_PAPD_PROBE_TYPE);
|
|
+
|
|
+ if (type == AR5K_PHY_PAPD_PROBE_TYPE_CCK)
|
|
+ ah->ah_gain.g_current += AR5K_GAIN_CCK_PROBE_CORR;
|
|
+
|
|
+ if (ah->ah_radio >= AR5K_RF5112) {
|
|
+ ath5k_hw_rfregs_gainf_corr(ah);
|
|
+ ah->ah_gain.g_current =
|
|
+ ah->ah_gain.g_current>=ah->ah_gain.g_f_corr ?
|
|
+ (ah->ah_gain.g_current-ah->ah_gain.g_f_corr) :
|
|
+ 0;
|
|
+ }
|
|
+
|
|
+ if (ath5k_hw_rfregs_gain_readback(ah) &&
|
|
+ AR5K_GAIN_CHECK_ADJUST(&ah->ah_gain) &&
|
|
+ ath5k_hw_rfregs_gain_adjust(ah))
|
|
+ ah->ah_rf_gain = AR5K_RFGAIN_NEED_CHANGE;
|
|
+ }
|
|
+
|
|
+done:
|
|
+ return ah->ah_rf_gain;
|
|
+}
|
|
+
|
|
+int ath5k_hw_set_rfgain_opt(struct ath5k_hw *ah)
|
|
+{
|
|
+ /* Initialize the gain optimization values */
|
|
+ switch (ah->ah_radio) {
|
|
+ case AR5K_RF5111:
|
|
+ ah->ah_gain.g_step_idx = rfgain_opt_5111.go_default;
|
|
+ ah->ah_gain.g_step =
|
|
+ &rfgain_opt_5111.go_step[ah->ah_gain.g_step_idx];
|
|
+ ah->ah_gain.g_low = 20;
|
|
+ ah->ah_gain.g_high = 35;
|
|
+ ah->ah_gain.g_active = 1;
|
|
+ break;
|
|
+ case AR5K_RF5112:
|
|
+ case AR5K_RF5413: /* ??? */
|
|
+ ah->ah_gain.g_step_idx = rfgain_opt_5112.go_default;
|
|
+ ah->ah_gain.g_step =
|
|
+ &rfgain_opt_5112.go_step[ah->ah_gain.g_step_idx];
|
|
+ ah->ah_gain.g_low = 20;
|
|
+ ah->ah_gain.g_high = 85;
|
|
+ ah->ah_gain.g_active = 1;
|
|
+ break;
|
|
+ default:
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/**************************\
|
|
+ PHY/RF channel functions
|
|
+\**************************/
|
|
+
|
|
+/*
|
|
+ * Check if a channel is supported
|
|
+ */
|
|
+bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags)
|
|
+{
|
|
+ /* Check if the channel is in our supported range */
|
|
+ if (flags & CHANNEL_2GHZ) {
|
|
+ if ((freq >= ah->ah_capabilities.cap_range.range_2ghz_min) &&
|
|
+ (freq <= ah->ah_capabilities.cap_range.range_2ghz_max))
|
|
+ return true;
|
|
+ } else if (flags & CHANNEL_5GHZ)
|
|
+ if ((freq >= ah->ah_capabilities.cap_range.range_5ghz_min) &&
|
|
+ (freq <= ah->ah_capabilities.cap_range.range_5ghz_max))
|
|
+ return true;
|
|
+
|
|
+ return false;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Convertion needed for RF5110
|
|
+ */
|
|
+static u32 ath5k_hw_rf5110_chan2athchan(struct ieee80211_channel *channel)
|
|
+{
|
|
+ u32 athchan;
|
|
+
|
|
+ /*
|
|
+ * Convert IEEE channel/MHz to an internal channel value used
|
|
+ * by the AR5210 chipset. This has not been verified with
|
|
+ * newer chipsets like the AR5212A who have a completely
|
|
+ * different RF/PHY part.
|
|
+ */
|
|
+ athchan = (ath5k_hw_bitswap((channel->chan - 24) / 2, 5) << 1) |
|
|
+ (1 << 6) | 0x1;
|
|
+
|
|
+ return athchan;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Set channel on RF5110
|
|
+ */
|
|
+static int ath5k_hw_rf5110_channel(struct ath5k_hw *ah,
|
|
+ struct ieee80211_channel *channel)
|
|
+{
|
|
+ u32 data;
|
|
+
|
|
+ /*
|
|
+ * Set the channel and wait
|
|
+ */
|
|
+ data = ath5k_hw_rf5110_chan2athchan(channel);
|
|
+ ath5k_hw_reg_write(ah, data, AR5K_RF_BUFFER);
|
|
+ ath5k_hw_reg_write(ah, 0, AR5K_RF_BUFFER_CONTROL_0);
|
|
+ mdelay(1);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Convertion needed for 5111
|
|
+ */
|
|
+static int ath5k_hw_rf5111_chan2athchan(unsigned int ieee,
|
|
+ struct ath5k_athchan_2ghz *athchan)
|
|
+{
|
|
+ int channel;
|
|
+
|
|
+ /* Cast this value to catch negative channel numbers (>= -19) */
|
|
+ channel = (int)ieee;
|
|
+
|
|
+ /*
|
|
+ * Map 2GHz IEEE channel to 5GHz Atheros channel
|
|
+ */
|
|
+ if (channel <= 13) {
|
|
+ athchan->a2_athchan = 115 + channel;
|
|
+ athchan->a2_flags = 0x46;
|
|
+ } else if (channel == 14) {
|
|
+ athchan->a2_athchan = 124;
|
|
+ athchan->a2_flags = 0x44;
|
|
+ } else if (channel >= 15 && channel <= 26) {
|
|
+ athchan->a2_athchan = ((channel - 14) * 4) + 132;
|
|
+ athchan->a2_flags = 0x46;
|
|
+ } else
|
|
+ return -EINVAL;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Set channel on 5111
|
|
+ */
|
|
+static int ath5k_hw_rf5111_channel(struct ath5k_hw *ah,
|
|
+ struct ieee80211_channel *channel)
|
|
+{
|
|
+ struct ath5k_athchan_2ghz ath5k_channel_2ghz;
|
|
+ unsigned int ath5k_channel = channel->chan;
|
|
+ u32 data0, data1, clock;
|
|
+ int ret;
|
|
+
|
|
+ /*
|
|
+ * Set the channel on the RF5111 radio
|
|
+ */
|
|
+ data0 = data1 = 0;
|
|
+
|
|
+ if (channel->val & CHANNEL_2GHZ) {
|
|
+ /* Map 2GHz channel to 5GHz Atheros channel ID */
|
|
+ ret = ath5k_hw_rf5111_chan2athchan(channel->chan,
|
|
+ &ath5k_channel_2ghz);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ ath5k_channel = ath5k_channel_2ghz.a2_athchan;
|
|
+ data0 = ((ath5k_hw_bitswap(ath5k_channel_2ghz.a2_flags, 8) & 0xff)
|
|
+ << 5) | (1 << 4);
|
|
+ }
|
|
+
|
|
+ if (ath5k_channel < 145 || !(ath5k_channel & 1)) {
|
|
+ clock = 1;
|
|
+ data1 = ((ath5k_hw_bitswap(ath5k_channel - 24, 8) & 0xff) << 2) |
|
|
+ (clock << 1) | (1 << 10) | 1;
|
|
+ } else {
|
|
+ clock = 0;
|
|
+ data1 = ((ath5k_hw_bitswap((ath5k_channel - 24) / 2, 8) & 0xff)
|
|
+ << 2) | (clock << 1) | (1 << 10) | 1;
|
|
+ }
|
|
+
|
|
+ ath5k_hw_reg_write(ah, (data1 & 0xff) | ((data0 & 0xff) << 8),
|
|
+ AR5K_RF_BUFFER);
|
|
+ ath5k_hw_reg_write(ah, ((data1 >> 8) & 0xff) | (data0 & 0xff00),
|
|
+ AR5K_RF_BUFFER_CONTROL_3);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Set channel on 5112 and newer
|
|
+ */
|
|
+static int ath5k_hw_rf5112_channel(struct ath5k_hw *ah,
|
|
+ struct ieee80211_channel *channel)
|
|
+{
|
|
+ u32 data, data0, data1, data2;
|
|
+ u16 c;
|
|
+
|
|
+ data = data0 = data1 = data2 = 0;
|
|
+ c = channel->freq;
|
|
+
|
|
+ /*
|
|
+ * Set the channel on the RF5112 or newer
|
|
+ */
|
|
+ if (c < 4800) {
|
|
+ if (!((c - 2224) % 5)) {
|
|
+ data0 = ((2 * (c - 704)) - 3040) / 10;
|
|
+ data1 = 1;
|
|
+ } else if (!((c - 2192) % 5)) {
|
|
+ data0 = ((2 * (c - 672)) - 3040) / 10;
|
|
+ data1 = 0;
|
|
+ } else
|
|
+ return -EINVAL;
|
|
+
|
|
+ data0 = ath5k_hw_bitswap((data0 << 2) & 0xff, 8);
|
|
+ } else {
|
|
+ if (!(c % 20) && c >= 5120) {
|
|
+ data0 = ath5k_hw_bitswap(((c - 4800) / 20 << 2), 8);
|
|
+ data2 = ath5k_hw_bitswap(3, 2);
|
|
+ } else if (!(c % 10)) {
|
|
+ data0 = ath5k_hw_bitswap(((c - 4800) / 10 << 1), 8);
|
|
+ data2 = ath5k_hw_bitswap(2, 2);
|
|
+ } else if (!(c % 5)) {
|
|
+ data0 = ath5k_hw_bitswap((c - 4800) / 5, 8);
|
|
+ data2 = ath5k_hw_bitswap(1, 2);
|
|
+ } else
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ data = (data0 << 4) | (data1 << 1) | (data2 << 2) | 0x1001;
|
|
+
|
|
+ ath5k_hw_reg_write(ah, data & 0xff, AR5K_RF_BUFFER);
|
|
+ ath5k_hw_reg_write(ah, (data >> 8) & 0x7f, AR5K_RF_BUFFER_CONTROL_5);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Set a channel on the radio chip
|
|
+ */
|
|
+int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel)
|
|
+{
|
|
+ int ret;
|
|
+
|
|
+ /*
|
|
+ * Check bounds supported by the PHY
|
|
+ * (don't care about regulation restrictions at this point)
|
|
+ */
|
|
+ if ((channel->freq < ah->ah_capabilities.cap_range.range_2ghz_min ||
|
|
+ channel->freq > ah->ah_capabilities.cap_range.range_2ghz_max) &&
|
|
+ (channel->freq < ah->ah_capabilities.cap_range.range_5ghz_min ||
|
|
+ channel->freq > ah->ah_capabilities.cap_range.range_5ghz_max)) {
|
|
+ ATH5K_ERR(ah->ah_sc,
|
|
+ "channel out of supported range (%u MHz)\n",
|
|
+ channel->freq);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Set the channel and wait
|
|
+ */
|
|
+ switch (ah->ah_radio) {
|
|
+ case AR5K_RF5110:
|
|
+ ret = ath5k_hw_rf5110_channel(ah, channel);
|
|
+ break;
|
|
+ case AR5K_RF5111:
|
|
+ ret = ath5k_hw_rf5111_channel(ah, channel);
|
|
+ break;
|
|
+ default:
|
|
+ ret = ath5k_hw_rf5112_channel(ah, channel);
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ ah->ah_current_channel.freq = channel->freq;
|
|
+ ah->ah_current_channel.val = channel->val;
|
|
+ ah->ah_turbo = channel->val == CHANNEL_T ? true : false;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*****************\
|
|
+ PHY calibration
|
|
+\*****************/
|
|
+
|
|
+/**
|
|
+ * ath5k_hw_noise_floor_calibration - perform PHY noise floor calibration
|
|
+ *
|
|
+ * @ah: struct ath5k_hw pointer we are operating on
|
|
+ * @freq: the channel frequency, just used for error logging
|
|
+ *
|
|
+ * This function performs a noise floor calibration of the PHY and waits for
|
|
+ * it to complete. Then the noise floor value is compared to some maximum
|
|
+ * noise floor we consider valid.
|
|
+ *
|
|
+ * Note that this is different from what the madwifi HAL does: it reads the
|
|
+ * noise floor and afterwards initiates the calibration. Since the noise floor
|
|
+ * calibration can take some time to finish, depending on the current channel
|
|
+ * use, that avoids the occasional timeout warnings we are seeing now.
|
|
+ *
|
|
+ * See the following link for an Atheros patent on noise floor calibration:
|
|
+ * http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&Sect2=HITOFF&d=PALL \
|
|
+ * &p=1&u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&r=1&f=G&l=50&s1=7245893.PN.&OS=PN/7
|
|
+ *
|
|
+ */
|
|
+int
|
|
+ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq)
|
|
+{
|
|
+ int ret;
|
|
+ unsigned int i;
|
|
+ s32 noise_floor;
|
|
+
|
|
+ /*
|
|
+ * Enable noise floor calibration and wait until completion
|
|
+ */
|
|
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL,
|
|
+ AR5K_PHY_AGCCTL_NF);
|
|
+
|
|
+ ret = ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL,
|
|
+ AR5K_PHY_AGCCTL_NF, 0, false);
|
|
+ if (ret) {
|
|
+ ATH5K_ERR(ah->ah_sc,
|
|
+ "noise floor calibration timeout (%uMHz)\n", freq);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ /* Wait until the noise floor is calibrated and read the value */
|
|
+ for (i = 20; i > 0; i--) {
|
|
+ mdelay(1);
|
|
+ noise_floor = ath5k_hw_reg_read(ah, AR5K_PHY_NF);
|
|
+ noise_floor = AR5K_PHY_NF_RVAL(noise_floor);
|
|
+ if (noise_floor & AR5K_PHY_NF_ACTIVE) {
|
|
+ noise_floor = AR5K_PHY_NF_AVAL(noise_floor);
|
|
+
|
|
+ if (noise_floor <= AR5K_TUNE_NOISE_FLOOR)
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_CALIBRATE,
|
|
+ "noise floor %d\n", noise_floor);
|
|
+
|
|
+ if (noise_floor > AR5K_TUNE_NOISE_FLOOR) {
|
|
+ ATH5K_ERR(ah->ah_sc,
|
|
+ "noise floor calibration failed (%uMHz)\n", freq);
|
|
+ return -EIO;
|
|
+ }
|
|
+
|
|
+ ah->ah_noise_floor = noise_floor;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Perform a PHY calibration on RF5110
|
|
+ * -Fix BPSK/QAM Constellation (I/Q correction)
|
|
+ * -Calculate Noise Floor
|
|
+ */
|
|
+static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah,
|
|
+ struct ieee80211_channel *channel)
|
|
+{
|
|
+ u32 phy_sig, phy_agc, phy_sat, beacon;
|
|
+ int ret;
|
|
+
|
|
+ /*
|
|
+ * Disable beacons and RX/TX queues, wait
|
|
+ */
|
|
+ AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5210,
|
|
+ AR5K_DIAG_SW_DIS_TX | AR5K_DIAG_SW_DIS_RX_5210);
|
|
+ beacon = ath5k_hw_reg_read(ah, AR5K_BEACON_5210);
|
|
+ ath5k_hw_reg_write(ah, beacon & ~AR5K_BEACON_ENABLE, AR5K_BEACON_5210);
|
|
+
|
|
+ udelay(2300);
|
|
+
|
|
+ /*
|
|
+ * Set the channel (with AGC turned off)
|
|
+ */
|
|
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE);
|
|
+ udelay(10);
|
|
+ ret = ath5k_hw_channel(ah, channel);
|
|
+
|
|
+ /*
|
|
+ * Activate PHY and wait
|
|
+ */
|
|
+ ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT);
|
|
+ mdelay(1);
|
|
+
|
|
+ AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE);
|
|
+
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ /*
|
|
+ * Calibrate the radio chip
|
|
+ */
|
|
+
|
|
+ /* Remember normal state */
|
|
+ phy_sig = ath5k_hw_reg_read(ah, AR5K_PHY_SIG);
|
|
+ phy_agc = ath5k_hw_reg_read(ah, AR5K_PHY_AGCCOARSE);
|
|
+ phy_sat = ath5k_hw_reg_read(ah, AR5K_PHY_ADCSAT);
|
|
+
|
|
+ /* Update radio registers */
|
|
+ ath5k_hw_reg_write(ah, (phy_sig & ~(AR5K_PHY_SIG_FIRPWR)) |
|
|
+ AR5K_REG_SM(-1, AR5K_PHY_SIG_FIRPWR), AR5K_PHY_SIG);
|
|
+
|
|
+ ath5k_hw_reg_write(ah, (phy_agc & ~(AR5K_PHY_AGCCOARSE_HI |
|
|
+ AR5K_PHY_AGCCOARSE_LO)) |
|
|
+ AR5K_REG_SM(-1, AR5K_PHY_AGCCOARSE_HI) |
|
|
+ AR5K_REG_SM(-127, AR5K_PHY_AGCCOARSE_LO), AR5K_PHY_AGCCOARSE);
|
|
+
|
|
+ ath5k_hw_reg_write(ah, (phy_sat & ~(AR5K_PHY_ADCSAT_ICNT |
|
|
+ AR5K_PHY_ADCSAT_THR)) |
|
|
+ AR5K_REG_SM(2, AR5K_PHY_ADCSAT_ICNT) |
|
|
+ AR5K_REG_SM(12, AR5K_PHY_ADCSAT_THR), AR5K_PHY_ADCSAT);
|
|
+
|
|
+ udelay(20);
|
|
+
|
|
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE);
|
|
+ udelay(10);
|
|
+ ath5k_hw_reg_write(ah, AR5K_PHY_RFSTG_DISABLE, AR5K_PHY_RFSTG);
|
|
+ AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE);
|
|
+
|
|
+ mdelay(1);
|
|
+
|
|
+ /*
|
|
+ * Enable calibration and wait until completion
|
|
+ */
|
|
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, AR5K_PHY_AGCCTL_CAL);
|
|
+
|
|
+ ret = ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL,
|
|
+ AR5K_PHY_AGCCTL_CAL, 0, false);
|
|
+
|
|
+ /* Reset to normal state */
|
|
+ ath5k_hw_reg_write(ah, phy_sig, AR5K_PHY_SIG);
|
|
+ ath5k_hw_reg_write(ah, phy_agc, AR5K_PHY_AGCCOARSE);
|
|
+ ath5k_hw_reg_write(ah, phy_sat, AR5K_PHY_ADCSAT);
|
|
+
|
|
+ if (ret) {
|
|
+ ATH5K_ERR(ah->ah_sc, "calibration timeout (%uMHz)\n",
|
|
+ channel->freq);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ ret = ath5k_hw_noise_floor_calibration(ah, channel->freq);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ /*
|
|
+ * Re-enable RX/TX and beacons
|
|
+ */
|
|
+ AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW_5210,
|
|
+ AR5K_DIAG_SW_DIS_TX | AR5K_DIAG_SW_DIS_RX_5210);
|
|
+ ath5k_hw_reg_write(ah, beacon, AR5K_BEACON_5210);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Perform a PHY calibration on RF5111/5112
|
|
+ */
|
|
+static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah,
|
|
+ struct ieee80211_channel *channel)
|
|
+{
|
|
+ u32 i_pwr, q_pwr;
|
|
+ s32 iq_corr, i_coff, i_coffd, q_coff, q_coffd;
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+
|
|
+ if (ah->ah_calibration == false ||
|
|
+ ath5k_hw_reg_read(ah, AR5K_PHY_IQ) & AR5K_PHY_IQ_RUN)
|
|
+ goto done;
|
|
+
|
|
+ ah->ah_calibration = false;
|
|
+
|
|
+ iq_corr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_CORR);
|
|
+ i_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_I);
|
|
+ q_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_Q);
|
|
+ i_coffd = ((i_pwr >> 1) + (q_pwr >> 1)) >> 7;
|
|
+ q_coffd = q_pwr >> 6;
|
|
+
|
|
+ if (i_coffd == 0 || q_coffd == 0)
|
|
+ goto done;
|
|
+
|
|
+ i_coff = ((-iq_corr) / i_coffd) & 0x3f;
|
|
+ q_coff = (((s32)i_pwr / q_coffd) - 64) & 0x1f;
|
|
+
|
|
+ /* Commit new IQ value */
|
|
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_ENABLE |
|
|
+ ((u32)q_coff) | ((u32)i_coff << AR5K_PHY_IQ_CORR_Q_I_COFF_S));
|
|
+
|
|
+done:
|
|
+ ath5k_hw_noise_floor_calibration(ah, channel->freq);
|
|
+
|
|
+ /* Request RF gain */
|
|
+ if (channel->val & CHANNEL_5GHZ) {
|
|
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txpower.txp_max,
|
|
+ AR5K_PHY_PAPD_PROBE_TXPOWER) |
|
|
+ AR5K_PHY_PAPD_PROBE_TX_NEXT, AR5K_PHY_PAPD_PROBE);
|
|
+ ah->ah_rf_gain = AR5K_RFGAIN_READ_REQUESTED;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Perform a PHY calibration
|
|
+ */
|
|
+int ath5k_hw_phy_calibrate(struct ath5k_hw *ah,
|
|
+ struct ieee80211_channel *channel)
|
|
+{
|
|
+ int ret;
|
|
+
|
|
+ if (ah->ah_radio == AR5K_RF5110)
|
|
+ ret = ath5k_hw_rf5110_calibrate(ah, channel);
|
|
+ else
|
|
+ ret = ath5k_hw_rf511x_calibrate(ah, channel);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+int ath5k_hw_phy_disable(struct ath5k_hw *ah)
|
|
+{
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+ /*Just a try M.F.*/
|
|
+ ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/********************\
|
|
+ Misc PHY functions
|
|
+\********************/
|
|
+
|
|
+/*
|
|
+ * Get the PHY Chip revision
|
|
+ */
|
|
+u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan)
|
|
+{
|
|
+ unsigned int i;
|
|
+ u32 srev;
|
|
+ u16 ret;
|
|
+
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+
|
|
+ /*
|
|
+ * Set the radio chip access register
|
|
+ */
|
|
+ switch (chan) {
|
|
+ case CHANNEL_2GHZ:
|
|
+ ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_2GHZ, AR5K_PHY(0));
|
|
+ break;
|
|
+ case CHANNEL_5GHZ:
|
|
+ ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0));
|
|
+ break;
|
|
+ default:
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ mdelay(2);
|
|
+
|
|
+ /* ...wait until PHY is ready and read the selected radio revision */
|
|
+ ath5k_hw_reg_write(ah, 0x00001c16, AR5K_PHY(0x34));
|
|
+
|
|
+ for (i = 0; i < 8; i++)
|
|
+ ath5k_hw_reg_write(ah, 0x00010000, AR5K_PHY(0x20));
|
|
+
|
|
+ if (ah->ah_version == AR5K_AR5210) {
|
|
+ srev = ath5k_hw_reg_read(ah, AR5K_PHY(256) >> 28) & 0xf;
|
|
+ ret = (u16)ath5k_hw_bitswap(srev, 4) + 1;
|
|
+ } else {
|
|
+ srev = (ath5k_hw_reg_read(ah, AR5K_PHY(0x100)) >> 24) & 0xff;
|
|
+ ret = (u16)ath5k_hw_bitswap(((srev & 0xf0) >> 4) |
|
|
+ ((srev & 0x0f) << 4), 8);
|
|
+ }
|
|
+
|
|
+ /* Reset to the 5GHz mode */
|
|
+ ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0));
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+void /*TODO:Boundary check*/
|
|
+ath5k_hw_set_def_antenna(struct ath5k_hw *ah, unsigned int ant)
|
|
+{
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+ /*Just a try M.F.*/
|
|
+ if (ah->ah_version != AR5K_AR5210)
|
|
+ ath5k_hw_reg_write(ah, ant, AR5K_DEFAULT_ANTENNA);
|
|
+}
|
|
+
|
|
+unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah)
|
|
+{
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+ /*Just a try M.F.*/
|
|
+ if (ah->ah_version != AR5K_AR5210)
|
|
+ return ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA);
|
|
+
|
|
+ return false; /*XXX: What do we return for 5210 ?*/
|
|
+}
|
|
+
|
|
+/*
|
|
+ * TX power setup
|
|
+ */
|
|
+
|
|
+/*
|
|
+ * Initialize the tx power table (not fully implemented)
|
|
+ */
|
|
+static void ath5k_txpower_table(struct ath5k_hw *ah,
|
|
+ struct ieee80211_channel *channel, s16 max_power)
|
|
+{
|
|
+ unsigned int i, min, max, n;
|
|
+ u16 txpower, *rates;
|
|
+
|
|
+ rates = ah->ah_txpower.txp_rates;
|
|
+
|
|
+ txpower = AR5K_TUNE_DEFAULT_TXPOWER * 2;
|
|
+ if (max_power > txpower)
|
|
+ txpower = max_power > AR5K_TUNE_MAX_TXPOWER ?
|
|
+ AR5K_TUNE_MAX_TXPOWER : max_power;
|
|
+
|
|
+ for (i = 0; i < AR5K_MAX_RATES; i++)
|
|
+ rates[i] = txpower;
|
|
+
|
|
+ /* XXX setup target powers by rate */
|
|
+
|
|
+ ah->ah_txpower.txp_min = rates[7];
|
|
+ ah->ah_txpower.txp_max = rates[0];
|
|
+ ah->ah_txpower.txp_ofdm = rates[0];
|
|
+
|
|
+ /* Calculate the power table */
|
|
+ n = ARRAY_SIZE(ah->ah_txpower.txp_pcdac);
|
|
+ min = AR5K_EEPROM_PCDAC_START;
|
|
+ max = AR5K_EEPROM_PCDAC_STOP;
|
|
+ for (i = 0; i < n; i += AR5K_EEPROM_PCDAC_STEP)
|
|
+ ah->ah_txpower.txp_pcdac[i] =
|
|
+#ifdef notyet
|
|
+ min + ((i * (max - min)) / n);
|
|
+#else
|
|
+ min;
|
|
+#endif
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Set transmition power
|
|
+ */
|
|
+int /*O.K. - txpower_table is unimplemented so this doesn't work*/
|
|
+ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel,
|
|
+ unsigned int txpower)
|
|
+{
|
|
+ bool tpc = ah->ah_txpower.txp_tpc;
|
|
+ unsigned int i;
|
|
+
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+ if (txpower > AR5K_TUNE_MAX_TXPOWER) {
|
|
+ ATH5K_ERR(ah->ah_sc, "invalid tx power: %u\n", txpower);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ /* Reset TX power values */
|
|
+ memset(&ah->ah_txpower, 0, sizeof(ah->ah_txpower));
|
|
+ ah->ah_txpower.txp_tpc = tpc;
|
|
+
|
|
+ /* Initialize TX power table */
|
|
+ ath5k_txpower_table(ah, channel, txpower);
|
|
+
|
|
+ /*
|
|
+ * Write TX power values
|
|
+ */
|
|
+ for (i = 0; i < (AR5K_EEPROM_POWER_TABLE_SIZE / 2); i++) {
|
|
+ ath5k_hw_reg_write(ah,
|
|
+ ((((ah->ah_txpower.txp_pcdac[(i << 1) + 1] << 8) | 0xff) & 0xffff) << 16) |
|
|
+ (((ah->ah_txpower.txp_pcdac[(i << 1) ] << 8) | 0xff) & 0xffff),
|
|
+ AR5K_PHY_PCDAC_TXPOWER(i));
|
|
+ }
|
|
+
|
|
+ ath5k_hw_reg_write(ah, AR5K_TXPOWER_OFDM(3, 24) |
|
|
+ AR5K_TXPOWER_OFDM(2, 16) | AR5K_TXPOWER_OFDM(1, 8) |
|
|
+ AR5K_TXPOWER_OFDM(0, 0), AR5K_PHY_TXPOWER_RATE1);
|
|
+
|
|
+ ath5k_hw_reg_write(ah, AR5K_TXPOWER_OFDM(7, 24) |
|
|
+ AR5K_TXPOWER_OFDM(6, 16) | AR5K_TXPOWER_OFDM(5, 8) |
|
|
+ AR5K_TXPOWER_OFDM(4, 0), AR5K_PHY_TXPOWER_RATE2);
|
|
+
|
|
+ ath5k_hw_reg_write(ah, AR5K_TXPOWER_CCK(10, 24) |
|
|
+ AR5K_TXPOWER_CCK(9, 16) | AR5K_TXPOWER_CCK(15, 8) |
|
|
+ AR5K_TXPOWER_CCK(8, 0), AR5K_PHY_TXPOWER_RATE3);
|
|
+
|
|
+ ath5k_hw_reg_write(ah, AR5K_TXPOWER_CCK(14, 24) |
|
|
+ AR5K_TXPOWER_CCK(13, 16) | AR5K_TXPOWER_CCK(12, 8) |
|
|
+ AR5K_TXPOWER_CCK(11, 0), AR5K_PHY_TXPOWER_RATE4);
|
|
+
|
|
+ if (ah->ah_txpower.txp_tpc == true)
|
|
+ ath5k_hw_reg_write(ah, AR5K_PHY_TXPOWER_RATE_MAX_TPC_ENABLE |
|
|
+ AR5K_TUNE_MAX_TXPOWER, AR5K_PHY_TXPOWER_RATE_MAX);
|
|
+ else
|
|
+ ath5k_hw_reg_write(ah, AR5K_PHY_TXPOWER_RATE_MAX |
|
|
+ AR5K_TUNE_MAX_TXPOWER, AR5K_PHY_TXPOWER_RATE_MAX);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, unsigned int power)
|
|
+{
|
|
+ /*Just a try M.F.*/
|
|
+ struct ieee80211_channel *channel = &ah->ah_current_channel;
|
|
+
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+ ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_TXPOWER,
|
|
+ "changing txpower to %d\n", power);
|
|
+
|
|
+ return ath5k_hw_txpower(ah, channel, power);
|
|
+}
|
|
diff -up /dev/null linux-2.6.23.noarch/drivers/net/wireless/ath5k/ath5k.h
|
|
--- /dev/null 2007-12-21 08:33:07.834165456 -0500
|
|
+++ linux-2.6.23.noarch/drivers/net/wireless/ath5k/ath5k.h 2007-12-21 12:18:50.000000000 -0500
|
|
@@ -0,0 +1,1153 @@
|
|
+/*
|
|
+ * Copyright (c) 2004-2007 Reyk Floeter <reyk@openbsd.org>
|
|
+ * Copyright (c) 2006-2007 Nick Kossifidis <mickflemm@gmail.com>
|
|
+ *
|
|
+ * Permission to use, copy, modify, and distribute this software for any
|
|
+ * purpose with or without fee is hereby granted, provided that the above
|
|
+ * copyright notice and this permission notice appear in all copies.
|
|
+ *
|
|
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
+ */
|
|
+
|
|
+#ifndef _ATH5K_H
|
|
+#define _ATH5K_H
|
|
+
|
|
+/* Set this to 1 to disable regulatory domain restrictions for channel tests.
|
|
+ * WARNING: This is for debuging only and has side effects (eg. scan takes too
|
|
+ * long and results timeouts). It's also illegal to tune to some of the
|
|
+ * supported frequencies in some countries, so use this at your own risk,
|
|
+ * you've been warned. */
|
|
+#define CHAN_DEBUG 0
|
|
+
|
|
+#include <linux/io.h>
|
|
+#include <linux/types.h>
|
|
+#include <net/mac80211.h>
|
|
+
|
|
+#include "hw.h"
|
|
+#include "regdom.h"
|
|
+
|
|
+/* PCI IDs */
|
|
+#define PCI_DEVICE_ID_ATHEROS_AR5210 0x0007 /* AR5210 */
|
|
+#define PCI_DEVICE_ID_ATHEROS_AR5311 0x0011 /* AR5311 */
|
|
+#define PCI_DEVICE_ID_ATHEROS_AR5211 0x0012 /* AR5211 */
|
|
+#define PCI_DEVICE_ID_ATHEROS_AR5212 0x0013 /* AR5212 */
|
|
+#define PCI_DEVICE_ID_3COM_3CRDAG675 0x0013 /* 3CRDAG675 (Atheros AR5212) */
|
|
+#define PCI_DEVICE_ID_3COM_2_3CRPAG175 0x0013 /* 3CRPAG175 (Atheros AR5212) */
|
|
+#define PCI_DEVICE_ID_ATHEROS_AR5210_AP 0x0207 /* AR5210 (Early) */
|
|
+#define PCI_DEVICE_ID_ATHEROS_AR5212_IBM 0x1014 /* AR5212 (IBM MiniPCI) */
|
|
+#define PCI_DEVICE_ID_ATHEROS_AR5210_DEFAULT 0x1107 /* AR5210 (no eeprom) */
|
|
+#define PCI_DEVICE_ID_ATHEROS_AR5212_DEFAULT 0x1113 /* AR5212 (no eeprom) */
|
|
+#define PCI_DEVICE_ID_ATHEROS_AR5211_DEFAULT 0x1112 /* AR5211 (no eeprom) */
|
|
+#define PCI_DEVICE_ID_ATHEROS_AR5212_FPGA 0xf013 /* AR5212 (emulation board) */
|
|
+#define PCI_DEVICE_ID_ATHEROS_AR5211_LEGACY 0xff12 /* AR5211 (emulation board) */
|
|
+#define PCI_DEVICE_ID_ATHEROS_AR5211_FPGA11B 0xf11b /* AR5211 (emulation board) */
|
|
+#define PCI_DEVICE_ID_ATHEROS_AR5312_REV2 0x0052 /* AR5312 WMAC (AP31) */
|
|
+#define PCI_DEVICE_ID_ATHEROS_AR5312_REV7 0x0057 /* AR5312 WMAC (AP30-040) */
|
|
+#define PCI_DEVICE_ID_ATHEROS_AR5312_REV8 0x0058 /* AR5312 WMAC (AP43-030) */
|
|
+#define PCI_DEVICE_ID_ATHEROS_AR5212_0014 0x0014 /* AR5212 compatible */
|
|
+#define PCI_DEVICE_ID_ATHEROS_AR5212_0015 0x0015 /* AR5212 compatible */
|
|
+#define PCI_DEVICE_ID_ATHEROS_AR5212_0016 0x0016 /* AR5212 compatible */
|
|
+#define PCI_DEVICE_ID_ATHEROS_AR5212_0017 0x0017 /* AR5212 compatible */
|
|
+#define PCI_DEVICE_ID_ATHEROS_AR5212_0018 0x0018 /* AR5212 compatible */
|
|
+#define PCI_DEVICE_ID_ATHEROS_AR5212_0019 0x0019 /* AR5212 compatible */
|
|
+#define PCI_DEVICE_ID_ATHEROS_AR2413 0x001a /* AR2413 (Griffin-lite) */
|
|
+#define PCI_DEVICE_ID_ATHEROS_AR5413 0x001b /* AR5413 (Eagle) */
|
|
+#define PCI_DEVICE_ID_ATHEROS_AR5424 0x001c /* AR5424 (Condor PCI-E) */
|
|
+#define PCI_DEVICE_ID_ATHEROS_AR5416 0x0023 /* AR5416 */
|
|
+#define PCI_DEVICE_ID_ATHEROS_AR5418 0x0024 /* AR5418 */
|
|
+
|
|
+/****************************\
|
|
+ GENERIC DRIVER DEFINITIONS
|
|
+\****************************/
|
|
+
|
|
+#define ATH5K_PRINTF(fmt, ...) printk("%s: " fmt, __func__, ##__VA_ARGS__)
|
|
+
|
|
+#define ATH5K_PRINTK(_sc, _level, _fmt, ...) \
|
|
+ printk(_level "ath5k %s: " _fmt, \
|
|
+ ((_sc) && (_sc)->hw) ? wiphy_name((_sc)->hw->wiphy) : "", \
|
|
+ ##__VA_ARGS__)
|
|
+
|
|
+#define ATH5K_PRINTK_LIMIT(_sc, _level, _fmt, ...) do { \
|
|
+ if (net_ratelimit()) \
|
|
+ ATH5K_PRINTK(_sc, _level, _fmt, ##__VA_ARGS__); \
|
|
+ } while (0)
|
|
+
|
|
+#define ATH5K_INFO(_sc, _fmt, ...) \
|
|
+ ATH5K_PRINTK(_sc, KERN_INFO, _fmt, ##__VA_ARGS__)
|
|
+
|
|
+#define ATH5K_WARN(_sc, _fmt, ...) \
|
|
+ ATH5K_PRINTK_LIMIT(_sc, KERN_WARNING, _fmt, ##__VA_ARGS__)
|
|
+
|
|
+#define ATH5K_ERR(_sc, _fmt, ...) \
|
|
+ ATH5K_PRINTK_LIMIT(_sc, KERN_ERR, _fmt, ##__VA_ARGS__)
|
|
+
|
|
+/*
|
|
+ * Some tuneable values (these should be changeable by the user)
|
|
+ */
|
|
+#define AR5K_TUNE_DMA_BEACON_RESP 2
|
|
+#define AR5K_TUNE_SW_BEACON_RESP 10
|
|
+#define AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF 0
|
|
+#define AR5K_TUNE_RADAR_ALERT false
|
|
+#define AR5K_TUNE_MIN_TX_FIFO_THRES 1
|
|
+#define AR5K_TUNE_MAX_TX_FIFO_THRES ((IEEE80211_MAX_LEN / 64) + 1)
|
|
+#define AR5K_TUNE_REGISTER_TIMEOUT 20000
|
|
+/* Register for RSSI threshold has a mask of 0xff, so 255 seems to
|
|
+ * be the max value. */
|
|
+#define AR5K_TUNE_RSSI_THRES 129
|
|
+/* This must be set when setting the RSSI threshold otherwise it can
|
|
+ * prevent a reset. If AR5K_RSSI_THR is read after writing to it
|
|
+ * the BMISS_THRES will be seen as 0, seems harware doesn't keep
|
|
+ * track of it. Max value depends on harware. For AR5210 this is just 7.
|
|
+ * For AR5211+ this seems to be up to 255. */
|
|
+#define AR5K_TUNE_BMISS_THRES 7
|
|
+#define AR5K_TUNE_REGISTER_DWELL_TIME 20000
|
|
+#define AR5K_TUNE_BEACON_INTERVAL 100
|
|
+#define AR5K_TUNE_AIFS 2
|
|
+#define AR5K_TUNE_AIFS_11B 2
|
|
+#define AR5K_TUNE_AIFS_XR 0
|
|
+#define AR5K_TUNE_CWMIN 15
|
|
+#define AR5K_TUNE_CWMIN_11B 31
|
|
+#define AR5K_TUNE_CWMIN_XR 3
|
|
+#define AR5K_TUNE_CWMAX 1023
|
|
+#define AR5K_TUNE_CWMAX_11B 1023
|
|
+#define AR5K_TUNE_CWMAX_XR 7
|
|
+#define AR5K_TUNE_NOISE_FLOOR -72
|
|
+#define AR5K_TUNE_MAX_TXPOWER 60
|
|
+#define AR5K_TUNE_DEFAULT_TXPOWER 30
|
|
+#define AR5K_TUNE_TPC_TXPOWER true
|
|
+#define AR5K_TUNE_ANT_DIVERSITY true
|
|
+#define AR5K_TUNE_HWTXTRIES 4
|
|
+
|
|
+/* token to use for aifs, cwmin, cwmax in MadWiFi */
|
|
+#define AR5K_TXQ_USEDEFAULT ((u32) -1)
|
|
+
|
|
+/* GENERIC CHIPSET DEFINITIONS */
|
|
+
|
|
+/* MAC Chips */
|
|
+enum ath5k_version {
|
|
+ AR5K_AR5210 = 0,
|
|
+ AR5K_AR5211 = 1,
|
|
+ AR5K_AR5212 = 2,
|
|
+};
|
|
+
|
|
+/* PHY Chips */
|
|
+enum ath5k_radio {
|
|
+ AR5K_RF5110 = 0,
|
|
+ AR5K_RF5111 = 1,
|
|
+ AR5K_RF5112 = 2,
|
|
+ AR5K_RF5413 = 3,
|
|
+};
|
|
+
|
|
+/*
|
|
+ * Common silicon revision/version values
|
|
+ */
|
|
+
|
|
+enum ath5k_srev_type {
|
|
+ AR5K_VERSION_VER,
|
|
+ AR5K_VERSION_RAD,
|
|
+};
|
|
+
|
|
+struct ath5k_srev_name {
|
|
+ const char *sr_name;
|
|
+ enum ath5k_srev_type sr_type;
|
|
+ u_int sr_val;
|
|
+};
|
|
+
|
|
+#define AR5K_SREV_UNKNOWN 0xffff
|
|
+
|
|
+#define AR5K_SREV_VER_AR5210 0x00
|
|
+#define AR5K_SREV_VER_AR5311 0x10
|
|
+#define AR5K_SREV_VER_AR5311A 0x20
|
|
+#define AR5K_SREV_VER_AR5311B 0x30
|
|
+#define AR5K_SREV_VER_AR5211 0x40
|
|
+#define AR5K_SREV_VER_AR5212 0x50
|
|
+#define AR5K_SREV_VER_AR5213 0x55
|
|
+#define AR5K_SREV_VER_AR5213A 0x59
|
|
+#define AR5K_SREV_VER_AR2424 0xa0
|
|
+#define AR5K_SREV_VER_AR5424 0xa3
|
|
+#define AR5K_SREV_VER_AR5413 0xa4
|
|
+#define AR5K_SREV_VER_AR5414 0xa5
|
|
+#define AR5K_SREV_VER_AR5416 0xc0 /* ? */
|
|
+#define AR5K_SREV_VER_AR5418 0xca
|
|
+
|
|
+#define AR5K_SREV_RAD_5110 0x00
|
|
+#define AR5K_SREV_RAD_5111 0x10
|
|
+#define AR5K_SREV_RAD_5111A 0x15
|
|
+#define AR5K_SREV_RAD_2111 0x20
|
|
+#define AR5K_SREV_RAD_5112 0x30
|
|
+#define AR5K_SREV_RAD_5112A 0x35
|
|
+#define AR5K_SREV_RAD_2112 0x40
|
|
+#define AR5K_SREV_RAD_2112A 0x45
|
|
+#define AR5K_SREV_RAD_SC1 0x63 /* Found on 5413/5414 */
|
|
+#define AR5K_SREV_RAD_SC2 0xa2 /* Found on 2424/5424 */
|
|
+#define AR5K_SREV_RAD_5133 0xc0 /* MIMO found on 5418 */
|
|
+
|
|
+/* IEEE defs */
|
|
+
|
|
+#define IEEE80211_MAX_LEN 2500
|
|
+
|
|
+/* TODO add support to mac80211 for vendor-specific rates and modes */
|
|
+
|
|
+/*
|
|
+ * Some of this information is based on Documentation from:
|
|
+ *
|
|
+ * http://madwifi.org/wiki/ChipsetFeatures/SuperAG
|
|
+ *
|
|
+ * Modulation for Atheros' eXtended Range - range enhancing extension that is
|
|
+ * supposed to double the distance an Atheros client device can keep a
|
|
+ * connection with an Atheros access point. This is achieved by increasing
|
|
+ * the receiver sensitivity up to, -105dBm, which is about 20dB above what
|
|
+ * the 802.11 specifications demand. In addition, new (proprietary) data rates
|
|
+ * are introduced: 3, 2, 1, 0.5 and 0.25 MBit/s.
|
|
+ *
|
|
+ * Please note that can you either use XR or TURBO but you cannot use both,
|
|
+ * they are exclusive.
|
|
+ *
|
|
+ */
|
|
+#define MODULATION_XR 0x00000200
|
|
+/*
|
|
+ * Modulation for Atheros' Turbo G and Turbo A, its supposed to provide a
|
|
+ * throughput transmission speed up to 40Mbit/s-60Mbit/s at a 108Mbit/s
|
|
+ * signaling rate achieved through the bonding of two 54Mbit/s 802.11g
|
|
+ * channels. To use this feature your Access Point must also suport it.
|
|
+ * There is also a distinction between "static" and "dynamic" turbo modes:
|
|
+ *
|
|
+ * - Static: is the dumb version: devices set to this mode stick to it until
|
|
+ * the mode is turned off.
|
|
+ * - Dynamic: is the intelligent version, the network decides itself if it
|
|
+ * is ok to use turbo. As soon as traffic is detected on adjacent channels
|
|
+ * (which would get used in turbo mode), or when a non-turbo station joins
|
|
+ * the network, turbo mode won't be used until the situation changes again.
|
|
+ * Dynamic mode is achieved by Atheros' Adaptive Radio (AR) feature which
|
|
+ * monitors the used radio band in order to decide whether turbo mode may
|
|
+ * be used or not.
|
|
+ *
|
|
+ * This article claims Super G sticks to bonding of channels 5 and 6 for
|
|
+ * USA:
|
|
+ *
|
|
+ * http://www.pcworld.com/article/id,113428-page,1/article.html
|
|
+ *
|
|
+ * The channel bonding seems to be driver specific though. In addition to
|
|
+ * deciding what channels will be used, these "Turbo" modes are accomplished
|
|
+ * by also enabling the following features:
|
|
+ *
|
|
+ * - Bursting: allows multiple frames to be sent at once, rather than pausing
|
|
+ * after each frame. Bursting is a standards-compliant feature that can be
|
|
+ * used with any Access Point.
|
|
+ * - Fast frames: increases the amount of information that can be sent per
|
|
+ * frame, also resulting in a reduction of transmission overhead. It is a
|
|
+ * proprietary feature that needs to be supported by the Access Point.
|
|
+ * - Compression: data frames are compressed in real time using a Lempel Ziv
|
|
+ * algorithm. This is done transparently. Once this feature is enabled,
|
|
+ * compression and decompression takes place inside the chipset, without
|
|
+ * putting additional load on the host CPU.
|
|
+ *
|
|
+ */
|
|
+#define MODULATION_TURBO 0x00000080
|
|
+
|
|
+enum ath5k_vendor_mode {
|
|
+ MODE_ATHEROS_TURBO = NUM_IEEE80211_MODES+1,
|
|
+ MODE_ATHEROS_TURBOG
|
|
+};
|
|
+
|
|
+/* Number of supported mac80211 enum ieee80211_phymode modes by this driver */
|
|
+#define NUM_DRIVER_MODES 3
|
|
+
|
|
+/* adding this flag to rate_code enables short preamble, see ar5212_reg.h */
|
|
+#define AR5K_SET_SHORT_PREAMBLE 0x04
|
|
+
|
|
+#define HAS_SHPREAMBLE(_ix) (rt->rates[_ix].modulation == IEEE80211_RATE_CCK_2)
|
|
+#define SHPREAMBLE_FLAG(_ix) (HAS_SHPREAMBLE(_ix) ? AR5K_SET_SHORT_PREAMBLE : 0)
|
|
+
|
|
+/****************\
|
|
+ TX DEFINITIONS
|
|
+\****************/
|
|
+
|
|
+/*
|
|
+ * Tx Descriptor
|
|
+ */
|
|
+struct ath5k_tx_status {
|
|
+ u16 ts_seqnum;
|
|
+ u16 ts_tstamp;
|
|
+ u8 ts_status;
|
|
+ u8 ts_rate;
|
|
+ s8 ts_rssi;
|
|
+ u8 ts_shortretry;
|
|
+ u8 ts_longretry;
|
|
+ u8 ts_virtcol;
|
|
+ u8 ts_antenna;
|
|
+};
|
|
+
|
|
+#define AR5K_TXSTAT_ALTRATE 0x80
|
|
+#define AR5K_TXERR_XRETRY 0x01
|
|
+#define AR5K_TXERR_FILT 0x02
|
|
+#define AR5K_TXERR_FIFO 0x04
|
|
+
|
|
+/*
|
|
+ * Queue types used to classify tx queues.
|
|
+ */
|
|
+enum ath5k_tx_queue {
|
|
+ AR5K_TX_QUEUE_INACTIVE = 0, /* q is unused -- see ath5k_hw_release_tx_queue */
|
|
+ AR5K_TX_QUEUE_DATA, /*A normal data queue*/
|
|
+ AR5K_TX_QUEUE_XR_DATA, /*An XR-data queue*/
|
|
+ AR5K_TX_QUEUE_BEACON, /*The beacon queue*/
|
|
+ AR5K_TX_QUEUE_CAB, /*The ater-beacon queue*/
|
|
+ AR5K_TX_QUEUE_UAPSD, /*Unscheduled Automatic Power Save Delivery queue*/
|
|
+};
|
|
+
|
|
+#define AR5K_NUM_TX_QUEUES 10
|
|
+#define AR5K_NUM_TX_QUEUES_NOQCU 2
|
|
+
|
|
+/*
|
|
+ * Queue syb-types to classify normal data queues.
|
|
+ * These are the 4 Access Categories as defined in
|
|
+ * WME spec. 0 is the lowest priority and 4 is the
|
|
+ * highest. Normal data that hasn't been classified
|
|
+ * goes to the Best Effort AC.
|
|
+ */
|
|
+enum ath5k_tx_queue_subtype {
|
|
+ AR5K_WME_AC_BK = 0, /*Background traffic*/
|
|
+ AR5K_WME_AC_BE, /*Best-effort (normal) traffic)*/
|
|
+ AR5K_WME_AC_VI, /*Video traffic*/
|
|
+ AR5K_WME_AC_VO, /*Voice traffic*/
|
|
+};
|
|
+
|
|
+/*
|
|
+ * Queue ID numbers as returned by the hw functions, each number
|
|
+ * represents a hw queue. If hw does not support hw queues
|
|
+ * (eg 5210) all data goes in one queue. These match
|
|
+ * d80211 definitions (net80211/MadWiFi don't use them).
|
|
+ */
|
|
+enum ath5k_tx_queue_id {
|
|
+ AR5K_TX_QUEUE_ID_NOQCU_DATA = 0,
|
|
+ AR5K_TX_QUEUE_ID_NOQCU_BEACON = 1,
|
|
+ AR5K_TX_QUEUE_ID_DATA_MIN = 0, /*IEEE80211_TX_QUEUE_DATA0*/
|
|
+ AR5K_TX_QUEUE_ID_DATA_MAX = 4, /*IEEE80211_TX_QUEUE_DATA4*/
|
|
+ AR5K_TX_QUEUE_ID_DATA_SVP = 5, /*IEEE80211_TX_QUEUE_SVP - Spectralink Voice Protocol*/
|
|
+ AR5K_TX_QUEUE_ID_CAB = 6, /*IEEE80211_TX_QUEUE_AFTER_BEACON*/
|
|
+ AR5K_TX_QUEUE_ID_BEACON = 7, /*IEEE80211_TX_QUEUE_BEACON*/
|
|
+ AR5K_TX_QUEUE_ID_UAPSD = 8,
|
|
+ AR5K_TX_QUEUE_ID_XR_DATA = 9,
|
|
+};
|
|
+
|
|
+
|
|
+/*
|
|
+ * Flags to set hw queue's parameters...
|
|
+ */
|
|
+#define AR5K_TXQ_FLAG_TXOKINT_ENABLE 0x0001 /* Enable TXOK interrupt */
|
|
+#define AR5K_TXQ_FLAG_TXERRINT_ENABLE 0x0002 /* Enable TXERR interrupt */
|
|
+#define AR5K_TXQ_FLAG_TXEOLINT_ENABLE 0x0004 /* Enable TXEOL interrupt -not used- */
|
|
+#define AR5K_TXQ_FLAG_TXDESCINT_ENABLE 0x0008 /* Enable TXDESC interrupt -not used- */
|
|
+#define AR5K_TXQ_FLAG_TXURNINT_ENABLE 0x0010 /* Enable TXURN interrupt */
|
|
+#define AR5K_TXQ_FLAG_BACKOFF_DISABLE 0x0020 /* Disable random post-backoff */
|
|
+#define AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE 0x0040 /* Enable ready time expiry policy (?)*/
|
|
+#define AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE 0x0080 /* Enable backoff while bursting */
|
|
+#define AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS 0x0100 /* Disable backoff while bursting */
|
|
+#define AR5K_TXQ_FLAG_COMPRESSION_ENABLE 0x0200 /* Enable hw compression -not implemented-*/
|
|
+
|
|
+/*
|
|
+ * A struct to hold tx queue's parameters
|
|
+ */
|
|
+struct ath5k_txq_info {
|
|
+ enum ath5k_tx_queue tqi_type;
|
|
+ enum ath5k_tx_queue_subtype tqi_subtype;
|
|
+ u16 tqi_flags; /* Tx queue flags (see above) */
|
|
+ u32 tqi_aifs; /* Arbitrated Interframe Space */
|
|
+ s32 tqi_cw_min; /* Minimum Contention Window */
|
|
+ s32 tqi_cw_max; /* Maximum Contention Window */
|
|
+ u32 tqi_cbr_period; /* Constant bit rate period */
|
|
+ u32 tqi_cbr_overflow_limit;
|
|
+ u32 tqi_burst_time;
|
|
+ u32 tqi_ready_time; /* Not used */
|
|
+};
|
|
+
|
|
+/*
|
|
+ * Transmit packet types.
|
|
+ * These are not fully used inside OpenHAL yet
|
|
+ */
|
|
+enum ath5k_pkt_type {
|
|
+ AR5K_PKT_TYPE_NORMAL = 0,
|
|
+ AR5K_PKT_TYPE_ATIM = 1,
|
|
+ AR5K_PKT_TYPE_PSPOLL = 2,
|
|
+ AR5K_PKT_TYPE_BEACON = 3,
|
|
+ AR5K_PKT_TYPE_PROBE_RESP = 4,
|
|
+ AR5K_PKT_TYPE_PIFS = 5,
|
|
+};
|
|
+
|
|
+/*
|
|
+ * TX power and TPC settings
|
|
+ */
|
|
+#define AR5K_TXPOWER_OFDM(_r, _v) ( \
|
|
+ ((0 & 1) << ((_v) + 6)) | \
|
|
+ (((ah->ah_txpower.txp_rates[(_r)]) & 0x3f) << (_v)) \
|
|
+)
|
|
+
|
|
+#define AR5K_TXPOWER_CCK(_r, _v) ( \
|
|
+ (ah->ah_txpower.txp_rates[(_r)] & 0x3f) << (_v) \
|
|
+)
|
|
+
|
|
+/*
|
|
+ * DMA size definitions (2^n+2)
|
|
+ */
|
|
+enum ath5k_dmasize {
|
|
+ AR5K_DMASIZE_4B = 0,
|
|
+ AR5K_DMASIZE_8B,
|
|
+ AR5K_DMASIZE_16B,
|
|
+ AR5K_DMASIZE_32B,
|
|
+ AR5K_DMASIZE_64B,
|
|
+ AR5K_DMASIZE_128B,
|
|
+ AR5K_DMASIZE_256B,
|
|
+ AR5K_DMASIZE_512B
|
|
+};
|
|
+
|
|
+
|
|
+/****************\
|
|
+ RX DEFINITIONS
|
|
+\****************/
|
|
+
|
|
+/*
|
|
+ * Rx Descriptor
|
|
+ */
|
|
+struct ath5k_rx_status {
|
|
+ u16 rs_datalen;
|
|
+ u16 rs_tstamp;
|
|
+ u8 rs_status;
|
|
+ u8 rs_phyerr;
|
|
+ s8 rs_rssi;
|
|
+ u8 rs_keyix;
|
|
+ u8 rs_rate;
|
|
+ u8 rs_antenna;
|
|
+ u8 rs_more;
|
|
+};
|
|
+
|
|
+#define AR5K_RXERR_CRC 0x01
|
|
+#define AR5K_RXERR_PHY 0x02
|
|
+#define AR5K_RXERR_FIFO 0x04
|
|
+#define AR5K_RXERR_DECRYPT 0x08
|
|
+#define AR5K_RXERR_MIC 0x10
|
|
+#define AR5K_RXKEYIX_INVALID ((u8) - 1)
|
|
+#define AR5K_TXKEYIX_INVALID ((u32) - 1)
|
|
+
|
|
+struct ath5k_mib_stats {
|
|
+ u32 ackrcv_bad;
|
|
+ u32 rts_bad;
|
|
+ u32 rts_good;
|
|
+ u32 fcs_bad;
|
|
+ u32 beacons;
|
|
+};
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+/**************************\
|
|
+ BEACON TIMERS DEFINITIONS
|
|
+\**************************/
|
|
+
|
|
+#define AR5K_BEACON_PERIOD 0x0000ffff
|
|
+#define AR5K_BEACON_ENA 0x00800000 /*enable beacon xmit*/
|
|
+#define AR5K_BEACON_RESET_TSF 0x01000000 /*force a TSF reset*/
|
|
+
|
|
+/*
|
|
+ * Per-station beacon timer state.
|
|
+ */
|
|
+struct ath5k_beacon_state {
|
|
+ u32 bs_next_beacon;
|
|
+ u32 bs_next_dtim;
|
|
+ u32 bs_interval; /*in TU's -see net80211/ieee80211_var.h-
|
|
+ can also include the above flags*/
|
|
+ u8 bs_dtim_period;
|
|
+ u8 bs_cfp_period;
|
|
+ u16 bs_cfp_max_duration; /*if non-zero hw is setup to coexist with
|
|
+ a Point Coordination Function capable AP*/
|
|
+ u16 bs_cfp_du_remain;
|
|
+ u16 bs_tim_offset;
|
|
+ u16 bs_sleep_duration;
|
|
+ u16 bs_bmiss_threshold;
|
|
+ u32 bs_cfp_next;
|
|
+};
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+/********************\
|
|
+ COMMON DEFINITIONS
|
|
+\********************/
|
|
+
|
|
+/*
|
|
+ * Atheros descriptor
|
|
+ */
|
|
+struct ath5k_desc {
|
|
+ u32 ds_link;
|
|
+ u32 ds_data;
|
|
+ u32 ds_ctl0;
|
|
+ u32 ds_ctl1;
|
|
+ u32 ds_hw[4];
|
|
+
|
|
+ union {
|
|
+ struct ath5k_rx_status rx;
|
|
+ struct ath5k_tx_status tx;
|
|
+ } ds_us;
|
|
+
|
|
+#define ds_rxstat ds_us.rx
|
|
+#define ds_txstat ds_us.tx
|
|
+
|
|
+} __packed;
|
|
+
|
|
+#define AR5K_RXDESC_INTREQ 0x0020
|
|
+
|
|
+#define AR5K_TXDESC_CLRDMASK 0x0001
|
|
+#define AR5K_TXDESC_NOACK 0x0002 /*[5211+]*/
|
|
+#define AR5K_TXDESC_RTSENA 0x0004
|
|
+#define AR5K_TXDESC_CTSENA 0x0008
|
|
+#define AR5K_TXDESC_INTREQ 0x0010
|
|
+#define AR5K_TXDESC_VEOL 0x0020 /*[5211+]*/
|
|
+
|
|
+#define AR5K_SLOT_TIME_9 396
|
|
+#define AR5K_SLOT_TIME_20 880
|
|
+#define AR5K_SLOT_TIME_MAX 0xffff
|
|
+
|
|
+/* channel_flags */
|
|
+#define CHANNEL_CW_INT 0x0008 /* Contention Window interference detected */
|
|
+#define CHANNEL_TURBO 0x0010 /* Turbo Channel */
|
|
+#define CHANNEL_CCK 0x0020 /* CCK channel */
|
|
+#define CHANNEL_OFDM 0x0040 /* OFDM channel */
|
|
+#define CHANNEL_2GHZ 0x0080 /* 2GHz channel. */
|
|
+#define CHANNEL_5GHZ 0x0100 /* 5GHz channel */
|
|
+#define CHANNEL_PASSIVE 0x0200 /* Only passive scan allowed */
|
|
+#define CHANNEL_DYN 0x0400 /* Dynamic CCK-OFDM channel (for g operation) */
|
|
+#define CHANNEL_XR 0x0800 /* XR channel */
|
|
+
|
|
+#define CHANNEL_A (CHANNEL_5GHZ|CHANNEL_OFDM)
|
|
+#define CHANNEL_B (CHANNEL_2GHZ|CHANNEL_CCK)
|
|
+#define CHANNEL_G (CHANNEL_2GHZ|CHANNEL_OFDM)
|
|
+#define CHANNEL_T (CHANNEL_5GHZ|CHANNEL_OFDM|CHANNEL_TURBO)
|
|
+#define CHANNEL_TG (CHANNEL_2GHZ|CHANNEL_OFDM|CHANNEL_TURBO)
|
|
+#define CHANNEL_108A CHANNEL_T
|
|
+#define CHANNEL_108G CHANNEL_TG
|
|
+#define CHANNEL_X (CHANNEL_5GHZ|CHANNEL_OFDM|CHANNEL_XR)
|
|
+
|
|
+#define CHANNEL_ALL (CHANNEL_OFDM|CHANNEL_CCK|CHANNEL_2GHZ|CHANNEL_5GHZ| \
|
|
+ CHANNEL_TURBO)
|
|
+
|
|
+#define CHANNEL_ALL_NOTURBO (CHANNEL_ALL & ~CHANNEL_TURBO)
|
|
+#define CHANNEL_MODES CHANNEL_ALL
|
|
+
|
|
+/*
|
|
+ * Used internaly in OpenHAL (ar5211.c/ar5212.c
|
|
+ * for reset_tx_queue). Also see struct struct ieee80211_channel.
|
|
+ */
|
|
+#define IS_CHAN_XR(_c) ((_c.val & CHANNEL_XR) != 0)
|
|
+#define IS_CHAN_B(_c) ((_c.val & CHANNEL_B) != 0)
|
|
+
|
|
+/*
|
|
+ * The following structure will be used to map 2GHz channels to
|
|
+ * 5GHz Atheros channels.
|
|
+ */
|
|
+struct ath5k_athchan_2ghz {
|
|
+ u32 a2_flags;
|
|
+ u16 a2_athchan;
|
|
+};
|
|
+
|
|
+/*
|
|
+ * Rate definitions
|
|
+ * TODO: Clean them up or move them on mac80211 -most of these infos are
|
|
+ * used by the rate control algorytm on MadWiFi.
|
|
+ */
|
|
+
|
|
+/* Max number of rates on the rate table and what it seems
|
|
+ * Atheros hardware supports */
|
|
+#define AR5K_MAX_RATES 32
|
|
+
|
|
+/**
|
|
+ * struct ath5k_rate - rate structure
|
|
+ * @valid: is this a valid rate for the current mode
|
|
+ * @modulation: respective mac80211 modulation
|
|
+ * @rate_kbps: rate in kbit/s
|
|
+ * @rate_code: hardware rate value, used in &struct ath5k_desc, on RX on
|
|
+ * &struct ath5k_rx_status.rs_rate and on TX on
|
|
+ * &struct ath5k_tx_status.ts_rate. Seems the ar5xxx harware supports
|
|
+ * up to 32 rates, indexed by 1-32. This means we really only need
|
|
+ * 6 bits for the rate_code.
|
|
+ * @dot11_rate: respective IEEE-802.11 rate value
|
|
+ * @control_rate: index of rate assumed to be used to send control frames.
|
|
+ * This can be used to set override the value on the rate duration
|
|
+ * registers. This is only useful if we can override in the harware at
|
|
+ * what rate we want to send control frames at. Note that IEEE-802.11
|
|
+ * Ch. 9.6 (after IEEE 802.11g changes) defines the rate at which we
|
|
+ * should send ACK/CTS, if we change this value we can be breaking
|
|
+ * the spec.
|
|
+ *
|
|
+ * This structure is used to get the RX rate or set the TX rate on the
|
|
+ * hardware descriptors. It is also used for internal modulation control
|
|
+ * and settings.
|
|
+ *
|
|
+ * On RX after the &struct ath5k_desc is parsed by the appropriate
|
|
+ * ah_proc_rx_desc() the respective hardware rate value is set in
|
|
+ * &struct ath5k_rx_status.rs_rate. On TX the desired rate is set in
|
|
+ * &struct ath5k_tx_status.ts_rate which is later used to setup the
|
|
+ * &struct ath5k_desc correctly. This is the hardware rate map we are
|
|
+ * aware of:
|
|
+ *
|
|
+ * rate_code 1 2 3 4 5 6 7 8
|
|
+ * rate_kbps 3000 1000 ? ? ? 2000 500 48000
|
|
+ *
|
|
+ * rate_code 9 10 11 12 13 14 15 16
|
|
+ * rate_kbps 24000 12000 6000 54000 36000 18000 9000 ?
|
|
+ *
|
|
+ * rate_code 17 18 19 20 21 22 23 24
|
|
+ * rate_kbps ? ? ? ? ? ? ? 11000
|
|
+ *
|
|
+ * rate_code 25 26 27 28 29 30 31 32
|
|
+ * rate_kbps 5500 2000 1000 ? ? ? ? ?
|
|
+ *
|
|
+ */
|
|
+struct ath5k_rate {
|
|
+ u8 valid;
|
|
+ u32 modulation;
|
|
+ u16 rate_kbps;
|
|
+ u8 rate_code;
|
|
+ u8 dot11_rate;
|
|
+ u8 control_rate;
|
|
+};
|
|
+
|
|
+/* XXX: GRR all this stuff to get leds blinking ??? (check out setcurmode) */
|
|
+struct ath5k_rate_table {
|
|
+ u16 rate_count;
|
|
+ u8 rate_code_to_index[AR5K_MAX_RATES]; /* Back-mapping */
|
|
+ struct ath5k_rate rates[AR5K_MAX_RATES];
|
|
+};
|
|
+
|
|
+/*
|
|
+ * Rate tables...
|
|
+ */
|
|
+#define AR5K_RATES_11A { 8, { \
|
|
+ 255, 255, 255, 255, 255, 255, 255, 255, 6, 4, 2, 0, \
|
|
+ 7, 5, 3, 1, 255, 255, 255, 255, 255, 255, 255, 255, \
|
|
+ 255, 255, 255, 255, 255, 255, 255, 255 }, { \
|
|
+ { 1, IEEE80211_RATE_OFDM, 6000, 11, 140, 0 }, \
|
|
+ { 1, IEEE80211_RATE_OFDM, 9000, 15, 18, 0 }, \
|
|
+ { 1, IEEE80211_RATE_OFDM, 12000, 10, 152, 2 }, \
|
|
+ { 1, IEEE80211_RATE_OFDM, 18000, 14, 36, 2 }, \
|
|
+ { 1, IEEE80211_RATE_OFDM, 24000, 9, 176, 4 }, \
|
|
+ { 1, IEEE80211_RATE_OFDM, 36000, 13, 72, 4 }, \
|
|
+ { 1, IEEE80211_RATE_OFDM, 48000, 8, 96, 4 }, \
|
|
+ { 1, IEEE80211_RATE_OFDM, 54000, 12, 108, 4 } } \
|
|
+}
|
|
+
|
|
+#define AR5K_RATES_11B { 4, { \
|
|
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, \
|
|
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, \
|
|
+ 3, 2, 1, 0, 255, 255, 255, 255 }, { \
|
|
+ { 1, IEEE80211_RATE_CCK, 1000, 27, 130, 0 }, \
|
|
+ { 1, IEEE80211_RATE_CCK_2, 2000, 26, 132, 1 }, \
|
|
+ { 1, IEEE80211_RATE_CCK_2, 5500, 25, 139, 1 }, \
|
|
+ { 1, IEEE80211_RATE_CCK_2, 11000, 24, 150, 1 } } \
|
|
+}
|
|
+
|
|
+#define AR5K_RATES_11G { 12, { \
|
|
+ 255, 255, 255, 255, 255, 255, 255, 255, 10, 8, 6, 4, \
|
|
+ 11, 9, 7, 5, 255, 255, 255, 255, 255, 255, 255, 255, \
|
|
+ 3, 2, 1, 0, 255, 255, 255, 255 }, { \
|
|
+ { 1, IEEE80211_RATE_CCK, 1000, 27, 2, 0 }, \
|
|
+ { 1, IEEE80211_RATE_CCK_2, 2000, 26, 4, 1 }, \
|
|
+ { 1, IEEE80211_RATE_CCK_2, 5500, 25, 11, 1 }, \
|
|
+ { 1, IEEE80211_RATE_CCK_2, 11000, 24, 22, 1 }, \
|
|
+ { 0, IEEE80211_RATE_OFDM, 6000, 11, 12, 4 }, \
|
|
+ { 0, IEEE80211_RATE_OFDM, 9000, 15, 18, 4 }, \
|
|
+ { 1, IEEE80211_RATE_OFDM, 12000, 10, 24, 6 }, \
|
|
+ { 1, IEEE80211_RATE_OFDM, 18000, 14, 36, 6 }, \
|
|
+ { 1, IEEE80211_RATE_OFDM, 24000, 9, 48, 8 }, \
|
|
+ { 1, IEEE80211_RATE_OFDM, 36000, 13, 72, 8 }, \
|
|
+ { 1, IEEE80211_RATE_OFDM, 48000, 8, 96, 8 }, \
|
|
+ { 1, IEEE80211_RATE_OFDM, 54000, 12, 108, 8 } } \
|
|
+}
|
|
+
|
|
+#define AR5K_RATES_TURBO { 8, { \
|
|
+ 255, 255, 255, 255, 255, 255, 255, 255, 6, 4, 2, 0, \
|
|
+ 7, 5, 3, 1, 255, 255, 255, 255, 255, 255, 255, 255, \
|
|
+ 255, 255, 255, 255, 255, 255, 255, 255 }, { \
|
|
+ { 1, MODULATION_TURBO, 6000, 11, 140, 0 }, \
|
|
+ { 1, MODULATION_TURBO, 9000, 15, 18, 0 }, \
|
|
+ { 1, MODULATION_TURBO, 12000, 10, 152, 2 }, \
|
|
+ { 1, MODULATION_TURBO, 18000, 14, 36, 2 }, \
|
|
+ { 1, MODULATION_TURBO, 24000, 9, 176, 4 }, \
|
|
+ { 1, MODULATION_TURBO, 36000, 13, 72, 4 }, \
|
|
+ { 1, MODULATION_TURBO, 48000, 8, 96, 4 }, \
|
|
+ { 1, MODULATION_TURBO, 54000, 12, 108, 4 } } \
|
|
+}
|
|
+
|
|
+#define AR5K_RATES_XR { 12, { \
|
|
+ 255, 3, 1, 255, 255, 255, 2, 0, 10, 8, 6, 4, \
|
|
+ 11, 9, 7, 5, 255, 255, 255, 255, 255, 255, 255, 255, \
|
|
+ 255, 255, 255, 255, 255, 255, 255, 255 }, { \
|
|
+ { 1, MODULATION_XR, 500, 7, 129, 0 }, \
|
|
+ { 1, MODULATION_XR, 1000, 2, 139, 1 }, \
|
|
+ { 1, MODULATION_XR, 2000, 6, 150, 2 }, \
|
|
+ { 1, MODULATION_XR, 3000, 1, 150, 3 }, \
|
|
+ { 1, IEEE80211_RATE_OFDM, 6000, 11, 140, 4 }, \
|
|
+ { 1, IEEE80211_RATE_OFDM, 9000, 15, 18, 4 }, \
|
|
+ { 1, IEEE80211_RATE_OFDM, 12000, 10, 152, 6 }, \
|
|
+ { 1, IEEE80211_RATE_OFDM, 18000, 14, 36, 6 }, \
|
|
+ { 1, IEEE80211_RATE_OFDM, 24000, 9, 176, 8 }, \
|
|
+ { 1, IEEE80211_RATE_OFDM, 36000, 13, 72, 8 }, \
|
|
+ { 1, IEEE80211_RATE_OFDM, 48000, 8, 96, 8 }, \
|
|
+ { 1, IEEE80211_RATE_OFDM, 54000, 12, 108, 8 } } \
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Crypto definitions
|
|
+ */
|
|
+
|
|
+#define AR5K_KEYCACHE_SIZE 8
|
|
+
|
|
+/***********************\
|
|
+ HW RELATED DEFINITIONS
|
|
+\***********************/
|
|
+
|
|
+/*
|
|
+ * Misc definitions
|
|
+ */
|
|
+#define AR5K_RSSI_EP_MULTIPLIER (1<<7)
|
|
+
|
|
+#define AR5K_ASSERT_ENTRY(_e, _s) do { \
|
|
+ if (_e >= _s) \
|
|
+ return (false); \
|
|
+} while (0)
|
|
+
|
|
+
|
|
+enum ath5k_ant_setting {
|
|
+ AR5K_ANT_VARIABLE = 0, /* variable by programming */
|
|
+ AR5K_ANT_FIXED_A = 1, /* fixed to 11a frequencies */
|
|
+ AR5K_ANT_FIXED_B = 2, /* fixed to 11b frequencies */
|
|
+ AR5K_ANT_MAX = 3,
|
|
+};
|
|
+
|
|
+/*
|
|
+ * Hardware interrupt abstraction
|
|
+ */
|
|
+
|
|
+/**
|
|
+ * enum ath5k_int - Hardware interrupt masks helpers
|
|
+ *
|
|
+ * @AR5K_INT_RX: mask to identify received frame interrupts, of type
|
|
+ * AR5K_ISR_RXOK or AR5K_ISR_RXERR
|
|
+ * @AR5K_INT_RXDESC: Request RX descriptor/Read RX descriptor (?)
|
|
+ * @AR5K_INT_RXNOFRM: No frame received (?)
|
|
+ * @AR5K_INT_RXEOL: received End Of List for VEOL (Virtual End Of List). The
|
|
+ * Queue Control Unit (QCU) signals an EOL interrupt only if a descriptor's
|
|
+ * LinkPtr is NULL. For more details, refer to:
|
|
+ * http://www.freepatentsonline.com/20030225739.html
|
|
+ * @AR5K_INT_RXORN: Indicates we got RX overrun (eg. no more descriptors).
|
|
+ * Note that Rx overrun is not always fatal, on some chips we can continue
|
|
+ * operation without reseting the card, that's why int_fatal is not
|
|
+ * common for all chips.
|
|
+ * @AR5K_INT_TX: mask to identify received frame interrupts, of type
|
|
+ * AR5K_ISR_TXOK or AR5K_ISR_TXERR
|
|
+ * @AR5K_INT_TXDESC: Request TX descriptor/Read TX status descriptor (?)
|
|
+ * @AR5K_INT_TXURN: received when we should increase the TX trigger threshold
|
|
+ * We currently do increments on interrupt by
|
|
+ * (AR5K_TUNE_MAX_TX_FIFO_THRES - current_trigger_level) / 2
|
|
+ * @AR5K_INT_MIB: Indicates the Management Information Base counters should be
|
|
+ * checked. We should do this with ath5k_hw_update_mib_counters() but
|
|
+ * it seems we should also then do some noise immunity work.
|
|
+ * @AR5K_INT_RXPHY: RX PHY Error
|
|
+ * @AR5K_INT_RXKCM: ??
|
|
+ * @AR5K_INT_SWBA: SoftWare Beacon Alert - indicates its time to send a
|
|
+ * beacon that must be handled in software. The alternative is if you
|
|
+ * have VEOL support, in that case you let the hardware deal with things.
|
|
+ * @AR5K_INT_BMISS: If in STA mode this indicates we have stopped seeing
|
|
+ * beacons from the AP have associated with, we should probably try to
|
|
+ * reassociate. When in IBSS mode this might mean we have not received
|
|
+ * any beacons from any local stations. Note that every station in an
|
|
+ * IBSS schedules to send beacons at the Target Beacon Transmission Time
|
|
+ * (TBTT) with a random backoff.
|
|
+ * @AR5K_INT_BNR: Beacon Not Ready interrupt - ??
|
|
+ * @AR5K_INT_GPIO: GPIO interrupt is used for RF Kill, disabled for now
|
|
+ * until properly handled
|
|
+ * @AR5K_INT_FATAL: Fatal errors were encountered, typically caused by DMA
|
|
+ * errors. These types of errors we can enable seem to be of type
|
|
+ * AR5K_SIMR2_MCABT, AR5K_SIMR2_SSERR and AR5K_SIMR2_DPERR.
|
|
+ * @AR5K_INT_GLOBAL: Seems to be used to clear and set the IER
|
|
+ * @AR5K_INT_NOCARD: signals the card has been removed
|
|
+ * @AR5K_INT_COMMON: common interrupts shared amogst MACs with the same
|
|
+ * bit value
|
|
+ *
|
|
+ * These are mapped to take advantage of some common bits
|
|
+ * between the MACs, to be able to set intr properties
|
|
+ * easier. Some of them are not used yet inside hw.c. Most map
|
|
+ * to the respective hw interrupt value as they are common amogst different
|
|
+ * MACs.
|
|
+ */
|
|
+enum ath5k_int {
|
|
+ AR5K_INT_RX = 0x00000001, /* Not common */
|
|
+ AR5K_INT_RXDESC = 0x00000002,
|
|
+ AR5K_INT_RXNOFRM = 0x00000008,
|
|
+ AR5K_INT_RXEOL = 0x00000010,
|
|
+ AR5K_INT_RXORN = 0x00000020,
|
|
+ AR5K_INT_TX = 0x00000040, /* Not common */
|
|
+ AR5K_INT_TXDESC = 0x00000080,
|
|
+ AR5K_INT_TXURN = 0x00000800,
|
|
+ AR5K_INT_MIB = 0x00001000,
|
|
+ AR5K_INT_RXPHY = 0x00004000,
|
|
+ AR5K_INT_RXKCM = 0x00008000,
|
|
+ AR5K_INT_SWBA = 0x00010000,
|
|
+ AR5K_INT_BMISS = 0x00040000,
|
|
+ AR5K_INT_BNR = 0x00100000, /* Not common */
|
|
+ AR5K_INT_GPIO = 0x01000000,
|
|
+ AR5K_INT_FATAL = 0x40000000, /* Not common */
|
|
+ AR5K_INT_GLOBAL = 0x80000000,
|
|
+
|
|
+ AR5K_INT_COMMON = AR5K_INT_RXNOFRM
|
|
+ | AR5K_INT_RXDESC
|
|
+ | AR5K_INT_RXEOL
|
|
+ | AR5K_INT_RXORN
|
|
+ | AR5K_INT_TXURN
|
|
+ | AR5K_INT_TXDESC
|
|
+ | AR5K_INT_MIB
|
|
+ | AR5K_INT_RXPHY
|
|
+ | AR5K_INT_RXKCM
|
|
+ | AR5K_INT_SWBA
|
|
+ | AR5K_INT_BMISS
|
|
+ | AR5K_INT_GPIO,
|
|
+ AR5K_INT_NOCARD = 0xffffffff
|
|
+};
|
|
+
|
|
+/*
|
|
+ * Power management
|
|
+ */
|
|
+enum ath5k_power_mode {
|
|
+ AR5K_PM_UNDEFINED = 0,
|
|
+ AR5K_PM_AUTO,
|
|
+ AR5K_PM_AWAKE,
|
|
+ AR5K_PM_FULL_SLEEP,
|
|
+ AR5K_PM_NETWORK_SLEEP,
|
|
+};
|
|
+
|
|
+/*
|
|
+ * These match net80211 definitions (not used in
|
|
+ * d80211).
|
|
+ */
|
|
+#define AR5K_LED_INIT 0 /*IEEE80211_S_INIT*/
|
|
+#define AR5K_LED_SCAN 1 /*IEEE80211_S_SCAN*/
|
|
+#define AR5K_LED_AUTH 2 /*IEEE80211_S_AUTH*/
|
|
+#define AR5K_LED_ASSOC 3 /*IEEE80211_S_ASSOC*/
|
|
+#define AR5K_LED_RUN 4 /*IEEE80211_S_RUN*/
|
|
+
|
|
+/* GPIO-controlled software LED */
|
|
+#define AR5K_SOFTLED_PIN 0
|
|
+#define AR5K_SOFTLED_ON 0
|
|
+#define AR5K_SOFTLED_OFF 1
|
|
+
|
|
+/*
|
|
+ * Chipset capabilities -see ath5k_hw_get_capability-
|
|
+ * get_capability function is not yet fully implemented
|
|
+ * in OpenHAL so most of these don't work yet...
|
|
+ */
|
|
+enum ath5k_capability_type {
|
|
+ AR5K_CAP_REG_DMN = 0, /* Used to get current reg. domain id */
|
|
+ AR5K_CAP_TKIP_MIC = 2, /* Can handle TKIP MIC in hardware */
|
|
+ AR5K_CAP_TKIP_SPLIT = 3, /* TKIP uses split keys */
|
|
+ AR5K_CAP_PHYCOUNTERS = 4, /* PHY error counters */
|
|
+ AR5K_CAP_DIVERSITY = 5, /* Supports fast diversity */
|
|
+ AR5K_CAP_NUM_TXQUEUES = 6, /* Used to get max number of hw txqueues */
|
|
+ AR5K_CAP_VEOL = 7, /* Supports virtual EOL */
|
|
+ AR5K_CAP_COMPRESSION = 8, /* Supports compression */
|
|
+ AR5K_CAP_BURST = 9, /* Supports packet bursting */
|
|
+ AR5K_CAP_FASTFRAME = 10, /* Supports fast frames */
|
|
+ AR5K_CAP_TXPOW = 11, /* Used to get global tx power limit */
|
|
+ AR5K_CAP_TPC = 12, /* Can do per-packet tx power control (needed for 802.11a) */
|
|
+ AR5K_CAP_BSSIDMASK = 13, /* Supports bssid mask */
|
|
+ AR5K_CAP_MCAST_KEYSRCH = 14, /* Supports multicast key search */
|
|
+ AR5K_CAP_TSF_ADJUST = 15, /* Supports beacon tsf adjust */
|
|
+ AR5K_CAP_XR = 16, /* Supports XR mode */
|
|
+ AR5K_CAP_WME_TKIPMIC = 17, /* Supports TKIP MIC when using WMM */
|
|
+ AR5K_CAP_CHAN_HALFRATE = 18, /* Supports half rate channels */
|
|
+ AR5K_CAP_CHAN_QUARTERRATE = 19, /* Supports quarter rate channels */
|
|
+ AR5K_CAP_RFSILENT = 20, /* Supports RFsilent */
|
|
+};
|
|
+
|
|
+struct ath5k_capabilities {
|
|
+ /*
|
|
+ * Supported PHY modes
|
|
+ * (ie. CHANNEL_A, CHANNEL_B, ...)
|
|
+ */
|
|
+ DECLARE_BITMAP(cap_mode, NUM_DRIVER_MODES);
|
|
+
|
|
+ /*
|
|
+ * Frequency range (without regulation restrictions)
|
|
+ */
|
|
+ struct {
|
|
+ u16 range_2ghz_min;
|
|
+ u16 range_2ghz_max;
|
|
+ u16 range_5ghz_min;
|
|
+ u16 range_5ghz_max;
|
|
+ } cap_range;
|
|
+
|
|
+ /*
|
|
+ * Active regulation domain settings
|
|
+ */
|
|
+ struct {
|
|
+ enum ath5k_regdom reg_current;
|
|
+ enum ath5k_regdom reg_hw;
|
|
+ } cap_regdomain;
|
|
+
|
|
+ /*
|
|
+ * Values stored in the EEPROM (some of them...)
|
|
+ */
|
|
+ struct ath5k_eeprom_info cap_eeprom;
|
|
+
|
|
+ /*
|
|
+ * Queue information
|
|
+ */
|
|
+ struct {
|
|
+ u8 q_tx_num;
|
|
+ } cap_queues;
|
|
+};
|
|
+
|
|
+
|
|
+/***************************************\
|
|
+ HARDWARE ABSTRACTION LAYER STRUCTURE
|
|
+\***************************************/
|
|
+
|
|
+/*
|
|
+ * Misc defines
|
|
+ */
|
|
+
|
|
+#define AR5K_MAX_GPIO 10
|
|
+#define AR5K_MAX_RF_BANKS 8
|
|
+
|
|
+struct ath5k_hw {
|
|
+ u32 ah_magic;
|
|
+
|
|
+ struct ath5k_softc *ah_sc;
|
|
+ void __iomem *ah_iobase;
|
|
+
|
|
+ enum ath5k_int ah_imr;
|
|
+
|
|
+ enum ieee80211_if_types ah_op_mode;
|
|
+ enum ath5k_power_mode ah_power_mode;
|
|
+ struct ieee80211_channel ah_current_channel;
|
|
+ /* Current BSSID we are trying to assoc to / creating, this
|
|
+ * comes from ieee80211_if_conf. This is passed by mac80211 on
|
|
+ * config_interface() */
|
|
+ u8 bssid[ETH_ALEN];
|
|
+ bool ah_turbo;
|
|
+ bool ah_calibration;
|
|
+ bool ah_running;
|
|
+ bool ah_single_chip;
|
|
+ enum ath5k_rfgain ah_rf_gain;
|
|
+
|
|
+ u32 ah_mac_srev;
|
|
+ u16 ah_mac_version;
|
|
+ u16 ah_mac_revision;
|
|
+ u16 ah_phy_revision;
|
|
+ u16 ah_radio_5ghz_revision;
|
|
+ u16 ah_radio_2ghz_revision;
|
|
+
|
|
+ enum ath5k_version ah_version;
|
|
+ enum ath5k_radio ah_radio;
|
|
+ u32 ah_phy;
|
|
+
|
|
+ bool ah_5ghz;
|
|
+ bool ah_2ghz;
|
|
+
|
|
+#define ah_regdomain ah_capabilities.cap_regdomain.reg_current
|
|
+#define ah_regdomain_hw ah_capabilities.cap_regdomain.reg_hw
|
|
+#define ah_modes ah_capabilities.cap_mode
|
|
+#define ah_ee_version ah_capabilities.cap_eeprom.ee_version
|
|
+
|
|
+ u32 ah_atim_window;
|
|
+ u32 ah_aifs;
|
|
+ u32 ah_cw_min;
|
|
+ u32 ah_cw_max;
|
|
+ bool ah_software_retry;
|
|
+ u32 ah_limit_tx_retries;
|
|
+
|
|
+ u32 ah_antenna[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX];
|
|
+ bool ah_ant_diversity;
|
|
+
|
|
+ u8 ah_sta_id[ETH_ALEN];
|
|
+ u8 ah_bssid[ETH_ALEN];
|
|
+
|
|
+ u32 ah_gpio[AR5K_MAX_GPIO];
|
|
+ int ah_gpio_npins;
|
|
+
|
|
+ struct ath5k_capabilities ah_capabilities;
|
|
+
|
|
+ struct ath5k_txq_info ah_txq[AR5K_NUM_TX_QUEUES];
|
|
+ u32 ah_txq_status;
|
|
+ u32 ah_txq_imr_txok;
|
|
+ u32 ah_txq_imr_txerr;
|
|
+ u32 ah_txq_imr_txurn;
|
|
+ u32 ah_txq_imr_txdesc;
|
|
+ u32 ah_txq_imr_txeol;
|
|
+ u32 *ah_rf_banks;
|
|
+ size_t ah_rf_banks_size;
|
|
+ struct ath5k_gain ah_gain;
|
|
+ u32 ah_offset[AR5K_MAX_RF_BANKS];
|
|
+
|
|
+ struct {
|
|
+ u16 txp_pcdac[AR5K_EEPROM_POWER_TABLE_SIZE];
|
|
+ u16 txp_rates[AR5K_MAX_RATES];
|
|
+ s16 txp_min;
|
|
+ s16 txp_max;
|
|
+ bool txp_tpc;
|
|
+ s16 txp_ofdm;
|
|
+ } ah_txpower;
|
|
+
|
|
+ struct {
|
|
+ bool r_enabled;
|
|
+ int r_last_alert;
|
|
+ struct ieee80211_channel r_last_channel;
|
|
+ } ah_radar;
|
|
+
|
|
+ /* noise floor from last periodic calibration */
|
|
+ s32 ah_noise_floor;
|
|
+
|
|
+ /*
|
|
+ * Function pointers
|
|
+ */
|
|
+ int (*ah_setup_tx_desc)(struct ath5k_hw *, struct ath5k_desc *,
|
|
+ unsigned int, unsigned int, enum ath5k_pkt_type, unsigned int,
|
|
+ unsigned int, unsigned int, unsigned int, unsigned int,
|
|
+ unsigned int, unsigned int, unsigned int);
|
|
+ bool (*ah_setup_xtx_desc)(struct ath5k_hw *, struct ath5k_desc *,
|
|
+ unsigned int, unsigned int, unsigned int, unsigned int,
|
|
+ unsigned int, unsigned int);
|
|
+ int (*ah_proc_tx_desc)(struct ath5k_hw *, struct ath5k_desc *);
|
|
+ int (*ah_proc_rx_desc)(struct ath5k_hw *, struct ath5k_desc *);
|
|
+};
|
|
+
|
|
+/*
|
|
+ * Prototypes
|
|
+ */
|
|
+
|
|
+/* General Functions */
|
|
+extern int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val, bool is_set);
|
|
+/* Attach/Detach Functions */
|
|
+extern struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version);
|
|
+extern const struct ath5k_rate_table *ath5k_hw_get_rate_table(struct ath5k_hw *ah, unsigned int mode);
|
|
+extern void ath5k_hw_detach(struct ath5k_hw *ah);
|
|
+/* Reset Functions */
|
|
+extern int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, struct ieee80211_channel *channel, bool change_channel);
|
|
+/* Power management functions */
|
|
+extern int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, bool set_chip, u16 sleep_duration);
|
|
+/* DMA Related Functions */
|
|
+extern void ath5k_hw_start_rx(struct ath5k_hw *ah);
|
|
+extern int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah);
|
|
+extern u32 ath5k_hw_get_rx_buf(struct ath5k_hw *ah);
|
|
+extern void ath5k_hw_put_rx_buf(struct ath5k_hw *ah, u32 phys_addr);
|
|
+extern int ath5k_hw_tx_start(struct ath5k_hw *ah, unsigned int queue);
|
|
+extern int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue);
|
|
+extern u32 ath5k_hw_get_tx_buf(struct ath5k_hw *ah, unsigned int queue);
|
|
+extern int ath5k_hw_put_tx_buf(struct ath5k_hw *ah, unsigned int queue, u32 phys_addr);
|
|
+extern int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase);
|
|
+/* Interrupt handling */
|
|
+extern bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah);
|
|
+extern int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask);
|
|
+extern enum ath5k_int ath5k_hw_set_intr(struct ath5k_hw *ah, enum ath5k_int new_mask);
|
|
+/* EEPROM access functions */
|
|
+extern int ath5k_hw_set_regdomain(struct ath5k_hw *ah, u16 regdomain);
|
|
+/* Protocol Control Unit Functions */
|
|
+extern int ath5k_hw_set_opmode(struct ath5k_hw *ah);
|
|
+/* BSSID Functions */
|
|
+extern void ath5k_hw_get_lladdr(struct ath5k_hw *ah, u8 *mac);
|
|
+extern int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac);
|
|
+extern void ath5k_hw_set_associd(struct ath5k_hw *ah, const u8 *bssid, u16 assoc_id);
|
|
+extern int ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask);
|
|
+/* Receive start/stop functions */
|
|
+extern void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah);
|
|
+extern void ath5k_hw_stop_pcu_recv(struct ath5k_hw *ah);
|
|
+/* RX Filter functions */
|
|
+extern void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1);
|
|
+extern int ath5k_hw_set_mcast_filterindex(struct ath5k_hw *ah, u32 index);
|
|
+extern int ath5k_hw_clear_mcast_filter_idx(struct ath5k_hw *ah, u32 index);
|
|
+extern u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah);
|
|
+extern void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter);
|
|
+/* Beacon related functions */
|
|
+extern u32 ath5k_hw_get_tsf32(struct ath5k_hw *ah);
|
|
+extern u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah);
|
|
+extern void ath5k_hw_reset_tsf(struct ath5k_hw *ah);
|
|
+extern void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval);
|
|
+extern int ath5k_hw_set_beacon_timers(struct ath5k_hw *ah, const struct ath5k_beacon_state *state);
|
|
+extern void ath5k_hw_reset_beacon(struct ath5k_hw *ah);
|
|
+extern int ath5k_hw_wait_for_beacon(struct ath5k_hw *ah, unsigned long phys_addr);
|
|
+extern void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, struct ath5k_mib_stats *statistics);
|
|
+/* ACK bit rate */
|
|
+void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high);
|
|
+/* ACK/CTS Timeouts */
|
|
+extern int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout);
|
|
+extern unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah);
|
|
+extern int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout);
|
|
+extern unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah);
|
|
+/* Key table (WEP) functions */
|
|
+extern int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry);
|
|
+extern int ath5k_hw_is_key_valid(struct ath5k_hw *ah, u16 entry);
|
|
+extern int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry, const struct ieee80211_key_conf *key, const u8 *mac);
|
|
+extern int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac);
|
|
+/* Queue Control Unit, DFS Control Unit Functions */
|
|
+extern int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type, struct ath5k_txq_info *queue_info);
|
|
+extern int ath5k_hw_setup_tx_queueprops(struct ath5k_hw *ah, int queue, const struct ath5k_txq_info *queue_info);
|
|
+extern int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, struct ath5k_txq_info *queue_info);
|
|
+extern void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue);
|
|
+extern int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue);
|
|
+extern u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue);
|
|
+extern int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time);
|
|
+extern unsigned int ath5k_hw_get_slot_time(struct ath5k_hw *ah);
|
|
+/* Hardware Descriptor Functions */
|
|
+extern int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, u32 size, unsigned int flags);
|
|
+/* GPIO Functions */
|
|
+extern void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state);
|
|
+extern int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio);
|
|
+extern int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio);
|
|
+extern u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio);
|
|
+extern int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val);
|
|
+extern void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio, u32 interrupt_level);
|
|
+/* Regulatory Domain/Channels Setup */
|
|
+extern u16 ath5k_get_regdomain(struct ath5k_hw *ah);
|
|
+/* Misc functions */
|
|
+extern int ath5k_hw_get_capability(struct ath5k_hw *ah, enum ath5k_capability_type cap_type, u32 capability, u32 *result);
|
|
+
|
|
+
|
|
+/* Initial register settings functions */
|
|
+extern int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel);
|
|
+/* Initialize RF */
|
|
+extern int ath5k_hw_rfregs(struct ath5k_hw *ah, struct ieee80211_channel *channel, unsigned int mode);
|
|
+extern int ath5k_hw_rfgain(struct ath5k_hw *ah, unsigned int freq);
|
|
+extern enum ath5k_rfgain ath5k_hw_get_rf_gain(struct ath5k_hw *ah);
|
|
+extern int ath5k_hw_set_rfgain_opt(struct ath5k_hw *ah);
|
|
+
|
|
+
|
|
+/* PHY/RF channel functions */
|
|
+extern bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags);
|
|
+extern int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel);
|
|
+/* PHY calibration */
|
|
+extern int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, struct ieee80211_channel *channel);
|
|
+extern int ath5k_hw_phy_disable(struct ath5k_hw *ah);
|
|
+/* Misc PHY functions */
|
|
+extern u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan);
|
|
+extern void ath5k_hw_set_def_antenna(struct ath5k_hw *ah, unsigned int ant);
|
|
+extern unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah);
|
|
+extern int ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq);
|
|
+/* TX power setup */
|
|
+extern int ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, unsigned int txpower);
|
|
+extern int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, unsigned int power);
|
|
+
|
|
+
|
|
+static inline u32 ath5k_hw_reg_read(struct ath5k_hw *ah, u16 reg)
|
|
+{
|
|
+ return ioread32(ah->ah_iobase + reg);
|
|
+}
|
|
+
|
|
+static inline void ath5k_hw_reg_write(struct ath5k_hw *ah, u32 val, u16 reg)
|
|
+{
|
|
+ iowrite32(val, ah->ah_iobase + reg);
|
|
+}
|
|
+
|
|
+#endif
|
|
diff -up /dev/null linux-2.6.23.noarch/drivers/net/wireless/ath5k/Makefile
|
|
--- /dev/null 2007-12-21 08:33:07.834165456 -0500
|
|
+++ linux-2.6.23.noarch/drivers/net/wireless/ath5k/Makefile 2007-12-21 12:18:50.000000000 -0500
|
|
@@ -0,0 +1,2 @@
|
|
+ath5k-objs = base.o hw.o regdom.o initvals.o phy.o debug.o
|
|
+obj-$(CONFIG_ATH5K) += ath5k.o
|
|
diff -up /dev/null linux-2.6.23.noarch/drivers/net/wireless/ath5k/reg.h
|
|
--- /dev/null 2007-12-21 08:33:07.834165456 -0500
|
|
+++ linux-2.6.23.noarch/drivers/net/wireless/ath5k/reg.h 2007-12-21 12:18:50.000000000 -0500
|
|
@@ -0,0 +1,1987 @@
|
|
+/*
|
|
+ * Copyright (c) 2007 Nick Kossifidis <mickflemm@gmail.com>
|
|
+ * Copyright (c) 2004, 2005, 2006, 2007 Reyk Floeter <reyk@openbsd.org>
|
|
+ * Copyright (c) 2007 Michael Taylor <mike.taylor@apprion.com>
|
|
+ *
|
|
+ * Permission to use, copy, modify, and distribute this software for any
|
|
+ * purpose with or without fee is hereby granted, provided that the above
|
|
+ * copyright notice and this permission notice appear in all copies.
|
|
+ *
|
|
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
+ *
|
|
+ */
|
|
+
|
|
+/*
|
|
+ * Register values for Atheros 5210/5211/5212 cards from OpenBSD's ar5k
|
|
+ * maintained by Reyk Floeter
|
|
+ *
|
|
+ * I tried to document those registers by looking at ar5k code, some
|
|
+ * 802.11 (802.11e mostly) papers and by reading various public available
|
|
+ * Atheros presentations and papers like these:
|
|
+ *
|
|
+ * 5210 - http://nova.stanford.edu/~bbaas/ps/isscc2002_slides.pdf
|
|
+ * http://www.it.iitb.ac.in/~janak/wifire/01222734.pdf
|
|
+ *
|
|
+ * 5211 - http://www.hotchips.org/archives/hc14/3_Tue/16_mcfarland.pdf
|
|
+ */
|
|
+
|
|
+
|
|
+
|
|
+/*====MAC DMA REGISTERS====*/
|
|
+
|
|
+/*
|
|
+ * AR5210-Specific TXDP registers
|
|
+ * 5210 has only 2 transmit queues so no DCU/QCU, just
|
|
+ * 2 transmit descriptor pointers...
|
|
+ */
|
|
+#define AR5K_NOQCU_TXDP0 0x0000 /* Queue 0 - data */
|
|
+#define AR5K_NOQCU_TXDP1 0x0004 /* Queue 1 - beacons */
|
|
+
|
|
+/*
|
|
+ * Mac Control Register
|
|
+ */
|
|
+#define AR5K_CR 0x0008 /* Register Address */
|
|
+#define AR5K_CR_TXE0 0x00000001 /* TX Enable for queue 0 on 5210 */
|
|
+#define AR5K_CR_TXE1 0x00000002 /* TX Enable for queue 1 on 5210 */
|
|
+#define AR5K_CR_RXE 0x00000004 /* RX Enable */
|
|
+#define AR5K_CR_TXD0 0x00000008 /* TX Disable for queue 0 on 5210 */
|
|
+#define AR5K_CR_TXD1 0x00000010 /* TX Disable for queue 1 on 5210 */
|
|
+#define AR5K_CR_RXD 0x00000020 /* RX Disable */
|
|
+#define AR5K_CR_SWI 0x00000040
|
|
+
|
|
+/*
|
|
+ * RX Descriptor Pointer register
|
|
+ */
|
|
+#define AR5K_RXDP 0x000c
|
|
+
|
|
+/*
|
|
+ * Configuration and status register
|
|
+ */
|
|
+#define AR5K_CFG 0x0014 /* Register Address */
|
|
+#define AR5K_CFG_SWTD 0x00000001 /* Byte-swap TX descriptor (for big endian archs) */
|
|
+#define AR5K_CFG_SWTB 0x00000002 /* Byte-swap TX buffer (?) */
|
|
+#define AR5K_CFG_SWRD 0x00000004 /* Byte-swap RX descriptor */
|
|
+#define AR5K_CFG_SWRB 0x00000008 /* Byte-swap RX buffer (?) */
|
|
+#define AR5K_CFG_SWRG 0x00000010 /* Byte-swap Register values (?) */
|
|
+#define AR5K_CFG_ADHOC 0x00000020 /* [5211+] */
|
|
+#define AR5K_CFG_PHY_OK 0x00000100 /* [5211+] */
|
|
+#define AR5K_CFG_EEBS 0x00000200 /* EEPROM is busy */
|
|
+#define AR5K_CFG_CLKGD 0x00000400 /* Clock gated (?) */
|
|
+#define AR5K_CFG_TXCNT 0x00007800 /* Tx frame count (?) [5210] */
|
|
+#define AR5K_CFG_TXCNT_S 11
|
|
+#define AR5K_CFG_TXFSTAT 0x00008000 /* Tx frame status (?) [5210] */
|
|
+#define AR5K_CFG_TXFSTRT 0x00010000 /* [5210] */
|
|
+#define AR5K_CFG_PCI_THRES 0x00060000 /* [5211+] */
|
|
+#define AR5K_CFG_PCI_THRES_S 17
|
|
+
|
|
+/*
|
|
+ * Interrupt enable register
|
|
+ */
|
|
+#define AR5K_IER 0x0024 /* Register Address */
|
|
+#define AR5K_IER_DISABLE 0x00000000 /* Disable card interrupts */
|
|
+#define AR5K_IER_ENABLE 0x00000001 /* Enable card interrupts */
|
|
+
|
|
+
|
|
+/*
|
|
+ * 0x0028 is Beacon Control Register on 5210
|
|
+ * and first RTS duration register on 5211
|
|
+ */
|
|
+
|
|
+/*
|
|
+ * Beacon control register [5210]
|
|
+ */
|
|
+#define AR5K_BCR 0x0028 /* Register Address */
|
|
+#define AR5K_BCR_AP 0x00000000 /* AP mode */
|
|
+#define AR5K_BCR_ADHOC 0x00000001 /* Ad-Hoc mode */
|
|
+#define AR5K_BCR_BDMAE 0x00000002 /* DMA enable */
|
|
+#define AR5K_BCR_TQ1FV 0x00000004 /* Use Queue1 for CAB traffic */
|
|
+#define AR5K_BCR_TQ1V 0x00000008 /* Use Queue1 for Beacon traffic */
|
|
+#define AR5K_BCR_BCGET 0x00000010
|
|
+
|
|
+/*
|
|
+ * First RTS duration register [5211]
|
|
+ */
|
|
+#define AR5K_RTSD0 0x0028 /* Register Address */
|
|
+#define AR5K_RTSD0_6 0x000000ff /* 6Mb RTS duration mask (?) */
|
|
+#define AR5K_RTSD0_6_S 0 /* 6Mb RTS duration shift (?) */
|
|
+#define AR5K_RTSD0_9 0x0000ff00 /* 9Mb*/
|
|
+#define AR5K_RTSD0_9_S 8
|
|
+#define AR5K_RTSD0_12 0x00ff0000 /* 12Mb*/
|
|
+#define AR5K_RTSD0_12_S 16
|
|
+#define AR5K_RTSD0_18 0xff000000 /* 16Mb*/
|
|
+#define AR5K_RTSD0_18_S 24
|
|
+
|
|
+
|
|
+/*
|
|
+ * 0x002c is Beacon Status Register on 5210
|
|
+ * and second RTS duration register on 5211
|
|
+ */
|
|
+
|
|
+/*
|
|
+ * Beacon status register [5210]
|
|
+ *
|
|
+ * As i can see in ar5k_ar5210_tx_start Reyk uses some of the values of BCR
|
|
+ * for this register, so i guess TQ1V,TQ1FV and BDMAE have the same meaning
|
|
+ * here and SNP/SNAP means "snapshot" (so this register gets synced with BCR).
|
|
+ * So SNAPPEDBCRVALID sould also stand for "snapped BCR -values- valid", so i
|
|
+ * renamed it to SNAPSHOTSVALID to make more sense. I realy have no idea what
|
|
+ * else can it be. I also renamed SNPBCMD to SNPADHOC to match BCR.
|
|
+ */
|
|
+#define AR5K_BSR 0x002c /* Register Address */
|
|
+#define AR5K_BSR_BDLYSW 0x00000001 /* SW Beacon delay (?) */
|
|
+#define AR5K_BSR_BDLYDMA 0x00000002 /* DMA Beacon delay (?) */
|
|
+#define AR5K_BSR_TXQ1F 0x00000004 /* Beacon queue (1) finished */
|
|
+#define AR5K_BSR_ATIMDLY 0x00000008 /* ATIM delay (?) */
|
|
+#define AR5K_BSR_SNPADHOC 0x00000100 /* Ad-hoc mode set (?) */
|
|
+#define AR5K_BSR_SNPBDMAE 0x00000200 /* Beacon DMA enabled (?) */
|
|
+#define AR5K_BSR_SNPTQ1FV 0x00000400 /* Queue1 is used for CAB traffic (?) */
|
|
+#define AR5K_BSR_SNPTQ1V 0x00000800 /* Queue1 is used for Beacon traffic (?) */
|
|
+#define AR5K_BSR_SNAPSHOTSVALID 0x00001000 /* BCR snapshots are valid (?) */
|
|
+#define AR5K_BSR_SWBA_CNT 0x00ff0000
|
|
+
|
|
+/*
|
|
+ * Second RTS duration register [5211]
|
|
+ */
|
|
+#define AR5K_RTSD1 0x002c /* Register Address */
|
|
+#define AR5K_RTSD1_24 0x000000ff /* 24Mb */
|
|
+#define AR5K_RTSD1_24_S 0
|
|
+#define AR5K_RTSD1_36 0x0000ff00 /* 36Mb */
|
|
+#define AR5K_RTSD1_36_S 8
|
|
+#define AR5K_RTSD1_48 0x00ff0000 /* 48Mb */
|
|
+#define AR5K_RTSD1_48_S 16
|
|
+#define AR5K_RTSD1_54 0xff000000 /* 54Mb */
|
|
+#define AR5K_RTSD1_54_S 24
|
|
+
|
|
+
|
|
+/*
|
|
+ * Transmit configuration register
|
|
+ */
|
|
+#define AR5K_TXCFG 0x0030 /* Register Address */
|
|
+#define AR5K_TXCFG_SDMAMR 0x00000007 /* DMA size */
|
|
+#define AR5K_TXCFG_SDMAMR_S 0
|
|
+#define AR5K_TXCFG_B_MODE 0x00000008 /* Set b mode for 5111 (enable 2111) */
|
|
+#define AR5K_TXCFG_TXFSTP 0x00000008 /* TX DMA full Stop [5210] */
|
|
+#define AR5K_TXCFG_TXFULL 0x000003f0 /* TX Triger level mask */
|
|
+#define AR5K_TXCFG_TXFULL_S 4
|
|
+#define AR5K_TXCFG_TXFULL_0B 0x00000000
|
|
+#define AR5K_TXCFG_TXFULL_64B 0x00000010
|
|
+#define AR5K_TXCFG_TXFULL_128B 0x00000020
|
|
+#define AR5K_TXCFG_TXFULL_192B 0x00000030
|
|
+#define AR5K_TXCFG_TXFULL_256B 0x00000040
|
|
+#define AR5K_TXCFG_TXCONT_EN 0x00000080
|
|
+#define AR5K_TXCFG_DMASIZE 0x00000100 /* Flag for passing DMA size [5210] */
|
|
+#define AR5K_TXCFG_JUMBO_TXE 0x00000400 /* Enable jumbo frames transmition (?) [5211+] */
|
|
+#define AR5K_TXCFG_RTSRND 0x00001000 /* [5211+] */
|
|
+#define AR5K_TXCFG_FRMPAD_DIS 0x00002000 /* [5211+] */
|
|
+#define AR5K_TXCFG_RDY_DIS 0x00004000 /* [5211+] */
|
|
+
|
|
+/*
|
|
+ * Receive configuration register
|
|
+ */
|
|
+#define AR5K_RXCFG 0x0034 /* Register Address */
|
|
+#define AR5K_RXCFG_SDMAMW 0x00000007 /* DMA size */
|
|
+#define AR5K_RXCFG_SDMAMW_S 0
|
|
+#define AR5K_RXCFG_DEF_ANTENNA 0x00000008 /* Default antenna */
|
|
+#define AR5K_RXCFG_ZLFDMA 0x00000010 /* Zero-length DMA */
|
|
+#define AR5K_RXCFG_JUMBO_RXE 0x00000020 /* Enable jumbo frames reception (?) [5211+] */
|
|
+#define AR5K_RXCFG_JUMBO_WRAP 0x00000040 /* Wrap jumbo frames (?) [5211+] */
|
|
+
|
|
+/*
|
|
+ * Receive jumbo descriptor last address register
|
|
+ * Only found in 5211 (?)
|
|
+ */
|
|
+#define AR5K_RXJLA 0x0038
|
|
+
|
|
+/*
|
|
+ * MIB control register
|
|
+ */
|
|
+#define AR5K_MIBC 0x0040 /* Register Address */
|
|
+#define AR5K_MIBC_COW 0x00000001
|
|
+#define AR5K_MIBC_FMC 0x00000002 /* Freeze Mib Counters (?) */
|
|
+#define AR5K_MIBC_CMC 0x00000004 /* Clean Mib Counters (?) */
|
|
+#define AR5K_MIBC_MCS 0x00000008
|
|
+
|
|
+/*
|
|
+ * Timeout prescale register
|
|
+ */
|
|
+#define AR5K_TOPS 0x0044
|
|
+#define AR5K_TOPS_M 0x0000ffff /* [5211+] (?) */
|
|
+
|
|
+/*
|
|
+ * Receive timeout register (no frame received)
|
|
+ */
|
|
+#define AR5K_RXNOFRM 0x0048
|
|
+#define AR5K_RXNOFRM_M 0x000003ff /* [5211+] (?) */
|
|
+
|
|
+/*
|
|
+ * Transmit timeout register (no frame sent)
|
|
+ */
|
|
+#define AR5K_TXNOFRM 0x004c
|
|
+#define AR5K_TXNOFRM_M 0x000003ff /* [5211+] (?) */
|
|
+#define AR5K_TXNOFRM_QCU 0x000ffc00 /* [5211+] (?) */
|
|
+
|
|
+/*
|
|
+ * Receive frame gap timeout register
|
|
+ */
|
|
+#define AR5K_RPGTO 0x0050
|
|
+#define AR5K_RPGTO_M 0x000003ff /* [5211+] (?) */
|
|
+
|
|
+/*
|
|
+ * Receive frame count limit register
|
|
+ */
|
|
+#define AR5K_RFCNT 0x0054
|
|
+#define AR5K_RFCNT_M 0x0000001f /* [5211+] (?) */
|
|
+#define AR5K_RFCNT_RFCL 0x0000000f /* [5210] */
|
|
+
|
|
+/*
|
|
+ * Misc settings register
|
|
+ */
|
|
+#define AR5K_MISC 0x0058 /* Register Address */
|
|
+#define AR5K_MISC_DMA_OBS_M 0x000001e0
|
|
+#define AR5K_MISC_DMA_OBS_S 5
|
|
+#define AR5K_MISC_MISC_OBS_M 0x00000e00
|
|
+#define AR5K_MISC_MISC_OBS_S 9
|
|
+#define AR5K_MISC_MAC_OBS_LSB_M 0x00007000
|
|
+#define AR5K_MISC_MAC_OBS_LSB_S 12
|
|
+#define AR5K_MISC_MAC_OBS_MSB_M 0x00038000
|
|
+#define AR5K_MISC_MAC_OBS_MSB_S 15
|
|
+#define AR5K_MISC_LED_DECAY 0x001c0000 /* [5210] */
|
|
+#define AR5K_MISC_LED_BLINK 0x00e00000 /* [5210] */
|
|
+
|
|
+/*
|
|
+ * QCU/DCU clock gating register (5311)
|
|
+ */
|
|
+#define AR5K_QCUDCU_CLKGT 0x005c /* Register Address (?) */
|
|
+#define AR5K_QCUDCU_CLKGT_QCU 0x0000ffff /* Mask for QCU clock */
|
|
+#define AR5K_QCUDCU_CLKGT_DCU 0x07ff0000 /* Mask for DCU clock */
|
|
+
|
|
+/*
|
|
+ * Interrupt Status Registers
|
|
+ *
|
|
+ * For 5210 there is only one status register but for
|
|
+ * 5211/5212 we have one primary and 4 secondary registers.
|
|
+ * So we have AR5K_ISR for 5210 and AR5K_PISR /SISRx for 5211/5212.
|
|
+ * Most of these bits are common for all chipsets.
|
|
+ */
|
|
+#define AR5K_ISR 0x001c /* Register Address [5210] */
|
|
+#define AR5K_PISR 0x0080 /* Register Address [5211+] */
|
|
+#define AR5K_ISR_RXOK 0x00000001 /* Frame successfuly recieved */
|
|
+#define AR5K_ISR_RXDESC 0x00000002 /* RX descriptor request */
|
|
+#define AR5K_ISR_RXERR 0x00000004 /* Receive error */
|
|
+#define AR5K_ISR_RXNOFRM 0x00000008 /* No frame received (receive timeout) */
|
|
+#define AR5K_ISR_RXEOL 0x00000010 /* Empty RX descriptor */
|
|
+#define AR5K_ISR_RXORN 0x00000020 /* Receive FIFO overrun */
|
|
+#define AR5K_ISR_TXOK 0x00000040 /* Frame successfuly transmited */
|
|
+#define AR5K_ISR_TXDESC 0x00000080 /* TX descriptor request */
|
|
+#define AR5K_ISR_TXERR 0x00000100 /* Transmit error */
|
|
+#define AR5K_ISR_TXNOFRM 0x00000200 /* No frame transmited (transmit timeout) */
|
|
+#define AR5K_ISR_TXEOL 0x00000400 /* Empty TX descriptor */
|
|
+#define AR5K_ISR_TXURN 0x00000800 /* Transmit FIFO underrun */
|
|
+#define AR5K_ISR_MIB 0x00001000 /* Update MIB counters */
|
|
+#define AR5K_ISR_SWI 0x00002000 /* Software interrupt (?) */
|
|
+#define AR5K_ISR_RXPHY 0x00004000 /* PHY error */
|
|
+#define AR5K_ISR_RXKCM 0x00008000
|
|
+#define AR5K_ISR_SWBA 0x00010000 /* Software beacon alert */
|
|
+#define AR5K_ISR_BRSSI 0x00020000
|
|
+#define AR5K_ISR_BMISS 0x00040000 /* Beacon missed */
|
|
+#define AR5K_ISR_HIUERR 0x00080000 /* Host Interface Unit error [5211+] */
|
|
+#define AR5K_ISR_BNR 0x00100000 /* Beacon not ready [5211+] */
|
|
+#define AR5K_ISR_MCABT 0x00100000 /* [5210] */
|
|
+#define AR5K_ISR_RXCHIRP 0x00200000 /* [5212+] */
|
|
+#define AR5K_ISR_SSERR 0x00200000 /* [5210] */
|
|
+#define AR5K_ISR_DPERR 0x00400000 /* [5210] */
|
|
+#define AR5K_ISR_TIM 0x00800000 /* [5210] */
|
|
+#define AR5K_ISR_BCNMISC 0x00800000 /* [5212+] */
|
|
+#define AR5K_ISR_GPIO 0x01000000 /* GPIO (rf kill)*/
|
|
+#define AR5K_ISR_QCBRORN 0x02000000 /* CBR overrun (?) [5211+] */
|
|
+#define AR5K_ISR_QCBRURN 0x04000000 /* CBR underrun (?) [5211+] */
|
|
+#define AR5K_ISR_QTRIG 0x08000000 /* [5211+] */
|
|
+
|
|
+/*
|
|
+ * Secondary status registers [5211+] (0 - 4)
|
|
+ *
|
|
+ * I guess from the names that these give the status for each
|
|
+ * queue, that's why only masks are defined here, haven't got
|
|
+ * any info about them (couldn't find them anywhere in ar5k code).
|
|
+ */
|
|
+#define AR5K_SISR0 0x0084 /* Register Address [5211+] */
|
|
+#define AR5K_SISR0_QCU_TXOK 0x000003ff /* Mask for QCU_TXOK */
|
|
+#define AR5K_SISR0_QCU_TXDESC 0x03ff0000 /* Mask for QCU_TXDESC */
|
|
+
|
|
+#define AR5K_SISR1 0x0088 /* Register Address [5211+] */
|
|
+#define AR5K_SISR1_QCU_TXERR 0x000003ff /* Mask for QCU_TXERR */
|
|
+#define AR5K_SISR1_QCU_TXEOL 0x03ff0000 /* Mask for QCU_TXEOL */
|
|
+
|
|
+#define AR5K_SISR2 0x008c /* Register Address [5211+] */
|
|
+#define AR5K_SISR2_QCU_TXURN 0x000003ff /* Mask for QCU_TXURN */
|
|
+#define AR5K_SISR2_MCABT 0x00100000
|
|
+#define AR5K_SISR2_SSERR 0x00200000
|
|
+#define AR5K_SISR2_DPERR 0x00400000
|
|
+#define AR5K_SISR2_TIM 0x01000000 /* [5212+] */
|
|
+#define AR5K_SISR2_CAB_END 0x02000000 /* [5212+] */
|
|
+#define AR5K_SISR2_DTIM_SYNC 0x04000000 /* [5212+] */
|
|
+#define AR5K_SISR2_BCN_TIMEOUT 0x08000000 /* [5212+] */
|
|
+#define AR5K_SISR2_CAB_TIMEOUT 0x10000000 /* [5212+] */
|
|
+#define AR5K_SISR2_DTIM 0x20000000 /* [5212+] */
|
|
+
|
|
+#define AR5K_SISR3 0x0090 /* Register Address [5211+] */
|
|
+#define AR5K_SISR3_QCBRORN 0x000003ff /* Mask for QCBRORN */
|
|
+#define AR5K_SISR3_QCBRURN 0x03ff0000 /* Mask for QCBRURN */
|
|
+
|
|
+#define AR5K_SISR4 0x0094 /* Register Address [5211+] */
|
|
+#define AR5K_SISR4_QTRIG 0x000003ff /* Mask for QTRIG */
|
|
+
|
|
+/*
|
|
+ * Shadow read-and-clear interrupt status registers [5211+]
|
|
+ */
|
|
+#define AR5K_RAC_PISR 0x00c0 /* Read and clear PISR */
|
|
+#define AR5K_RAC_SISR0 0x00c4 /* Read and clear SISR0 */
|
|
+#define AR5K_RAC_SISR1 0x00c8 /* Read and clear SISR1 */
|
|
+#define AR5K_RAC_SISR2 0x00cc /* Read and clear SISR2 */
|
|
+#define AR5K_RAC_SISR3 0x00d0 /* Read and clear SISR3 */
|
|
+#define AR5K_RAC_SISR4 0x00d4 /* Read and clear SISR4 */
|
|
+
|
|
+/*
|
|
+ * Interrupt Mask Registers
|
|
+ *
|
|
+ * As whith ISRs 5210 has one IMR (AR5K_IMR) and 5211/5212 has one primary
|
|
+ * (AR5K_PIMR) and 4 secondary IMRs (AR5K_SIMRx). Note that ISR/IMR flags match.
|
|
+ */
|
|
+#define AR5K_IMR 0x0020 /* Register Address [5210] */
|
|
+#define AR5K_PIMR 0x00a0 /* Register Address [5211+] */
|
|
+#define AR5K_IMR_RXOK 0x00000001 /* Frame successfuly recieved*/
|
|
+#define AR5K_IMR_RXDESC 0x00000002 /* RX descriptor request*/
|
|
+#define AR5K_IMR_RXERR 0x00000004 /* Receive error*/
|
|
+#define AR5K_IMR_RXNOFRM 0x00000008 /* No frame received (receive timeout)*/
|
|
+#define AR5K_IMR_RXEOL 0x00000010 /* Empty RX descriptor*/
|
|
+#define AR5K_IMR_RXORN 0x00000020 /* Receive FIFO overrun*/
|
|
+#define AR5K_IMR_TXOK 0x00000040 /* Frame successfuly transmited*/
|
|
+#define AR5K_IMR_TXDESC 0x00000080 /* TX descriptor request*/
|
|
+#define AR5K_IMR_TXERR 0x00000100 /* Transmit error*/
|
|
+#define AR5K_IMR_TXNOFRM 0x00000200 /* No frame transmited (transmit timeout)*/
|
|
+#define AR5K_IMR_TXEOL 0x00000400 /* Empty TX descriptor*/
|
|
+#define AR5K_IMR_TXURN 0x00000800 /* Transmit FIFO underrun*/
|
|
+#define AR5K_IMR_MIB 0x00001000 /* Update MIB counters*/
|
|
+#define AR5K_IMR_SWI 0x00002000
|
|
+#define AR5K_IMR_RXPHY 0x00004000 /* PHY error*/
|
|
+#define AR5K_IMR_RXKCM 0x00008000
|
|
+#define AR5K_IMR_SWBA 0x00010000 /* Software beacon alert*/
|
|
+#define AR5K_IMR_BRSSI 0x00020000
|
|
+#define AR5K_IMR_BMISS 0x00040000 /* Beacon missed*/
|
|
+#define AR5K_IMR_HIUERR 0x00080000 /* Host Interface Unit error [5211+] */
|
|
+#define AR5K_IMR_BNR 0x00100000 /* Beacon not ready [5211+] */
|
|
+#define AR5K_IMR_MCABT 0x00100000 /* [5210] */
|
|
+#define AR5K_IMR_RXCHIRP 0x00200000 /* [5212+]*/
|
|
+#define AR5K_IMR_SSERR 0x00200000 /* [5210] */
|
|
+#define AR5K_IMR_DPERR 0x00400000 /* [5210] */
|
|
+#define AR5K_IMR_TIM 0x00800000 /* [5211+] */
|
|
+#define AR5K_IMR_BCNMISC 0x00800000 /* [5212+] */
|
|
+#define AR5K_IMR_GPIO 0x01000000 /* GPIO (rf kill)*/
|
|
+#define AR5K_IMR_QCBRORN 0x02000000 /* CBR overrun (?) [5211+] */
|
|
+#define AR5K_IMR_QCBRURN 0x04000000 /* CBR underrun (?) [5211+] */
|
|
+#define AR5K_IMR_QTRIG 0x08000000 /* [5211+] */
|
|
+
|
|
+/*
|
|
+ * Secondary interrupt mask registers [5211+] (0 - 4)
|
|
+ */
|
|
+#define AR5K_SIMR0 0x00a4 /* Register Address [5211+] */
|
|
+#define AR5K_SIMR0_QCU_TXOK 0x000003ff /* Mask for QCU_TXOK */
|
|
+#define AR5K_SIMR0_QCU_TXOK_S 0
|
|
+#define AR5K_SIMR0_QCU_TXDESC 0x03ff0000 /* Mask for QCU_TXDESC */
|
|
+#define AR5K_SIMR0_QCU_TXDESC_S 16
|
|
+
|
|
+#define AR5K_SIMR1 0x00a8 /* Register Address [5211+] */
|
|
+#define AR5K_SIMR1_QCU_TXERR 0x000003ff /* Mask for QCU_TXERR */
|
|
+#define AR5K_SIMR1_QCU_TXERR_S 0
|
|
+#define AR5K_SIMR1_QCU_TXEOL 0x03ff0000 /* Mask for QCU_TXEOL */
|
|
+#define AR5K_SIMR1_QCU_TXEOL_S 16
|
|
+
|
|
+#define AR5K_SIMR2 0x00ac /* Register Address [5211+] */
|
|
+#define AR5K_SIMR2_QCU_TXURN 0x000003ff /* Mask for QCU_TXURN */
|
|
+#define AR5K_SIMR2_QCU_TXURN_S 0
|
|
+#define AR5K_SIMR2_MCABT 0x00100000
|
|
+#define AR5K_SIMR2_SSERR 0x00200000
|
|
+#define AR5K_SIMR2_DPERR 0x00400000
|
|
+#define AR5K_SIMR2_TIM 0x01000000 /* [5212+] */
|
|
+#define AR5K_SIMR2_CAB_END 0x02000000 /* [5212+] */
|
|
+#define AR5K_SIMR2_DTIM_SYNC 0x04000000 /* [5212+] */
|
|
+#define AR5K_SIMR2_BCN_TIMEOUT 0x08000000 /* [5212+] */
|
|
+#define AR5K_SIMR2_CAB_TIMEOUT 0x10000000 /* [5212+] */
|
|
+#define AR5K_SIMR2_DTIM 0x20000000 /* [5212+] */
|
|
+
|
|
+#define AR5K_SIMR3 0x00b0 /* Register Address [5211+] */
|
|
+#define AR5K_SIMR3_QCBRORN 0x000003ff /* Mask for QCBRORN */
|
|
+#define AR5K_SIMR3_QCBRORN_S 0
|
|
+#define AR5K_SIMR3_QCBRURN 0x03ff0000 /* Mask for QCBRURN */
|
|
+#define AR5K_SIMR3_QCBRURN_S 16
|
|
+
|
|
+#define AR5K_SIMR4 0x00b4 /* Register Address [5211+] */
|
|
+#define AR5K_SIMR4_QTRIG 0x000003ff /* Mask for QTRIG */
|
|
+#define AR5K_SIMR4_QTRIG_S 0
|
|
+
|
|
+
|
|
+/*
|
|
+ * Decompression mask registers [5212+]
|
|
+ */
|
|
+#define AR5K_DCM_ADDR 0x0400 /*Decompression mask address (?)*/
|
|
+#define AR5K_DCM_DATA 0x0404 /*Decompression mask data (?)*/
|
|
+
|
|
+/*
|
|
+ * Decompression configuration registers [5212+]
|
|
+ */
|
|
+#define AR5K_DCCFG 0x0420
|
|
+
|
|
+/*
|
|
+ * Compression configuration registers [5212+]
|
|
+ */
|
|
+#define AR5K_CCFG 0x0600
|
|
+#define AR5K_CCFG_CUP 0x0604
|
|
+
|
|
+/*
|
|
+ * Compression performance counter registers [5212+]
|
|
+ */
|
|
+#define AR5K_CPC0 0x0610 /* Compression performance counter 0 */
|
|
+#define AR5K_CPC1 0x0614 /* Compression performance counter 1*/
|
|
+#define AR5K_CPC2 0x0618 /* Compression performance counter 2 */
|
|
+#define AR5K_CPC3 0x061c /* Compression performance counter 3 */
|
|
+#define AR5K_CPCORN 0x0620 /* Compression performance overrun (?) */
|
|
+
|
|
+
|
|
+/*
|
|
+ * Queue control unit (QCU) registers [5211+]
|
|
+ *
|
|
+ * Card has 12 TX Queues but i see that only 0-9 are used (?)
|
|
+ * both in binary HAL (see ah.h) and ar5k. Each queue has it's own
|
|
+ * TXDP at addresses 0x0800 - 0x082c, a CBR (Constant Bit Rate)
|
|
+ * configuration register (0x08c0 - 0x08ec), a ready time configuration
|
|
+ * register (0x0900 - 0x092c), a misc configuration register (0x09c0 -
|
|
+ * 0x09ec) and a status register (0x0a00 - 0x0a2c). We also have some
|
|
+ * global registers, QCU transmit enable/disable and "one shot arm (?)"
|
|
+ * set/clear, which contain status for all queues (we shift by 1 for each
|
|
+ * queue). To access these registers easily we define some macros here
|
|
+ * that are used inside HAL. For more infos check out *_tx_queue functs.
|
|
+ *
|
|
+ * TODO: Boundary checking on macros (here?)
|
|
+ */
|
|
+
|
|
+/*
|
|
+ * Generic QCU Register access macros
|
|
+ */
|
|
+#define AR5K_QUEUE_REG(_r, _q) (((_q) << 2) + _r)
|
|
+#define AR5K_QCU_GLOBAL_READ(_r, _q) (AR5K_REG_READ(_r) & (1 << _q))
|
|
+#define AR5K_QCU_GLOBAL_WRITE(_r, _q) AR5K_REG_WRITE(_r, (1 << _q))
|
|
+
|
|
+/*
|
|
+ * QCU Transmit descriptor pointer registers
|
|
+ */
|
|
+#define AR5K_QCU_TXDP_BASE 0x0800 /* Register Address - Queue0 TXDP */
|
|
+#define AR5K_QUEUE_TXDP(_q) AR5K_QUEUE_REG(AR5K_QCU_TXDP_BASE, _q)
|
|
+
|
|
+/*
|
|
+ * QCU Transmit enable register
|
|
+ */
|
|
+#define AR5K_QCU_TXE 0x0840
|
|
+#define AR5K_ENABLE_QUEUE(_q) AR5K_QCU_GLOBAL_WRITE(AR5K_QCU_TXE, _q)
|
|
+#define AR5K_QUEUE_ENABLED(_q) AR5K_QCU_GLOBAL_READ(AR5K_QCU_TXE, _q)
|
|
+
|
|
+/*
|
|
+ * QCU Transmit disable register
|
|
+ */
|
|
+#define AR5K_QCU_TXD 0x0880
|
|
+#define AR5K_DISABLE_QUEUE(_q) AR5K_QCU_GLOBAL_WRITE(AR5K_QCU_TXD, _q)
|
|
+#define AR5K_QUEUE_DISABLED(_q) AR5K_QCU_GLOBAL_READ(AR5K_QCU_TXD, _q)
|
|
+
|
|
+/*
|
|
+ * QCU Constant Bit Rate configuration registers
|
|
+ */
|
|
+#define AR5K_QCU_CBRCFG_BASE 0x08c0 /* Register Address - Queue0 CBRCFG */
|
|
+#define AR5K_QCU_CBRCFG_INTVAL 0x00ffffff /* CBR Interval mask */
|
|
+#define AR5K_QCU_CBRCFG_INTVAL_S 0
|
|
+#define AR5K_QCU_CBRCFG_ORN_THRES 0xff000000 /* CBR overrun threshold mask */
|
|
+#define AR5K_QCU_CBRCFG_ORN_THRES_S 24
|
|
+#define AR5K_QUEUE_CBRCFG(_q) AR5K_QUEUE_REG(AR5K_QCU_CBRCFG_BASE, _q)
|
|
+
|
|
+/*
|
|
+ * QCU Ready time configuration registers
|
|
+ */
|
|
+#define AR5K_QCU_RDYTIMECFG_BASE 0x0900 /* Register Address - Queue0 RDYTIMECFG */
|
|
+#define AR5K_QCU_RDYTIMECFG_INTVAL 0x00ffffff /* Ready time interval mask */
|
|
+#define AR5K_QCU_RDYTIMECFG_INTVAL_S 0
|
|
+#define AR5K_QCU_RDYTIMECFG_DURATION 0x00ffffff /* Ready time duration mask */
|
|
+#define AR5K_QCU_RDYTIMECFG_ENABLE 0x01000000 /* Ready time enable mask */
|
|
+#define AR5K_QUEUE_RDYTIMECFG(_q) AR5K_QUEUE_REG(AR5K_QCU_RDYTIMECFG_BASE, _q)
|
|
+
|
|
+/*
|
|
+ * QCU one shot arm set registers
|
|
+ */
|
|
+#define AR5K_QCU_ONESHOTARM_SET 0x0940 /* Register Address -QCU "one shot arm set (?)" */
|
|
+#define AR5K_QCU_ONESHOTARM_SET_M 0x0000ffff
|
|
+
|
|
+/*
|
|
+ * QCU one shot arm clear registers
|
|
+ */
|
|
+#define AR5K_QCU_ONESHOTARM_CLEAR 0x0980 /* Register Address -QCU "one shot arm clear (?)" */
|
|
+#define AR5K_QCU_ONESHOTARM_CLEAR_M 0x0000ffff
|
|
+
|
|
+/*
|
|
+ * QCU misc registers
|
|
+ */
|
|
+#define AR5K_QCU_MISC_BASE 0x09c0 /* Register Address -Queue0 MISC */
|
|
+#define AR5K_QCU_MISC_FRSHED_M 0x0000000f /* Frame sheduling mask */
|
|
+#define AR5K_QCU_MISC_FRSHED_ASAP 0 /* ASAP */
|
|
+#define AR5K_QCU_MISC_FRSHED_CBR 1 /* Constant Bit Rate */
|
|
+#define AR5K_QCU_MISC_FRSHED_DBA_GT 2 /* DMA Beacon alert gated (?) */
|
|
+#define AR5K_QCU_MISC_FRSHED_TIM_GT 3 /* Time gated (?) */
|
|
+#define AR5K_QCU_MISC_FRSHED_BCN_SENT_GT 4 /* Beacon sent gated (?) */
|
|
+#define AR5K_QCU_MISC_ONESHOT_ENABLE 0x00000010 /* Oneshot enable */
|
|
+#define AR5K_QCU_MISC_CBREXP 0x00000020 /* CBR expired (normal queue) */
|
|
+#define AR5K_QCU_MISC_CBREXP_BCN 0x00000040 /* CBR expired (beacon queue) */
|
|
+#define AR5K_QCU_MISC_BCN_ENABLE 0x00000080 /* Beacons enabled */
|
|
+#define AR5K_QCU_MISC_CBR_THRES_ENABLE 0x00000100 /* CBR threshold enabled (?) */
|
|
+#define AR5K_QCU_MISC_TXE 0x00000200 /* TXE reset when RDYTIME enalbed (?) */
|
|
+#define AR5K_QCU_MISC_CBR 0x00000400 /* CBR threshold reset (?) */
|
|
+#define AR5K_QCU_MISC_DCU_EARLY 0x00000800 /* DCU reset (?) */
|
|
+#define AR5K_QUEUE_MISC(_q) AR5K_QUEUE_REG(AR5K_QCU_MISC_BASE, _q)
|
|
+
|
|
+
|
|
+/*
|
|
+ * QCU status registers
|
|
+ */
|
|
+#define AR5K_QCU_STS_BASE 0x0a00 /* Register Address - Queue0 STS */
|
|
+#define AR5K_QCU_STS_FRMPENDCNT 0x00000003 /* Frames pending counter */
|
|
+#define AR5K_QCU_STS_CBREXPCNT 0x0000ff00 /* CBR expired counter (?) */
|
|
+#define AR5K_QUEUE_STATUS(_q) AR5K_QUEUE_REG(AR5K_QCU_STS_BASE, _q)
|
|
+
|
|
+/*
|
|
+ * QCU ready time shutdown register
|
|
+ */
|
|
+#define AR5K_QCU_RDYTIMESHDN 0x0a40
|
|
+#define AR5K_QCU_RDYTIMESHDN_M 0x000003ff
|
|
+
|
|
+/*
|
|
+ * QCU compression buffer base registers [5212+]
|
|
+ */
|
|
+#define AR5K_QCU_CBB_SELECT 0x0b00
|
|
+#define AR5K_QCU_CBB_ADDR 0x0b04
|
|
+
|
|
+/*
|
|
+ * QCU compression buffer configuration register [5212+]
|
|
+ */
|
|
+#define AR5K_QCU_CBCFG 0x0b08
|
|
+
|
|
+
|
|
+
|
|
+/*
|
|
+ * Distributed Coordination Function (DCF) control unit (DCU)
|
|
+ * registers [5211+]
|
|
+ *
|
|
+ * These registers control the various characteristics of each queue
|
|
+ * for 802.11e (WME) combatibility so they go together with
|
|
+ * QCU registers in pairs. For each queue we have a QCU mask register,
|
|
+ * (0x1000 - 0x102c), a local-IFS settings register (0x1040 - 0x106c),
|
|
+ * a retry limit register (0x1080 - 0x10ac), a channel time register
|
|
+ * (0x10c0 - 0x10ec), a misc-settings register (0x1100 - 0x112c) and
|
|
+ * a sequence number register (0x1140 - 0x116c). It seems that "global"
|
|
+ * registers here afect all queues (see use of DCU_GBL_IFS_SLOT in ar5k).
|
|
+ * We use the same macros here for easier register access.
|
|
+ *
|
|
+ */
|
|
+
|
|
+/*
|
|
+ * DCU QCU mask registers
|
|
+ */
|
|
+#define AR5K_DCU_QCUMASK_BASE 0x1000 /* Register Address -Queue0 DCU_QCUMASK */
|
|
+#define AR5K_DCU_QCUMASK_M 0x000003ff
|
|
+#define AR5K_QUEUE_QCUMASK(_q) AR5K_QUEUE_REG(AR5K_DCU_QCUMASK_BASE, _q)
|
|
+
|
|
+/*
|
|
+ * DCU local Inter Frame Space settings register
|
|
+ */
|
|
+#define AR5K_DCU_LCL_IFS_BASE 0x1040 /* Register Address -Queue0 DCU_LCL_IFS */
|
|
+#define AR5K_DCU_LCL_IFS_CW_MIN 0x000003ff /* Minimum Contention Window */
|
|
+#define AR5K_DCU_LCL_IFS_CW_MIN_S 0
|
|
+#define AR5K_DCU_LCL_IFS_CW_MAX 0x000ffc00 /* Maximum Contention Window */
|
|
+#define AR5K_DCU_LCL_IFS_CW_MAX_S 10
|
|
+#define AR5K_DCU_LCL_IFS_AIFS 0x0ff00000 /* Arbitrated Interframe Space */
|
|
+#define AR5K_DCU_LCL_IFS_AIFS_S 20
|
|
+#define AR5K_QUEUE_DFS_LOCAL_IFS(_q) AR5K_QUEUE_REG(AR5K_DCU_LCL_IFS_BASE, _q)
|
|
+
|
|
+/*
|
|
+ * DCU retry limit registers
|
|
+ */
|
|
+#define AR5K_DCU_RETRY_LMT_BASE 0x1080 /* Register Address -Queue0 DCU_RETRY_LMT */
|
|
+#define AR5K_DCU_RETRY_LMT_SH_RETRY 0x0000000f /* Short retry limit mask */
|
|
+#define AR5K_DCU_RETRY_LMT_SH_RETRY_S 0
|
|
+#define AR5K_DCU_RETRY_LMT_LG_RETRY 0x000000f0 /* Long retry limit mask */
|
|
+#define AR5K_DCU_RETRY_LMT_LG_RETRY_S 4
|
|
+#define AR5K_DCU_RETRY_LMT_SSH_RETRY 0x00003f00 /* Station short retry limit mask (?) */
|
|
+#define AR5K_DCU_RETRY_LMT_SSH_RETRY_S 8
|
|
+#define AR5K_DCU_RETRY_LMT_SLG_RETRY 0x000fc000 /* Station long retry limit mask (?) */
|
|
+#define AR5K_DCU_RETRY_LMT_SLG_RETRY_S 14
|
|
+#define AR5K_QUEUE_DFS_RETRY_LIMIT(_q) AR5K_QUEUE_REG(AR5K_DCU_RETRY_LMT_BASE, _q)
|
|
+
|
|
+/*
|
|
+ * DCU channel time registers
|
|
+ */
|
|
+#define AR5K_DCU_CHAN_TIME_BASE 0x10c0 /* Register Address -Queue0 DCU_CHAN_TIME */
|
|
+#define AR5K_DCU_CHAN_TIME_DUR 0x000fffff /* Channel time duration */
|
|
+#define AR5K_DCU_CHAN_TIME_DUR_S 0
|
|
+#define AR5K_DCU_CHAN_TIME_ENABLE 0x00100000 /* Enable channel time */
|
|
+#define AR5K_QUEUE_DFS_CHANNEL_TIME(_q) AR5K_QUEUE_REG(AR5K_DCU_CHAN_TIME_BASE, _q)
|
|
+
|
|
+/*
|
|
+ * DCU misc registers [5211+]
|
|
+ *
|
|
+ * For some of the registers i couldn't find in the code
|
|
+ * (only backoff stuff is there realy) i tried to match the
|
|
+ * names with 802.11e parameters etc, so i guess VIRTCOL here
|
|
+ * means Virtual Collision and HCFPOLL means Hybrid Coordination
|
|
+ * factor Poll (CF- Poll). Arbiter lockout control controls the
|
|
+ * behaviour on low priority queues when we have multiple queues
|
|
+ * with pending frames. Intra-frame lockout means we wait until
|
|
+ * the queue's current frame transmits (with post frame backoff and bursting)
|
|
+ * before we transmit anything else and global lockout means we
|
|
+ * wait for the whole queue to finish before higher priority queues
|
|
+ * can transmit (this is used on beacon and CAB queues).
|
|
+ * No lockout means there is no special handling.
|
|
+ */
|
|
+#define AR5K_DCU_MISC_BASE 0x1100 /* Register Address -Queue0 DCU_MISC */
|
|
+#define AR5K_DCU_MISC_BACKOFF 0x000007ff /* Mask for backoff setting (?) */
|
|
+#define AR5K_DCU_MISC_BACKOFF_FRAG 0x00000200 /* Enable backoff while bursting */
|
|
+#define AR5K_DCU_MISC_HCFPOLL_ENABLE 0x00000800 /* CF - Poll (?) */
|
|
+#define AR5K_DCU_MISC_BACKOFF_PERSIST 0x00001000 /* Persistent backoff (?) */
|
|
+#define AR5K_DCU_MISC_FRMPRFTCH_ENABLE 0x00002000 /* Enable frame pre-fetch (?) */
|
|
+#define AR5K_DCU_MISC_VIRTCOL 0x0000c000 /* Mask for Virtual Collision (?) */
|
|
+#define AR5K_DCU_MISC_VIRTCOL_NORMAL 0
|
|
+#define AR5K_DCU_MISC_VIRTCOL_MODIFIED 1
|
|
+#define AR5K_DCU_MISC_VIRTCOL_IGNORE 2
|
|
+#define AR5K_DCU_MISC_BCN_ENABLE 0x00010000 /* Beacon enable (?) */
|
|
+#define AR5K_DCU_MISC_ARBLOCK_CTL 0x00060000 /* Arbiter lockout control mask */
|
|
+#define AR5K_DCU_MISC_ARBLOCK_CTL_S 17
|
|
+#define AR5K_DCU_MISC_ARBLOCK_CTL_NONE 0 /* No arbiter lockout */
|
|
+#define AR5K_DCU_MISC_ARBLOCK_CTL_INTFRM 1 /* Intra-frame lockout */
|
|
+#define AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL 2 /* Global lockout */
|
|
+#define AR5K_DCU_MISC_ARBLOCK_IGNORE 0x00080000
|
|
+#define AR5K_DCU_MISC_SEQ_NUM_INCR_DIS 0x00100000 /* Disable sequence number increment (?) */
|
|
+#define AR5K_DCU_MISC_POST_FR_BKOFF_DIS 0x00200000 /* Disable post-frame backoff (?) */
|
|
+#define AR5K_DCU_MISC_VIRT_COLL_POLICY 0x00400000 /* Virtual Collision policy (?) */
|
|
+#define AR5K_DCU_MISC_BLOWN_IFS_POLICY 0x00800000
|
|
+#define AR5K_DCU_MISC_SEQNUM_CTL 0x01000000 /* Sequence number control (?) */
|
|
+#define AR5K_QUEUE_DFS_MISC(_q) AR5K_QUEUE_REG(AR5K_DCU_MISC_BASE, _q)
|
|
+
|
|
+/*
|
|
+ * DCU frame sequence number registers
|
|
+ */
|
|
+#define AR5K_DCU_SEQNUM_BASE 0x1140
|
|
+#define AR5K_DCU_SEQNUM_M 0x00000fff
|
|
+#define AR5K_QUEUE_DFS_SEQNUM(_q) AR5K_QUEUE_REG(AR5K_DCU_SEQNUM_BASE, _q)
|
|
+
|
|
+/*
|
|
+ * DCU global IFS SIFS registers
|
|
+ */
|
|
+#define AR5K_DCU_GBL_IFS_SIFS 0x1030
|
|
+#define AR5K_DCU_GBL_IFS_SIFS_M 0x0000ffff
|
|
+
|
|
+/*
|
|
+ * DCU global IFS slot interval registers
|
|
+ */
|
|
+#define AR5K_DCU_GBL_IFS_SLOT 0x1070
|
|
+#define AR5K_DCU_GBL_IFS_SLOT_M 0x0000ffff
|
|
+
|
|
+/*
|
|
+ * DCU global IFS EIFS registers
|
|
+ */
|
|
+#define AR5K_DCU_GBL_IFS_EIFS 0x10b0
|
|
+#define AR5K_DCU_GBL_IFS_EIFS_M 0x0000ffff
|
|
+
|
|
+/*
|
|
+ * DCU global IFS misc registers
|
|
+ */
|
|
+#define AR5K_DCU_GBL_IFS_MISC 0x10f0 /* Register Address */
|
|
+#define AR5K_DCU_GBL_IFS_MISC_LFSR_SLICE 0x00000007
|
|
+#define AR5K_DCU_GBL_IFS_MISC_TURBO_MODE 0x00000008 /* Turbo mode (?) */
|
|
+#define AR5K_DCU_GBL_IFS_MISC_SIFS_DUR_USEC 0x000003f0 /* SIFS Duration mask (?) */
|
|
+#define AR5K_DCU_GBL_IFS_MISC_USEC_DUR 0x000ffc00
|
|
+#define AR5K_DCU_GBL_IFS_MISC_DCU_ARB_DELAY 0x00300000
|
|
+
|
|
+/*
|
|
+ * DCU frame prefetch control register
|
|
+ */
|
|
+#define AR5K_DCU_FP 0x1230
|
|
+
|
|
+/*
|
|
+ * DCU transmit pause control/status register
|
|
+ */
|
|
+#define AR5K_DCU_TXP 0x1270 /* Register Address */
|
|
+#define AR5K_DCU_TXP_M 0x000003ff /* Tx pause mask (?) */
|
|
+#define AR5K_DCU_TXP_STATUS 0x00010000 /* Tx pause status (?) */
|
|
+
|
|
+/*
|
|
+ * DCU transmit filter register
|
|
+ */
|
|
+#define AR5K_DCU_TX_FILTER 0x1038
|
|
+
|
|
+/*
|
|
+ * DCU clear transmit filter register
|
|
+ */
|
|
+#define AR5K_DCU_TX_FILTER_CLR 0x143c
|
|
+
|
|
+/*
|
|
+ * DCU set transmit filter register
|
|
+ */
|
|
+#define AR5K_DCU_TX_FILTER_SET 0x147c
|
|
+
|
|
+/*
|
|
+ * Reset control register
|
|
+ *
|
|
+ * 4 and 8 are not used in 5211/5212 and
|
|
+ * 2 means "baseband reset" on 5211/5212.
|
|
+ */
|
|
+#define AR5K_RESET_CTL 0x4000 /* Register Address */
|
|
+#define AR5K_RESET_CTL_PCU 0x00000001 /* Protocol Control Unit reset */
|
|
+#define AR5K_RESET_CTL_DMA 0x00000002 /* DMA (Rx/Tx) reset [5210] */
|
|
+#define AR5K_RESET_CTL_BASEBAND 0x00000002 /* Baseband reset [5211+] */
|
|
+#define AR5K_RESET_CTL_MAC 0x00000004 /* MAC reset (PCU+Baseband ?) [5210] */
|
|
+#define AR5K_RESET_CTL_PHY 0x00000008 /* PHY reset [5210] */
|
|
+#define AR5K_RESET_CTL_PCI 0x00000010 /* PCI Core reset (interrupts etc) */
|
|
+#define AR5K_RESET_CTL_CHIP (AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_DMA | \
|
|
+ AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_PHY)
|
|
+
|
|
+/*
|
|
+ * Sleep control register
|
|
+ */
|
|
+#define AR5K_SLEEP_CTL 0x4004 /* Register Address */
|
|
+#define AR5K_SLEEP_CTL_SLDUR 0x0000ffff /* Sleep duration mask */
|
|
+#define AR5K_SLEEP_CTL_SLDUR_S 0
|
|
+#define AR5K_SLEEP_CTL_SLE 0x00030000 /* Sleep enable mask */
|
|
+#define AR5K_SLEEP_CTL_SLE_S 16
|
|
+#define AR5K_SLEEP_CTL_SLE_WAKE 0x00000000 /* Force chip awake */
|
|
+#define AR5K_SLEEP_CTL_SLE_SLP 0x00010000 /* Force chip sleep */
|
|
+#define AR5K_SLEEP_CTL_SLE_ALLOW 0x00020000
|
|
+#define AR5K_SLEEP_CTL_SLE_UNITS 0x00000008 /* [5211+] */
|
|
+
|
|
+/*
|
|
+ * Interrupt pending register
|
|
+ */
|
|
+#define AR5K_INTPEND 0x4008
|
|
+#define AR5K_INTPEND_M 0x00000001
|
|
+
|
|
+/*
|
|
+ * Sleep force register
|
|
+ */
|
|
+#define AR5K_SFR 0x400c
|
|
+#define AR5K_SFR_M 0x00000001
|
|
+
|
|
+/*
|
|
+ * PCI configuration register
|
|
+ */
|
|
+#define AR5K_PCICFG 0x4010 /* Register Address */
|
|
+#define AR5K_PCICFG_EEAE 0x00000001 /* Eeprom access enable [5210] */
|
|
+#define AR5K_PCICFG_CLKRUNEN 0x00000004 /* CLKRUN enable [5211+] */
|
|
+#define AR5K_PCICFG_EESIZE 0x00000018 /* Mask for EEPROM size [5211+] */
|
|
+#define AR5K_PCICFG_EESIZE_S 3
|
|
+#define AR5K_PCICFG_EESIZE_4K 0 /* 4K */
|
|
+#define AR5K_PCICFG_EESIZE_8K 1 /* 8K */
|
|
+#define AR5K_PCICFG_EESIZE_16K 2 /* 16K */
|
|
+#define AR5K_PCICFG_EESIZE_FAIL 3 /* Failed to get size (?) [5211+] */
|
|
+#define AR5K_PCICFG_LED 0x00000060 /* Led status [5211+] */
|
|
+#define AR5K_PCICFG_LED_NONE 0x00000000 /* Default [5211+] */
|
|
+#define AR5K_PCICFG_LED_PEND 0x00000020 /* Scan / Auth pending */
|
|
+#define AR5K_PCICFG_LED_ASSOC 0x00000040 /* Associated */
|
|
+#define AR5K_PCICFG_BUS_SEL 0x00000380 /* Mask for "bus select" [5211+] (?) */
|
|
+#define AR5K_PCICFG_CBEFIX_DIS 0x00000400 /* Disable CBE fix (?) */
|
|
+#define AR5K_PCICFG_SL_INTEN 0x00000800 /* Enable interrupts when asleep (?) */
|
|
+#define AR5K_PCICFG_LED_BCTL 0x00001000 /* Led blink (?) [5210] */
|
|
+#define AR5K_PCICFG_SL_INPEN 0x00002800 /* Sleep even whith pending interrupts (?) */
|
|
+#define AR5K_PCICFG_SPWR_DN 0x00010000 /* Mask for power status */
|
|
+#define AR5K_PCICFG_LEDMODE 0x000e0000 /* Ledmode [5211+] */
|
|
+#define AR5K_PCICFG_LEDMODE_PROP 0x00000000 /* Blink on standard traffic [5211+] */
|
|
+#define AR5K_PCICFG_LEDMODE_PROM 0x00020000 /* Default mode (blink on any traffic) [5211+] */
|
|
+#define AR5K_PCICFG_LEDMODE_PWR 0x00040000 /* Some other blinking mode (?) [5211+] */
|
|
+#define AR5K_PCICFG_LEDMODE_RAND 0x00060000 /* Random blinking (?) [5211+] */
|
|
+#define AR5K_PCICFG_LEDBLINK 0x00700000
|
|
+#define AR5K_PCICFG_LEDBLINK_S 20
|
|
+#define AR5K_PCICFG_LEDSLOW 0x00800000 /* Slow led blink rate (?) [5211+] */
|
|
+#define AR5K_PCICFG_LEDSTATE \
|
|
+ (AR5K_PCICFG_LED | AR5K_PCICFG_LEDMODE | \
|
|
+ AR5K_PCICFG_LEDBLINK | AR5K_PCICFG_LEDSLOW)
|
|
+
|
|
+/*
|
|
+ * "General Purpose Input/Output" (GPIO) control register
|
|
+ *
|
|
+ * I'm not sure about this but after looking at the code
|
|
+ * for all chipsets here is what i got.
|
|
+ *
|
|
+ * We have 6 GPIOs (pins), each GPIO has 4 modes (2 bits)
|
|
+ * Mode 0 -> always input
|
|
+ * Mode 1 -> output when GPIODO for this GPIO is set to 0
|
|
+ * Mode 2 -> output when GPIODO for this GPIO is set to 1
|
|
+ * Mode 3 -> always output
|
|
+ *
|
|
+ * For more infos check out get_gpio/set_gpio and
|
|
+ * set_gpio_input/set_gpio_output functs.
|
|
+ * For more infos on gpio interrupt check out set_gpio_intr.
|
|
+ */
|
|
+#define AR5K_NUM_GPIO 6
|
|
+
|
|
+#define AR5K_GPIOCR 0x4014 /* Register Address */
|
|
+#define AR5K_GPIOCR_INT_ENA 0x00008000 /* Enable GPIO interrupt */
|
|
+#define AR5K_GPIOCR_INT_SELL 0x00000000 /* Generate interrupt when pin is off (?) */
|
|
+#define AR5K_GPIOCR_INT_SELH 0x00010000 /* Generate interrupt when pin is on */
|
|
+#define AR5K_GPIOCR_IN(n) (0 << ((n) * 2)) /* Mode 0 for pin n */
|
|
+#define AR5K_GPIOCR_OUT0(n) (1 << ((n) * 2)) /* Mode 1 for pin n */
|
|
+#define AR5K_GPIOCR_OUT1(n) (2 << ((n) * 2)) /* Mode 2 for pin n */
|
|
+#define AR5K_GPIOCR_OUT(n) (3 << ((n) * 2)) /* Mode 3 for pin n */
|
|
+#define AR5K_GPIOCR_INT_SEL(n) ((n) << 12) /* Interrupt for GPIO pin n */
|
|
+
|
|
+/*
|
|
+ * "General Purpose Input/Output" (GPIO) data output register
|
|
+ */
|
|
+#define AR5K_GPIODO 0x4018
|
|
+
|
|
+/*
|
|
+ * "General Purpose Input/Output" (GPIO) data input register
|
|
+ */
|
|
+#define AR5K_GPIODI 0x401c
|
|
+#define AR5K_GPIODI_M 0x0000002f
|
|
+
|
|
+
|
|
+/*
|
|
+ * Silicon revision register
|
|
+ */
|
|
+#define AR5K_SREV 0x4020 /* Register Address */
|
|
+#define AR5K_SREV_REV 0x0000000f /* Mask for revision */
|
|
+#define AR5K_SREV_REV_S 0
|
|
+#define AR5K_SREV_VER 0x000000ff /* Mask for version */
|
|
+#define AR5K_SREV_VER_S 4
|
|
+
|
|
+
|
|
+
|
|
+/*====EEPROM REGISTERS====*/
|
|
+
|
|
+/*
|
|
+ * EEPROM access registers
|
|
+ *
|
|
+ * Here we got a difference between 5210/5211-12
|
|
+ * read data register for 5210 is at 0x6800 and
|
|
+ * status register is at 0x6c00. There is also
|
|
+ * no eeprom command register on 5210 and the
|
|
+ * offsets are different.
|
|
+ *
|
|
+ * To read eeprom data for a specific offset:
|
|
+ * 5210 - enable eeprom access (AR5K_PCICFG_EEAE)
|
|
+ * read AR5K_EEPROM_BASE +(4 * offset)
|
|
+ * check the eeprom status register
|
|
+ * and read eeprom data register.
|
|
+ *
|
|
+ * 5211 - write offset to AR5K_EEPROM_BASE
|
|
+ * 5212 write AR5K_EEPROM_CMD_READ on AR5K_EEPROM_CMD
|
|
+ * check the eeprom status register
|
|
+ * and read eeprom data register.
|
|
+ *
|
|
+ * To write eeprom data for a specific offset:
|
|
+ * 5210 - enable eeprom access (AR5K_PCICFG_EEAE)
|
|
+ * write data to AR5K_EEPROM_BASE +(4 * offset)
|
|
+ * check the eeprom status register
|
|
+ * 5211 - write AR5K_EEPROM_CMD_RESET on AR5K_EEPROM_CMD
|
|
+ * 5212 write offset to AR5K_EEPROM_BASE
|
|
+ * write data to data register
|
|
+ * write AR5K_EEPROM_CMD_WRITE on AR5K_EEPROM_CMD
|
|
+ * check the eeprom status register
|
|
+ *
|
|
+ * For more infos check eeprom_* functs and the ar5k.c
|
|
+ * file posted in madwifi-devel mailing list.
|
|
+ * http://sourceforge.net/mailarchive/message.php?msg_id=8966525
|
|
+ *
|
|
+ */
|
|
+#define AR5K_EEPROM_BASE 0x6000
|
|
+
|
|
+/*
|
|
+ * Common ar5xxx EEPROM data offsets (set these on AR5K_EEPROM_BASE)
|
|
+ */
|
|
+#define AR5K_EEPROM_MAGIC 0x003d /* EEPROM Magic number */
|
|
+#define AR5K_EEPROM_MAGIC_VALUE 0x5aa5 /* Default - found on EEPROM */
|
|
+#define AR5K_EEPROM_MAGIC_5212 0x0000145c /* 5212 */
|
|
+#define AR5K_EEPROM_MAGIC_5211 0x0000145b /* 5211 */
|
|
+#define AR5K_EEPROM_MAGIC_5210 0x0000145a /* 5210 */
|
|
+
|
|
+#define AR5K_EEPROM_PROTECT 0x003f /* EEPROM protect status */
|
|
+#define AR5K_EEPROM_PROTECT_RD_0_31 0x0001 /* Read protection bit for offsets 0x0 - 0x1f */
|
|
+#define AR5K_EEPROM_PROTECT_WR_0_31 0x0002 /* Write protection bit for offsets 0x0 - 0x1f */
|
|
+#define AR5K_EEPROM_PROTECT_RD_32_63 0x0004 /* 0x20 - 0x3f */
|
|
+#define AR5K_EEPROM_PROTECT_WR_32_63 0x0008
|
|
+#define AR5K_EEPROM_PROTECT_RD_64_127 0x0010 /* 0x40 - 0x7f */
|
|
+#define AR5K_EEPROM_PROTECT_WR_64_127 0x0020
|
|
+#define AR5K_EEPROM_PROTECT_RD_128_191 0x0040 /* 0x80 - 0xbf (regdom) */
|
|
+#define AR5K_EEPROM_PROTECT_WR_128_191 0x0080
|
|
+#define AR5K_EEPROM_PROTECT_RD_192_207 0x0100 /* 0xc0 - 0xcf */
|
|
+#define AR5K_EEPROM_PROTECT_WR_192_207 0x0200
|
|
+#define AR5K_EEPROM_PROTECT_RD_208_223 0x0400 /* 0xd0 - 0xdf */
|
|
+#define AR5K_EEPROM_PROTECT_WR_208_223 0x0800
|
|
+#define AR5K_EEPROM_PROTECT_RD_224_239 0x1000 /* 0xe0 - 0xef */
|
|
+#define AR5K_EEPROM_PROTECT_WR_224_239 0x2000
|
|
+#define AR5K_EEPROM_PROTECT_RD_240_255 0x4000 /* 0xf0 - 0xff */
|
|
+#define AR5K_EEPROM_PROTECT_WR_240_255 0x8000
|
|
+#define AR5K_EEPROM_REG_DOMAIN 0x00bf /* EEPROM regdom */
|
|
+#define AR5K_EEPROM_INFO_BASE 0x00c0 /* EEPROM header */
|
|
+#define AR5K_EEPROM_INFO_MAX (0x400 - AR5K_EEPROM_INFO_BASE)
|
|
+#define AR5K_EEPROM_INFO_CKSUM 0xffff
|
|
+#define AR5K_EEPROM_INFO(_n) (AR5K_EEPROM_INFO_BASE + (_n))
|
|
+
|
|
+#define AR5K_EEPROM_VERSION AR5K_EEPROM_INFO(1) /* EEPROM Version */
|
|
+#define AR5K_EEPROM_VERSION_3_0 0x3000 /* No idea what's going on before this version */
|
|
+#define AR5K_EEPROM_VERSION_3_1 0x3001 /* ob/db values for 2Ghz (ar5211_rfregs) */
|
|
+#define AR5K_EEPROM_VERSION_3_2 0x3002 /* different frequency representation (eeprom_bin2freq) */
|
|
+#define AR5K_EEPROM_VERSION_3_3 0x3003 /* offsets changed, has 32 CTLs (see below) and ee_false_detect (eeprom_read_modes) */
|
|
+#define AR5K_EEPROM_VERSION_3_4 0x3004 /* has ee_i_gain ee_cck_ofdm_power_delta (eeprom_read_modes) */
|
|
+#define AR5K_EEPROM_VERSION_4_0 0x4000 /* has ee_misc*, ee_cal_pier, ee_turbo_max_power and ee_xr_power (eeprom_init) */
|
|
+#define AR5K_EEPROM_VERSION_4_1 0x4001 /* has ee_margin_tx_rx (eeprom_init) */
|
|
+#define AR5K_EEPROM_VERSION_4_2 0x4002 /* has ee_cck_ofdm_gain_delta (eeprom_init) */
|
|
+#define AR5K_EEPROM_VERSION_4_3 0x4003
|
|
+#define AR5K_EEPROM_VERSION_4_4 0x4004
|
|
+#define AR5K_EEPROM_VERSION_4_5 0x4005
|
|
+#define AR5K_EEPROM_VERSION_4_6 0x4006 /* has ee_scaled_cck_delta */
|
|
+#define AR5K_EEPROM_VERSION_4_7 0x3007
|
|
+
|
|
+#define AR5K_EEPROM_MODE_11A 0
|
|
+#define AR5K_EEPROM_MODE_11B 1
|
|
+#define AR5K_EEPROM_MODE_11G 2
|
|
+
|
|
+#define AR5K_EEPROM_HDR AR5K_EEPROM_INFO(2) /* Header that contains the device caps */
|
|
+#define AR5K_EEPROM_HDR_11A(_v) (((_v) >> AR5K_EEPROM_MODE_11A) & 0x1)
|
|
+#define AR5K_EEPROM_HDR_11B(_v) (((_v) >> AR5K_EEPROM_MODE_11B) & 0x1)
|
|
+#define AR5K_EEPROM_HDR_11G(_v) (((_v) >> AR5K_EEPROM_MODE_11G) & 0x1)
|
|
+#define AR5K_EEPROM_HDR_T_2GHZ_DIS(_v) (((_v) >> 3) & 0x1) /* Disable turbo for 2Ghz (?) */
|
|
+#define AR5K_EEPROM_HDR_T_5GHZ_DBM(_v) (((_v) >> 4) & 0x7f) /* Max turbo power for a/XR mode (eeprom_init) */
|
|
+#define AR5K_EEPROM_HDR_DEVICE(_v) (((_v) >> 11) & 0x7)
|
|
+#define AR5K_EEPROM_HDR_T_5GHZ_DIS(_v) (((_v) >> 15) & 0x1) /* Disable turbo for 5Ghz (?) */
|
|
+#define AR5K_EEPROM_HDR_RFKILL(_v) (((_v) >> 14) & 0x1) /* Device has RFKill support */
|
|
+
|
|
+#define AR5K_EEPROM_RFKILL_GPIO_SEL 0x0000001c
|
|
+#define AR5K_EEPROM_RFKILL_GPIO_SEL_S 2
|
|
+#define AR5K_EEPROM_RFKILL_POLARITY 0x00000002
|
|
+#define AR5K_EEPROM_RFKILL_POLARITY_S 1
|
|
+
|
|
+/* Newer EEPROMs are using a different offset */
|
|
+#define AR5K_EEPROM_OFF(_v, _v3_0, _v3_3) \
|
|
+ (((_v) >= AR5K_EEPROM_VERSION_3_3) ? _v3_3 : _v3_0)
|
|
+
|
|
+#define AR5K_EEPROM_ANT_GAIN(_v) AR5K_EEPROM_OFF(_v, 0x00c4, 0x00c3)
|
|
+#define AR5K_EEPROM_ANT_GAIN_5GHZ(_v) ((int8_t)(((_v) >> 8) & 0xff))
|
|
+#define AR5K_EEPROM_ANT_GAIN_2GHZ(_v) ((int8_t)((_v) & 0xff))
|
|
+
|
|
+/* calibration settings */
|
|
+#define AR5K_EEPROM_MODES_11A(_v) AR5K_EEPROM_OFF(_v, 0x00c5, 0x00d4)
|
|
+#define AR5K_EEPROM_MODES_11B(_v) AR5K_EEPROM_OFF(_v, 0x00d0, 0x00f2)
|
|
+#define AR5K_EEPROM_MODES_11G(_v) AR5K_EEPROM_OFF(_v, 0x00da, 0x010d)
|
|
+#define AR5K_EEPROM_CTL(_v) AR5K_EEPROM_OFF(_v, 0x00e4, 0x0128) /* Conformance test limits */
|
|
+
|
|
+/* [3.1 - 3.3] */
|
|
+#define AR5K_EEPROM_OBDB0_2GHZ 0x00ec
|
|
+#define AR5K_EEPROM_OBDB1_2GHZ 0x00ed
|
|
+
|
|
+/* Misc values available since EEPROM 4.0 */
|
|
+#define AR5K_EEPROM_MISC0 0x00c4
|
|
+#define AR5K_EEPROM_EARSTART(_v) ((_v) & 0xfff)
|
|
+#define AR5K_EEPROM_EEMAP(_v) (((_v) >> 14) & 0x3)
|
|
+#define AR5K_EEPROM_MISC1 0x00c5
|
|
+#define AR5K_EEPROM_TARGET_PWRSTART(_v) ((_v) & 0xfff)
|
|
+#define AR5K_EEPROM_HAS32KHZCRYSTAL(_v) (((_v) >> 14) & 0x1)
|
|
+
|
|
+/*
|
|
+ * EEPROM data register
|
|
+ */
|
|
+#define AR5K_EEPROM_DATA_5211 0x6004
|
|
+#define AR5K_EEPROM_DATA_5210 0x6800
|
|
+#define AR5K_EEPROM_DATA (ah->ah_version == AR5K_AR5210 ? \
|
|
+ AR5K_EEPROM_DATA_5210 : AR5K_EEPROM_DATA_5211)
|
|
+
|
|
+/*
|
|
+ * EEPROM command register
|
|
+ */
|
|
+#define AR5K_EEPROM_CMD 0x6008 /* Register Addres */
|
|
+#define AR5K_EEPROM_CMD_READ 0x00000001 /* EEPROM read */
|
|
+#define AR5K_EEPROM_CMD_WRITE 0x00000002 /* EEPROM write */
|
|
+#define AR5K_EEPROM_CMD_RESET 0x00000004 /* EEPROM reset */
|
|
+
|
|
+/*
|
|
+ * EEPROM status register
|
|
+ */
|
|
+#define AR5K_EEPROM_STAT_5210 0x6c00 /* Register Address [5210] */
|
|
+#define AR5K_EEPROM_STAT_5211 0x600c /* Register Address [5211+] */
|
|
+#define AR5K_EEPROM_STATUS (ah->ah_version == AR5K_AR5210 ? \
|
|
+ AR5K_EEPROM_STAT_5210 : AR5K_EEPROM_STAT_5211)
|
|
+#define AR5K_EEPROM_STAT_RDERR 0x00000001 /* EEPROM read failed */
|
|
+#define AR5K_EEPROM_STAT_RDDONE 0x00000002 /* EEPROM read successful */
|
|
+#define AR5K_EEPROM_STAT_WRERR 0x00000004 /* EEPROM write failed */
|
|
+#define AR5K_EEPROM_STAT_WRDONE 0x00000008 /* EEPROM write successful */
|
|
+
|
|
+/*
|
|
+ * EEPROM config register (?)
|
|
+ */
|
|
+#define AR5K_EEPROM_CFG 0x6010
|
|
+
|
|
+
|
|
+
|
|
+/*
|
|
+ * Protocol Control Unit (PCU) registers
|
|
+ */
|
|
+/*
|
|
+ * Used for checking initial register writes
|
|
+ * during channel reset (see reset func)
|
|
+ */
|
|
+#define AR5K_PCU_MIN 0x8000
|
|
+#define AR5K_PCU_MAX 0x8fff
|
|
+
|
|
+/*
|
|
+ * First station id register (MAC address in lower 32 bits)
|
|
+ */
|
|
+#define AR5K_STA_ID0 0x8000
|
|
+
|
|
+/*
|
|
+ * Second station id register (MAC address in upper 16 bits)
|
|
+ */
|
|
+#define AR5K_STA_ID1 0x8004 /* Register Address */
|
|
+#define AR5K_STA_ID1_AP 0x00010000 /* Set AP mode */
|
|
+#define AR5K_STA_ID1_ADHOC 0x00020000 /* Set Ad-Hoc mode */
|
|
+#define AR5K_STA_ID1_PWR_SV 0x00040000 /* Power save reporting (?) */
|
|
+#define AR5K_STA_ID1_NO_KEYSRCH 0x00080000 /* No key search */
|
|
+#define AR5K_STA_ID1_NO_PSPOLL 0x00100000 /* No power save polling [5210] */
|
|
+#define AR5K_STA_ID1_PCF_5211 0x00100000 /* Enable PCF on [5211+] */
|
|
+#define AR5K_STA_ID1_PCF_5210 0x00200000 /* Enable PCF on [5210]*/
|
|
+#define AR5K_STA_ID1_PCF (ah->ah_version == AR5K_AR5210 ? \
|
|
+ AR5K_STA_ID1_PCF_5210 : AR5K_STA_ID1_PCF_5211)
|
|
+#define AR5K_STA_ID1_DEFAULT_ANTENNA 0x00200000 /* Use default antenna */
|
|
+#define AR5K_STA_ID1_DESC_ANTENNA 0x00400000 /* Update antenna from descriptor */
|
|
+#define AR5K_STA_ID1_RTS_DEF_ANTENNA 0x00800000 /* Use default antenna for RTS (?) */
|
|
+#define AR5K_STA_ID1_ACKCTS_6MB 0x01000000 /* Use 6Mbit/s for ACK/CTS (?) */
|
|
+#define AR5K_STA_ID1_BASE_RATE_11B 0x02000000 /* Use 11b base rate (for ACK/CTS ?) [5211+] */
|
|
+
|
|
+/*
|
|
+ * First BSSID register (MAC address, lower 32bits)
|
|
+ */
|
|
+#define AR5K_BSS_ID0 0x8008
|
|
+
|
|
+/*
|
|
+ * Second BSSID register (MAC address in upper 16 bits)
|
|
+ *
|
|
+ * AID: Association ID
|
|
+ */
|
|
+#define AR5K_BSS_ID1 0x800c
|
|
+#define AR5K_BSS_ID1_AID 0xffff0000
|
|
+#define AR5K_BSS_ID1_AID_S 16
|
|
+
|
|
+/*
|
|
+ * Backoff slot time register
|
|
+ */
|
|
+#define AR5K_SLOT_TIME 0x8010
|
|
+
|
|
+/*
|
|
+ * ACK/CTS timeout register
|
|
+ */
|
|
+#define AR5K_TIME_OUT 0x8014 /* Register Address */
|
|
+#define AR5K_TIME_OUT_ACK 0x00001fff /* ACK timeout mask */
|
|
+#define AR5K_TIME_OUT_ACK_S 0
|
|
+#define AR5K_TIME_OUT_CTS 0x1fff0000 /* CTS timeout mask */
|
|
+#define AR5K_TIME_OUT_CTS_S 16
|
|
+
|
|
+/*
|
|
+ * RSSI threshold register
|
|
+ */
|
|
+#define AR5K_RSSI_THR 0x8018 /* Register Address */
|
|
+#define AR5K_RSSI_THR_M 0x000000ff /* Mask for RSSI threshold [5211+] */
|
|
+#define AR5K_RSSI_THR_BMISS_5210 0x00000700 /* Mask for Beacon Missed threshold [5210] */
|
|
+#define AR5K_RSSI_THR_BMISS_5210_S 8
|
|
+#define AR5K_RSSI_THR_BMISS_5211 0x0000ff00 /* Mask for Beacon Missed threshold [5211+] */
|
|
+#define AR5K_RSSI_THR_BMISS_5211_S 8
|
|
+#define AR5K_RSSI_THR_BMISS (ah->ah_version == AR5K_AR5210 ? \
|
|
+ AR5K_RSSI_THR_BMISS_5210 : AR5K_RSSI_THR_BMISS_5211)
|
|
+#define AR5K_RSSI_THR_BMISS_S 8
|
|
+
|
|
+/*
|
|
+ * 5210 has more PCU registers because there is no QCU/DCU
|
|
+ * so queue parameters are set here, this way a lot common
|
|
+ * registers have different address for 5210. To make things
|
|
+ * easier we define a macro based on ah->ah_version for common
|
|
+ * registers with different addresses and common flags.
|
|
+ */
|
|
+
|
|
+/*
|
|
+ * Retry limit register
|
|
+ *
|
|
+ * Retry limit register for 5210 (no QCU/DCU so it's done in PCU)
|
|
+ */
|
|
+#define AR5K_NODCU_RETRY_LMT 0x801c /*Register Address */
|
|
+#define AR5K_NODCU_RETRY_LMT_SH_RETRY 0x0000000f /* Short retry limit mask */
|
|
+#define AR5K_NODCU_RETRY_LMT_SH_RETRY_S 0
|
|
+#define AR5K_NODCU_RETRY_LMT_LG_RETRY 0x000000f0 /* Long retry mask */
|
|
+#define AR5K_NODCU_RETRY_LMT_LG_RETRY_S 4
|
|
+#define AR5K_NODCU_RETRY_LMT_SSH_RETRY 0x00003f00 /* Station short retry limit mask */
|
|
+#define AR5K_NODCU_RETRY_LMT_SSH_RETRY_S 8
|
|
+#define AR5K_NODCU_RETRY_LMT_SLG_RETRY 0x000fc000 /* Station long retry limit mask */
|
|
+#define AR5K_NODCU_RETRY_LMT_SLG_RETRY_S 14
|
|
+#define AR5K_NODCU_RETRY_LMT_CW_MIN 0x3ff00000 /* Minimum contention window mask */
|
|
+#define AR5K_NODCU_RETRY_LMT_CW_MIN_S 20
|
|
+
|
|
+/*
|
|
+ * Transmit latency register
|
|
+ */
|
|
+#define AR5K_USEC_5210 0x8020 /* Register Address [5210] */
|
|
+#define AR5K_USEC_5211 0x801c /* Register Address [5211+] */
|
|
+#define AR5K_USEC (ah->ah_version == AR5K_AR5210 ? \
|
|
+ AR5K_USEC_5210 : AR5K_USEC_5211)
|
|
+#define AR5K_USEC_1 0x0000007f
|
|
+#define AR5K_USEC_1_S 0
|
|
+#define AR5K_USEC_32 0x00003f80
|
|
+#define AR5K_USEC_32_S 7
|
|
+#define AR5K_USEC_TX_LATENCY_5211 0x007fc000
|
|
+#define AR5K_USEC_TX_LATENCY_5211_S 14
|
|
+#define AR5K_USEC_RX_LATENCY_5211 0x1f800000
|
|
+#define AR5K_USEC_RX_LATENCY_5211_S 23
|
|
+#define AR5K_USEC_TX_LATENCY_5210 0x000fc000 /* also for 5311 */
|
|
+#define AR5K_USEC_TX_LATENCY_5210_S 14
|
|
+#define AR5K_USEC_RX_LATENCY_5210 0x03f00000 /* also for 5311 */
|
|
+#define AR5K_USEC_RX_LATENCY_5210_S 20
|
|
+
|
|
+/*
|
|
+ * PCU beacon control register
|
|
+ */
|
|
+#define AR5K_BEACON_5210 0x8024
|
|
+#define AR5K_BEACON_5211 0x8020
|
|
+#define AR5K_BEACON (ah->ah_version == AR5K_AR5210 ? \
|
|
+ AR5K_BEACON_5210 : AR5K_BEACON_5211)
|
|
+#define AR5K_BEACON_PERIOD 0x0000ffff
|
|
+#define AR5K_BEACON_PERIOD_S 0
|
|
+#define AR5K_BEACON_TIM 0x007f0000
|
|
+#define AR5K_BEACON_TIM_S 16
|
|
+#define AR5K_BEACON_ENABLE 0x00800000
|
|
+#define AR5K_BEACON_RESET_TSF 0x01000000
|
|
+
|
|
+/*
|
|
+ * CFP period register
|
|
+ */
|
|
+#define AR5K_CFP_PERIOD_5210 0x8028
|
|
+#define AR5K_CFP_PERIOD_5211 0x8024
|
|
+#define AR5K_CFP_PERIOD (ah->ah_version == AR5K_AR5210 ? \
|
|
+ AR5K_CFP_PERIOD_5210 : AR5K_CFP_PERIOD_5211)
|
|
+
|
|
+/*
|
|
+ * Next beacon time register
|
|
+ */
|
|
+#define AR5K_TIMER0_5210 0x802c
|
|
+#define AR5K_TIMER0_5211 0x8028
|
|
+#define AR5K_TIMER0 (ah->ah_version == AR5K_AR5210 ? \
|
|
+ AR5K_TIMER0_5210 : AR5K_TIMER0_5211)
|
|
+
|
|
+/*
|
|
+ * Next DMA beacon alert register
|
|
+ */
|
|
+#define AR5K_TIMER1_5210 0x8030
|
|
+#define AR5K_TIMER1_5211 0x802c
|
|
+#define AR5K_TIMER1 (ah->ah_version == AR5K_AR5210 ? \
|
|
+ AR5K_TIMER1_5210 : AR5K_TIMER1_5211)
|
|
+
|
|
+/*
|
|
+ * Next software beacon alert register
|
|
+ */
|
|
+#define AR5K_TIMER2_5210 0x8034
|
|
+#define AR5K_TIMER2_5211 0x8030
|
|
+#define AR5K_TIMER2 (ah->ah_version == AR5K_AR5210 ? \
|
|
+ AR5K_TIMER2_5210 : AR5K_TIMER2_5211)
|
|
+
|
|
+/*
|
|
+ * Next ATIM window time register
|
|
+ */
|
|
+#define AR5K_TIMER3_5210 0x8038
|
|
+#define AR5K_TIMER3_5211 0x8034
|
|
+#define AR5K_TIMER3 (ah->ah_version == AR5K_AR5210 ? \
|
|
+ AR5K_TIMER3_5210 : AR5K_TIMER3_5211)
|
|
+
|
|
+
|
|
+/*
|
|
+ * 5210 First inter frame spacing register (IFS)
|
|
+ */
|
|
+#define AR5K_IFS0 0x8040
|
|
+#define AR5K_IFS0_SIFS 0x000007ff
|
|
+#define AR5K_IFS0_SIFS_S 0
|
|
+#define AR5K_IFS0_DIFS 0x007ff800
|
|
+#define AR5K_IFS0_DIFS_S 11
|
|
+
|
|
+/*
|
|
+ * 5210 Second inter frame spacing register (IFS)
|
|
+ */
|
|
+#define AR5K_IFS1 0x8044
|
|
+#define AR5K_IFS1_PIFS 0x00000fff
|
|
+#define AR5K_IFS1_PIFS_S 0
|
|
+#define AR5K_IFS1_EIFS 0x03fff000
|
|
+#define AR5K_IFS1_EIFS_S 12
|
|
+#define AR5K_IFS1_CS_EN 0x04000000
|
|
+
|
|
+
|
|
+/*
|
|
+ * CFP duration register
|
|
+ */
|
|
+#define AR5K_CFP_DUR_5210 0x8048
|
|
+#define AR5K_CFP_DUR_5211 0x8038
|
|
+#define AR5K_CFP_DUR (ah->ah_version == AR5K_AR5210 ? \
|
|
+ AR5K_CFP_DUR_5210 : AR5K_CFP_DUR_5211)
|
|
+
|
|
+/*
|
|
+ * Receive filter register
|
|
+ * TODO: Get these out of ar5xxx.h on ath5k
|
|
+ */
|
|
+#define AR5K_RX_FILTER_5210 0x804c /* Register Address [5210] */
|
|
+#define AR5K_RX_FILTER_5211 0x803c /* Register Address [5211+] */
|
|
+#define AR5K_RX_FILTER (ah->ah_version == AR5K_AR5210 ? \
|
|
+ AR5K_RX_FILTER_5210 : AR5K_RX_FILTER_5211)
|
|
+#define AR5K_RX_FILTER_UCAST 0x00000001 /* Don't filter unicast frames */
|
|
+#define AR5K_RX_FILTER_MCAST 0x00000002 /* Don't filter multicast frames */
|
|
+#define AR5K_RX_FILTER_BCAST 0x00000004 /* Don't filter broadcast frames */
|
|
+#define AR5K_RX_FILTER_CONTROL 0x00000008 /* Don't filter control frames */
|
|
+#define AR5K_RX_FILTER_BEACON 0x00000010 /* Don't filter beacon frames */
|
|
+#define AR5K_RX_FILTER_PROM 0x00000020 /* Set promiscuous mode */
|
|
+#define AR5K_RX_FILTER_XRPOLL 0x00000040 /* Don't filter XR poll frame [5212+] */
|
|
+#define AR5K_RX_FILTER_PROBEREQ 0x00000080 /* Don't filter probe requests [5212+] */
|
|
+#define AR5K_RX_FILTER_PHYERR_5212 0x00000100 /* Don't filter phy errors [5212+] */
|
|
+#define AR5K_RX_FILTER_RADARERR_5212 0x00000200 /* Don't filter phy radar errors [5212+] */
|
|
+#define AR5K_RX_FILTER_PHYERR_5211 0x00000040 /* [5211] */
|
|
+#define AR5K_RX_FILTER_RADARERR_5211 0x00000080 /* [5211] */
|
|
+#define AR5K_RX_FILTER_PHYERR \
|
|
+ ((ah->ah_version == AR5K_AR5211 ? \
|
|
+ AR5K_RX_FILTER_PHYERR_5211 : AR5K_RX_FILTER_PHYERR_5212))
|
|
+#define AR5K_RX_FILTER_RADARERR \
|
|
+ ((ah->ah_version == AR5K_AR5211 ? \
|
|
+ AR5K_RX_FILTER_RADARERR_5211 : AR5K_RX_FILTER_RADARERR_5212))
|
|
+
|
|
+/*
|
|
+ * Multicast filter register (lower 32 bits)
|
|
+ */
|
|
+#define AR5K_MCAST_FILTER0_5210 0x8050
|
|
+#define AR5K_MCAST_FILTER0_5211 0x8040
|
|
+#define AR5K_MCAST_FILTER0 (ah->ah_version == AR5K_AR5210 ? \
|
|
+ AR5K_MCAST_FILTER0_5210 : AR5K_MCAST_FILTER0_5211)
|
|
+
|
|
+/*
|
|
+ * Multicast filter register (higher 16 bits)
|
|
+ */
|
|
+#define AR5K_MCAST_FILTER1_5210 0x8054
|
|
+#define AR5K_MCAST_FILTER1_5211 0x8044
|
|
+#define AR5K_MCAST_FILTER1 (ah->ah_version == AR5K_AR5210 ? \
|
|
+ AR5K_MCAST_FILTER1_5210 : AR5K_MCAST_FILTER1_5211)
|
|
+
|
|
+
|
|
+/*
|
|
+ * Transmit mask register (lower 32 bits) [5210]
|
|
+ */
|
|
+#define AR5K_TX_MASK0 0x8058
|
|
+
|
|
+/*
|
|
+ * Transmit mask register (higher 16 bits) [5210]
|
|
+ */
|
|
+#define AR5K_TX_MASK1 0x805c
|
|
+
|
|
+/*
|
|
+ * Clear transmit mask [5210]
|
|
+ */
|
|
+#define AR5K_CLR_TMASK 0x8060
|
|
+
|
|
+/*
|
|
+ * Trigger level register (before transmission) [5210]
|
|
+ */
|
|
+#define AR5K_TRIG_LVL 0x8064
|
|
+
|
|
+
|
|
+/*
|
|
+ * PCU control register
|
|
+ *
|
|
+ * Only DIS_RX is used in the code, the rest i guess are
|
|
+ * for tweaking/diagnostics.
|
|
+ */
|
|
+#define AR5K_DIAG_SW_5210 0x8068 /* Register Address [5210] */
|
|
+#define AR5K_DIAG_SW_5211 0x8048 /* Register Address [5211+] */
|
|
+#define AR5K_DIAG_SW (ah->ah_version == AR5K_AR5210 ? \
|
|
+ AR5K_DIAG_SW_5210 : AR5K_DIAG_SW_5211)
|
|
+#define AR5K_DIAG_SW_DIS_WEP_ACK 0x00000001
|
|
+#define AR5K_DIAG_SW_DIS_ACK 0x00000002 /* Disable ACKs (?) */
|
|
+#define AR5K_DIAG_SW_DIS_CTS 0x00000004 /* Disable CTSs (?) */
|
|
+#define AR5K_DIAG_SW_DIS_ENC 0x00000008 /* Disable encryption (?) */
|
|
+#define AR5K_DIAG_SW_DIS_DEC 0x00000010 /* Disable decryption (?) */
|
|
+#define AR5K_DIAG_SW_DIS_TX 0x00000020 /* Disable transmit [5210] */
|
|
+#define AR5K_DIAG_SW_DIS_RX_5210 0x00000040 /* Disable recieve */
|
|
+#define AR5K_DIAG_SW_DIS_RX_5211 0x00000020
|
|
+#define AR5K_DIAG_SW_DIS_RX (ah->ah_version == AR5K_AR5210 ? \
|
|
+ AR5K_DIAG_SW_DIS_RX_5210 : AR5K_DIAG_SW_DIS_RX_5211)
|
|
+#define AR5K_DIAG_SW_LOOP_BACK_5210 0x00000080 /* Loopback (i guess it goes with DIS_TX) [5210] */
|
|
+#define AR5K_DIAG_SW_LOOP_BACK_5211 0x00000040
|
|
+#define AR5K_DIAG_SW_LOOP_BACK (ah->ah_version == AR5K_AR5210 ? \
|
|
+ AR5K_DIAG_SW_LOOP_BACK_5210 : AR5K_DIAG_SW_LOOP_BACK_5211)
|
|
+#define AR5K_DIAG_SW_CORR_FCS_5210 0x00000100
|
|
+#define AR5K_DIAG_SW_CORR_FCS_5211 0x00000080
|
|
+#define AR5K_DIAG_SW_CORR_FCS (ah->ah_version == AR5K_AR5210 ? \
|
|
+ AR5K_DIAG_SW_CORR_FCS_5210 : AR5K_DIAG_SW_CORR_FCS_5211)
|
|
+#define AR5K_DIAG_SW_CHAN_INFO_5210 0x00000200
|
|
+#define AR5K_DIAG_SW_CHAN_INFO_5211 0x00000100
|
|
+#define AR5K_DIAG_SW_CHAN_INFO (ah->ah_version == AR5K_AR5210 ? \
|
|
+ AR5K_DIAG_SW_CHAN_INFO_5210 : AR5K_DIAG_SW_CHAN_INFO_5211)
|
|
+#define AR5K_DIAG_SW_EN_SCRAM_SEED_5211 0x00000200 /* Scrambler seed (?) */
|
|
+#define AR5K_DIAG_SW_EN_SCRAM_SEED_5210 0x00000400
|
|
+#define AR5K_DIAG_SW_EN_SCRAM_SEED (ah->ah_version == AR5K_AR5210 ? \
|
|
+ AR5K_DIAG_SW_EN_SCRAM_SEED_5210 : AR5K_DIAG_SW_EN_SCRAM_SEED_5211)
|
|
+#define AR5K_DIAG_SW_ECO_ENABLE 0x00000400 /* [5211+] */
|
|
+#define AR5K_DIAG_SW_SCVRAM_SEED 0x0003f800 /* [5210] */
|
|
+#define AR5K_DIAG_SW_SCRAM_SEED_M 0x0001fc00 /* Scrambler seed mask (?) */
|
|
+#define AR5K_DIAG_SW_SCRAM_SEED_S 10
|
|
+#define AR5K_DIAG_SW_DIS_SEQ_INC 0x00040000 /* Disable seqnum increment (?)[5210] */
|
|
+#define AR5K_DIAG_SW_FRAME_NV0_5210 0x00080000
|
|
+#define AR5K_DIAG_SW_FRAME_NV0_5211 0x00020000
|
|
+#define AR5K_DIAG_SW_FRAME_NV0 (ah->ah_version == AR5K_AR5210 ? \
|
|
+ AR5K_DIAG_SW_FRAME_NV0_5210 : AR5K_DIAG_SW_FRAME_NV0_5211)
|
|
+#define AR5K_DIAG_SW_OBSPT_M 0x000c0000
|
|
+#define AR5K_DIAG_SW_OBSPT_S 18
|
|
+
|
|
+/*
|
|
+ * TSF (clock) register (lower 32 bits)
|
|
+ */
|
|
+#define AR5K_TSF_L32_5210 0x806c
|
|
+#define AR5K_TSF_L32_5211 0x804c
|
|
+#define AR5K_TSF_L32 (ah->ah_version == AR5K_AR5210 ? \
|
|
+ AR5K_TSF_L32_5210 : AR5K_TSF_L32_5211)
|
|
+
|
|
+/*
|
|
+ * TSF (clock) register (higher 32 bits)
|
|
+ */
|
|
+#define AR5K_TSF_U32_5210 0x8070
|
|
+#define AR5K_TSF_U32_5211 0x8050
|
|
+#define AR5K_TSF_U32 (ah->ah_version == AR5K_AR5210 ? \
|
|
+ AR5K_TSF_U32_5210 : AR5K_TSF_U32_5211)
|
|
+
|
|
+/*
|
|
+ * Last beacon timestamp register
|
|
+ */
|
|
+#define AR5K_LAST_TSTP 0x8080
|
|
+
|
|
+/*
|
|
+ * ADDAC test register [5211+]
|
|
+ */
|
|
+#define AR5K_ADDAC_TEST 0x8054
|
|
+#define AR5K_ADDAC_TEST_TXCONT 0x00000001
|
|
+
|
|
+/*
|
|
+ * Default antenna register [5211+]
|
|
+ */
|
|
+#define AR5K_DEFAULT_ANTENNA 0x8058
|
|
+
|
|
+
|
|
+
|
|
+/*
|
|
+ * Retry count register [5210]
|
|
+ */
|
|
+#define AR5K_RETRY_CNT 0x8084 /* Register Address [5210] */
|
|
+#define AR5K_RETRY_CNT_SSH 0x0000003f /* Station short retry count (?) */
|
|
+#define AR5K_RETRY_CNT_SLG 0x00000fc0 /* Station long retry count (?) */
|
|
+
|
|
+/*
|
|
+ * Back-off status register [5210]
|
|
+ */
|
|
+#define AR5K_BACKOFF 0x8088 /* Register Address [5210] */
|
|
+#define AR5K_BACKOFF_CW 0x000003ff /* Backoff Contention Window (?) */
|
|
+#define AR5K_BACKOFF_CNT 0x03ff0000 /* Backoff count (?) */
|
|
+
|
|
+
|
|
+
|
|
+/*
|
|
+ * NAV register (current)
|
|
+ */
|
|
+#define AR5K_NAV_5210 0x808c
|
|
+#define AR5K_NAV_5211 0x8084
|
|
+#define AR5K_NAV (ah->ah_version == AR5K_AR5210 ? \
|
|
+ AR5K_NAV_5210 : AR5K_NAV_5211)
|
|
+
|
|
+/*
|
|
+ * RTS success register
|
|
+ */
|
|
+#define AR5K_RTS_OK_5210 0x8090
|
|
+#define AR5K_RTS_OK_5211 0x8088
|
|
+#define AR5K_RTS_OK (ah->ah_version == AR5K_AR5210 ? \
|
|
+ AR5K_RTS_OK_5210 : AR5K_RTS_OK_5211)
|
|
+
|
|
+/*
|
|
+ * RTS failure register
|
|
+ */
|
|
+#define AR5K_RTS_FAIL_5210 0x8094
|
|
+#define AR5K_RTS_FAIL_5211 0x808c
|
|
+#define AR5K_RTS_FAIL (ah->ah_version == AR5K_AR5210 ? \
|
|
+ AR5K_RTS_FAIL_5210 : AR5K_RTS_FAIL_5211)
|
|
+
|
|
+/*
|
|
+ * ACK failure register
|
|
+ */
|
|
+#define AR5K_ACK_FAIL_5210 0x8098
|
|
+#define AR5K_ACK_FAIL_5211 0x8090
|
|
+#define AR5K_ACK_FAIL (ah->ah_version == AR5K_AR5210 ? \
|
|
+ AR5K_ACK_FAIL_5210 : AR5K_ACK_FAIL_5211)
|
|
+
|
|
+/*
|
|
+ * FCS failure register
|
|
+ */
|
|
+#define AR5K_FCS_FAIL_5210 0x809c
|
|
+#define AR5K_FCS_FAIL_5211 0x8094
|
|
+#define AR5K_FCS_FAIL (ah->ah_version == AR5K_AR5210 ? \
|
|
+ AR5K_FCS_FAIL_5210 : AR5K_FCS_FAIL_5211)
|
|
+
|
|
+/*
|
|
+ * Beacon count register
|
|
+ */
|
|
+#define AR5K_BEACON_CNT_5210 0x80a0
|
|
+#define AR5K_BEACON_CNT_5211 0x8098
|
|
+#define AR5K_BEACON_CNT (ah->ah_version == AR5K_AR5210 ? \
|
|
+ AR5K_BEACON_CNT_5210 : AR5K_BEACON_CNT_5211)
|
|
+
|
|
+
|
|
+/*===5212 Specific PCU registers===*/
|
|
+
|
|
+/*
|
|
+ * XR (eXtended Range) mode register
|
|
+ */
|
|
+#define AR5K_XRMODE 0x80c0
|
|
+#define AR5K_XRMODE_POLL_TYPE_M 0x0000003f
|
|
+#define AR5K_XRMODE_POLL_TYPE_S 0
|
|
+#define AR5K_XRMODE_POLL_SUBTYPE_M 0x0000003c
|
|
+#define AR5K_XRMODE_POLL_SUBTYPE_S 2
|
|
+#define AR5K_XRMODE_POLL_WAIT_ALL 0x00000080
|
|
+#define AR5K_XRMODE_SIFS_DELAY 0x000fff00
|
|
+#define AR5K_XRMODE_FRAME_HOLD_M 0xfff00000
|
|
+#define AR5K_XRMODE_FRAME_HOLD_S 20
|
|
+
|
|
+/*
|
|
+ * XR delay register
|
|
+ */
|
|
+#define AR5K_XRDELAY 0x80c4
|
|
+#define AR5K_XRDELAY_SLOT_DELAY_M 0x0000ffff
|
|
+#define AR5K_XRDELAY_SLOT_DELAY_S 0
|
|
+#define AR5K_XRDELAY_CHIRP_DELAY_M 0xffff0000
|
|
+#define AR5K_XRDELAY_CHIRP_DELAY_S 16
|
|
+
|
|
+/*
|
|
+ * XR timeout register
|
|
+ */
|
|
+#define AR5K_XRTIMEOUT 0x80c8
|
|
+#define AR5K_XRTIMEOUT_CHIRP_M 0x0000ffff
|
|
+#define AR5K_XRTIMEOUT_CHIRP_S 0
|
|
+#define AR5K_XRTIMEOUT_POLL_M 0xffff0000
|
|
+#define AR5K_XRTIMEOUT_POLL_S 16
|
|
+
|
|
+/*
|
|
+ * XR chirp register
|
|
+ */
|
|
+#define AR5K_XRCHIRP 0x80cc
|
|
+#define AR5K_XRCHIRP_SEND 0x00000001
|
|
+#define AR5K_XRCHIRP_GAP 0xffff0000
|
|
+
|
|
+/*
|
|
+ * XR stomp register
|
|
+ */
|
|
+#define AR5K_XRSTOMP 0x80d0
|
|
+#define AR5K_XRSTOMP_TX 0x00000001
|
|
+#define AR5K_XRSTOMP_RX_ABORT 0x00000002
|
|
+#define AR5K_XRSTOMP_RSSI_THRES 0x0000ff00
|
|
+
|
|
+/*
|
|
+ * First enhanced sleep register
|
|
+ */
|
|
+#define AR5K_SLEEP0 0x80d4
|
|
+#define AR5K_SLEEP0_NEXT_DTIM 0x0007ffff
|
|
+#define AR5K_SLEEP0_NEXT_DTIM_S 0
|
|
+#define AR5K_SLEEP0_ASSUME_DTIM 0x00080000
|
|
+#define AR5K_SLEEP0_ENH_SLEEP_EN 0x00100000
|
|
+#define AR5K_SLEEP0_CABTO 0xff000000
|
|
+#define AR5K_SLEEP0_CABTO_S 24
|
|
+
|
|
+/*
|
|
+ * Second enhanced sleep register
|
|
+ */
|
|
+#define AR5K_SLEEP1 0x80d8
|
|
+#define AR5K_SLEEP1_NEXT_TIM 0x0007ffff
|
|
+#define AR5K_SLEEP1_NEXT_TIM_S 0
|
|
+#define AR5K_SLEEP1_BEACON_TO 0xff000000
|
|
+#define AR5K_SLEEP1_BEACON_TO_S 24
|
|
+
|
|
+/*
|
|
+ * Third enhanced sleep register
|
|
+ */
|
|
+#define AR5K_SLEEP2 0x80dc
|
|
+#define AR5K_SLEEP2_TIM_PER 0x0000ffff
|
|
+#define AR5K_SLEEP2_TIM_PER_S 0
|
|
+#define AR5K_SLEEP2_DTIM_PER 0xffff0000
|
|
+#define AR5K_SLEEP2_DTIM_PER_S 16
|
|
+
|
|
+/*
|
|
+ * BSSID mask registers
|
|
+ */
|
|
+#define AR5K_BSS_IDM0 0x80e0
|
|
+#define AR5K_BSS_IDM1 0x80e4
|
|
+
|
|
+/*
|
|
+ * TX power control (TPC) register
|
|
+ */
|
|
+#define AR5K_TXPC 0x80e8
|
|
+#define AR5K_TXPC_ACK_M 0x0000003f
|
|
+#define AR5K_TXPC_ACK_S 0
|
|
+#define AR5K_TXPC_CTS_M 0x00003f00
|
|
+#define AR5K_TXPC_CTS_S 8
|
|
+#define AR5K_TXPC_CHIRP_M 0x003f0000
|
|
+#define AR5K_TXPC_CHIRP_S 22
|
|
+
|
|
+/*
|
|
+ * Profile count registers
|
|
+ */
|
|
+#define AR5K_PROFCNT_TX 0x80ec
|
|
+#define AR5K_PROFCNT_RX 0x80f0
|
|
+#define AR5K_PROFCNT_RXCLR 0x80f4
|
|
+#define AR5K_PROFCNT_CYCLE 0x80f8
|
|
+
|
|
+/*
|
|
+ * TSF parameter register
|
|
+ */
|
|
+#define AR5K_TSF_PARM 0x8104
|
|
+#define AR5K_TSF_PARM_INC_M 0x000000ff
|
|
+#define AR5K_TSF_PARM_INC_S 0
|
|
+
|
|
+/*
|
|
+ * PHY error filter register
|
|
+ */
|
|
+#define AR5K_PHY_ERR_FIL 0x810c
|
|
+#define AR5K_PHY_ERR_FIL_RADAR 0x00000020
|
|
+#define AR5K_PHY_ERR_FIL_OFDM 0x00020000
|
|
+#define AR5K_PHY_ERR_FIL_CCK 0x02000000
|
|
+
|
|
+/*
|
|
+ * Rate duration register
|
|
+ */
|
|
+#define AR5K_RATE_DUR_BASE 0x8700
|
|
+#define AR5K_RATE_DUR(_n) (AR5K_RATE_DUR_BASE + ((_n) << 2))
|
|
+
|
|
+/*===5212 end===*/
|
|
+
|
|
+/*
|
|
+ * Key table (WEP) register
|
|
+ */
|
|
+#define AR5K_KEYTABLE_0_5210 0x9000
|
|
+#define AR5K_KEYTABLE_0_5211 0x8800
|
|
+#define AR5K_KEYTABLE_5210(_n) (AR5K_KEYTABLE_0_5210 + ((_n) << 5))
|
|
+#define AR5K_KEYTABLE_5211(_n) (AR5K_KEYTABLE_0_5211 + ((_n) << 5))
|
|
+#define AR5K_KEYTABLE(_n) (ah->ah_version == AR5K_AR5210 ? \
|
|
+ AR5K_KEYTABLE_5210(_n) : AR5K_KEYTABLE_5211(_n))
|
|
+#define AR5K_KEYTABLE_OFF(_n, x) (AR5K_KEYTABLE(_n) + (x << 2))
|
|
+#define AR5K_KEYTABLE_TYPE(_n) AR5K_KEYTABLE_OFF(_n, 5)
|
|
+#define AR5K_KEYTABLE_TYPE_40 0x00000000
|
|
+#define AR5K_KEYTABLE_TYPE_104 0x00000001
|
|
+#define AR5K_KEYTABLE_TYPE_128 0x00000003
|
|
+#define AR5K_KEYTABLE_TYPE_TKIP 0x00000004 /* [5212+] */
|
|
+#define AR5K_KEYTABLE_TYPE_AES 0x00000005 /* [5211+] */
|
|
+#define AR5K_KEYTABLE_TYPE_CCM 0x00000006 /* [5212+] */
|
|
+#define AR5K_KEYTABLE_TYPE_NULL 0x00000007 /* [5211+] */
|
|
+#define AR5K_KEYTABLE_ANTENNA 0x00000008 /* [5212+] */
|
|
+#define AR5K_KEYTABLE_MAC0(_n) AR5K_KEYTABLE_OFF(_n, 6)
|
|
+#define AR5K_KEYTABLE_MAC1(_n) AR5K_KEYTABLE_OFF(_n, 7)
|
|
+#define AR5K_KEYTABLE_VALID 0x00008000
|
|
+
|
|
+/* WEP 40-bit = 40-bit entered key + 24 bit IV = 64-bit
|
|
+ * WEP 104-bit = 104-bit entered key + 24-bit IV = 128-bit
|
|
+ * WEP 128-bit = 128-bit entered key + 24 bit IV = 152-bit
|
|
+ *
|
|
+ * Some vendors have introduced bigger WEP keys to address
|
|
+ * security vulnerabilities in WEP. This includes:
|
|
+ *
|
|
+ * WEP 232-bit = 232-bit entered key + 24 bit IV = 256-bit
|
|
+ *
|
|
+ * We can expand this if we find ar5k Atheros cards with a larger
|
|
+ * key table size.
|
|
+ */
|
|
+#define AR5K_KEYTABLE_SIZE_5210 64
|
|
+#define AR5K_KEYTABLE_SIZE_5211 128
|
|
+#define AR5K_KEYTABLE_SIZE (ah->ah_version == AR5K_AR5210 ? \
|
|
+ AR5K_KEYTABLE_SIZE_5210 : AR5K_KEYTABLE_SIZE_5211)
|
|
+
|
|
+
|
|
+/*===PHY REGISTERS===*/
|
|
+
|
|
+/*
|
|
+ * PHY register
|
|
+ */
|
|
+#define AR5K_PHY_BASE 0x9800
|
|
+#define AR5K_PHY(_n) (AR5K_PHY_BASE + ((_n) << 2))
|
|
+#define AR5K_PHY_SHIFT_2GHZ 0x00004007
|
|
+#define AR5K_PHY_SHIFT_5GHZ 0x00000007
|
|
+
|
|
+/*
|
|
+ * PHY frame control register [5110] /turbo mode register [5111+]
|
|
+ *
|
|
+ * There is another frame control register for [5111+]
|
|
+ * at address 0x9944 (see below) but the 2 first flags
|
|
+ * are common here between 5110 frame control register
|
|
+ * and [5111+] turbo mode register, so this also works as
|
|
+ * a "turbo mode register" for 5110. We treat this one as
|
|
+ * a frame control register for 5110 below.
|
|
+ */
|
|
+#define AR5K_PHY_TURBO 0x9804
|
|
+#define AR5K_PHY_TURBO_MODE 0x00000001
|
|
+#define AR5K_PHY_TURBO_SHORT 0x00000002
|
|
+
|
|
+/*
|
|
+ * PHY agility command register
|
|
+ */
|
|
+#define AR5K_PHY_AGC 0x9808
|
|
+#define AR5K_PHY_AGC_DISABLE 0x08000000
|
|
+
|
|
+/*
|
|
+ * PHY timing register [5112+]
|
|
+ */
|
|
+#define AR5K_PHY_TIMING_3 0x9814
|
|
+#define AR5K_PHY_TIMING_3_DSC_MAN 0xfffe0000
|
|
+#define AR5K_PHY_TIMING_3_DSC_MAN_S 17
|
|
+#define AR5K_PHY_TIMING_3_DSC_EXP 0x0001e000
|
|
+#define AR5K_PHY_TIMING_3_DSC_EXP_S 13
|
|
+
|
|
+/*
|
|
+ * PHY chip revision register
|
|
+ */
|
|
+#define AR5K_PHY_CHIP_ID 0x9818
|
|
+
|
|
+/*
|
|
+ * PHY activation register
|
|
+ */
|
|
+#define AR5K_PHY_ACT 0x981c
|
|
+#define AR5K_PHY_ACT_ENABLE 0x00000001
|
|
+#define AR5K_PHY_ACT_DISABLE 0x00000002
|
|
+
|
|
+/*
|
|
+ * PHY signal register
|
|
+ */
|
|
+#define AR5K_PHY_SIG 0x9858
|
|
+#define AR5K_PHY_SIG_FIRSTEP 0x0003f000
|
|
+#define AR5K_PHY_SIG_FIRSTEP_S 12
|
|
+#define AR5K_PHY_SIG_FIRPWR 0x03fc0000
|
|
+#define AR5K_PHY_SIG_FIRPWR_S 18
|
|
+
|
|
+/*
|
|
+ * PHY coarse agility control register
|
|
+ */
|
|
+#define AR5K_PHY_AGCCOARSE 0x985c
|
|
+#define AR5K_PHY_AGCCOARSE_LO 0x00007f80
|
|
+#define AR5K_PHY_AGCCOARSE_LO_S 7
|
|
+#define AR5K_PHY_AGCCOARSE_HI 0x003f8000
|
|
+#define AR5K_PHY_AGCCOARSE_HI_S 15
|
|
+
|
|
+/*
|
|
+ * PHY agility control register
|
|
+ */
|
|
+#define AR5K_PHY_AGCCTL 0x9860 /* Register address */
|
|
+#define AR5K_PHY_AGCCTL_CAL 0x00000001 /* Enable PHY calibration */
|
|
+#define AR5K_PHY_AGCCTL_NF 0x00000002 /* Enable Noise Floor calibration */
|
|
+
|
|
+/*
|
|
+ * PHY noise floor status register
|
|
+ */
|
|
+#define AR5K_PHY_NF 0x9864
|
|
+#define AR5K_PHY_NF_M 0x000001ff
|
|
+#define AR5K_PHY_NF_ACTIVE 0x00000100
|
|
+#define AR5K_PHY_NF_RVAL(_n) (((_n) >> 19) & AR5K_PHY_NF_M)
|
|
+#define AR5K_PHY_NF_AVAL(_n) (-((_n) ^ AR5K_PHY_NF_M) + 1)
|
|
+#define AR5K_PHY_NF_SVAL(_n) (((_n) & AR5K_PHY_NF_M) | (1 << 9))
|
|
+
|
|
+/*
|
|
+ * PHY ADC saturation register [5110]
|
|
+ */
|
|
+#define AR5K_PHY_ADCSAT 0x9868
|
|
+#define AR5K_PHY_ADCSAT_ICNT 0x0001f800
|
|
+#define AR5K_PHY_ADCSAT_ICNT_S 11
|
|
+#define AR5K_PHY_ADCSAT_THR 0x000007e0
|
|
+#define AR5K_PHY_ADCSAT_THR_S 5
|
|
+
|
|
+/*
|
|
+ * PHY sleep registers [5112+]
|
|
+ */
|
|
+#define AR5K_PHY_SCR 0x9870
|
|
+#define AR5K_PHY_SCR_32MHZ 0x0000001f
|
|
+#define AR5K_PHY_SLMT 0x9874
|
|
+#define AR5K_PHY_SLMT_32MHZ 0x0000007f
|
|
+#define AR5K_PHY_SCAL 0x9878
|
|
+#define AR5K_PHY_SCAL_32MHZ 0x0000000e
|
|
+
|
|
+/*
|
|
+ * PHY PLL (Phase Locked Loop) control register
|
|
+ */
|
|
+#define AR5K_PHY_PLL 0x987c
|
|
+#define AR5K_PHY_PLL_20MHZ 0x13 /* For half rate (?) [5111+] */
|
|
+#define AR5K_PHY_PLL_40MHZ_5211 0x18 /* For 802.11a */
|
|
+#define AR5K_PHY_PLL_40MHZ_5212 0x000000aa
|
|
+#define AR5K_PHY_PLL_40MHZ (ah->ah_version == AR5K_AR5211 ? \
|
|
+ AR5K_PHY_PLL_40MHZ_5211 : AR5K_PHY_PLL_40MHZ_5212)
|
|
+#define AR5K_PHY_PLL_44MHZ_5211 0x19 /* For 802.11b/g */
|
|
+#define AR5K_PHY_PLL_44MHZ_5212 0x000000ab
|
|
+#define AR5K_PHY_PLL_44MHZ (ah->ah_version == AR5K_AR5211 ? \
|
|
+ AR5K_PHY_PLL_44MHZ_5211 : AR5K_PHY_PLL_44MHZ_5212)
|
|
+#define AR5K_PHY_PLL_RF5111 0x00000000
|
|
+#define AR5K_PHY_PLL_RF5112 0x00000040
|
|
+
|
|
+/*
|
|
+ * RF Buffer register
|
|
+ *
|
|
+ * There are some special control registers on the RF chip
|
|
+ * that hold various operation settings related mostly to
|
|
+ * the analog parts (channel, gain adjustment etc).
|
|
+ *
|
|
+ * We don't write on those registers directly but
|
|
+ * we send a data packet on the buffer register and
|
|
+ * then write on another special register to notify hw
|
|
+ * to apply the settings. This is done so that control registers
|
|
+ * can be dynamicaly programmed during operation and the settings
|
|
+ * are applied faster on the hw.
|
|
+ *
|
|
+ * We sent such data packets during rf initialization and channel change
|
|
+ * through ath5k_hw_rf*_rfregs and ath5k_hw_rf*_channel functions.
|
|
+ *
|
|
+ * The data packets we send during initializadion are inside ath5k_ini_rf
|
|
+ * struct (see ath5k_hw.h) and each one is related to an "rf register bank".
|
|
+ * We use *rfregs functions to modify them acording to current operation
|
|
+ * mode and eeprom values and pass them all together to the chip.
|
|
+ *
|
|
+ * It's obvious from the code that 0x989c is the buffer register but
|
|
+ * for the other special registers that we write to after sending each
|
|
+ * packet, i have no idea. So i'll name them BUFFER_CONTROL_X registers
|
|
+ * for now. It's interesting that they are also used for some other operations.
|
|
+ *
|
|
+ * Also check out hw.h and U.S. Patent 6677779 B1 (about buffer
|
|
+ * registers and control registers):
|
|
+ *
|
|
+ * http://www.google.com/patents?id=qNURAAAAEBAJ
|
|
+ */
|
|
+
|
|
+#define AR5K_RF_BUFFER 0x989c
|
|
+#define AR5K_RF_BUFFER_CONTROL_0 0x98c0 /* Channel on 5110 */
|
|
+#define AR5K_RF_BUFFER_CONTROL_1 0x98c4 /* Bank 7 on 5112 */
|
|
+#define AR5K_RF_BUFFER_CONTROL_2 0x98cc /* Bank 7 on 5111 */
|
|
+
|
|
+#define AR5K_RF_BUFFER_CONTROL_3 0x98d0 /* Bank 2 on 5112 */
|
|
+ /* Channel set on 5111 */
|
|
+ /* Used to read radio revision*/
|
|
+
|
|
+#define AR5K_RF_BUFFER_CONTROL_4 0x98d4 /* RF Stage register on 5110 */
|
|
+ /* Bank 0,1,2,6 on 5111 */
|
|
+ /* Bank 1 on 5112 */
|
|
+ /* Used during activation on 5111 */
|
|
+
|
|
+#define AR5K_RF_BUFFER_CONTROL_5 0x98d8 /* Bank 3 on 5111 */
|
|
+ /* Used during activation on 5111 */
|
|
+ /* Channel on 5112 */
|
|
+ /* Bank 6 on 5112 */
|
|
+
|
|
+#define AR5K_RF_BUFFER_CONTROL_6 0x98dc /* Bank 3 on 5112 */
|
|
+
|
|
+/*
|
|
+ * PHY RF stage register [5210]
|
|
+ */
|
|
+#define AR5K_PHY_RFSTG 0x98d4
|
|
+#define AR5K_PHY_RFSTG_DISABLE 0x00000021
|
|
+
|
|
+/*
|
|
+ * PHY receiver delay register [5111+]
|
|
+ */
|
|
+#define AR5K_PHY_RX_DELAY 0x9914
|
|
+#define AR5K_PHY_RX_DELAY_M 0x00003fff
|
|
+
|
|
+/*
|
|
+ * PHY timing I(nphase) Q(adrature) control register [5111+]
|
|
+ */
|
|
+#define AR5K_PHY_IQ 0x9920 /* Register address */
|
|
+#define AR5K_PHY_IQ_CORR_Q_Q_COFF 0x0000001f /* Mask for q correction info */
|
|
+#define AR5K_PHY_IQ_CORR_Q_I_COFF 0x000007e0 /* Mask for i correction info */
|
|
+#define AR5K_PHY_IQ_CORR_Q_I_COFF_S 5
|
|
+#define AR5K_PHY_IQ_CORR_ENABLE 0x00000800 /* Enable i/q correction */
|
|
+#define AR5K_PHY_IQ_CAL_NUM_LOG_MAX 0x0000f000
|
|
+#define AR5K_PHY_IQ_CAL_NUM_LOG_MAX_S 12
|
|
+#define AR5K_PHY_IQ_RUN 0x00010000 /* Run i/q calibration */
|
|
+
|
|
+
|
|
+/*
|
|
+ * PHY PAPD probe register [5111+ (?)]
|
|
+ * Is this only present in 5212 ?
|
|
+ * Because it's always 0 in 5211 initialization code
|
|
+ */
|
|
+#define AR5K_PHY_PAPD_PROBE 0x9930
|
|
+#define AR5K_PHY_PAPD_PROBE_TXPOWER 0x00007e00
|
|
+#define AR5K_PHY_PAPD_PROBE_TXPOWER_S 9
|
|
+#define AR5K_PHY_PAPD_PROBE_TX_NEXT 0x00008000
|
|
+#define AR5K_PHY_PAPD_PROBE_TYPE 0x01800000 /* [5112+] */
|
|
+#define AR5K_PHY_PAPD_PROBE_TYPE_S 23
|
|
+#define AR5K_PHY_PAPD_PROBE_TYPE_OFDM 0
|
|
+#define AR5K_PHY_PAPD_PROBE_TYPE_XR 1
|
|
+#define AR5K_PHY_PAPD_PROBE_TYPE_CCK 2
|
|
+#define AR5K_PHY_PAPD_PROBE_GAINF 0xfe000000
|
|
+#define AR5K_PHY_PAPD_PROBE_GAINF_S 25
|
|
+#define AR5K_PHY_PAPD_PROBE_INI_5111 0x00004883 /* [5212+] */
|
|
+#define AR5K_PHY_PAPD_PROBE_INI_5112 0x00004882 /* [5212+] */
|
|
+
|
|
+
|
|
+/*
|
|
+ * PHY TX rate power registers [5112+]
|
|
+ */
|
|
+#define AR5K_PHY_TXPOWER_RATE1 0x9934
|
|
+#define AR5K_PHY_TXPOWER_RATE2 0x9938
|
|
+#define AR5K_PHY_TXPOWER_RATE_MAX 0x993c
|
|
+#define AR5K_PHY_TXPOWER_RATE_MAX_TPC_ENABLE 0x00000040
|
|
+#define AR5K_PHY_TXPOWER_RATE3 0xa234
|
|
+#define AR5K_PHY_TXPOWER_RATE4 0xa238
|
|
+
|
|
+/*
|
|
+ * PHY frame control register [5111+]
|
|
+ */
|
|
+#define AR5K_PHY_FRAME_CTL_5210 0x9804
|
|
+#define AR5K_PHY_FRAME_CTL_5211 0x9944
|
|
+#define AR5K_PHY_FRAME_CTL (ah->ah_version == AR5K_AR5210 ? \
|
|
+ AR5K_PHY_FRAME_CTL_5210 : AR5K_PHY_FRAME_CTL_5211)
|
|
+/*---[5111+]---*/
|
|
+#define AR5K_PHY_FRAME_CTL_TX_CLIP 0x00000038
|
|
+#define AR5K_PHY_FRAME_CTL_TX_CLIP_S 3
|
|
+/*---[5110/5111]---*/
|
|
+#define AR5K_PHY_FRAME_CTL_TIMING_ERR 0x01000000
|
|
+#define AR5K_PHY_FRAME_CTL_PARITY_ERR 0x02000000
|
|
+#define AR5K_PHY_FRAME_CTL_ILLRATE_ERR 0x04000000 /* illegal rate */
|
|
+#define AR5K_PHY_FRAME_CTL_ILLLEN_ERR 0x08000000 /* illegal length */
|
|
+#define AR5K_PHY_FRAME_CTL_SERVICE_ERR 0x20000000
|
|
+#define AR5K_PHY_FRAME_CTL_TXURN_ERR 0x40000000 /* tx underrun */
|
|
+#define AR5K_PHY_FRAME_CTL_INI AR5K_PHY_FRAME_CTL_SERVICE_ERR | \
|
|
+ AR5K_PHY_FRAME_CTL_TXURN_ERR | \
|
|
+ AR5K_PHY_FRAME_CTL_ILLLEN_ERR | \
|
|
+ AR5K_PHY_FRAME_CTL_ILLRATE_ERR | \
|
|
+ AR5K_PHY_FRAME_CTL_PARITY_ERR | \
|
|
+ AR5K_PHY_FRAME_CTL_TIMING_ERR
|
|
+
|
|
+/*
|
|
+ * PHY radar detection register [5111+]
|
|
+ */
|
|
+#define AR5K_PHY_RADAR 0x9954
|
|
+
|
|
+/* Radar enable ........ ........ ........ .......1 */
|
|
+#define AR5K_PHY_RADAR_ENABLE 0x00000001
|
|
+#define AR5K_PHY_RADAR_DISABLE 0x00000000
|
|
+#define AR5K_PHY_RADAR_ENABLE_S 0
|
|
+
|
|
+/* This is the value found on the card .1.111.1 .1.1.... 111....1 1...1...
|
|
+at power on. */
|
|
+#define AR5K_PHY_RADAR_PWONDEF_AR5213 0x5d50e188
|
|
+
|
|
+/* This is the value found on the card .1.1.111 ..11...1 .1...1.1 1...11.1
|
|
+after DFS is enabled */
|
|
+#define AR5K_PHY_RADAR_ENABLED_AR5213 0x5731458d
|
|
+
|
|
+/* Finite Impulse Response (FIR) filter .1111111 ........ ........ ........
|
|
+ * power out threshold.
|
|
+ * 7-bits, standard power range {0..127} in 1/2 dBm units. */
|
|
+#define AR5K_PHY_RADAR_FIRPWROUTTHR 0x7f000000
|
|
+#define AR5K_PHY_RADAR_FIRPWROUTTHR_S 24
|
|
+
|
|
+/* Radar RSSI/SNR threshold. ........ 111111.. ........ ........
|
|
+ * 6-bits, dBm range {0..63} in dBm units. */
|
|
+#define AR5K_PHY_RADAR_RADARRSSITHR 0x00fc0000
|
|
+#define AR5K_PHY_RADAR_RADARRSSITHR_S 18
|
|
+
|
|
+/* Pulse height threshold ........ ......11 1111.... ........
|
|
+ * 6-bits, dBm range {0..63} in dBm units. */
|
|
+#define AR5K_PHY_RADAR_PULSEHEIGHTTHR 0x0003f000
|
|
+#define AR5K_PHY_RADAR_PULSEHEIGHTTHR_S 12
|
|
+
|
|
+/* Pulse RSSI/SNR threshold ........ ........ ....1111 11......
|
|
+ * 6-bits, dBm range {0..63} in dBm units. */
|
|
+#define AR5K_PHY_RADAR_PULSERSSITHR 0x00000fc0
|
|
+#define AR5K_PHY_RADAR_PULSERSSITHR_S 6
|
|
+
|
|
+/* Inband threshold ........ ........ ........ ..11111.
|
|
+ * 5-bits, units unknown {0..31} (? MHz ?) */
|
|
+#define AR5K_PHY_RADAR_INBANDTHR 0x0000003e
|
|
+#define AR5K_PHY_RADAR_INBANDTHR_S 1
|
|
+
|
|
+/*
|
|
+ * PHY antenna switch table registers [5110]
|
|
+ */
|
|
+#define AR5K_PHY_ANT_SWITCH_TABLE_0 0x9960
|
|
+#define AR5K_PHY_ANT_SWITCH_TABLE_1 0x9964
|
|
+
|
|
+/*
|
|
+ * PHY clock sleep registers [5112+]
|
|
+ */
|
|
+#define AR5K_PHY_SCLOCK 0x99f0
|
|
+#define AR5K_PHY_SCLOCK_32MHZ 0x0000000c
|
|
+#define AR5K_PHY_SDELAY 0x99f4
|
|
+#define AR5K_PHY_SDELAY_32MHZ 0x000000ff
|
|
+#define AR5K_PHY_SPENDING 0x99f8
|
|
+#define AR5K_PHY_SPENDING_RF5111 0x00000018
|
|
+#define AR5K_PHY_SPENDING_RF5112 0x00000014
|
|
+
|
|
+/*
|
|
+ * Misc PHY/radio registers [5110 - 5111]
|
|
+ */
|
|
+#define AR5K_BB_GAIN_BASE 0x9b00 /* BaseBand Amplifier Gain table base address */
|
|
+#define AR5K_BB_GAIN(_n) (AR5K_BB_GAIN_BASE + ((_n) << 2))
|
|
+#define AR5K_RF_GAIN_BASE 0x9a00 /* RF Amplrifier Gain table base address */
|
|
+#define AR5K_RF_GAIN(_n) (AR5K_RF_GAIN_BASE + ((_n) << 2))
|
|
+
|
|
+/*
|
|
+ * PHY timing IQ calibration result register [5111+]
|
|
+ */
|
|
+#define AR5K_PHY_IQRES_CAL_PWR_I 0x9c10 /* I (Inphase) power value */
|
|
+#define AR5K_PHY_IQRES_CAL_PWR_Q 0x9c14 /* Q (Quadrature) power value */
|
|
+#define AR5K_PHY_IQRES_CAL_CORR 0x9c18 /* I/Q Correlation */
|
|
+
|
|
+/*
|
|
+ * PHY current RSSI register [5111+]
|
|
+ */
|
|
+#define AR5K_PHY_CURRENT_RSSI 0x9c1c
|
|
+
|
|
+/*
|
|
+ * PHY PCDAC TX power table
|
|
+ */
|
|
+#define AR5K_PHY_PCDAC_TXPOWER_BASE_5211 0xa180
|
|
+#define AR5K_PHY_PCDAC_TXPOWER_BASE_5413 0xa280
|
|
+#define AR5K_PHY_PCDAC_TXPOWER_BASE (ah->ah_radio >= AR5K_RF5413 ? \
|
|
+ AR5K_PHY_PCDAC_TXPOWER_BASE_5413 :\
|
|
+ AR5K_PHY_PCDAC_TXPOWER_BASE_5211)
|
|
+#define AR5K_PHY_PCDAC_TXPOWER(_n) (AR5K_PHY_PCDAC_TXPOWER_BASE + ((_n) << 2))
|
|
+
|
|
+/*
|
|
+ * PHY mode register [5111+]
|
|
+ */
|
|
+#define AR5K_PHY_MODE 0x0a200 /* Register address */
|
|
+#define AR5K_PHY_MODE_MOD 0x00000001 /* PHY Modulation mask*/
|
|
+#define AR5K_PHY_MODE_MOD_OFDM 0
|
|
+#define AR5K_PHY_MODE_MOD_CCK 1
|
|
+#define AR5K_PHY_MODE_FREQ 0x00000002 /* Freq mode mask */
|
|
+#define AR5K_PHY_MODE_FREQ_5GHZ 0
|
|
+#define AR5K_PHY_MODE_FREQ_2GHZ 2
|
|
+#define AR5K_PHY_MODE_MOD_DYN 0x00000004 /* Dynamic OFDM/CCK mode mask [5112+] */
|
|
+#define AR5K_PHY_MODE_RAD 0x00000008 /* [5212+] */
|
|
+#define AR5K_PHY_MODE_RAD_RF5111 0
|
|
+#define AR5K_PHY_MODE_RAD_RF5112 8
|
|
+#define AR5K_PHY_MODE_XR 0x00000010 /* [5112+] */
|
|
+
|
|
+/*
|
|
+ * PHY CCK transmit control register [5111+ (?)]
|
|
+ */
|
|
+#define AR5K_PHY_CCKTXCTL 0xa204
|
|
+#define AR5K_PHY_CCKTXCTL_WORLD 0x00000000
|
|
+#define AR5K_PHY_CCKTXCTL_JAPAN 0x00000010
|
|
+
|
|
+/*
|
|
+ * PHY 2GHz gain register [5111+]
|
|
+ */
|
|
+#define AR5K_PHY_GAIN_2GHZ 0xa20c
|
|
+#define AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX 0x00fc0000
|
|
+#define AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX_S 18
|
|
+#define AR5K_PHY_GAIN_2GHZ_INI_5111 0x6480416c
|
|
diff -up /dev/null linux-2.6.23.noarch/drivers/net/wireless/ath5k/regdom.h
|
|
--- /dev/null 2007-12-21 08:33:07.834165456 -0500
|
|
+++ linux-2.6.23.noarch/drivers/net/wireless/ath5k/regdom.h 2007-12-21 12:18:50.000000000 -0500
|
|
@@ -0,0 +1,500 @@
|
|
+/*
|
|
+ * Copyright (c) 2004, 2005 Reyk Floeter <reyk@openbsd.org>
|
|
+ *
|
|
+ * Permission to use, copy, modify, and distribute this software for any
|
|
+ * purpose with or without fee is hereby granted, provided that the above
|
|
+ * copyright notice and this permission notice appear in all copies.
|
|
+ *
|
|
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
+ */
|
|
+
|
|
+#ifndef _IEEE80211_REGDOMAIN_H_
|
|
+#define _IEEE80211_REGDOMAIN_H_
|
|
+
|
|
+#include <linux/types.h>
|
|
+
|
|
+/* Default regulation domain if stored value EEPROM value is invalid */
|
|
+#define AR5K_TUNE_REGDOMAIN DMN_FCC2_FCCA /* Canada */
|
|
+#define AR5K_TUNE_CTRY CTRY_DEFAULT
|
|
+
|
|
+
|
|
+enum ath5k_regdom {
|
|
+ DMN_DEFAULT = 0x00,
|
|
+ DMN_NULL_WORLD = 0x03,
|
|
+ DMN_NULL_ETSIB = 0x07,
|
|
+ DMN_NULL_ETSIC = 0x08,
|
|
+ DMN_FCC1_FCCA = 0x10,
|
|
+ DMN_FCC1_WORLD = 0x11,
|
|
+ DMN_FCC2_FCCA = 0x20,
|
|
+ DMN_FCC2_WORLD = 0x21,
|
|
+ DMN_FCC2_ETSIC = 0x22,
|
|
+ DMN_FRANCE_NULL = 0x31,
|
|
+ DMN_FCC3_FCCA = 0x3A,
|
|
+ DMN_ETSI1_WORLD = 0x37,
|
|
+ DMN_ETSI3_ETSIA = 0x32,
|
|
+ DMN_ETSI2_WORLD = 0x35,
|
|
+ DMN_ETSI3_WORLD = 0x36,
|
|
+ DMN_ETSI4_WORLD = 0x30,
|
|
+ DMN_ETSI4_ETSIC = 0x38,
|
|
+ DMN_ETSI5_WORLD = 0x39,
|
|
+ DMN_ETSI6_WORLD = 0x34,
|
|
+ DMN_ETSI_NULL = 0x33,
|
|
+ DMN_MKK1_MKKA = 0x40,
|
|
+ DMN_MKK1_MKKB = 0x41,
|
|
+ DMN_APL4_WORLD = 0x42,
|
|
+ DMN_MKK2_MKKA = 0x43,
|
|
+ DMN_APL_NULL = 0x44,
|
|
+ DMN_APL2_WORLD = 0x45,
|
|
+ DMN_APL2_APLC = 0x46,
|
|
+ DMN_APL3_WORLD = 0x47,
|
|
+ DMN_MKK1_FCCA = 0x48,
|
|
+ DMN_APL2_APLD = 0x49,
|
|
+ DMN_MKK1_MKKA1 = 0x4A,
|
|
+ DMN_MKK1_MKKA2 = 0x4B,
|
|
+ DMN_APL1_WORLD = 0x52,
|
|
+ DMN_APL1_FCCA = 0x53,
|
|
+ DMN_APL1_APLA = 0x54,
|
|
+ DMN_APL1_ETSIC = 0x55,
|
|
+ DMN_APL2_ETSIC = 0x56,
|
|
+ DMN_APL5_WORLD = 0x58,
|
|
+ DMN_WOR0_WORLD = 0x60,
|
|
+ DMN_WOR1_WORLD = 0x61,
|
|
+ DMN_WOR2_WORLD = 0x62,
|
|
+ DMN_WOR3_WORLD = 0x63,
|
|
+ DMN_WOR4_WORLD = 0x64,
|
|
+ DMN_WOR5_ETSIC = 0x65,
|
|
+ DMN_WOR01_WORLD = 0x66,
|
|
+ DMN_WOR02_WORLD = 0x67,
|
|
+ DMN_EU1_WORLD = 0x68,
|
|
+ DMN_WOR9_WORLD = 0x69,
|
|
+ DMN_WORA_WORLD = 0x6A,
|
|
+
|
|
+ DMN_APL1 = 0xf0000001,
|
|
+ DMN_APL2 = 0xf0000002,
|
|
+ DMN_APL3 = 0xf0000004,
|
|
+ DMN_APL4 = 0xf0000008,
|
|
+ DMN_APL5 = 0xf0000010,
|
|
+ DMN_ETSI1 = 0xf0000020,
|
|
+ DMN_ETSI2 = 0xf0000040,
|
|
+ DMN_ETSI3 = 0xf0000080,
|
|
+ DMN_ETSI4 = 0xf0000100,
|
|
+ DMN_ETSI5 = 0xf0000200,
|
|
+ DMN_ETSI6 = 0xf0000400,
|
|
+ DMN_ETSIA = 0xf0000800,
|
|
+ DMN_ETSIB = 0xf0001000,
|
|
+ DMN_ETSIC = 0xf0002000,
|
|
+ DMN_FCC1 = 0xf0004000,
|
|
+ DMN_FCC2 = 0xf0008000,
|
|
+ DMN_FCC3 = 0xf0010000,
|
|
+ DMN_FCCA = 0xf0020000,
|
|
+ DMN_APLD = 0xf0040000,
|
|
+ DMN_MKK1 = 0xf0080000,
|
|
+ DMN_MKK2 = 0xf0100000,
|
|
+ DMN_MKKA = 0xf0200000,
|
|
+ DMN_NULL = 0xf0400000,
|
|
+ DMN_WORLD = 0xf0800000,
|
|
+ DMN_DEBUG = 0xf1000000 /* used for debugging */
|
|
+};
|
|
+
|
|
+#define IEEE80211_DMN(_d) ((_d) & ~0xf0000000)
|
|
+
|
|
+enum ath5k_countrycode {
|
|
+ CTRY_DEFAULT = 0, /* Default domain (NA) */
|
|
+ CTRY_ALBANIA = 8, /* Albania */
|
|
+ CTRY_ALGERIA = 12, /* Algeria */
|
|
+ CTRY_ARGENTINA = 32, /* Argentina */
|
|
+ CTRY_ARMENIA = 51, /* Armenia */
|
|
+ CTRY_AUSTRALIA = 36, /* Australia */
|
|
+ CTRY_AUSTRIA = 40, /* Austria */
|
|
+ CTRY_AZERBAIJAN = 31, /* Azerbaijan */
|
|
+ CTRY_BAHRAIN = 48, /* Bahrain */
|
|
+ CTRY_BELARUS = 112, /* Belarus */
|
|
+ CTRY_BELGIUM = 56, /* Belgium */
|
|
+ CTRY_BELIZE = 84, /* Belize */
|
|
+ CTRY_BOLIVIA = 68, /* Bolivia */
|
|
+ CTRY_BRAZIL = 76, /* Brazil */
|
|
+ CTRY_BRUNEI_DARUSSALAM = 96, /* Brunei Darussalam */
|
|
+ CTRY_BULGARIA = 100, /* Bulgaria */
|
|
+ CTRY_CANADA = 124, /* Canada */
|
|
+ CTRY_CHILE = 152, /* Chile */
|
|
+ CTRY_CHINA = 156, /* People's Republic of China */
|
|
+ CTRY_COLOMBIA = 170, /* Colombia */
|
|
+ CTRY_COSTA_RICA = 188, /* Costa Rica */
|
|
+ CTRY_CROATIA = 191, /* Croatia */
|
|
+ CTRY_CYPRUS = 196, /* Cyprus */
|
|
+ CTRY_CZECH = 203, /* Czech Republic */
|
|
+ CTRY_DENMARK = 208, /* Denmark */
|
|
+ CTRY_DOMINICAN_REPUBLIC = 214, /* Dominican Republic */
|
|
+ CTRY_ECUADOR = 218, /* Ecuador */
|
|
+ CTRY_EGYPT = 818, /* Egypt */
|
|
+ CTRY_EL_SALVADOR = 222, /* El Salvador */
|
|
+ CTRY_ESTONIA = 233, /* Estonia */
|
|
+ CTRY_FAEROE_ISLANDS = 234, /* Faeroe Islands */
|
|
+ CTRY_FINLAND = 246, /* Finland */
|
|
+ CTRY_FRANCE = 250, /* France */
|
|
+ CTRY_FRANCE2 = 255, /* France2 */
|
|
+ CTRY_GEORGIA = 268, /* Georgia */
|
|
+ CTRY_GERMANY = 276, /* Germany */
|
|
+ CTRY_GREECE = 300, /* Greece */
|
|
+ CTRY_GUATEMALA = 320, /* Guatemala */
|
|
+ CTRY_HONDURAS = 340, /* Honduras */
|
|
+ CTRY_HONG_KONG = 344, /* Hong Kong S.A.R., P.R.C. */
|
|
+ CTRY_HUNGARY = 348, /* Hungary */
|
|
+ CTRY_ICELAND = 352, /* Iceland */
|
|
+ CTRY_INDIA = 356, /* India */
|
|
+ CTRY_INDONESIA = 360, /* Indonesia */
|
|
+ CTRY_IRAN = 364, /* Iran */
|
|
+ CTRY_IRAQ = 368, /* Iraq */
|
|
+ CTRY_IRELAND = 372, /* Ireland */
|
|
+ CTRY_ISRAEL = 376, /* Israel */
|
|
+ CTRY_ITALY = 380, /* Italy */
|
|
+ CTRY_JAMAICA = 388, /* Jamaica */
|
|
+ CTRY_JAPAN = 392, /* Japan */
|
|
+ CTRY_JAPAN1 = 393, /* Japan (JP1) */
|
|
+ CTRY_JAPAN2 = 394, /* Japan (JP0) */
|
|
+ CTRY_JAPAN3 = 395, /* Japan (JP1-1) */
|
|
+ CTRY_JAPAN4 = 396, /* Japan (JE1) */
|
|
+ CTRY_JAPAN5 = 397, /* Japan (JE2) */
|
|
+ CTRY_JORDAN = 400, /* Jordan */
|
|
+ CTRY_KAZAKHSTAN = 398, /* Kazakhstan */
|
|
+ CTRY_KENYA = 404, /* Kenya */
|
|
+ CTRY_KOREA_NORTH = 408, /* North Korea */
|
|
+ CTRY_KOREA_ROC = 410, /* South Korea */
|
|
+ CTRY_KOREA_ROC2 = 411, /* South Korea */
|
|
+ CTRY_KUWAIT = 414, /* Kuwait */
|
|
+ CTRY_LATVIA = 428, /* Latvia */
|
|
+ CTRY_LEBANON = 422, /* Lebanon */
|
|
+ CTRY_LIBYA = 434, /* Libya */
|
|
+ CTRY_LIECHTENSTEIN = 438, /* Liechtenstein */
|
|
+ CTRY_LITHUANIA = 440, /* Lithuania */
|
|
+ CTRY_LUXEMBOURG = 442, /* Luxembourg */
|
|
+ CTRY_MACAU = 446, /* Macau */
|
|
+ CTRY_MACEDONIA = 807, /* Republic of Macedonia */
|
|
+ CTRY_MALAYSIA = 458, /* Malaysia */
|
|
+ CTRY_MEXICO = 484, /* Mexico */
|
|
+ CTRY_MONACO = 492, /* Principality of Monaco */
|
|
+ CTRY_MOROCCO = 504, /* Morocco */
|
|
+ CTRY_NETHERLANDS = 528, /* Netherlands */
|
|
+ CTRY_NEW_ZEALAND = 554, /* New Zealand */
|
|
+ CTRY_NICARAGUA = 558, /* Nicaragua */
|
|
+ CTRY_NORWAY = 578, /* Norway */
|
|
+ CTRY_OMAN = 512, /* Oman */
|
|
+ CTRY_PAKISTAN = 586, /* Islamic Republic of Pakistan */
|
|
+ CTRY_PANAMA = 591, /* Panama */
|
|
+ CTRY_PARAGUAY = 600, /* Paraguay */
|
|
+ CTRY_PERU = 604, /* Peru */
|
|
+ CTRY_PHILIPPINES = 608, /* Republic of the Philippines */
|
|
+ CTRY_POLAND = 616, /* Poland */
|
|
+ CTRY_PORTUGAL = 620, /* Portugal */
|
|
+ CTRY_PUERTO_RICO = 630, /* Puerto Rico */
|
|
+ CTRY_QATAR = 634, /* Qatar */
|
|
+ CTRY_ROMANIA = 642, /* Romania */
|
|
+ CTRY_RUSSIA = 643, /* Russia */
|
|
+ CTRY_SAUDI_ARABIA = 682, /* Saudi Arabia */
|
|
+ CTRY_SINGAPORE = 702, /* Singapore */
|
|
+ CTRY_SLOVAKIA = 703, /* Slovak Republic */
|
|
+ CTRY_SLOVENIA = 705, /* Slovenia */
|
|
+ CTRY_SOUTH_AFRICA = 710, /* South Africa */
|
|
+ CTRY_SPAIN = 724, /* Spain */
|
|
+ CTRY_SRI_LANKA = 728, /* Sri Lanka */
|
|
+ CTRY_SWEDEN = 752, /* Sweden */
|
|
+ CTRY_SWITZERLAND = 756, /* Switzerland */
|
|
+ CTRY_SYRIA = 760, /* Syria */
|
|
+ CTRY_TAIWAN = 158, /* Taiwan */
|
|
+ CTRY_THAILAND = 764, /* Thailand */
|
|
+ CTRY_TRINIDAD_Y_TOBAGO = 780, /* Trinidad y Tobago */
|
|
+ CTRY_TUNISIA = 788, /* Tunisia */
|
|
+ CTRY_TURKEY = 792, /* Turkey */
|
|
+ CTRY_UAE = 784, /* U.A.E. */
|
|
+ CTRY_UKRAINE = 804, /* Ukraine */
|
|
+ CTRY_UNITED_KINGDOM = 826, /* United Kingdom */
|
|
+ CTRY_UNITED_STATES = 840, /* United States */
|
|
+ CTRY_URUGUAY = 858, /* Uruguay */
|
|
+ CTRY_UZBEKISTAN = 860, /* Uzbekistan */
|
|
+ CTRY_VENEZUELA = 862, /* Venezuela */
|
|
+ CTRY_VIET_NAM = 704, /* Viet Nam */
|
|
+ CTRY_YEMEN = 887, /* Yemen */
|
|
+ CTRY_ZIMBABWE = 716, /* Zimbabwe */
|
|
+};
|
|
+
|
|
+#define IEEE80211_CHANNELS_2GHZ_MIN 2412 /* 2GHz channel 1 */
|
|
+#define IEEE80211_CHANNELS_2GHZ_MAX 2732 /* 2GHz channel 26 */
|
|
+#define IEEE80211_CHANNELS_5GHZ_MIN 5005 /* 5GHz channel 1 */
|
|
+#define IEEE80211_CHANNELS_5GHZ_MAX 6100 /* 5GHz channel 220 */
|
|
+
|
|
+struct ath5k_regchannel {
|
|
+ u16 chan;
|
|
+ enum ath5k_regdom domain;
|
|
+ u32 mode;
|
|
+};
|
|
+
|
|
+#define IEEE80211_CHANNELS_2GHZ { \
|
|
+/*2412*/ { 1, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+/*2417*/ { 2, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+/*2422*/ { 3, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+/*2427*/ { 4, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+/*2432*/ { 5, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+/*2437*/ { 6, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+/*2442*/ { 7, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+/*2447*/ { 8, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+/*2452*/ { 9, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+/*2457*/ { 10, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+/*2462*/ { 11, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+/*2467*/ { 12, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+/*2472*/ { 13, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+ \
|
|
+/*2432*/ { 5, DMN_ETSIB, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+/*2437*/ { 6, DMN_ETSIB, CHANNEL_CCK|CHANNEL_OFDM|CHANNEL_TURBO }, \
|
|
+/*2442*/ { 7, DMN_ETSIB, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+ \
|
|
+/*2412*/ { 1, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+/*2417*/ { 2, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+/*2422*/ { 3, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+/*2427*/ { 4, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+/*2432*/ { 5, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+/*2437*/ { 6, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM|CHANNEL_TURBO }, \
|
|
+/*2442*/ { 7, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+/*2447*/ { 8, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+/*2452*/ { 9, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+/*2457*/ { 10, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+/*2462*/ { 11, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+/*2467*/ { 12, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+/*2472*/ { 13, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+ \
|
|
+/*2412*/ { 1, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+/*2417*/ { 2, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+/*2422*/ { 3, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+/*2427*/ { 4, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+/*2432*/ { 5, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+/*2437*/ { 6, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM|CHANNEL_TURBO }, \
|
|
+/*2442*/ { 7, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+/*2447*/ { 8, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+/*2452*/ { 9, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+/*2457*/ { 10, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+/*2462*/ { 11, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+ \
|
|
+/*2412*/ { 1, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+/*2417*/ { 2, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+/*2422*/ { 3, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+/*2427*/ { 4, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+/*2432*/ { 5, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+/*2437*/ { 6, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+/*2442*/ { 7, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+/*2447*/ { 8, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+/*2452*/ { 9, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+/*2457*/ { 10, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+/*2462*/ { 11, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+/*2467*/ { 12, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+/*2472*/ { 13, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+/*2484*/ { 14, DMN_MKKA, CHANNEL_CCK }, \
|
|
+ \
|
|
+/*2412*/ { 1, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+/*2417*/ { 2, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+/*2422*/ { 3, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+/*2427*/ { 4, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+/*2432*/ { 5, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+/*2437*/ { 6, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM|CHANNEL_TURBO }, \
|
|
+/*2442*/ { 7, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+/*2447*/ { 8, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+/*2452*/ { 9, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+/*2457*/ { 10, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+/*2462*/ { 11, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+/*2467*/ { 12, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+/*2472*/ { 13, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \
|
|
+}
|
|
+
|
|
+#define IEEE80211_CHANNELS_5GHZ { \
|
|
+/*5745*/ { 149, DMN_APL1, CHANNEL_OFDM }, \
|
|
+/*5765*/ { 153, DMN_APL1, CHANNEL_OFDM }, \
|
|
+/*5785*/ { 157, DMN_APL1, CHANNEL_OFDM }, \
|
|
+/*5805*/ { 161, DMN_APL1, CHANNEL_OFDM }, \
|
|
+/*5825*/ { 165, DMN_APL1, CHANNEL_OFDM }, \
|
|
+ \
|
|
+/*5745*/ { 149, DMN_APL2, CHANNEL_OFDM }, \
|
|
+/*5765*/ { 153, DMN_APL2, CHANNEL_OFDM }, \
|
|
+/*5785*/ { 157, DMN_APL2, CHANNEL_OFDM }, \
|
|
+/*5805*/ { 161, DMN_APL2, CHANNEL_OFDM }, \
|
|
+ \
|
|
+/*5280*/ { 56, DMN_APL3, CHANNEL_OFDM }, \
|
|
+/*5300*/ { 60, DMN_APL3, CHANNEL_OFDM }, \
|
|
+/*5320*/ { 64, DMN_APL3, CHANNEL_OFDM }, \
|
|
+/*5745*/ { 149, DMN_APL3, CHANNEL_OFDM }, \
|
|
+/*5765*/ { 153, DMN_APL3, CHANNEL_OFDM }, \
|
|
+/*5785*/ { 157, DMN_APL3, CHANNEL_OFDM }, \
|
|
+/*5805*/ { 161, DMN_APL3, CHANNEL_OFDM }, \
|
|
+ \
|
|
+/*5180*/ { 36, DMN_APL4, CHANNEL_OFDM }, \
|
|
+/*5200*/ { 40, DMN_APL4, CHANNEL_OFDM }, \
|
|
+/*5220*/ { 44, DMN_APL4, CHANNEL_OFDM }, \
|
|
+/*5240*/ { 48, DMN_APL4, CHANNEL_OFDM }, \
|
|
+/*5745*/ { 149, DMN_APL4, CHANNEL_OFDM }, \
|
|
+/*5765*/ { 153, DMN_APL4, CHANNEL_OFDM }, \
|
|
+/*5785*/ { 157, DMN_APL4, CHANNEL_OFDM }, \
|
|
+/*5805*/ { 161, DMN_APL4, CHANNEL_OFDM }, \
|
|
+/*5825*/ { 165, DMN_APL4, CHANNEL_OFDM }, \
|
|
+ \
|
|
+/*5745*/ { 149, DMN_APL5, CHANNEL_OFDM }, \
|
|
+/*5765*/ { 153, DMN_APL5, CHANNEL_OFDM }, \
|
|
+/*5785*/ { 157, DMN_APL5, CHANNEL_OFDM }, \
|
|
+/*5805*/ { 161, DMN_APL5, CHANNEL_OFDM }, \
|
|
+/*5825*/ { 165, DMN_APL5, CHANNEL_OFDM }, \
|
|
+ \
|
|
+/*5180*/ { 36, DMN_ETSI1, CHANNEL_OFDM }, \
|
|
+/*5200*/ { 40, DMN_ETSI1, CHANNEL_OFDM }, \
|
|
+/*5220*/ { 44, DMN_ETSI1, CHANNEL_OFDM }, \
|
|
+/*5240*/ { 48, DMN_ETSI1, CHANNEL_OFDM }, \
|
|
+/*5260*/ { 52, DMN_ETSI1, CHANNEL_OFDM }, \
|
|
+/*5280*/ { 56, DMN_ETSI1, CHANNEL_OFDM }, \
|
|
+/*5300*/ { 60, DMN_ETSI1, CHANNEL_OFDM }, \
|
|
+/*5320*/ { 64, DMN_ETSI1, CHANNEL_OFDM }, \
|
|
+/*5500*/ { 100, DMN_ETSI1, CHANNEL_OFDM }, \
|
|
+/*5520*/ { 104, DMN_ETSI1, CHANNEL_OFDM }, \
|
|
+/*5540*/ { 108, DMN_ETSI1, CHANNEL_OFDM }, \
|
|
+/*5560*/ { 112, DMN_ETSI1, CHANNEL_OFDM }, \
|
|
+/*5580*/ { 116, DMN_ETSI1, CHANNEL_OFDM }, \
|
|
+/*5600*/ { 120, DMN_ETSI1, CHANNEL_OFDM }, \
|
|
+/*5620*/ { 124, DMN_ETSI1, CHANNEL_OFDM }, \
|
|
+/*5640*/ { 128, DMN_ETSI1, CHANNEL_OFDM }, \
|
|
+/*5660*/ { 132, DMN_ETSI1, CHANNEL_OFDM }, \
|
|
+/*5680*/ { 136, DMN_ETSI1, CHANNEL_OFDM }, \
|
|
+/*5700*/ { 140, DMN_ETSI1, CHANNEL_OFDM }, \
|
|
+ \
|
|
+/*5180*/ { 36, DMN_ETSI2, CHANNEL_OFDM }, \
|
|
+/*5200*/ { 40, DMN_ETSI2, CHANNEL_OFDM }, \
|
|
+/*5220*/ { 44, DMN_ETSI2, CHANNEL_OFDM }, \
|
|
+/*5240*/ { 48, DMN_ETSI2, CHANNEL_OFDM }, \
|
|
+ \
|
|
+/*5180*/ { 36, DMN_ETSI3, CHANNEL_OFDM }, \
|
|
+/*5200*/ { 40, DMN_ETSI3, CHANNEL_OFDM }, \
|
|
+/*5220*/ { 44, DMN_ETSI3, CHANNEL_OFDM }, \
|
|
+/*5240*/ { 48, DMN_ETSI3, CHANNEL_OFDM }, \
|
|
+/*5260*/ { 52, DMN_ETSI3, CHANNEL_OFDM }, \
|
|
+/*5280*/ { 56, DMN_ETSI3, CHANNEL_OFDM }, \
|
|
+/*5300*/ { 60, DMN_ETSI3, CHANNEL_OFDM }, \
|
|
+/*5320*/ { 64, DMN_ETSI3, CHANNEL_OFDM }, \
|
|
+ \
|
|
+/*5180*/ { 36, DMN_ETSI4, CHANNEL_OFDM }, \
|
|
+/*5200*/ { 40, DMN_ETSI4, CHANNEL_OFDM }, \
|
|
+/*5220*/ { 44, DMN_ETSI4, CHANNEL_OFDM }, \
|
|
+/*5240*/ { 48, DMN_ETSI4, CHANNEL_OFDM }, \
|
|
+/*5260*/ { 52, DMN_ETSI4, CHANNEL_OFDM }, \
|
|
+/*5280*/ { 56, DMN_ETSI4, CHANNEL_OFDM }, \
|
|
+/*5300*/ { 60, DMN_ETSI4, CHANNEL_OFDM }, \
|
|
+/*5320*/ { 64, DMN_ETSI4, CHANNEL_OFDM }, \
|
|
+ \
|
|
+/*5180*/ { 36, DMN_ETSI5, CHANNEL_OFDM }, \
|
|
+/*5200*/ { 40, DMN_ETSI5, CHANNEL_OFDM }, \
|
|
+/*5220*/ { 44, DMN_ETSI5, CHANNEL_OFDM }, \
|
|
+/*5240*/ { 48, DMN_ETSI5, CHANNEL_OFDM }, \
|
|
+ \
|
|
+/*5180*/ { 36, DMN_ETSI6, CHANNEL_OFDM }, \
|
|
+/*5200*/ { 40, DMN_ETSI6, CHANNEL_OFDM }, \
|
|
+/*5220*/ { 44, DMN_ETSI6, CHANNEL_OFDM }, \
|
|
+/*5240*/ { 48, DMN_ETSI6, CHANNEL_OFDM }, \
|
|
+/*5260*/ { 52, DMN_ETSI6, CHANNEL_OFDM }, \
|
|
+/*5280*/ { 56, DMN_ETSI6, CHANNEL_OFDM }, \
|
|
+/*5500*/ { 100, DMN_ETSI6, CHANNEL_OFDM }, \
|
|
+/*5520*/ { 104, DMN_ETSI6, CHANNEL_OFDM }, \
|
|
+/*5540*/ { 108, DMN_ETSI6, CHANNEL_OFDM }, \
|
|
+/*5560*/ { 112, DMN_ETSI6, CHANNEL_OFDM }, \
|
|
+/*5580*/ { 116, DMN_ETSI6, CHANNEL_OFDM }, \
|
|
+/*5600*/ { 120, DMN_ETSI6, CHANNEL_OFDM }, \
|
|
+/*5620*/ { 124, DMN_ETSI6, CHANNEL_OFDM }, \
|
|
+/*5640*/ { 128, DMN_ETSI6, CHANNEL_OFDM }, \
|
|
+/*5660*/ { 132, DMN_ETSI6, CHANNEL_OFDM }, \
|
|
+/*5680*/ { 136, DMN_ETSI6, CHANNEL_OFDM }, \
|
|
+/*5700*/ { 140, DMN_ETSI6, CHANNEL_OFDM }, \
|
|
+ \
|
|
+/*5180*/ { 36, DMN_FCC1, CHANNEL_OFDM }, \
|
|
+/*5200*/ { 40, DMN_FCC1, CHANNEL_OFDM }, \
|
|
+/*5210*/ { 42, DMN_FCC1, CHANNEL_OFDM|CHANNEL_TURBO }, \
|
|
+/*5220*/ { 44, DMN_FCC1, CHANNEL_OFDM }, \
|
|
+/*5240*/ { 48, DMN_FCC1, CHANNEL_OFDM }, \
|
|
+/*5250*/ { 50, DMN_FCC1, CHANNEL_OFDM|CHANNEL_TURBO }, \
|
|
+/*5260*/ { 52, DMN_FCC1, CHANNEL_OFDM }, \
|
|
+/*5280*/ { 56, DMN_FCC1, CHANNEL_OFDM }, \
|
|
+/*5290*/ { 58, DMN_FCC1, CHANNEL_OFDM|CHANNEL_TURBO }, \
|
|
+/*5300*/ { 60, DMN_FCC1, CHANNEL_OFDM }, \
|
|
+/*5320*/ { 64, DMN_FCC1, CHANNEL_OFDM }, \
|
|
+/*5745*/ { 149, DMN_FCC1, CHANNEL_OFDM }, \
|
|
+/*5760*/ { 152, DMN_FCC1, CHANNEL_OFDM|CHANNEL_TURBO }, \
|
|
+/*5765*/ { 153, DMN_FCC1, CHANNEL_OFDM }, \
|
|
+/*5785*/ { 157, DMN_FCC1, CHANNEL_OFDM }, \
|
|
+/*5800*/ { 160, DMN_FCC1, CHANNEL_OFDM|CHANNEL_TURBO }, \
|
|
+/*5805*/ { 161, DMN_FCC1, CHANNEL_OFDM }, \
|
|
+/*5825*/ { 165, DMN_FCC1, CHANNEL_OFDM }, \
|
|
+ \
|
|
+/*5180*/ { 36, DMN_FCC2, CHANNEL_OFDM }, \
|
|
+/*5200*/ { 40, DMN_FCC2, CHANNEL_OFDM }, \
|
|
+/*5220*/ { 44, DMN_FCC2, CHANNEL_OFDM }, \
|
|
+/*5240*/ { 48, DMN_FCC2, CHANNEL_OFDM }, \
|
|
+/*5260*/ { 52, DMN_FCC2, CHANNEL_OFDM }, \
|
|
+/*5280*/ { 56, DMN_FCC2, CHANNEL_OFDM }, \
|
|
+/*5300*/ { 60, DMN_FCC2, CHANNEL_OFDM }, \
|
|
+/*5320*/ { 64, DMN_FCC2, CHANNEL_OFDM }, \
|
|
+/*5745*/ { 149, DMN_FCC2, CHANNEL_OFDM }, \
|
|
+/*5765*/ { 153, DMN_FCC2, CHANNEL_OFDM }, \
|
|
+/*5785*/ { 157, DMN_FCC2, CHANNEL_OFDM }, \
|
|
+/*5805*/ { 161, DMN_FCC2, CHANNEL_OFDM }, \
|
|
+/*5825*/ { 165, DMN_FCC2, CHANNEL_OFDM }, \
|
|
+ \
|
|
+/*5180*/ { 36, DMN_FCC3, CHANNEL_OFDM }, \
|
|
+/*5200*/ { 40, DMN_FCC3, CHANNEL_OFDM }, \
|
|
+/*5210*/ { 42, DMN_FCC3, CHANNEL_OFDM|CHANNEL_TURBO }, \
|
|
+/*5220*/ { 44, DMN_FCC3, CHANNEL_OFDM }, \
|
|
+/*5240*/ { 48, DMN_FCC3, CHANNEL_OFDM }, \
|
|
+/*5250*/ { 50, DMN_FCC3, CHANNEL_OFDM|CHANNEL_TURBO }, \
|
|
+/*5260*/ { 52, DMN_FCC3, CHANNEL_OFDM }, \
|
|
+/*5280*/ { 56, DMN_FCC3, CHANNEL_OFDM }, \
|
|
+/*5290*/ { 58, DMN_FCC3, CHANNEL_OFDM|CHANNEL_TURBO }, \
|
|
+/*5300*/ { 60, DMN_FCC3, CHANNEL_OFDM }, \
|
|
+/*5320*/ { 64, DMN_FCC3, CHANNEL_OFDM }, \
|
|
+/*5500*/ { 100, DMN_FCC3, CHANNEL_OFDM }, \
|
|
+/*5520*/ { 104, DMN_FCC3, CHANNEL_OFDM }, \
|
|
+/*5540*/ { 108, DMN_FCC3, CHANNEL_OFDM }, \
|
|
+/*5560*/ { 112, DMN_FCC3, CHANNEL_OFDM }, \
|
|
+/*5580*/ { 116, DMN_FCC3, CHANNEL_OFDM }, \
|
|
+/*5600*/ { 120, DMN_FCC3, CHANNEL_OFDM }, \
|
|
+/*5620*/ { 124, DMN_FCC3, CHANNEL_OFDM }, \
|
|
+/*5640*/ { 128, DMN_FCC3, CHANNEL_OFDM }, \
|
|
+/*5660*/ { 132, DMN_FCC3, CHANNEL_OFDM }, \
|
|
+/*5680*/ { 136, DMN_FCC3, CHANNEL_OFDM }, \
|
|
+/*5700*/ { 140, DMN_FCC3, CHANNEL_OFDM }, \
|
|
+/*5745*/ { 149, DMN_FCC3, CHANNEL_OFDM }, \
|
|
+/*5760*/ { 152, DMN_FCC3, CHANNEL_OFDM|CHANNEL_TURBO }, \
|
|
+/*5765*/ { 153, DMN_FCC3, CHANNEL_OFDM }, \
|
|
+/*5785*/ { 157, DMN_FCC3, CHANNEL_OFDM }, \
|
|
+/*5800*/ { 160, DMN_FCC3, CHANNEL_OFDM|CHANNEL_TURBO }, \
|
|
+/*5805*/ { 161, DMN_FCC3, CHANNEL_OFDM }, \
|
|
+/*5825*/ { 165, DMN_FCC3, CHANNEL_OFDM }, \
|
|
+ \
|
|
+/*5170*/ { 34, DMN_MKK1, CHANNEL_OFDM }, \
|
|
+/*5190*/ { 38, DMN_MKK1, CHANNEL_OFDM }, \
|
|
+/*5210*/ { 42, DMN_MKK1, CHANNEL_OFDM }, \
|
|
+/*5230*/ { 46, DMN_MKK1, CHANNEL_OFDM }, \
|
|
+ \
|
|
+/*5040*/ { 8, DMN_MKK2, CHANNEL_OFDM }, \
|
|
+/*5060*/ { 12, DMN_MKK2, CHANNEL_OFDM }, \
|
|
+/*5080*/ { 16, DMN_MKK2, CHANNEL_OFDM }, \
|
|
+/*5170*/ { 34, DMN_MKK2, CHANNEL_OFDM }, \
|
|
+/*5190*/ { 38, DMN_MKK2, CHANNEL_OFDM }, \
|
|
+/*5210*/ { 42, DMN_MKK2, CHANNEL_OFDM }, \
|
|
+/*5230*/ { 46, DMN_MKK2, CHANNEL_OFDM }, \
|
|
+ \
|
|
+/*5180*/ { 36, DMN_WORLD, CHANNEL_OFDM }, \
|
|
+/*5200*/ { 40, DMN_WORLD, CHANNEL_OFDM }, \
|
|
+/*5220*/ { 44, DMN_WORLD, CHANNEL_OFDM }, \
|
|
+/*5240*/ { 48, DMN_WORLD, CHANNEL_OFDM }, \
|
|
+}
|
|
+
|
|
+enum ath5k_regdom ath5k_regdom2flag(enum ath5k_regdom, u16);
|
|
+u16 ath5k_regdom_from_ieee(enum ath5k_regdom ieee);
|
|
+enum ath5k_regdom ath5k_regdom_to_ieee(u16 regdomain);
|
|
+
|
|
+#endif
|
|
diff -up /dev/null linux-2.6.23.noarch/drivers/net/wireless/ath5k/debug.h
|
|
--- /dev/null 2007-12-21 08:33:07.834165456 -0500
|
|
+++ linux-2.6.23.noarch/drivers/net/wireless/ath5k/debug.h 2007-12-21 12:18:50.000000000 -0500
|
|
@@ -0,0 +1,216 @@
|
|
+/*
|
|
+ * Copyright (c) 2007 Bruno Randolf <bruno@thinktube.com>
|
|
+ *
|
|
+ * This file is free software: you may copy, redistribute 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 file is distributed in the hope that it will be useful, but
|
|
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ * General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU General Public License
|
|
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
+ *
|
|
+ *
|
|
+ * This file incorporates work covered by the following copyright and
|
|
+ * permission notice:
|
|
+ *
|
|
+ * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
|
|
+ * Copyright (c) 2004-2005 Atheros Communications, Inc.
|
|
+ * Copyright (c) 2006 Devicescape Software, Inc.
|
|
+ * Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com>
|
|
+ * Copyright (c) 2007 Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
|
|
+ *
|
|
+ * All rights reserved.
|
|
+ *
|
|
+ * Redistribution and use in source and binary forms, with or without
|
|
+ * modification, are permitted provided that the following conditions
|
|
+ * are met:
|
|
+ * 1. Redistributions of source code must retain the above copyright
|
|
+ * notice, this list of conditions and the following disclaimer,
|
|
+ * without modification.
|
|
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
|
+ * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
|
|
+ * redistribution must be conditioned upon including a substantially
|
|
+ * similar Disclaimer requirement for further binary redistribution.
|
|
+ * 3. Neither the names of the above-listed copyright holders nor the names
|
|
+ * of any contributors may be used to endorse or promote products derived
|
|
+ * from this software without specific prior written permission.
|
|
+ *
|
|
+ * Alternatively, this software may be distributed under the terms of the
|
|
+ * GNU General Public License ("GPL") version 2 as published by the Free
|
|
+ * Software Foundation.
|
|
+ *
|
|
+ * NO WARRANTY
|
|
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
|
|
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
|
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
|
|
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
|
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
|
+ * THE POSSIBILITY OF SUCH DAMAGES.
|
|
+ */
|
|
+
|
|
+#ifndef _ATH5K_DEBUG_H
|
|
+#define _ATH5K_DEBUG_H
|
|
+
|
|
+/* set this to 1 for debugging output */
|
|
+#ifndef ATH5K_DEBUG
|
|
+#define ATH5K_DEBUG 0
|
|
+#endif
|
|
+
|
|
+struct ath5k_softc;
|
|
+struct ath5k_hw;
|
|
+struct ieee80211_hw_mode;
|
|
+struct sk_buff;
|
|
+struct ath5k_buf;
|
|
+
|
|
+struct ath5k_dbg_info {
|
|
+ unsigned int level; /* debug level */
|
|
+ /* debugfs entries */
|
|
+ struct dentry *debugfs_phydir;
|
|
+ struct dentry *debugfs_debug;
|
|
+ struct dentry *debugfs_registers;
|
|
+ struct dentry *debugfs_tsf;
|
|
+ struct dentry *debugfs_beacon;
|
|
+ struct dentry *debugfs_reset;
|
|
+};
|
|
+
|
|
+/**
|
|
+ * enum ath5k_debug_level - ath5k debug level
|
|
+ *
|
|
+ * @ATH5K_DEBUG_RESET: reset processing
|
|
+ * @ATH5K_DEBUG_INTR: interrupt handling
|
|
+ * @ATH5K_DEBUG_MODE: mode init/setup
|
|
+ * @ATH5K_DEBUG_XMIT: basic xmit operation
|
|
+ * @ATH5K_DEBUG_BEACON: beacon handling
|
|
+ * @ATH5K_DEBUG_BEACON_PROC: beacon ISR proc
|
|
+ * @ATH5K_DEBUG_CALIBRATE: periodic calibration
|
|
+ * @ATH5K_DEBUG_TXPOWER: transmit power setting
|
|
+ * @ATH5K_DEBUG_LED: led management
|
|
+ * @ATH5K_DEBUG_DUMP_RX: print received skb content
|
|
+ * @ATH5K_DEBUG_DUMP_TX: print transmit skb content
|
|
+ * @ATH5K_DEBUG_DUMPMODES: dump modes
|
|
+ * @ATH5K_DEBUG_TRACE: trace function calls
|
|
+ * @ATH5K_DEBUG_FATAL: fatal errors
|
|
+ * @ATH5K_DEBUG_ANY: show at any debug level
|
|
+ *
|
|
+ * The debug level is used to control the amount and type of debugging output
|
|
+ * we want to see. The debug level is given in calls to ATH5K_DBG to specify
|
|
+ * where the message should appear, and the user can control the debugging
|
|
+ * messages he wants to see, either by the module parameter 'debug' on module
|
|
+ * load, or dynamically by using debugfs 'ath5k/phyX/debug'. these levels can
|
|
+ * be combined together by bitwise OR.
|
|
+ */
|
|
+enum ath5k_debug_level {
|
|
+ ATH5K_DEBUG_RESET = 0x00000001,
|
|
+ ATH5K_DEBUG_INTR = 0x00000002,
|
|
+ ATH5K_DEBUG_MODE = 0x00000004,
|
|
+ ATH5K_DEBUG_XMIT = 0x00000008,
|
|
+ ATH5K_DEBUG_BEACON = 0x00000010,
|
|
+ ATH5K_DEBUG_BEACON_PROC = 0x00000020,
|
|
+ ATH5K_DEBUG_CALIBRATE = 0x00000100,
|
|
+ ATH5K_DEBUG_TXPOWER = 0x00000200,
|
|
+ ATH5K_DEBUG_LED = 0x00000400,
|
|
+ ATH5K_DEBUG_DUMP_RX = 0x00001000,
|
|
+ ATH5K_DEBUG_DUMP_TX = 0x00002000,
|
|
+ ATH5K_DEBUG_DUMPMODES = 0x00004000,
|
|
+ ATH5K_DEBUG_TRACE = 0x00010000,
|
|
+ ATH5K_DEBUG_FATAL = 0x80000000,
|
|
+ ATH5K_DEBUG_ANY = 0xffffffff
|
|
+};
|
|
+
|
|
+#if ATH5K_DEBUG
|
|
+
|
|
+#define ATH5K_TRACE(_sc) do { \
|
|
+ if (unlikely((_sc)->debug.level & ATH5K_DEBUG_TRACE)) \
|
|
+ printk(KERN_DEBUG "ath5k trace %s:%d\n", __func__, __LINE__); \
|
|
+ } while (0)
|
|
+
|
|
+#define ATH5K_DBG(_sc, _m, _fmt, ...) do { \
|
|
+ if (unlikely((_sc)->debug.level & (_m) && net_ratelimit())) \
|
|
+ ATH5K_PRINTK(_sc, KERN_DEBUG, "(%s:%d): " _fmt, \
|
|
+ __func__, __LINE__, ##__VA_ARGS__); \
|
|
+ } while (0)
|
|
+
|
|
+#define ATH5K_DBG_UNLIMIT(_sc, _m, _fmt, ...) do { \
|
|
+ if (unlikely((_sc)->debug.level & (_m))) \
|
|
+ ATH5K_PRINTK(_sc, KERN_DEBUG, "(%s:%d): " _fmt, \
|
|
+ __func__, __LINE__, ##__VA_ARGS__); \
|
|
+ } while (0)
|
|
+
|
|
+void
|
|
+ath5k_debug_init(void);
|
|
+
|
|
+void
|
|
+ath5k_debug_init_device(struct ath5k_softc *sc);
|
|
+
|
|
+void
|
|
+ath5k_debug_finish(void);
|
|
+
|
|
+void
|
|
+ath5k_debug_finish_device(struct ath5k_softc *sc);
|
|
+
|
|
+void
|
|
+ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah);
|
|
+
|
|
+void
|
|
+ath5k_debug_dump_modes(struct ath5k_softc *sc,
|
|
+ struct ieee80211_hw_mode *modes);
|
|
+
|
|
+void
|
|
+ath5k_debug_dump_skb(struct ath5k_softc *sc,
|
|
+ struct sk_buff *skb, const char *prefix, int tx);
|
|
+
|
|
+void
|
|
+ath5k_debug_printtxbuf(struct ath5k_softc *sc,
|
|
+ struct ath5k_buf *bf, int done);
|
|
+
|
|
+#else /* no debugging */
|
|
+
|
|
+#define ATH5K_TRACE(_sc) /* empty */
|
|
+
|
|
+static inline void __attribute__ ((format (printf, 3, 4)))
|
|
+ATH5K_DBG(struct ath5k_softc *sc, unsigned int m, const char *fmt, ...) {}
|
|
+
|
|
+static inline void __attribute__ ((format (printf, 3, 4)))
|
|
+ATH5K_DBG_UNLIMIT(struct ath5k_softc *sc, unsigned int m, const char *fmt, ...)
|
|
+{}
|
|
+
|
|
+static inline void
|
|
+ath5k_debug_init(void) {}
|
|
+
|
|
+static inline void
|
|
+ath5k_debug_init_device(struct ath5k_softc *sc) {}
|
|
+
|
|
+static inline void
|
|
+ath5k_debug_finish(void) {}
|
|
+
|
|
+static inline void
|
|
+ath5k_debug_finish_device(struct ath5k_softc *sc) {}
|
|
+
|
|
+static inline void
|
|
+ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah) {}
|
|
+
|
|
+static inline void
|
|
+ath5k_debug_dump_modes(struct ath5k_softc *sc,
|
|
+ struct ieee80211_hw_mode *modes) {}
|
|
+
|
|
+static inline void
|
|
+ath5k_debug_dump_skb(struct ath5k_softc *sc,
|
|
+ struct sk_buff *skb, const char *prefix, int tx) {}
|
|
+
|
|
+static inline void
|
|
+ath5k_debug_printtxbuf(struct ath5k_softc *sc,
|
|
+ struct ath5k_buf *bf, int done) {}
|
|
+
|
|
+#endif /* if ATH5K_DEBUG */
|
|
+
|
|
+#endif /* ifndef _ATH5K_DEBUG_H */
|
|
diff -up /dev/null linux-2.6.23.noarch/drivers/net/wireless/ath5k/hw.c
|
|
--- /dev/null 2007-12-21 08:33:07.834165456 -0500
|
|
+++ linux-2.6.23.noarch/drivers/net/wireless/ath5k/hw.c 2007-12-21 12:18:50.000000000 -0500
|
|
@@ -0,0 +1,4349 @@
|
|
+ /*
|
|
+ * Copyright (c) 2004-2007 Reyk Floeter <reyk@openbsd.org>
|
|
+ * Copyright (c) 2006-2007 Nick Kossifidis <mickflemm@gmail.com>
|
|
+ * Copyright (c) 2007 Matthew W. S. Bell <mentor@madwifi.org>
|
|
+ * Copyright (c) 2007 Luis Rodriguez <mcgrof@winlab.rutgers.edu>
|
|
+ * Copyright (c) 2007 Pavel Roskin <proski@gnu.org>
|
|
+ * Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com>
|
|
+ *
|
|
+ * Permission to use, copy, modify, and distribute this software for any
|
|
+ * purpose with or without fee is hereby granted, provided that the above
|
|
+ * copyright notice and this permission notice appear in all copies.
|
|
+ *
|
|
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
+ *
|
|
+ */
|
|
+
|
|
+/*
|
|
+ * HW related functions for Atheros Wireless LAN devices.
|
|
+ */
|
|
+
|
|
+#include <linux/pci.h>
|
|
+#include <linux/delay.h>
|
|
+
|
|
+#include "reg.h"
|
|
+#include "base.h"
|
|
+#include "debug.h"
|
|
+
|
|
+/*Rate tables*/
|
|
+static const struct ath5k_rate_table ath5k_rt_11a = AR5K_RATES_11A;
|
|
+static const struct ath5k_rate_table ath5k_rt_11b = AR5K_RATES_11B;
|
|
+static const struct ath5k_rate_table ath5k_rt_11g = AR5K_RATES_11G;
|
|
+static const struct ath5k_rate_table ath5k_rt_turbo = AR5K_RATES_TURBO;
|
|
+static const struct ath5k_rate_table ath5k_rt_xr = AR5K_RATES_XR;
|
|
+
|
|
+/*Prototypes*/
|
|
+static int ath5k_hw_nic_reset(struct ath5k_hw *, u32);
|
|
+static int ath5k_hw_nic_wakeup(struct ath5k_hw *, int, bool);
|
|
+static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *, struct ath5k_desc *,
|
|
+ unsigned int, unsigned int, enum ath5k_pkt_type, unsigned int,
|
|
+ unsigned int, unsigned int, unsigned int, unsigned int, unsigned int,
|
|
+ unsigned int, unsigned int);
|
|
+static bool ath5k_hw_setup_xr_tx_desc(struct ath5k_hw *, struct ath5k_desc *,
|
|
+ unsigned int, unsigned int, unsigned int, unsigned int, unsigned int,
|
|
+ unsigned int);
|
|
+static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *, struct ath5k_desc *);
|
|
+static int ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *, struct ath5k_desc *,
|
|
+ unsigned int, unsigned int, enum ath5k_pkt_type, unsigned int,
|
|
+ unsigned int, unsigned int, unsigned int, unsigned int, unsigned int,
|
|
+ unsigned int, unsigned int);
|
|
+static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *, struct ath5k_desc *);
|
|
+static int ath5k_hw_proc_new_rx_status(struct ath5k_hw *, struct ath5k_desc *);
|
|
+static int ath5k_hw_proc_old_rx_status(struct ath5k_hw *, struct ath5k_desc *);
|
|
+static int ath5k_hw_get_capabilities(struct ath5k_hw *);
|
|
+
|
|
+static int ath5k_eeprom_init(struct ath5k_hw *);
|
|
+static int ath5k_eeprom_read_mac(struct ath5k_hw *, u8 *);
|
|
+
|
|
+static int ath5k_hw_enable_pspoll(struct ath5k_hw *, u8 *, u16);
|
|
+static int ath5k_hw_disable_pspoll(struct ath5k_hw *);
|
|
+
|
|
+/*
|
|
+ * Enable to overwrite the country code (use "00" for debug)
|
|
+ */
|
|
+#if 0
|
|
+#define COUNTRYCODE "00"
|
|
+#endif
|
|
+
|
|
+/*******************\
|
|
+ General Functions
|
|
+\*******************/
|
|
+
|
|
+/*
|
|
+ * Functions used internaly
|
|
+ */
|
|
+
|
|
+static inline unsigned int ath5k_hw_htoclock(unsigned int usec, bool turbo)
|
|
+{
|
|
+ return turbo == true ? (usec * 80) : (usec * 40);
|
|
+}
|
|
+
|
|
+static inline unsigned int ath5k_hw_clocktoh(unsigned int clock, bool turbo)
|
|
+{
|
|
+ return turbo == true ? (clock / 80) : (clock / 40);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Check if a register write has been completed
|
|
+ */
|
|
+int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val,
|
|
+ bool is_set)
|
|
+{
|
|
+ int i;
|
|
+ u32 data;
|
|
+
|
|
+ for (i = AR5K_TUNE_REGISTER_TIMEOUT; i > 0; i--) {
|
|
+ data = ath5k_hw_reg_read(ah, reg);
|
|
+ if ((is_set == true) && (data & flag))
|
|
+ break;
|
|
+ else if ((data & flag) == val)
|
|
+ break;
|
|
+ udelay(15);
|
|
+ }
|
|
+
|
|
+ return (i <= 0) ? -EAGAIN : 0;
|
|
+}
|
|
+
|
|
+
|
|
+/***************************************\
|
|
+ Attach/Detach Functions
|
|
+\***************************************/
|
|
+
|
|
+/*
|
|
+ * Check if the device is supported and initialize the needed structs
|
|
+ */
|
|
+struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version)
|
|
+{
|
|
+ struct ath5k_hw *ah;
|
|
+ u8 mac[ETH_ALEN];
|
|
+ int ret;
|
|
+ u32 srev;
|
|
+
|
|
+ /*If we passed the test malloc a ath5k_hw struct*/
|
|
+ ah = kzalloc(sizeof(struct ath5k_hw), GFP_KERNEL);
|
|
+ if (ah == NULL) {
|
|
+ ret = -ENOMEM;
|
|
+ ATH5K_ERR(sc, "out of memory\n");
|
|
+ goto err;
|
|
+ }
|
|
+
|
|
+ ah->ah_sc = sc;
|
|
+ ah->ah_iobase = sc->iobase;
|
|
+
|
|
+ /*
|
|
+ * HW information
|
|
+ */
|
|
+
|
|
+ /* Get reg domain from eeprom */
|
|
+ ath5k_get_regdomain(ah);
|
|
+
|
|
+ ah->ah_op_mode = IEEE80211_IF_TYPE_STA;
|
|
+ ah->ah_radar.r_enabled = AR5K_TUNE_RADAR_ALERT;
|
|
+ ah->ah_turbo = false;
|
|
+ ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER;
|
|
+ ah->ah_imr = 0;
|
|
+ ah->ah_atim_window = 0;
|
|
+ ah->ah_aifs = AR5K_TUNE_AIFS;
|
|
+ ah->ah_cw_min = AR5K_TUNE_CWMIN;
|
|
+ ah->ah_limit_tx_retries = AR5K_INIT_TX_RETRY;
|
|
+ ah->ah_software_retry = false;
|
|
+ ah->ah_ant_diversity = AR5K_TUNE_ANT_DIVERSITY;
|
|
+
|
|
+ /*
|
|
+ * Set the mac revision based on the pci id
|
|
+ */
|
|
+ ah->ah_version = mac_version;
|
|
+
|
|
+ /*Fill the ath5k_hw struct with the needed functions*/
|
|
+ if (ah->ah_version == AR5K_AR5212)
|
|
+ ah->ah_magic = AR5K_EEPROM_MAGIC_5212;
|
|
+ else if (ah->ah_version == AR5K_AR5211)
|
|
+ ah->ah_magic = AR5K_EEPROM_MAGIC_5211;
|
|
+
|
|
+ if (ah->ah_version == AR5K_AR5212) {
|
|
+ ah->ah_setup_tx_desc = ath5k_hw_setup_4word_tx_desc;
|
|
+ ah->ah_setup_xtx_desc = ath5k_hw_setup_xr_tx_desc;
|
|
+ ah->ah_proc_tx_desc = ath5k_hw_proc_4word_tx_status;
|
|
+ } else {
|
|
+ ah->ah_setup_tx_desc = ath5k_hw_setup_2word_tx_desc;
|
|
+ ah->ah_setup_xtx_desc = ath5k_hw_setup_xr_tx_desc;
|
|
+ ah->ah_proc_tx_desc = ath5k_hw_proc_2word_tx_status;
|
|
+ }
|
|
+
|
|
+ if (ah->ah_version == AR5K_AR5212)
|
|
+ ah->ah_proc_rx_desc = ath5k_hw_proc_new_rx_status;
|
|
+ else if (ah->ah_version <= AR5K_AR5211)
|
|
+ ah->ah_proc_rx_desc = ath5k_hw_proc_old_rx_status;
|
|
+
|
|
+ /* Bring device out of sleep and reset it's units */
|
|
+ ret = ath5k_hw_nic_wakeup(ah, AR5K_INIT_MODE, true);
|
|
+ if (ret)
|
|
+ goto err_free;
|
|
+
|
|
+ /* Get MAC, PHY and RADIO revisions */
|
|
+ srev = ath5k_hw_reg_read(ah, AR5K_SREV);
|
|
+ ah->ah_mac_srev = srev;
|
|
+ ah->ah_mac_version = AR5K_REG_MS(srev, AR5K_SREV_VER);
|
|
+ ah->ah_mac_revision = AR5K_REG_MS(srev, AR5K_SREV_REV);
|
|
+ ah->ah_phy_revision = ath5k_hw_reg_read(ah, AR5K_PHY_CHIP_ID) &
|
|
+ 0xffffffff;
|
|
+ ah->ah_radio_5ghz_revision = ath5k_hw_radio_revision(ah,
|
|
+ CHANNEL_5GHZ);
|
|
+
|
|
+ if (ah->ah_version == AR5K_AR5210)
|
|
+ ah->ah_radio_2ghz_revision = 0;
|
|
+ else
|
|
+ ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah,
|
|
+ CHANNEL_2GHZ);
|
|
+
|
|
+ /* Return on unsuported chips (unsupported eeprom etc) */
|
|
+ if(srev >= AR5K_SREV_VER_AR5416){
|
|
+ ATH5K_ERR(sc, "Device not yet supported.\n");
|
|
+ ret = -ENODEV;
|
|
+ goto err_free;
|
|
+ }
|
|
+
|
|
+ /* Identify single chip solutions */
|
|
+ if((srev <= AR5K_SREV_VER_AR5414) &&
|
|
+ (srev >= AR5K_SREV_VER_AR2424)) {
|
|
+ ah->ah_single_chip = true;
|
|
+ } else {
|
|
+ ah->ah_single_chip = false;
|
|
+ }
|
|
+
|
|
+ /* Single chip radio */
|
|
+ if (ah->ah_radio_2ghz_revision == ah->ah_radio_5ghz_revision)
|
|
+ ah->ah_radio_2ghz_revision = 0;
|
|
+
|
|
+ /* Identify the radio chip*/
|
|
+ if (ah->ah_version == AR5K_AR5210) {
|
|
+ ah->ah_radio = AR5K_RF5110;
|
|
+ } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5112) {
|
|
+ ah->ah_radio = AR5K_RF5111;
|
|
+ } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC1) {
|
|
+ ah->ah_radio = AR5K_RF5112;
|
|
+ } else {
|
|
+ ah->ah_radio = AR5K_RF5413;
|
|
+ }
|
|
+
|
|
+ ah->ah_phy = AR5K_PHY(0);
|
|
+
|
|
+ /*
|
|
+ * Get card capabilities, values, ...
|
|
+ */
|
|
+
|
|
+ ret = ath5k_eeprom_init(ah);
|
|
+ if (ret) {
|
|
+ ATH5K_ERR(sc, "unable to init EEPROM\n");
|
|
+ goto err_free;
|
|
+ }
|
|
+
|
|
+ /* Get misc capabilities */
|
|
+ ret = ath5k_hw_get_capabilities(ah);
|
|
+ if (ret) {
|
|
+ ATH5K_ERR(sc, "unable to get device capabilities: 0x%04x\n",
|
|
+ sc->pdev->device);
|
|
+ goto err_free;
|
|
+ }
|
|
+
|
|
+ /* Get MAC address */
|
|
+ ret = ath5k_eeprom_read_mac(ah, mac);
|
|
+ if (ret) {
|
|
+ ATH5K_ERR(sc, "unable to read address from EEPROM: 0x%04x\n",
|
|
+ sc->pdev->device);
|
|
+ goto err_free;
|
|
+ }
|
|
+
|
|
+ ath5k_hw_set_lladdr(ah, mac);
|
|
+ /* Set BSSID to bcast address: ff:ff:ff:ff:ff:ff for now */
|
|
+ memset(ah->bssid, 0xff, ETH_ALEN);
|
|
+ ath5k_hw_set_associd(ah, ah->bssid, 0);
|
|
+ ath5k_hw_set_opmode(ah);
|
|
+
|
|
+ ath5k_hw_set_rfgain_opt(ah);
|
|
+
|
|
+ return ah;
|
|
+err_free:
|
|
+ kfree(ah);
|
|
+err:
|
|
+ return ERR_PTR(ret);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Bring up MAC + PHY Chips
|
|
+ */
|
|
+static int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
|
|
+{
|
|
+ u32 turbo, mode, clock;
|
|
+ int ret;
|
|
+
|
|
+ turbo = 0;
|
|
+ mode = 0;
|
|
+ clock = 0;
|
|
+
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+
|
|
+ /* Wakeup the device */
|
|
+ ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
|
|
+ if (ret) {
|
|
+ ATH5K_ERR(ah->ah_sc, "failed to wakeup the MAC Chip\n");
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ if (ah->ah_version != AR5K_AR5210) {
|
|
+ /*
|
|
+ * Get channel mode flags
|
|
+ */
|
|
+
|
|
+ if (ah->ah_radio >= AR5K_RF5112) {
|
|
+ mode = AR5K_PHY_MODE_RAD_RF5112;
|
|
+ clock = AR5K_PHY_PLL_RF5112;
|
|
+ } else {
|
|
+ mode = AR5K_PHY_MODE_RAD_RF5111; /*Zero*/
|
|
+ clock = AR5K_PHY_PLL_RF5111; /*Zero*/
|
|
+ }
|
|
+
|
|
+ if (flags & CHANNEL_2GHZ) {
|
|
+ mode |= AR5K_PHY_MODE_FREQ_2GHZ;
|
|
+ clock |= AR5K_PHY_PLL_44MHZ;
|
|
+
|
|
+ if (flags & CHANNEL_CCK) {
|
|
+ mode |= AR5K_PHY_MODE_MOD_CCK;
|
|
+ } else if (flags & CHANNEL_OFDM) {
|
|
+ /* XXX Dynamic OFDM/CCK is not supported by the
|
|
+ * AR5211 so we set MOD_OFDM for plain g (no
|
|
+ * CCK headers) operation. We need to test
|
|
+ * this, 5211 might support ofdm-only g after
|
|
+ * all, there are also initial register values
|
|
+ * in the code for g mode (see initvals.c). */
|
|
+ if (ah->ah_version == AR5K_AR5211)
|
|
+ mode |= AR5K_PHY_MODE_MOD_OFDM;
|
|
+ else
|
|
+ mode |= AR5K_PHY_MODE_MOD_DYN;
|
|
+ } else {
|
|
+ ATH5K_ERR(ah->ah_sc,
|
|
+ "invalid radio modulation mode\n");
|
|
+ return -EINVAL;
|
|
+ }
|
|
+ } else if (flags & CHANNEL_5GHZ) {
|
|
+ mode |= AR5K_PHY_MODE_FREQ_5GHZ;
|
|
+ clock |= AR5K_PHY_PLL_40MHZ;
|
|
+
|
|
+ if (flags & CHANNEL_OFDM)
|
|
+ mode |= AR5K_PHY_MODE_MOD_OFDM;
|
|
+ else {
|
|
+ ATH5K_ERR(ah->ah_sc,
|
|
+ "invalid radio modulation mode\n");
|
|
+ return -EINVAL;
|
|
+ }
|
|
+ } else {
|
|
+ ATH5K_ERR(ah->ah_sc, "invalid radio frequency mode\n");
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ if (flags & CHANNEL_TURBO)
|
|
+ turbo = AR5K_PHY_TURBO_MODE | AR5K_PHY_TURBO_SHORT;
|
|
+ } else { /* Reset the device */
|
|
+
|
|
+ /* ...enable Atheros turbo mode if requested */
|
|
+ if (flags & CHANNEL_TURBO)
|
|
+ ath5k_hw_reg_write(ah, AR5K_PHY_TURBO_MODE,
|
|
+ AR5K_PHY_TURBO);
|
|
+ }
|
|
+
|
|
+ /* ...reset chipset and PCI device */
|
|
+ if (ah->ah_single_chip == false && ath5k_hw_nic_reset(ah,
|
|
+ AR5K_RESET_CTL_CHIP | AR5K_RESET_CTL_PCI)) {
|
|
+ ATH5K_ERR(ah->ah_sc, "failed to reset the MAC Chip + PCI\n");
|
|
+ return -EIO;
|
|
+ }
|
|
+
|
|
+ if (ah->ah_version == AR5K_AR5210)
|
|
+ udelay(2300);
|
|
+
|
|
+ /* ...wakeup again!*/
|
|
+ ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
|
|
+ if (ret) {
|
|
+ ATH5K_ERR(ah->ah_sc, "failed to resume the MAC Chip\n");
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ /* ...final warm reset */
|
|
+ if (ath5k_hw_nic_reset(ah, 0)) {
|
|
+ ATH5K_ERR(ah->ah_sc, "failed to warm reset the MAC Chip\n");
|
|
+ return -EIO;
|
|
+ }
|
|
+
|
|
+ if (ah->ah_version != AR5K_AR5210) {
|
|
+ /* ...set the PHY operating mode */
|
|
+ ath5k_hw_reg_write(ah, clock, AR5K_PHY_PLL);
|
|
+ udelay(300);
|
|
+
|
|
+ ath5k_hw_reg_write(ah, mode, AR5K_PHY_MODE);
|
|
+ ath5k_hw_reg_write(ah, turbo, AR5K_PHY_TURBO);
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Get the rate table for a specific operation mode
|
|
+ */
|
|
+const struct ath5k_rate_table *ath5k_hw_get_rate_table(struct ath5k_hw *ah,
|
|
+ unsigned int mode)
|
|
+{
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+
|
|
+ if (!test_bit(mode, ah->ah_capabilities.cap_mode))
|
|
+ return NULL;
|
|
+
|
|
+ /* Get rate tables */
|
|
+ switch (mode) {
|
|
+ case MODE_IEEE80211A:
|
|
+ return &ath5k_rt_11a;
|
|
+ case MODE_ATHEROS_TURBO:
|
|
+ return &ath5k_rt_turbo;
|
|
+ case MODE_IEEE80211B:
|
|
+ return &ath5k_rt_11b;
|
|
+ case MODE_IEEE80211G:
|
|
+ return &ath5k_rt_11g;
|
|
+ case MODE_ATHEROS_TURBOG:
|
|
+ return &ath5k_rt_xr;
|
|
+ }
|
|
+
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Free the ath5k_hw struct
|
|
+ */
|
|
+void ath5k_hw_detach(struct ath5k_hw *ah)
|
|
+{
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+
|
|
+ if (ah->ah_rf_banks != NULL)
|
|
+ kfree(ah->ah_rf_banks);
|
|
+
|
|
+ /* assume interrupts are down */
|
|
+ kfree(ah);
|
|
+}
|
|
+
|
|
+/****************************\
|
|
+ Reset function and helpers
|
|
+\****************************/
|
|
+
|
|
+/**
|
|
+ * ath5k_hw_write_ofdm_timings - set OFDM timings on AR5212
|
|
+ *
|
|
+ * @ah: the &struct ath5k_hw
|
|
+ * @channel: the currently set channel upon reset
|
|
+ *
|
|
+ * Write the OFDM timings for the AR5212 upon reset. This is a helper for
|
|
+ * ath5k_hw_reset(). This seems to tune the PLL a specified frequency
|
|
+ * depending on the bandwidth of the channel.
|
|
+ *
|
|
+ */
|
|
+static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah,
|
|
+ struct ieee80211_channel *channel)
|
|
+{
|
|
+ /* Get exponent and mantissa and set it */
|
|
+ u32 coef_scaled, coef_exp, coef_man,
|
|
+ ds_coef_exp, ds_coef_man, clock;
|
|
+
|
|
+ if (!(ah->ah_version == AR5K_AR5212) ||
|
|
+ !(channel->val & CHANNEL_OFDM))
|
|
+ BUG();
|
|
+
|
|
+ /* Seems there are two PLLs, one for baseband sampling and one
|
|
+ * for tuning. Tuning basebands are 40 MHz or 80MHz when in
|
|
+ * turbo. */
|
|
+ clock = channel->val & CHANNEL_TURBO ? 80 : 40;
|
|
+ coef_scaled = ((5 * (clock << 24)) / 2) /
|
|
+ channel->freq;
|
|
+
|
|
+ for (coef_exp = 31; coef_exp > 0; coef_exp--)
|
|
+ if ((coef_scaled >> coef_exp) & 0x1)
|
|
+ break;
|
|
+
|
|
+ if (!coef_exp)
|
|
+ return -EINVAL;
|
|
+
|
|
+ coef_exp = 14 - (coef_exp - 24);
|
|
+ coef_man = coef_scaled +
|
|
+ (1 << (24 - coef_exp - 1));
|
|
+ ds_coef_man = coef_man >> (24 - coef_exp);
|
|
+ ds_coef_exp = coef_exp - 16;
|
|
+
|
|
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3,
|
|
+ AR5K_PHY_TIMING_3_DSC_MAN, ds_coef_man);
|
|
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3,
|
|
+ AR5K_PHY_TIMING_3_DSC_EXP, ds_coef_exp);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * ath5k_hw_write_rate_duration - set rate duration during hw resets
|
|
+ *
|
|
+ * @ah: the &struct ath5k_hw
|
|
+ * @driver_mode: one of enum ieee80211_phymode or our one of our own
|
|
+ * vendor modes
|
|
+ *
|
|
+ * Write the rate duration table for the current mode upon hw reset. This
|
|
+ * is a helper for ath5k_hw_reset(). It seems all this is doing is setting
|
|
+ * an ACK timeout for the hardware for the current mode for each rate. The
|
|
+ * rates which are capable of short preamble (802.11b rates 2Mbps, 5.5Mbps,
|
|
+ * and 11Mbps) have another register for the short preamble ACK timeout
|
|
+ * calculation.
|
|
+ *
|
|
+ */
|
|
+static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah,
|
|
+ unsigned int driver_mode)
|
|
+{
|
|
+ struct ath5k_softc *sc = ah->ah_sc;
|
|
+ const struct ath5k_rate_table *rt;
|
|
+ unsigned int i;
|
|
+
|
|
+ /* Get rate table for the current operating mode */
|
|
+ rt = ath5k_hw_get_rate_table(ah,
|
|
+ driver_mode);
|
|
+
|
|
+ /* Write rate duration table */
|
|
+ for (i = 0; i < rt->rate_count; i++) {
|
|
+ const struct ath5k_rate *rate, *control_rate;
|
|
+ u32 reg;
|
|
+ u16 tx_time;
|
|
+
|
|
+ rate = &rt->rates[i];
|
|
+ control_rate = &rt->rates[rate->control_rate];
|
|
+
|
|
+ /* Set ACK timeout */
|
|
+ reg = AR5K_RATE_DUR(rate->rate_code);
|
|
+
|
|
+ /* An ACK frame consists of 10 bytes. If you add the FCS,
|
|
+ * which ieee80211_generic_frame_duration() adds,
|
|
+ * its 14 bytes. Note we use the control rate and not the
|
|
+ * actual rate for this rate. See mac80211 tx.c
|
|
+ * ieee80211_duration() for a brief description of
|
|
+ * what rate we should choose to TX ACKs. */
|
|
+ tx_time = ieee80211_generic_frame_duration(sc->hw,
|
|
+ sc->iface_id, 10, control_rate->rate_kbps/100);
|
|
+
|
|
+ ath5k_hw_reg_write(ah, tx_time, reg);
|
|
+
|
|
+ if (!HAS_SHPREAMBLE(i))
|
|
+ continue;
|
|
+
|
|
+ /*
|
|
+ * We're not distinguishing short preamble here,
|
|
+ * This is true, all we'll get is a longer value here
|
|
+ * which is not necessarilly bad. We could use
|
|
+ * export ieee80211_frame_duration() but that needs to be
|
|
+ * fixed first to be properly used by mac802111 drivers:
|
|
+ *
|
|
+ * - remove erp stuff and let the routine figure ofdm
|
|
+ * erp rates
|
|
+ * - remove passing argument ieee80211_local as
|
|
+ * drivers don't have access to it
|
|
+ * - move drivers using ieee80211_generic_frame_duration()
|
|
+ * to this
|
|
+ */
|
|
+ ath5k_hw_reg_write(ah, tx_time,
|
|
+ reg + (AR5K_SET_SHORT_PREAMBLE << 2));
|
|
+ }
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Main reset function
|
|
+ */
|
|
+int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
|
|
+ struct ieee80211_channel *channel, bool change_channel)
|
|
+{
|
|
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
|
|
+ u32 data, s_seq, s_ant, s_led[3];
|
|
+ unsigned int i, mode, freq, ee_mode, ant[2], driver_mode = -1;
|
|
+ int ret;
|
|
+
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+
|
|
+ s_seq = 0;
|
|
+ s_ant = 0;
|
|
+ ee_mode = 0;
|
|
+ freq = 0;
|
|
+ mode = 0;
|
|
+
|
|
+ /*
|
|
+ * Save some registers before a reset
|
|
+ */
|
|
+ /*DCU/Antenna selection not available on 5210*/
|
|
+ if (ah->ah_version != AR5K_AR5210) {
|
|
+ if (change_channel == true) {
|
|
+ /* Seq number for queue 0 -do this for all queues ? */
|
|
+ s_seq = ath5k_hw_reg_read(ah,
|
|
+ AR5K_QUEUE_DFS_SEQNUM(0));
|
|
+ /*Default antenna*/
|
|
+ s_ant = ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /*GPIOs*/
|
|
+ s_led[0] = ath5k_hw_reg_read(ah, AR5K_PCICFG) & AR5K_PCICFG_LEDSTATE;
|
|
+ s_led[1] = ath5k_hw_reg_read(ah, AR5K_GPIOCR);
|
|
+ s_led[2] = ath5k_hw_reg_read(ah, AR5K_GPIODO);
|
|
+
|
|
+ if (change_channel == true && ah->ah_rf_banks != NULL)
|
|
+ ath5k_hw_get_rf_gain(ah);
|
|
+
|
|
+
|
|
+ /*Wakeup the device*/
|
|
+ ret = ath5k_hw_nic_wakeup(ah, channel->val, false);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ /*
|
|
+ * Initialize operating mode
|
|
+ */
|
|
+ ah->ah_op_mode = op_mode;
|
|
+
|
|
+ /*
|
|
+ * 5111/5112 Settings
|
|
+ * 5210 only comes with RF5110
|
|
+ */
|
|
+ if (ah->ah_version != AR5K_AR5210) {
|
|
+ if (ah->ah_radio != AR5K_RF5111 &&
|
|
+ ah->ah_radio != AR5K_RF5112 &&
|
|
+ ah->ah_radio != AR5K_RF5413) {
|
|
+ ATH5K_ERR(ah->ah_sc,
|
|
+ "invalid phy radio: %u\n", ah->ah_radio);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ switch (channel->val & CHANNEL_MODES) {
|
|
+ case CHANNEL_A:
|
|
+ mode = AR5K_INI_VAL_11A;
|
|
+ freq = AR5K_INI_RFGAIN_5GHZ;
|
|
+ ee_mode = AR5K_EEPROM_MODE_11A;
|
|
+ driver_mode = MODE_IEEE80211A;
|
|
+ break;
|
|
+ case CHANNEL_G:
|
|
+ mode = AR5K_INI_VAL_11G;
|
|
+ freq = AR5K_INI_RFGAIN_2GHZ;
|
|
+ ee_mode = AR5K_EEPROM_MODE_11G;
|
|
+ driver_mode = MODE_IEEE80211G;
|
|
+ break;
|
|
+ case CHANNEL_B:
|
|
+ mode = AR5K_INI_VAL_11B;
|
|
+ freq = AR5K_INI_RFGAIN_2GHZ;
|
|
+ ee_mode = AR5K_EEPROM_MODE_11B;
|
|
+ driver_mode = MODE_IEEE80211B;
|
|
+ break;
|
|
+ case CHANNEL_T:
|
|
+ mode = AR5K_INI_VAL_11A_TURBO;
|
|
+ freq = AR5K_INI_RFGAIN_5GHZ;
|
|
+ ee_mode = AR5K_EEPROM_MODE_11A;
|
|
+ driver_mode = MODE_ATHEROS_TURBO;
|
|
+ break;
|
|
+ /*Is this ok on 5211 too ?*/
|
|
+ case CHANNEL_TG:
|
|
+ mode = AR5K_INI_VAL_11G_TURBO;
|
|
+ freq = AR5K_INI_RFGAIN_2GHZ;
|
|
+ ee_mode = AR5K_EEPROM_MODE_11G;
|
|
+ driver_mode = MODE_ATHEROS_TURBOG;
|
|
+ break;
|
|
+ case CHANNEL_XR:
|
|
+ if (ah->ah_version == AR5K_AR5211) {
|
|
+ ATH5K_ERR(ah->ah_sc,
|
|
+ "XR mode not available on 5211");
|
|
+ return -EINVAL;
|
|
+ }
|
|
+ mode = AR5K_INI_VAL_XR;
|
|
+ freq = AR5K_INI_RFGAIN_5GHZ;
|
|
+ ee_mode = AR5K_EEPROM_MODE_11A;
|
|
+ driver_mode = MODE_IEEE80211A;
|
|
+ break;
|
|
+ default:
|
|
+ ATH5K_ERR(ah->ah_sc,
|
|
+ "invalid channel: %d\n", channel->freq);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ /* PHY access enable */
|
|
+ ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0));
|
|
+
|
|
+ }
|
|
+
|
|
+ ret = ath5k_hw_write_initvals(ah, mode, change_channel);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ /*
|
|
+ * 5211/5212 Specific
|
|
+ */
|
|
+ if (ah->ah_version != AR5K_AR5210) {
|
|
+ /*
|
|
+ * Write initial RF gain settings
|
|
+ * This should work for both 5111/5112
|
|
+ */
|
|
+ ret = ath5k_hw_rfgain(ah, freq);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ mdelay(1);
|
|
+
|
|
+ /*
|
|
+ * Write some more initial register settings
|
|
+ */
|
|
+ if (ah->ah_version > AR5K_AR5211){ /* found on 5213+ */
|
|
+ ath5k_hw_reg_write(ah, 0x0002a002, AR5K_PHY(11));
|
|
+
|
|
+ if (channel->val == CHANNEL_G)
|
|
+ ath5k_hw_reg_write(ah, 0x00f80d80, AR5K_PHY(83)); /* 0x00fc0ec0 */
|
|
+ else
|
|
+ ath5k_hw_reg_write(ah, 0x00000000, AR5K_PHY(83));
|
|
+
|
|
+ ath5k_hw_reg_write(ah, 0x000001b5, 0xa228); /* 0x000009b5 */
|
|
+ ath5k_hw_reg_write(ah, 0x000009b5, 0xa228);
|
|
+ ath5k_hw_reg_write(ah, 0x0000000f, 0x8060);
|
|
+ ath5k_hw_reg_write(ah, 0x00000000, 0xa254);
|
|
+ ath5k_hw_reg_write(ah, 0x0000000e, AR5K_PHY_SCAL);
|
|
+ }
|
|
+
|
|
+ /* Fix for first revision of the RF5112 RF chipset */
|
|
+ if (ah->ah_radio >= AR5K_RF5112 &&
|
|
+ ah->ah_radio_5ghz_revision <
|
|
+ AR5K_SREV_RAD_5112A) {
|
|
+ ath5k_hw_reg_write(ah, AR5K_PHY_CCKTXCTL_WORLD,
|
|
+ AR5K_PHY_CCKTXCTL);
|
|
+ if (channel->val & CHANNEL_5GHZ)
|
|
+ data = 0xffb81020;
|
|
+ else
|
|
+ data = 0xffb80d20;
|
|
+ ath5k_hw_reg_write(ah, data, AR5K_PHY_FRAME_CTL);
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Set TX power (FIXME)
|
|
+ */
|
|
+ ret = ath5k_hw_txpower(ah, channel, AR5K_TUNE_DEFAULT_TXPOWER);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ /* Write rate duration table */
|
|
+ if (ah->ah_version == AR5K_AR5212)
|
|
+ ath5k_hw_write_rate_duration(ah, driver_mode);
|
|
+
|
|
+ /*
|
|
+ * Write RF registers
|
|
+ * TODO:Does this work on 5211 (5111) ?
|
|
+ */
|
|
+ ret = ath5k_hw_rfregs(ah, channel, mode);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ /*
|
|
+ * Configure additional registers
|
|
+ */
|
|
+
|
|
+ /* Write OFDM timings on 5212*/
|
|
+ if (ah->ah_version == AR5K_AR5212 &&
|
|
+ channel->val & CHANNEL_OFDM) {
|
|
+ ret = ath5k_hw_write_ofdm_timings(ah, channel);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ /*Enable/disable 802.11b mode on 5111
|
|
+ (enable 2111 frequency converter + CCK)*/
|
|
+ if (ah->ah_radio == AR5K_RF5111) {
|
|
+ if (driver_mode == MODE_IEEE80211B)
|
|
+ AR5K_REG_ENABLE_BITS(ah, AR5K_TXCFG,
|
|
+ AR5K_TXCFG_B_MODE);
|
|
+ else
|
|
+ AR5K_REG_DISABLE_BITS(ah, AR5K_TXCFG,
|
|
+ AR5K_TXCFG_B_MODE);
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Set channel and calibrate the PHY
|
|
+ */
|
|
+ ret = ath5k_hw_channel(ah, channel);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ /* Set antenna mode */
|
|
+ AR5K_REG_MASKED_BITS(ah, AR5K_PHY(0x44),
|
|
+ ah->ah_antenna[ee_mode][0], 0xfffffc06);
|
|
+
|
|
+ /*
|
|
+ * In case a fixed antenna was set as default
|
|
+ * write the same settings on both AR5K_PHY_ANT_SWITCH_TABLE
|
|
+ * registers.
|
|
+ */
|
|
+ if (s_ant != 0){
|
|
+ if (s_ant == AR5K_ANT_FIXED_A) /* 1 - Main */
|
|
+ ant[0] = ant[1] = AR5K_ANT_FIXED_A;
|
|
+ else /* 2 - Aux */
|
|
+ ant[0] = ant[1] = AR5K_ANT_FIXED_B;
|
|
+ } else {
|
|
+ ant[0] = AR5K_ANT_FIXED_A;
|
|
+ ant[1] = AR5K_ANT_FIXED_B;
|
|
+ }
|
|
+
|
|
+ ath5k_hw_reg_write(ah, ah->ah_antenna[ee_mode][ant[0]],
|
|
+ AR5K_PHY_ANT_SWITCH_TABLE_0);
|
|
+ ath5k_hw_reg_write(ah, ah->ah_antenna[ee_mode][ant[1]],
|
|
+ AR5K_PHY_ANT_SWITCH_TABLE_1);
|
|
+
|
|
+ /* Commit values from EEPROM */
|
|
+ if (ah->ah_radio == AR5K_RF5111)
|
|
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_FRAME_CTL,
|
|
+ AR5K_PHY_FRAME_CTL_TX_CLIP, ee->ee_tx_clip);
|
|
+
|
|
+ ath5k_hw_reg_write(ah,
|
|
+ AR5K_PHY_NF_SVAL(ee->ee_noise_floor_thr[ee_mode]),
|
|
+ AR5K_PHY(0x5a));
|
|
+
|
|
+ AR5K_REG_MASKED_BITS(ah, AR5K_PHY(0x11),
|
|
+ (ee->ee_switch_settling[ee_mode] << 7) & 0x3f80,
|
|
+ 0xffffc07f);
|
|
+ AR5K_REG_MASKED_BITS(ah, AR5K_PHY(0x12),
|
|
+ (ee->ee_ant_tx_rx[ee_mode] << 12) & 0x3f000,
|
|
+ 0xfffc0fff);
|
|
+ AR5K_REG_MASKED_BITS(ah, AR5K_PHY(0x14),
|
|
+ (ee->ee_adc_desired_size[ee_mode] & 0x00ff) |
|
|
+ ((ee->ee_pga_desired_size[ee_mode] << 8) & 0xff00),
|
|
+ 0xffff0000);
|
|
+
|
|
+ ath5k_hw_reg_write(ah,
|
|
+ (ee->ee_tx_end2xpa_disable[ee_mode] << 24) |
|
|
+ (ee->ee_tx_end2xpa_disable[ee_mode] << 16) |
|
|
+ (ee->ee_tx_frm2xpa_enable[ee_mode] << 8) |
|
|
+ (ee->ee_tx_frm2xpa_enable[ee_mode]), AR5K_PHY(0x0d));
|
|
+
|
|
+ AR5K_REG_MASKED_BITS(ah, AR5K_PHY(0x0a),
|
|
+ ee->ee_tx_end2xlna_enable[ee_mode] << 8, 0xffff00ff);
|
|
+ AR5K_REG_MASKED_BITS(ah, AR5K_PHY(0x19),
|
|
+ (ee->ee_thr_62[ee_mode] << 12) & 0x7f000, 0xfff80fff);
|
|
+ AR5K_REG_MASKED_BITS(ah, AR5K_PHY(0x49), 4, 0xffffff01);
|
|
+
|
|
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ,
|
|
+ AR5K_PHY_IQ_CORR_ENABLE |
|
|
+ (ee->ee_i_cal[ee_mode] << AR5K_PHY_IQ_CORR_Q_I_COFF_S) |
|
|
+ ee->ee_q_cal[ee_mode]);
|
|
+
|
|
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1)
|
|
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN_2GHZ,
|
|
+ AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX,
|
|
+ ee->ee_margin_tx_rx[ee_mode]);
|
|
+
|
|
+ } else {
|
|
+ mdelay(1);
|
|
+ /* Disable phy and wait */
|
|
+ ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT);
|
|
+ mdelay(1);
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Restore saved values
|
|
+ */
|
|
+ /*DCU/Antenna selection not available on 5210*/
|
|
+ if (ah->ah_version != AR5K_AR5210) {
|
|
+ ath5k_hw_reg_write(ah, s_seq, AR5K_QUEUE_DFS_SEQNUM(0));
|
|
+ ath5k_hw_reg_write(ah, s_ant, AR5K_DEFAULT_ANTENNA);
|
|
+ }
|
|
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, s_led[0]);
|
|
+ ath5k_hw_reg_write(ah, s_led[1], AR5K_GPIOCR);
|
|
+ ath5k_hw_reg_write(ah, s_led[2], AR5K_GPIODO);
|
|
+
|
|
+ /*
|
|
+ * Misc
|
|
+ */
|
|
+ /* XXX: add ah->aid once mac80211 gives this to us */
|
|
+ ath5k_hw_set_associd(ah, ah->bssid, 0);
|
|
+
|
|
+ ath5k_hw_set_opmode(ah);
|
|
+ /*PISR/SISR Not available on 5210*/
|
|
+ if (ah->ah_version != AR5K_AR5210) {
|
|
+ ath5k_hw_reg_write(ah, 0xffffffff, AR5K_PISR);
|
|
+ /* If we later allow tuning for this, store into sc structure */
|
|
+ data = AR5K_TUNE_RSSI_THRES |
|
|
+ AR5K_TUNE_BMISS_THRES << AR5K_RSSI_THR_BMISS_S;
|
|
+ ath5k_hw_reg_write(ah, data, AR5K_RSSI_THR);
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Set Rx/Tx DMA Configuration
|
|
+ *(passing dma size not available on 5210)
|
|
+ */
|
|
+ if (ah->ah_version != AR5K_AR5210) {
|
|
+ AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG, AR5K_TXCFG_SDMAMR,
|
|
+ AR5K_DMASIZE_512B | AR5K_TXCFG_DMASIZE);
|
|
+ AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_SDMAMW,
|
|
+ AR5K_DMASIZE_512B);
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Enable the PHY and wait until completion
|
|
+ */
|
|
+ ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT);
|
|
+
|
|
+ /*
|
|
+ * 5111/5112 Specific
|
|
+ */
|
|
+ if (ah->ah_version != AR5K_AR5210) {
|
|
+ data = ath5k_hw_reg_read(ah, AR5K_PHY_RX_DELAY) &
|
|
+ AR5K_PHY_RX_DELAY_M;
|
|
+ data = (channel->val & CHANNEL_CCK) ?
|
|
+ ((data << 2) / 22) : (data / 10);
|
|
+
|
|
+ udelay(100 + data);
|
|
+ } else {
|
|
+ mdelay(1);
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Enable calibration and wait until completion
|
|
+ */
|
|
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL,
|
|
+ AR5K_PHY_AGCCTL_CAL);
|
|
+
|
|
+ if (ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL,
|
|
+ AR5K_PHY_AGCCTL_CAL, 0, false)) {
|
|
+ ATH5K_ERR(ah->ah_sc, "calibration timeout (%uMHz)\n",
|
|
+ channel->freq);
|
|
+ return -EAGAIN;
|
|
+ }
|
|
+
|
|
+ ret = ath5k_hw_noise_floor_calibration(ah, channel->freq);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ ah->ah_calibration = false;
|
|
+
|
|
+ /* A and G modes can use QAM modulation which requires enabling
|
|
+ * I and Q calibration. Don't bother in B mode. */
|
|
+ if (!(driver_mode == MODE_IEEE80211B)) {
|
|
+ ah->ah_calibration = true;
|
|
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ,
|
|
+ AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15);
|
|
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ,
|
|
+ AR5K_PHY_IQ_RUN);
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Reset queues and start beacon timers at the end of the reset routine
|
|
+ */
|
|
+ for (i = 0; i < ah->ah_capabilities.cap_queues.q_tx_num; i++) {
|
|
+ /*No QCU on 5210*/
|
|
+ if (ah->ah_version != AR5K_AR5210)
|
|
+ AR5K_REG_WRITE_Q(ah, AR5K_QUEUE_QCUMASK(i), i);
|
|
+
|
|
+ ret = ath5k_hw_reset_tx_queue(ah, i);
|
|
+ if (ret) {
|
|
+ ATH5K_ERR(ah->ah_sc,
|
|
+ "failed to reset TX queue #%d\n", i);
|
|
+ return ret;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /* Pre-enable interrupts on 5211/5212*/
|
|
+ if (ah->ah_version != AR5K_AR5210)
|
|
+ ath5k_hw_set_intr(ah, AR5K_INT_RX | AR5K_INT_TX |
|
|
+ AR5K_INT_FATAL);
|
|
+
|
|
+ /*
|
|
+ * Set RF kill flags if supported by the device (read from the EEPROM)
|
|
+ * Disable gpio_intr for now since it results system hang.
|
|
+ * TODO: Handle this in ath5k_intr
|
|
+ */
|
|
+#if 0
|
|
+ if (AR5K_EEPROM_HDR_RFKILL(ah->ah_capabilities.cap_eeprom.ee_header)) {
|
|
+ ath5k_hw_set_gpio_input(ah, 0);
|
|
+ ah->ah_gpio[0] = ath5k_hw_get_gpio(ah, 0);
|
|
+ if (ah->ah_gpio[0] == 0)
|
|
+ ath5k_hw_set_gpio_intr(ah, 0, 1);
|
|
+ else
|
|
+ ath5k_hw_set_gpio_intr(ah, 0, 0);
|
|
+ }
|
|
+#endif
|
|
+
|
|
+ /*
|
|
+ * Set the 32MHz reference clock on 5212 phy clock sleep register
|
|
+ */
|
|
+ if (ah->ah_version == AR5K_AR5212) {
|
|
+ ath5k_hw_reg_write(ah, AR5K_PHY_SCR_32MHZ, AR5K_PHY_SCR);
|
|
+ ath5k_hw_reg_write(ah, AR5K_PHY_SLMT_32MHZ, AR5K_PHY_SLMT);
|
|
+ ath5k_hw_reg_write(ah, AR5K_PHY_SCAL_32MHZ, AR5K_PHY_SCAL);
|
|
+ ath5k_hw_reg_write(ah, AR5K_PHY_SCLOCK_32MHZ, AR5K_PHY_SCLOCK);
|
|
+ ath5k_hw_reg_write(ah, AR5K_PHY_SDELAY_32MHZ, AR5K_PHY_SDELAY);
|
|
+ ath5k_hw_reg_write(ah, ah->ah_radio == AR5K_RF5111 ?
|
|
+ AR5K_PHY_SPENDING_RF5111 : AR5K_PHY_SPENDING_RF5112,
|
|
+ AR5K_PHY_SPENDING);
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Disable beacons and reset the register
|
|
+ */
|
|
+ AR5K_REG_DISABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE |
|
|
+ AR5K_BEACON_RESET_TSF);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Reset chipset
|
|
+ */
|
|
+static int ath5k_hw_nic_reset(struct ath5k_hw *ah, u32 val)
|
|
+{
|
|
+ int ret;
|
|
+ u32 mask = val ? val : ~0U;
|
|
+
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+
|
|
+ /* Read-and-clear RX Descriptor Pointer*/
|
|
+ ath5k_hw_reg_read(ah, AR5K_RXDP);
|
|
+
|
|
+ /*
|
|
+ * Reset the device and wait until success
|
|
+ */
|
|
+ ath5k_hw_reg_write(ah, val, AR5K_RESET_CTL);
|
|
+
|
|
+ /* Wait at least 128 PCI clocks */
|
|
+ udelay(15);
|
|
+
|
|
+ if (ah->ah_version == AR5K_AR5210) {
|
|
+ val &= AR5K_RESET_CTL_CHIP;
|
|
+ mask &= AR5K_RESET_CTL_CHIP;
|
|
+ } else {
|
|
+ val &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_BASEBAND;
|
|
+ mask &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_BASEBAND;
|
|
+ }
|
|
+
|
|
+ ret = ath5k_hw_register_timeout(ah, AR5K_RESET_CTL, mask, val, false);
|
|
+
|
|
+ /*
|
|
+ * Reset configuration register (for hw byte-swap). Note that this
|
|
+ * is only set for big endian. We do the necessary magic in
|
|
+ * AR5K_INIT_CFG.
|
|
+ */
|
|
+ if ((val & AR5K_RESET_CTL_PCU) == 0)
|
|
+ ath5k_hw_reg_write(ah, AR5K_INIT_CFG, AR5K_CFG);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Power management functions
|
|
+ */
|
|
+
|
|
+/*
|
|
+ * Sleep control
|
|
+ */
|
|
+int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode,
|
|
+ bool set_chip, u16 sleep_duration)
|
|
+{
|
|
+ unsigned int i;
|
|
+ u32 staid;
|
|
+
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+ staid = ath5k_hw_reg_read(ah, AR5K_STA_ID1);
|
|
+
|
|
+ switch (mode) {
|
|
+ case AR5K_PM_AUTO:
|
|
+ staid &= ~AR5K_STA_ID1_DEFAULT_ANTENNA;
|
|
+ /* fallthrough */
|
|
+ case AR5K_PM_NETWORK_SLEEP:
|
|
+ if (set_chip == true)
|
|
+ ath5k_hw_reg_write(ah,
|
|
+ AR5K_SLEEP_CTL_SLE | sleep_duration,
|
|
+ AR5K_SLEEP_CTL);
|
|
+
|
|
+ staid |= AR5K_STA_ID1_PWR_SV;
|
|
+ break;
|
|
+
|
|
+ case AR5K_PM_FULL_SLEEP:
|
|
+ if (set_chip == true)
|
|
+ ath5k_hw_reg_write(ah, AR5K_SLEEP_CTL_SLE_SLP,
|
|
+ AR5K_SLEEP_CTL);
|
|
+
|
|
+ staid |= AR5K_STA_ID1_PWR_SV;
|
|
+ break;
|
|
+
|
|
+ case AR5K_PM_AWAKE:
|
|
+ if (set_chip == false)
|
|
+ goto commit;
|
|
+
|
|
+ ath5k_hw_reg_write(ah, AR5K_SLEEP_CTL_SLE_WAKE,
|
|
+ AR5K_SLEEP_CTL);
|
|
+
|
|
+ for (i = 5000; i > 0; i--) {
|
|
+ /* Check if the chip did wake up */
|
|
+ if ((ath5k_hw_reg_read(ah, AR5K_PCICFG) &
|
|
+ AR5K_PCICFG_SPWR_DN) == 0)
|
|
+ break;
|
|
+
|
|
+ /* Wait a bit and retry */
|
|
+ udelay(200);
|
|
+ ath5k_hw_reg_write(ah, AR5K_SLEEP_CTL_SLE_WAKE,
|
|
+ AR5K_SLEEP_CTL);
|
|
+ }
|
|
+
|
|
+ /* Fail if the chip didn't wake up */
|
|
+ if (i <= 0)
|
|
+ return -EIO;
|
|
+
|
|
+ staid &= ~AR5K_STA_ID1_PWR_SV;
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+commit:
|
|
+ ah->ah_power_mode = mode;
|
|
+ ath5k_hw_reg_write(ah, staid, AR5K_STA_ID1);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/***********************\
|
|
+ DMA Related Functions
|
|
+\***********************/
|
|
+
|
|
+/*
|
|
+ * Receive functions
|
|
+ */
|
|
+
|
|
+/*
|
|
+ * Start DMA receive
|
|
+ */
|
|
+void ath5k_hw_start_rx(struct ath5k_hw *ah)
|
|
+{
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+ ath5k_hw_reg_write(ah, AR5K_CR_RXE, AR5K_CR);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Stop DMA receive
|
|
+ */
|
|
+int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah)
|
|
+{
|
|
+ unsigned int i;
|
|
+
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+ ath5k_hw_reg_write(ah, AR5K_CR_RXD, AR5K_CR);
|
|
+
|
|
+ /*
|
|
+ * It may take some time to disable the DMA receive unit
|
|
+ */
|
|
+ for (i = 2000; i > 0 &&
|
|
+ (ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_CR_RXE) != 0;
|
|
+ i--)
|
|
+ udelay(10);
|
|
+
|
|
+ return i ? 0 : -EBUSY;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Get the address of the RX Descriptor
|
|
+ */
|
|
+u32 ath5k_hw_get_rx_buf(struct ath5k_hw *ah)
|
|
+{
|
|
+ return ath5k_hw_reg_read(ah, AR5K_RXDP);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Set the address of the RX Descriptor
|
|
+ */
|
|
+void ath5k_hw_put_rx_buf(struct ath5k_hw *ah, u32 phys_addr)
|
|
+{
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+
|
|
+ /*TODO:Shouldn't we check if RX is enabled first ?*/
|
|
+ ath5k_hw_reg_write(ah, phys_addr, AR5K_RXDP);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Transmit functions
|
|
+ */
|
|
+
|
|
+/*
|
|
+ * Start DMA transmit for a specific queue
|
|
+ * (see also QCU/DCU functions)
|
|
+ */
|
|
+int ath5k_hw_tx_start(struct ath5k_hw *ah, unsigned int queue)
|
|
+{
|
|
+ u32 tx_queue;
|
|
+
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+ AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
|
|
+
|
|
+ /* Return if queue is declared inactive */
|
|
+ if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE)
|
|
+ return -EIO;
|
|
+
|
|
+ if (ah->ah_version == AR5K_AR5210) {
|
|
+ tx_queue = ath5k_hw_reg_read(ah, AR5K_CR);
|
|
+
|
|
+ /*
|
|
+ * Set the queue by type on 5210
|
|
+ */
|
|
+ switch (ah->ah_txq[queue].tqi_type) {
|
|
+ case AR5K_TX_QUEUE_DATA:
|
|
+ tx_queue |= AR5K_CR_TXE0 & ~AR5K_CR_TXD0;
|
|
+ break;
|
|
+ case AR5K_TX_QUEUE_BEACON:
|
|
+ tx_queue |= AR5K_CR_TXE1 & ~AR5K_CR_TXD1;
|
|
+ ath5k_hw_reg_write(ah, AR5K_BCR_TQ1V | AR5K_BCR_BDMAE,
|
|
+ AR5K_BSR);
|
|
+ break;
|
|
+ case AR5K_TX_QUEUE_CAB:
|
|
+ tx_queue |= AR5K_CR_TXE1 & ~AR5K_CR_TXD1;
|
|
+ ath5k_hw_reg_write(ah, AR5K_BCR_TQ1FV | AR5K_BCR_TQ1V |
|
|
+ AR5K_BCR_BDMAE, AR5K_BSR);
|
|
+ break;
|
|
+ default:
|
|
+ return -EINVAL;
|
|
+ }
|
|
+ /* Start queue */
|
|
+ ath5k_hw_reg_write(ah, tx_queue, AR5K_CR);
|
|
+ } else {
|
|
+ /* Return if queue is disabled */
|
|
+ if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXD, queue))
|
|
+ return -EIO;
|
|
+
|
|
+ /* Start queue */
|
|
+ AR5K_REG_WRITE_Q(ah, AR5K_QCU_TXE, queue);
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Stop DMA transmit for a specific queue
|
|
+ * (see also QCU/DCU functions)
|
|
+ */
|
|
+int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue)
|
|
+{
|
|
+ unsigned int i = 100;
|
|
+ u32 tx_queue, pending;
|
|
+
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+ AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
|
|
+
|
|
+ /* Return if queue is declared inactive */
|
|
+ if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE)
|
|
+ return -EIO;
|
|
+
|
|
+ if (ah->ah_version == AR5K_AR5210) {
|
|
+ tx_queue = ath5k_hw_reg_read(ah, AR5K_CR);
|
|
+
|
|
+ /*
|
|
+ * Set by queue type
|
|
+ */
|
|
+ switch (ah->ah_txq[queue].tqi_type) {
|
|
+ case AR5K_TX_QUEUE_DATA:
|
|
+ tx_queue |= AR5K_CR_TXD0 & ~AR5K_CR_TXE0;
|
|
+ break;
|
|
+ case AR5K_TX_QUEUE_BEACON:
|
|
+ case AR5K_TX_QUEUE_CAB:
|
|
+ /* XXX Fix me... */
|
|
+ tx_queue |= AR5K_CR_TXD1 & ~AR5K_CR_TXD1;
|
|
+ ath5k_hw_reg_write(ah, 0, AR5K_BSR);
|
|
+ break;
|
|
+ default:
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ /* Stop queue */
|
|
+ ath5k_hw_reg_write(ah, tx_queue, AR5K_CR);
|
|
+ } else {
|
|
+ /*
|
|
+ * Schedule TX disable and wait until queue is empty
|
|
+ */
|
|
+ AR5K_REG_WRITE_Q(ah, AR5K_QCU_TXD, queue);
|
|
+
|
|
+ /*Check for pending frames*/
|
|
+ do {
|
|
+ pending = ath5k_hw_reg_read(ah,
|
|
+ AR5K_QUEUE_STATUS(queue)) &
|
|
+ AR5K_QCU_STS_FRMPENDCNT;
|
|
+ udelay(100);
|
|
+ } while (--i && pending);
|
|
+
|
|
+ /* Clear register */
|
|
+ ath5k_hw_reg_write(ah, 0, AR5K_QCU_TXD);
|
|
+ }
|
|
+
|
|
+ /* TODO: Check for success else return error */
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Get the address of the TX Descriptor for a specific queue
|
|
+ * (see also QCU/DCU functions)
|
|
+ */
|
|
+u32 ath5k_hw_get_tx_buf(struct ath5k_hw *ah, unsigned int queue)
|
|
+{
|
|
+ u16 tx_reg;
|
|
+
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+ AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
|
|
+
|
|
+ /*
|
|
+ * Get the transmit queue descriptor pointer from the selected queue
|
|
+ */
|
|
+ /*5210 doesn't have QCU*/
|
|
+ if (ah->ah_version == AR5K_AR5210) {
|
|
+ switch (ah->ah_txq[queue].tqi_type) {
|
|
+ case AR5K_TX_QUEUE_DATA:
|
|
+ tx_reg = AR5K_NOQCU_TXDP0;
|
|
+ break;
|
|
+ case AR5K_TX_QUEUE_BEACON:
|
|
+ case AR5K_TX_QUEUE_CAB:
|
|
+ tx_reg = AR5K_NOQCU_TXDP1;
|
|
+ break;
|
|
+ default:
|
|
+ return 0xffffffff;
|
|
+ }
|
|
+ } else {
|
|
+ tx_reg = AR5K_QUEUE_TXDP(queue);
|
|
+ }
|
|
+
|
|
+ return ath5k_hw_reg_read(ah, tx_reg);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Set the address of the TX Descriptor for a specific queue
|
|
+ * (see also QCU/DCU functions)
|
|
+ */
|
|
+int ath5k_hw_put_tx_buf(struct ath5k_hw *ah, unsigned int queue, u32 phys_addr)
|
|
+{
|
|
+ u16 tx_reg;
|
|
+
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+ AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
|
|
+
|
|
+ /*
|
|
+ * Set the transmit queue descriptor pointer register by type
|
|
+ * on 5210
|
|
+ */
|
|
+ if (ah->ah_version == AR5K_AR5210) {
|
|
+ switch (ah->ah_txq[queue].tqi_type) {
|
|
+ case AR5K_TX_QUEUE_DATA:
|
|
+ tx_reg = AR5K_NOQCU_TXDP0;
|
|
+ break;
|
|
+ case AR5K_TX_QUEUE_BEACON:
|
|
+ case AR5K_TX_QUEUE_CAB:
|
|
+ tx_reg = AR5K_NOQCU_TXDP1;
|
|
+ break;
|
|
+ default:
|
|
+ return -EINVAL;
|
|
+ }
|
|
+ } else {
|
|
+ /*
|
|
+ * Set the transmit queue descriptor pointer for
|
|
+ * the selected queue on QCU for 5211+
|
|
+ * (this won't work if the queue is still active)
|
|
+ */
|
|
+ if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue))
|
|
+ return -EIO;
|
|
+
|
|
+ tx_reg = AR5K_QUEUE_TXDP(queue);
|
|
+ }
|
|
+
|
|
+ /* Set descriptor pointer */
|
|
+ ath5k_hw_reg_write(ah, phys_addr, tx_reg);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Update tx trigger level
|
|
+ */
|
|
+int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase)
|
|
+{
|
|
+ u32 trigger_level, imr;
|
|
+ int ret = -EIO;
|
|
+
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+
|
|
+ /*
|
|
+ * Disable interrupts by setting the mask
|
|
+ */
|
|
+ imr = ath5k_hw_set_intr(ah, ah->ah_imr & ~AR5K_INT_GLOBAL);
|
|
+
|
|
+ /*TODO: Boundary check on trigger_level*/
|
|
+ trigger_level = AR5K_REG_MS(ath5k_hw_reg_read(ah, AR5K_TXCFG),
|
|
+ AR5K_TXCFG_TXFULL);
|
|
+
|
|
+ if (increase == false) {
|
|
+ if (--trigger_level < AR5K_TUNE_MIN_TX_FIFO_THRES)
|
|
+ goto done;
|
|
+ } else
|
|
+ trigger_level +=
|
|
+ ((AR5K_TUNE_MAX_TX_FIFO_THRES - trigger_level) / 2);
|
|
+
|
|
+ /*
|
|
+ * Update trigger level on success
|
|
+ */
|
|
+ if (ah->ah_version == AR5K_AR5210)
|
|
+ ath5k_hw_reg_write(ah, trigger_level, AR5K_TRIG_LVL);
|
|
+ else
|
|
+ AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG,
|
|
+ AR5K_TXCFG_TXFULL, trigger_level);
|
|
+
|
|
+ ret = 0;
|
|
+
|
|
+done:
|
|
+ /*
|
|
+ * Restore interrupt mask
|
|
+ */
|
|
+ ath5k_hw_set_intr(ah, imr);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Interrupt handling
|
|
+ */
|
|
+
|
|
+/*
|
|
+ * Check if we have pending interrupts
|
|
+ */
|
|
+bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah)
|
|
+{
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+ return ath5k_hw_reg_read(ah, AR5K_INTPEND);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Get interrupt mask (ISR)
|
|
+ */
|
|
+int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask)
|
|
+{
|
|
+ u32 data;
|
|
+
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+
|
|
+ /*
|
|
+ * Read interrupt status from the Interrupt Status register
|
|
+ * on 5210
|
|
+ */
|
|
+ if (ah->ah_version == AR5K_AR5210) {
|
|
+ data = ath5k_hw_reg_read(ah, AR5K_ISR);
|
|
+ if (unlikely(data == AR5K_INT_NOCARD)) {
|
|
+ *interrupt_mask = data;
|
|
+ return -ENODEV;
|
|
+ }
|
|
+ } else {
|
|
+ /*
|
|
+ * Read interrupt status from the Read-And-Clear shadow register
|
|
+ * Note: PISR/SISR Not available on 5210
|
|
+ */
|
|
+ data = ath5k_hw_reg_read(ah, AR5K_RAC_PISR);
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Get abstract interrupt mask (driver-compatible)
|
|
+ */
|
|
+ *interrupt_mask = (data & AR5K_INT_COMMON) & ah->ah_imr;
|
|
+
|
|
+ if (unlikely(data == AR5K_INT_NOCARD))
|
|
+ return -ENODEV;
|
|
+
|
|
+ if (data & (AR5K_ISR_RXOK | AR5K_ISR_RXERR))
|
|
+ *interrupt_mask |= AR5K_INT_RX;
|
|
+
|
|
+ if (data & (AR5K_ISR_TXOK | AR5K_ISR_TXERR
|
|
+ | AR5K_ISR_TXDESC | AR5K_ISR_TXEOL))
|
|
+ *interrupt_mask |= AR5K_INT_TX;
|
|
+
|
|
+ if (ah->ah_version != AR5K_AR5210) {
|
|
+ /*HIU = Host Interface Unit (PCI etc)*/
|
|
+ if (unlikely(data & (AR5K_ISR_HIUERR)))
|
|
+ *interrupt_mask |= AR5K_INT_FATAL;
|
|
+
|
|
+ /*Beacon Not Ready*/
|
|
+ if (unlikely(data & (AR5K_ISR_BNR)))
|
|
+ *interrupt_mask |= AR5K_INT_BNR;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * XXX: BMISS interrupts may occur after association.
|
|
+ * I found this on 5210 code but it needs testing. If this is
|
|
+ * true we should disable them before assoc and re-enable them
|
|
+ * after a successfull assoc + some jiffies.
|
|
+ */
|
|
+#if 0
|
|
+ interrupt_mask &= ~AR5K_INT_BMISS;
|
|
+#endif
|
|
+
|
|
+ /*
|
|
+ * In case we didn't handle anything,
|
|
+ * print the register value.
|
|
+ */
|
|
+ if (unlikely(*interrupt_mask == 0 && net_ratelimit()))
|
|
+ ATH5K_PRINTF("0x%08x\n", data);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Set interrupt mask
|
|
+ */
|
|
+enum ath5k_int ath5k_hw_set_intr(struct ath5k_hw *ah, enum ath5k_int new_mask)
|
|
+{
|
|
+ enum ath5k_int old_mask, int_mask;
|
|
+
|
|
+ /*
|
|
+ * Disable card interrupts to prevent any race conditions
|
|
+ * (they will be re-enabled afterwards).
|
|
+ */
|
|
+ ath5k_hw_reg_write(ah, AR5K_IER_DISABLE, AR5K_IER);
|
|
+
|
|
+ old_mask = ah->ah_imr;
|
|
+
|
|
+ /*
|
|
+ * Add additional, chipset-dependent interrupt mask flags
|
|
+ * and write them to the IMR (interrupt mask register).
|
|
+ */
|
|
+ int_mask = new_mask & AR5K_INT_COMMON;
|
|
+
|
|
+ if (new_mask & AR5K_INT_RX)
|
|
+ int_mask |= AR5K_IMR_RXOK | AR5K_IMR_RXERR | AR5K_IMR_RXORN |
|
|
+ AR5K_IMR_RXDESC;
|
|
+
|
|
+ if (new_mask & AR5K_INT_TX)
|
|
+ int_mask |= AR5K_IMR_TXOK | AR5K_IMR_TXERR | AR5K_IMR_TXDESC |
|
|
+ AR5K_IMR_TXURN;
|
|
+
|
|
+ if (ah->ah_version != AR5K_AR5210) {
|
|
+ if (new_mask & AR5K_INT_FATAL) {
|
|
+ int_mask |= AR5K_IMR_HIUERR;
|
|
+ AR5K_REG_ENABLE_BITS(ah, AR5K_SIMR2, AR5K_SIMR2_MCABT |
|
|
+ AR5K_SIMR2_SSERR | AR5K_SIMR2_DPERR);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ ath5k_hw_reg_write(ah, int_mask, AR5K_PIMR);
|
|
+
|
|
+ /* Store new interrupt mask */
|
|
+ ah->ah_imr = new_mask;
|
|
+
|
|
+ /* ..re-enable interrupts */
|
|
+ ath5k_hw_reg_write(ah, AR5K_IER_ENABLE, AR5K_IER);
|
|
+
|
|
+ return old_mask;
|
|
+}
|
|
+
|
|
+
|
|
+/*************************\
|
|
+ EEPROM access functions
|
|
+\*************************/
|
|
+
|
|
+/*
|
|
+ * Read from eeprom
|
|
+ */
|
|
+static int ath5k_hw_eeprom_read(struct ath5k_hw *ah, u32 offset, u16 *data)
|
|
+{
|
|
+ u32 status, timeout;
|
|
+
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+ /*
|
|
+ * Initialize EEPROM access
|
|
+ */
|
|
+ if (ah->ah_version == AR5K_AR5210) {
|
|
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, AR5K_PCICFG_EEAE);
|
|
+ (void)ath5k_hw_reg_read(ah, AR5K_EEPROM_BASE + (4 * offset));
|
|
+ } else {
|
|
+ ath5k_hw_reg_write(ah, offset, AR5K_EEPROM_BASE);
|
|
+ AR5K_REG_ENABLE_BITS(ah, AR5K_EEPROM_CMD,
|
|
+ AR5K_EEPROM_CMD_READ);
|
|
+ }
|
|
+
|
|
+ for (timeout = AR5K_TUNE_REGISTER_TIMEOUT; timeout > 0; timeout--) {
|
|
+ status = ath5k_hw_reg_read(ah, AR5K_EEPROM_STATUS);
|
|
+ if (status & AR5K_EEPROM_STAT_RDDONE) {
|
|
+ if (status & AR5K_EEPROM_STAT_RDERR)
|
|
+ return -EIO;
|
|
+ *data = (u16)(ath5k_hw_reg_read(ah, AR5K_EEPROM_DATA) &
|
|
+ 0xffff);
|
|
+ return 0;
|
|
+ }
|
|
+ udelay(15);
|
|
+ }
|
|
+
|
|
+ return -ETIMEDOUT;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Write to eeprom - currently disabled, use at your own risk
|
|
+ */
|
|
+static int ath5k_hw_eeprom_write(struct ath5k_hw *ah, u32 offset, u16 data)
|
|
+{
|
|
+#if 0
|
|
+ u32 status, timeout;
|
|
+
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+
|
|
+ /*
|
|
+ * Initialize eeprom access
|
|
+ */
|
|
+
|
|
+ if (ah->ah_version == AR5K_AR5210) {
|
|
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, AR5K_PCICFG_EEAE);
|
|
+ } else {
|
|
+ AR5K_REG_ENABLE_BITS(ah, AR5K_EEPROM_CMD,
|
|
+ AR5K_EEPROM_CMD_RESET);
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Write data to data register
|
|
+ */
|
|
+
|
|
+ if (ah->ah_version == AR5K_AR5210) {
|
|
+ ath5k_hw_reg_write(ah, data, AR5K_EEPROM_BASE + (4 * offset));
|
|
+ } else {
|
|
+ ath5k_hw_reg_write(ah, offset, AR5K_EEPROM_BASE);
|
|
+ ath5k_hw_reg_write(ah, data, AR5K_EEPROM_DATA);
|
|
+ AR5K_REG_ENABLE_BITS(ah, AR5K_EEPROM_CMD,
|
|
+ AR5K_EEPROM_CMD_WRITE);
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Check status
|
|
+ */
|
|
+
|
|
+ for (timeout = AR5K_TUNE_REGISTER_TIMEOUT; timeout > 0; timeout--) {
|
|
+ status = ath5k_hw_reg_read(ah, AR5K_EEPROM_STATUS);
|
|
+ if (status & AR5K_EEPROM_STAT_WRDONE) {
|
|
+ if (status & AR5K_EEPROM_STAT_WRERR)
|
|
+ return EIO;
|
|
+ return 0;
|
|
+ }
|
|
+ udelay(15);
|
|
+ }
|
|
+#endif
|
|
+ ATH5K_ERR(ah->ah_sc, "EEPROM Write is disabled!");
|
|
+ return -EIO;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Translate binary channel representation in EEPROM to frequency
|
|
+ */
|
|
+static u16 ath5k_eeprom_bin2freq(struct ath5k_hw *ah, u16 bin, unsigned int mode)
|
|
+{
|
|
+ u16 val;
|
|
+
|
|
+ if (bin == AR5K_EEPROM_CHANNEL_DIS)
|
|
+ return bin;
|
|
+
|
|
+ if (mode == AR5K_EEPROM_MODE_11A) {
|
|
+ if (ah->ah_ee_version > AR5K_EEPROM_VERSION_3_2)
|
|
+ val = (5 * bin) + 4800;
|
|
+ else
|
|
+ val = bin > 62 ? (10 * 62) + (5 * (bin - 62)) + 5100 :
|
|
+ (bin * 10) + 5100;
|
|
+ } else {
|
|
+ if (ah->ah_ee_version > AR5K_EEPROM_VERSION_3_2)
|
|
+ val = bin + 2300;
|
|
+ else
|
|
+ val = bin + 2400;
|
|
+ }
|
|
+
|
|
+ return val;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Read antenna infos from eeprom
|
|
+ */
|
|
+static int ath5k_eeprom_read_ants(struct ath5k_hw *ah, u32 *offset,
|
|
+ unsigned int mode)
|
|
+{
|
|
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
|
|
+ u32 o = *offset;
|
|
+ u16 val;
|
|
+ int ret, i = 0;
|
|
+
|
|
+ AR5K_EEPROM_READ(o++, val);
|
|
+ ee->ee_switch_settling[mode] = (val >> 8) & 0x7f;
|
|
+ ee->ee_ant_tx_rx[mode] = (val >> 2) & 0x3f;
|
|
+ ee->ee_ant_control[mode][i] = (val << 4) & 0x3f;
|
|
+
|
|
+ AR5K_EEPROM_READ(o++, val);
|
|
+ ee->ee_ant_control[mode][i++] |= (val >> 12) & 0xf;
|
|
+ ee->ee_ant_control[mode][i++] = (val >> 6) & 0x3f;
|
|
+ ee->ee_ant_control[mode][i++] = val & 0x3f;
|
|
+
|
|
+ AR5K_EEPROM_READ(o++, val);
|
|
+ ee->ee_ant_control[mode][i++] = (val >> 10) & 0x3f;
|
|
+ ee->ee_ant_control[mode][i++] = (val >> 4) & 0x3f;
|
|
+ ee->ee_ant_control[mode][i] = (val << 2) & 0x3f;
|
|
+
|
|
+ AR5K_EEPROM_READ(o++, val);
|
|
+ ee->ee_ant_control[mode][i++] |= (val >> 14) & 0x3;
|
|
+ ee->ee_ant_control[mode][i++] = (val >> 8) & 0x3f;
|
|
+ ee->ee_ant_control[mode][i++] = (val >> 2) & 0x3f;
|
|
+ ee->ee_ant_control[mode][i] = (val << 4) & 0x3f;
|
|
+
|
|
+ AR5K_EEPROM_READ(o++, val);
|
|
+ ee->ee_ant_control[mode][i++] |= (val >> 12) & 0xf;
|
|
+ ee->ee_ant_control[mode][i++] = (val >> 6) & 0x3f;
|
|
+ ee->ee_ant_control[mode][i++] = val & 0x3f;
|
|
+
|
|
+ /* Get antenna modes */
|
|
+ ah->ah_antenna[mode][0] =
|
|
+ (ee->ee_ant_control[mode][0] << 4) | 0x1;
|
|
+ ah->ah_antenna[mode][AR5K_ANT_FIXED_A] =
|
|
+ ee->ee_ant_control[mode][1] |
|
|
+ (ee->ee_ant_control[mode][2] << 6) |
|
|
+ (ee->ee_ant_control[mode][3] << 12) |
|
|
+ (ee->ee_ant_control[mode][4] << 18) |
|
|
+ (ee->ee_ant_control[mode][5] << 24);
|
|
+ ah->ah_antenna[mode][AR5K_ANT_FIXED_B] =
|
|
+ ee->ee_ant_control[mode][6] |
|
|
+ (ee->ee_ant_control[mode][7] << 6) |
|
|
+ (ee->ee_ant_control[mode][8] << 12) |
|
|
+ (ee->ee_ant_control[mode][9] << 18) |
|
|
+ (ee->ee_ant_control[mode][10] << 24);
|
|
+
|
|
+ /* return new offset */
|
|
+ *offset = o;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Read supported modes from eeprom
|
|
+ */
|
|
+static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset,
|
|
+ unsigned int mode)
|
|
+{
|
|
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
|
|
+ u32 o = *offset;
|
|
+ u16 val;
|
|
+ int ret;
|
|
+
|
|
+ AR5K_EEPROM_READ(o++, val);
|
|
+ ee->ee_tx_end2xlna_enable[mode] = (val >> 8) & 0xff;
|
|
+ ee->ee_thr_62[mode] = val & 0xff;
|
|
+
|
|
+ if (ah->ah_ee_version <= AR5K_EEPROM_VERSION_3_2)
|
|
+ ee->ee_thr_62[mode] = mode == AR5K_EEPROM_MODE_11A ? 15 : 28;
|
|
+
|
|
+ AR5K_EEPROM_READ(o++, val);
|
|
+ ee->ee_tx_end2xpa_disable[mode] = (val >> 8) & 0xff;
|
|
+ ee->ee_tx_frm2xpa_enable[mode] = val & 0xff;
|
|
+
|
|
+ AR5K_EEPROM_READ(o++, val);
|
|
+ ee->ee_pga_desired_size[mode] = (val >> 8) & 0xff;
|
|
+
|
|
+ if ((val & 0xff) & 0x80)
|
|
+ ee->ee_noise_floor_thr[mode] = -((((val & 0xff) ^ 0xff)) + 1);
|
|
+ else
|
|
+ ee->ee_noise_floor_thr[mode] = val & 0xff;
|
|
+
|
|
+ if (ah->ah_ee_version <= AR5K_EEPROM_VERSION_3_2)
|
|
+ ee->ee_noise_floor_thr[mode] =
|
|
+ mode == AR5K_EEPROM_MODE_11A ? -54 : -1;
|
|
+
|
|
+ AR5K_EEPROM_READ(o++, val);
|
|
+ ee->ee_xlna_gain[mode] = (val >> 5) & 0xff;
|
|
+ ee->ee_x_gain[mode] = (val >> 1) & 0xf;
|
|
+ ee->ee_xpd[mode] = val & 0x1;
|
|
+
|
|
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0)
|
|
+ ee->ee_fixed_bias[mode] = (val >> 13) & 0x1;
|
|
+
|
|
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_3_3) {
|
|
+ AR5K_EEPROM_READ(o++, val);
|
|
+ ee->ee_false_detect[mode] = (val >> 6) & 0x7f;
|
|
+
|
|
+ if (mode == AR5K_EEPROM_MODE_11A)
|
|
+ ee->ee_xr_power[mode] = val & 0x3f;
|
|
+ else {
|
|
+ ee->ee_ob[mode][0] = val & 0x7;
|
|
+ ee->ee_db[mode][0] = (val >> 3) & 0x7;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_4) {
|
|
+ ee->ee_i_gain[mode] = AR5K_EEPROM_I_GAIN;
|
|
+ ee->ee_cck_ofdm_power_delta = AR5K_EEPROM_CCK_OFDM_DELTA;
|
|
+ } else {
|
|
+ ee->ee_i_gain[mode] = (val >> 13) & 0x7;
|
|
+
|
|
+ AR5K_EEPROM_READ(o++, val);
|
|
+ ee->ee_i_gain[mode] |= (val << 3) & 0x38;
|
|
+
|
|
+ if (mode == AR5K_EEPROM_MODE_11G)
|
|
+ ee->ee_cck_ofdm_power_delta = (val >> 3) & 0xff;
|
|
+ }
|
|
+
|
|
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0 &&
|
|
+ mode == AR5K_EEPROM_MODE_11A) {
|
|
+ ee->ee_i_cal[mode] = (val >> 8) & 0x3f;
|
|
+ ee->ee_q_cal[mode] = (val >> 3) & 0x1f;
|
|
+ }
|
|
+
|
|
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_6 &&
|
|
+ mode == AR5K_EEPROM_MODE_11G)
|
|
+ ee->ee_scaled_cck_delta = (val >> 11) & 0x1f;
|
|
+
|
|
+ /* return new offset */
|
|
+ *offset = o;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Initialize eeprom & capabilities structs
|
|
+ */
|
|
+static int ath5k_eeprom_init(struct ath5k_hw *ah)
|
|
+{
|
|
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
|
|
+ unsigned int mode, i;
|
|
+ int ret;
|
|
+ u32 offset;
|
|
+ u16 val;
|
|
+
|
|
+ /* Initial TX thermal adjustment values */
|
|
+ ee->ee_tx_clip = 4;
|
|
+ ee->ee_pwd_84 = ee->ee_pwd_90 = 1;
|
|
+ ee->ee_gain_select = 1;
|
|
+
|
|
+ /*
|
|
+ * Read values from EEPROM and store them in the capability structure
|
|
+ */
|
|
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MAGIC, ee_magic);
|
|
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_PROTECT, ee_protect);
|
|
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_REG_DOMAIN, ee_regdomain);
|
|
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_VERSION, ee_version);
|
|
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_HDR, ee_header);
|
|
+
|
|
+ /* Return if we have an old EEPROM */
|
|
+ if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_0)
|
|
+ return 0;
|
|
+
|
|
+#ifdef notyet
|
|
+ /*
|
|
+ * Validate the checksum of the EEPROM date. There are some
|
|
+ * devices with invalid EEPROMs.
|
|
+ */
|
|
+ for (cksum = 0, offset = 0; offset < AR5K_EEPROM_INFO_MAX; offset++) {
|
|
+ AR5K_EEPROM_READ(AR5K_EEPROM_INFO(offset), val);
|
|
+ cksum ^= val;
|
|
+ }
|
|
+ if (cksum != AR5K_EEPROM_INFO_CKSUM) {
|
|
+ ATH5K_ERR(ah->ah_sc, "Invalid EEPROM checksum 0x%04x\n", cksum);
|
|
+ return -EIO;
|
|
+ }
|
|
+#endif
|
|
+
|
|
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_ANT_GAIN(ah->ah_ee_version),
|
|
+ ee_ant_gain);
|
|
+
|
|
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) {
|
|
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC0, ee_misc0);
|
|
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC1, ee_misc1);
|
|
+ }
|
|
+
|
|
+ if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_3) {
|
|
+ AR5K_EEPROM_READ(AR5K_EEPROM_OBDB0_2GHZ, val);
|
|
+ ee->ee_ob[AR5K_EEPROM_MODE_11B][0] = val & 0x7;
|
|
+ ee->ee_db[AR5K_EEPROM_MODE_11B][0] = (val >> 3) & 0x7;
|
|
+
|
|
+ AR5K_EEPROM_READ(AR5K_EEPROM_OBDB1_2GHZ, val);
|
|
+ ee->ee_ob[AR5K_EEPROM_MODE_11G][0] = val & 0x7;
|
|
+ ee->ee_db[AR5K_EEPROM_MODE_11G][0] = (val >> 3) & 0x7;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Get conformance test limit values
|
|
+ */
|
|
+ offset = AR5K_EEPROM_CTL(ah->ah_ee_version);
|
|
+ ee->ee_ctls = AR5K_EEPROM_N_CTLS(ah->ah_ee_version);
|
|
+
|
|
+ for (i = 0; i < ee->ee_ctls; i++) {
|
|
+ AR5K_EEPROM_READ(offset++, val);
|
|
+ ee->ee_ctl[i] = (val >> 8) & 0xff;
|
|
+ ee->ee_ctl[i + 1] = val & 0xff;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Get values for 802.11a (5GHz)
|
|
+ */
|
|
+ mode = AR5K_EEPROM_MODE_11A;
|
|
+
|
|
+ ee->ee_turbo_max_power[mode] =
|
|
+ AR5K_EEPROM_HDR_T_5GHZ_DBM(ee->ee_header);
|
|
+
|
|
+ offset = AR5K_EEPROM_MODES_11A(ah->ah_ee_version);
|
|
+
|
|
+ ret = ath5k_eeprom_read_ants(ah, &offset, mode);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ AR5K_EEPROM_READ(offset++, val);
|
|
+ ee->ee_adc_desired_size[mode] = (s8)((val >> 8) & 0xff);
|
|
+ ee->ee_ob[mode][3] = (val >> 5) & 0x7;
|
|
+ ee->ee_db[mode][3] = (val >> 2) & 0x7;
|
|
+ ee->ee_ob[mode][2] = (val << 1) & 0x7;
|
|
+
|
|
+ AR5K_EEPROM_READ(offset++, val);
|
|
+ ee->ee_ob[mode][2] |= (val >> 15) & 0x1;
|
|
+ ee->ee_db[mode][2] = (val >> 12) & 0x7;
|
|
+ ee->ee_ob[mode][1] = (val >> 9) & 0x7;
|
|
+ ee->ee_db[mode][1] = (val >> 6) & 0x7;
|
|
+ ee->ee_ob[mode][0] = (val >> 3) & 0x7;
|
|
+ ee->ee_db[mode][0] = val & 0x7;
|
|
+
|
|
+ ret = ath5k_eeprom_read_modes(ah, &offset, mode);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1) {
|
|
+ AR5K_EEPROM_READ(offset++, val);
|
|
+ ee->ee_margin_tx_rx[mode] = val & 0x3f;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Get values for 802.11b (2.4GHz)
|
|
+ */
|
|
+ mode = AR5K_EEPROM_MODE_11B;
|
|
+ offset = AR5K_EEPROM_MODES_11B(ah->ah_ee_version);
|
|
+
|
|
+ ret = ath5k_eeprom_read_ants(ah, &offset, mode);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ AR5K_EEPROM_READ(offset++, val);
|
|
+ ee->ee_adc_desired_size[mode] = (s8)((val >> 8) & 0xff);
|
|
+ ee->ee_ob[mode][1] = (val >> 4) & 0x7;
|
|
+ ee->ee_db[mode][1] = val & 0x7;
|
|
+
|
|
+ ret = ath5k_eeprom_read_modes(ah, &offset, mode);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) {
|
|
+ AR5K_EEPROM_READ(offset++, val);
|
|
+ ee->ee_cal_pier[mode][0] =
|
|
+ ath5k_eeprom_bin2freq(ah, val & 0xff, mode);
|
|
+ ee->ee_cal_pier[mode][1] =
|
|
+ ath5k_eeprom_bin2freq(ah, (val >> 8) & 0xff, mode);
|
|
+
|
|
+ AR5K_EEPROM_READ(offset++, val);
|
|
+ ee->ee_cal_pier[mode][2] =
|
|
+ ath5k_eeprom_bin2freq(ah, val & 0xff, mode);
|
|
+ }
|
|
+
|
|
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1)
|
|
+ ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f;
|
|
+
|
|
+ /*
|
|
+ * Get values for 802.11g (2.4GHz)
|
|
+ */
|
|
+ mode = AR5K_EEPROM_MODE_11G;
|
|
+ offset = AR5K_EEPROM_MODES_11G(ah->ah_ee_version);
|
|
+
|
|
+ ret = ath5k_eeprom_read_ants(ah, &offset, mode);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ AR5K_EEPROM_READ(offset++, val);
|
|
+ ee->ee_adc_desired_size[mode] = (s8)((val >> 8) & 0xff);
|
|
+ ee->ee_ob[mode][1] = (val >> 4) & 0x7;
|
|
+ ee->ee_db[mode][1] = val & 0x7;
|
|
+
|
|
+ ret = ath5k_eeprom_read_modes(ah, &offset, mode);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) {
|
|
+ AR5K_EEPROM_READ(offset++, val);
|
|
+ ee->ee_cal_pier[mode][0] =
|
|
+ ath5k_eeprom_bin2freq(ah, val & 0xff, mode);
|
|
+ ee->ee_cal_pier[mode][1] =
|
|
+ ath5k_eeprom_bin2freq(ah, (val >> 8) & 0xff, mode);
|
|
+
|
|
+ AR5K_EEPROM_READ(offset++, val);
|
|
+ ee->ee_turbo_max_power[mode] = val & 0x7f;
|
|
+ ee->ee_xr_power[mode] = (val >> 7) & 0x3f;
|
|
+
|
|
+ AR5K_EEPROM_READ(offset++, val);
|
|
+ ee->ee_cal_pier[mode][2] =
|
|
+ ath5k_eeprom_bin2freq(ah, val & 0xff, mode);
|
|
+
|
|
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1)
|
|
+ ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f;
|
|
+
|
|
+ AR5K_EEPROM_READ(offset++, val);
|
|
+ ee->ee_i_cal[mode] = (val >> 8) & 0x3f;
|
|
+ ee->ee_q_cal[mode] = (val >> 3) & 0x1f;
|
|
+
|
|
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_2) {
|
|
+ AR5K_EEPROM_READ(offset++, val);
|
|
+ ee->ee_cck_ofdm_gain_delta = val & 0xff;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Read 5GHz EEPROM channels
|
|
+ */
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Read the MAC address from eeprom
|
|
+ */
|
|
+static int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac)
|
|
+{
|
|
+ u8 mac_d[ETH_ALEN];
|
|
+ u32 total, offset;
|
|
+ u16 data;
|
|
+ int octet, ret;
|
|
+
|
|
+ memset(mac, 0, ETH_ALEN);
|
|
+ memset(mac_d, 0, ETH_ALEN);
|
|
+
|
|
+ ret = ath5k_hw_eeprom_read(ah, 0x20, &data);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) {
|
|
+ ret = ath5k_hw_eeprom_read(ah, offset, &data);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ total += data;
|
|
+ mac_d[octet + 1] = data & 0xff;
|
|
+ mac_d[octet] = data >> 8;
|
|
+ octet += 2;
|
|
+ }
|
|
+
|
|
+ memcpy(mac, mac_d, ETH_ALEN);
|
|
+
|
|
+ if (!total || total == 3 * 0xffff)
|
|
+ return -EINVAL;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Read/Write regulatory domain
|
|
+ */
|
|
+static bool ath5k_eeprom_regulation_domain(struct ath5k_hw *ah, bool write,
|
|
+ enum ath5k_regdom *regdomain)
|
|
+{
|
|
+ u16 ee_regdomain;
|
|
+
|
|
+ /* Read current value */
|
|
+ if (write != true) {
|
|
+ ee_regdomain = ah->ah_capabilities.cap_eeprom.ee_regdomain;
|
|
+ *regdomain = ath5k_regdom_to_ieee(ee_regdomain);
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ ee_regdomain = ath5k_regdom_from_ieee(*regdomain);
|
|
+
|
|
+ /* Try to write a new value */
|
|
+ if (ah->ah_capabilities.cap_eeprom.ee_protect &
|
|
+ AR5K_EEPROM_PROTECT_WR_128_191)
|
|
+ return false;
|
|
+ if (ath5k_hw_eeprom_write(ah, AR5K_EEPROM_REG_DOMAIN, ee_regdomain)!=0)
|
|
+ return false;
|
|
+
|
|
+ ah->ah_capabilities.cap_eeprom.ee_regdomain = ee_regdomain;
|
|
+
|
|
+ return true;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Use the above to write a new regulatory domain
|
|
+ */
|
|
+int ath5k_hw_set_regdomain(struct ath5k_hw *ah, u16 regdomain)
|
|
+{
|
|
+ enum ath5k_regdom ieee_regdomain;
|
|
+
|
|
+ ieee_regdomain = ath5k_regdom_to_ieee(regdomain);
|
|
+
|
|
+ if (ath5k_eeprom_regulation_domain(ah, true, &ieee_regdomain) == true)
|
|
+ return 0;
|
|
+
|
|
+ return -EIO;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Fill the capabilities struct
|
|
+ */
|
|
+static int ath5k_hw_get_capabilities(struct ath5k_hw *ah)
|
|
+{
|
|
+ u16 ee_header;
|
|
+
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+ /* Capabilities stored in the EEPROM */
|
|
+ ee_header = ah->ah_capabilities.cap_eeprom.ee_header;
|
|
+
|
|
+ if (ah->ah_version == AR5K_AR5210) {
|
|
+ /*
|
|
+ * Set radio capabilities
|
|
+ * (The AR5110 only supports the middle 5GHz band)
|
|
+ */
|
|
+ ah->ah_capabilities.cap_range.range_5ghz_min = 5120;
|
|
+ ah->ah_capabilities.cap_range.range_5ghz_max = 5430;
|
|
+ ah->ah_capabilities.cap_range.range_2ghz_min = 0;
|
|
+ ah->ah_capabilities.cap_range.range_2ghz_max = 0;
|
|
+
|
|
+ /* Set supported modes */
|
|
+ __set_bit(MODE_IEEE80211A, ah->ah_capabilities.cap_mode);
|
|
+ __set_bit(MODE_ATHEROS_TURBO, ah->ah_capabilities.cap_mode);
|
|
+ } else {
|
|
+ /*
|
|
+ * XXX The tranceiver supports frequencies from 4920 to 6100GHz
|
|
+ * XXX and from 2312 to 2732GHz. There are problems with the
|
|
+ * XXX current ieee80211 implementation because the IEEE
|
|
+ * XXX channel mapping does not support negative channel
|
|
+ * XXX numbers (2312MHz is channel -19). Of course, this
|
|
+ * XXX doesn't matter because these channels are out of range
|
|
+ * XXX but some regulation domains like MKK (Japan) will
|
|
+ * XXX support frequencies somewhere around 4.8GHz.
|
|
+ */
|
|
+
|
|
+ /*
|
|
+ * Set radio capabilities
|
|
+ */
|
|
+
|
|
+ if (AR5K_EEPROM_HDR_11A(ee_header)) {
|
|
+ ah->ah_capabilities.cap_range.range_5ghz_min = 5005; /* 4920 */
|
|
+ ah->ah_capabilities.cap_range.range_5ghz_max = 6100;
|
|
+
|
|
+ /* Set supported modes */
|
|
+ __set_bit(MODE_IEEE80211A,
|
|
+ ah->ah_capabilities.cap_mode);
|
|
+ __set_bit(MODE_ATHEROS_TURBO,
|
|
+ ah->ah_capabilities.cap_mode);
|
|
+ if (ah->ah_version == AR5K_AR5212)
|
|
+ __set_bit(MODE_ATHEROS_TURBOG,
|
|
+ ah->ah_capabilities.cap_mode);
|
|
+ }
|
|
+
|
|
+ /* Enable 802.11b if a 2GHz capable radio (2111/5112) is
|
|
+ * connected */
|
|
+ if (AR5K_EEPROM_HDR_11B(ee_header) ||
|
|
+ AR5K_EEPROM_HDR_11G(ee_header)) {
|
|
+ ah->ah_capabilities.cap_range.range_2ghz_min = 2412; /* 2312 */
|
|
+ ah->ah_capabilities.cap_range.range_2ghz_max = 2732;
|
|
+
|
|
+ if (AR5K_EEPROM_HDR_11B(ee_header))
|
|
+ __set_bit(MODE_IEEE80211B,
|
|
+ ah->ah_capabilities.cap_mode);
|
|
+
|
|
+ if (AR5K_EEPROM_HDR_11G(ee_header))
|
|
+ __set_bit(MODE_IEEE80211G,
|
|
+ ah->ah_capabilities.cap_mode);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /* GPIO */
|
|
+ ah->ah_gpio_npins = AR5K_NUM_GPIO;
|
|
+
|
|
+ /* Set number of supported TX queues */
|
|
+ if (ah->ah_version == AR5K_AR5210)
|
|
+ ah->ah_capabilities.cap_queues.q_tx_num =
|
|
+ AR5K_NUM_TX_QUEUES_NOQCU;
|
|
+ else
|
|
+ ah->ah_capabilities.cap_queues.q_tx_num = AR5K_NUM_TX_QUEUES;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*********************************\
|
|
+ Protocol Control Unit Functions
|
|
+\*********************************/
|
|
+
|
|
+/*
|
|
+ * Set Operation mode
|
|
+ */
|
|
+int ath5k_hw_set_opmode(struct ath5k_hw *ah)
|
|
+{
|
|
+ u32 pcu_reg, beacon_reg, low_id, high_id;
|
|
+
|
|
+ pcu_reg = 0;
|
|
+ beacon_reg = 0;
|
|
+
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+
|
|
+ switch (ah->ah_op_mode) {
|
|
+ case IEEE80211_IF_TYPE_IBSS:
|
|
+ pcu_reg |= AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_DESC_ANTENNA |
|
|
+ (ah->ah_version == AR5K_AR5210 ?
|
|
+ AR5K_STA_ID1_NO_PSPOLL : 0);
|
|
+ beacon_reg |= AR5K_BCR_ADHOC;
|
|
+ break;
|
|
+
|
|
+ case IEEE80211_IF_TYPE_AP:
|
|
+ pcu_reg |= AR5K_STA_ID1_AP | AR5K_STA_ID1_RTS_DEF_ANTENNA |
|
|
+ (ah->ah_version == AR5K_AR5210 ?
|
|
+ AR5K_STA_ID1_NO_PSPOLL : 0);
|
|
+ beacon_reg |= AR5K_BCR_AP;
|
|
+ break;
|
|
+
|
|
+ case IEEE80211_IF_TYPE_STA:
|
|
+ pcu_reg |= AR5K_STA_ID1_DEFAULT_ANTENNA |
|
|
+ (ah->ah_version == AR5K_AR5210 ?
|
|
+ AR5K_STA_ID1_PWR_SV : 0);
|
|
+ case IEEE80211_IF_TYPE_MNTR:
|
|
+ pcu_reg |= AR5K_STA_ID1_DEFAULT_ANTENNA |
|
|
+ (ah->ah_version == AR5K_AR5210 ?
|
|
+ AR5K_STA_ID1_NO_PSPOLL : 0);
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Set PCU registers
|
|
+ */
|
|
+ low_id = AR5K_LOW_ID(ah->ah_sta_id);
|
|
+ high_id = AR5K_HIGH_ID(ah->ah_sta_id);
|
|
+ ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0);
|
|
+ ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1);
|
|
+
|
|
+ /*
|
|
+ * Set Beacon Control Register on 5210
|
|
+ */
|
|
+ if (ah->ah_version == AR5K_AR5210)
|
|
+ ath5k_hw_reg_write(ah, beacon_reg, AR5K_BCR);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * BSSID Functions
|
|
+ */
|
|
+
|
|
+/*
|
|
+ * Get station id
|
|
+ */
|
|
+void ath5k_hw_get_lladdr(struct ath5k_hw *ah, u8 *mac)
|
|
+{
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+ memcpy(mac, ah->ah_sta_id, ETH_ALEN);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Set station id
|
|
+ */
|
|
+int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac)
|
|
+{
|
|
+ u32 low_id, high_id;
|
|
+
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+ /* Set new station ID */
|
|
+ memcpy(ah->ah_sta_id, mac, ETH_ALEN);
|
|
+
|
|
+ low_id = AR5K_LOW_ID(mac);
|
|
+ high_id = AR5K_HIGH_ID(mac);
|
|
+
|
|
+ ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0);
|
|
+ ath5k_hw_reg_write(ah, high_id, AR5K_STA_ID1);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Set BSSID
|
|
+ */
|
|
+void ath5k_hw_set_associd(struct ath5k_hw *ah, const u8 *bssid, u16 assoc_id)
|
|
+{
|
|
+ u32 low_id, high_id;
|
|
+ u16 tim_offset = 0;
|
|
+
|
|
+ /*
|
|
+ * Set simple BSSID mask on 5212
|
|
+ */
|
|
+ if (ah->ah_version == AR5K_AR5212) {
|
|
+ ath5k_hw_reg_write(ah, 0xfffffff, AR5K_BSS_IDM0);
|
|
+ ath5k_hw_reg_write(ah, 0xfffffff, AR5K_BSS_IDM1);
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Set BSSID which triggers the "SME Join" operation
|
|
+ */
|
|
+ low_id = AR5K_LOW_ID(bssid);
|
|
+ high_id = AR5K_HIGH_ID(bssid);
|
|
+ ath5k_hw_reg_write(ah, low_id, AR5K_BSS_ID0);
|
|
+ ath5k_hw_reg_write(ah, high_id | ((assoc_id & 0x3fff) <<
|
|
+ AR5K_BSS_ID1_AID_S), AR5K_BSS_ID1);
|
|
+ memcpy(&ah->ah_bssid, bssid, ETH_ALEN);
|
|
+
|
|
+ if (assoc_id == 0) {
|
|
+ ath5k_hw_disable_pspoll(ah);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ AR5K_REG_WRITE_BITS(ah, AR5K_BEACON, AR5K_BEACON_TIM,
|
|
+ tim_offset ? tim_offset + 4 : 0);
|
|
+
|
|
+ ath5k_hw_enable_pspoll(ah, NULL, 0);
|
|
+}
|
|
+/**
|
|
+ * ath5k_hw_set_bssid_mask - set common bits we should listen to
|
|
+ *
|
|
+ * The bssid_mask is a utility used by AR5212 hardware to inform the hardware
|
|
+ * which bits of the interface's MAC address should be looked at when trying
|
|
+ * to decide which packets to ACK. In station mode every bit matters. In AP
|
|
+ * mode with a single BSS every bit matters as well. In AP mode with
|
|
+ * multiple BSSes not every bit matters.
|
|
+ *
|
|
+ * @ah: the &struct ath5k_hw
|
|
+ * @mask: the bssid_mask, a u8 array of size ETH_ALEN
|
|
+ *
|
|
+ * Note that this is a simple filter and *does* not filter out all
|
|
+ * relevant frames. Some non-relevant frames will get through, probability
|
|
+ * jocks are welcomed to compute.
|
|
+ *
|
|
+ * When handling multiple BSSes (or VAPs) you can get the BSSID mask by
|
|
+ * computing the set of:
|
|
+ *
|
|
+ * ~ ( MAC XOR BSSID )
|
|
+ *
|
|
+ * When you do this you are essentially computing the common bits. Later it
|
|
+ * is assumed the harware will "and" (&) the BSSID mask with the MAC address
|
|
+ * to obtain the relevant bits which should match on the destination frame.
|
|
+ *
|
|
+ * Simple example: on your card you have have two BSSes you have created with
|
|
+ * BSSID-01 and BSSID-02. Lets assume BSSID-01 will not use the MAC address.
|
|
+ * There is another BSSID-03 but you are not part of it. For simplicity's sake,
|
|
+ * assuming only 4 bits for a mac address and for BSSIDs you can then have:
|
|
+ *
|
|
+ * \
|
|
+ * MAC: 0001 |
|
|
+ * BSSID-01: 0100 | --> Belongs to us
|
|
+ * BSSID-02: 1001 |
|
|
+ * /
|
|
+ * -------------------
|
|
+ * BSSID-03: 0110 | --> External
|
|
+ * -------------------
|
|
+ *
|
|
+ * Our bssid_mask would then be:
|
|
+ *
|
|
+ * On loop iteration for BSSID-01:
|
|
+ * ~(0001 ^ 0100) -> ~(0101)
|
|
+ * -> 1010
|
|
+ * bssid_mask = 1010
|
|
+ *
|
|
+ * On loop iteration for BSSID-02:
|
|
+ * bssid_mask &= ~(0001 ^ 1001)
|
|
+ * bssid_mask = (1010) & ~(0001 ^ 1001)
|
|
+ * bssid_mask = (1010) & ~(1001)
|
|
+ * bssid_mask = (1010) & (0110)
|
|
+ * bssid_mask = 0010
|
|
+ *
|
|
+ * A bssid_mask of 0010 means "only pay attention to the second least
|
|
+ * significant bit". This is because its the only bit common
|
|
+ * amongst the MAC and all BSSIDs we support. To findout what the real
|
|
+ * common bit is we can simply "&" the bssid_mask now with any BSSID we have
|
|
+ * or our MAC address (we assume the hardware uses the MAC address).
|
|
+ *
|
|
+ * Now, suppose there's an incoming frame for BSSID-03:
|
|
+ *
|
|
+ * IFRAME-01: 0110
|
|
+ *
|
|
+ * An easy eye-inspeciton of this already should tell you that this frame
|
|
+ * will not pass our check. This is beacuse the bssid_mask tells the
|
|
+ * hardware to only look at the second least significant bit and the
|
|
+ * common bit amongst the MAC and BSSIDs is 0, this frame has the 2nd LSB
|
|
+ * as 1, which does not match 0.
|
|
+ *
|
|
+ * So with IFRAME-01 we *assume* the hardware will do:
|
|
+ *
|
|
+ * allow = (IFRAME-01 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0;
|
|
+ * --> allow = (0110 & 0010) == (0010 & 0001) ? 1 : 0;
|
|
+ * --> allow = (0010) == 0000 ? 1 : 0;
|
|
+ * --> allow = 0
|
|
+ *
|
|
+ * Lets now test a frame that should work:
|
|
+ *
|
|
+ * IFRAME-02: 0001 (we should allow)
|
|
+ *
|
|
+ * allow = (0001 & 1010) == 1010
|
|
+ *
|
|
+ * allow = (IFRAME-02 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0;
|
|
+ * --> allow = (0001 & 0010) == (0010 & 0001) ? 1 :0;
|
|
+ * --> allow = (0010) == (0010)
|
|
+ * --> allow = 1
|
|
+ *
|
|
+ * Other examples:
|
|
+ *
|
|
+ * IFRAME-03: 0100 --> allowed
|
|
+ * IFRAME-04: 1001 --> allowed
|
|
+ * IFRAME-05: 1101 --> allowed but its not for us!!!
|
|
+ *
|
|
+ */
|
|
+int ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask)
|
|
+{
|
|
+ u32 low_id, high_id;
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+
|
|
+ if (ah->ah_version == AR5K_AR5212) {
|
|
+ low_id = AR5K_LOW_ID(mask);
|
|
+ high_id = AR5K_HIGH_ID(mask);
|
|
+
|
|
+ ath5k_hw_reg_write(ah, low_id, AR5K_BSS_IDM0);
|
|
+ ath5k_hw_reg_write(ah, high_id, AR5K_BSS_IDM1);
|
|
+
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ return -EIO;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Receive start/stop functions
|
|
+ */
|
|
+
|
|
+/*
|
|
+ * Start receive on PCU
|
|
+ */
|
|
+void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah)
|
|
+{
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+ AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Stop receive on PCU
|
|
+ */
|
|
+void ath5k_hw_stop_pcu_recv(struct ath5k_hw *ah)
|
|
+{
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+ AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * RX Filter functions
|
|
+ */
|
|
+
|
|
+/*
|
|
+ * Set multicast filter
|
|
+ */
|
|
+void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1)
|
|
+{
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+ /* Set the multicat filter */
|
|
+ ath5k_hw_reg_write(ah, filter0, AR5K_MCAST_FILTER0);
|
|
+ ath5k_hw_reg_write(ah, filter1, AR5K_MCAST_FILTER1);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Set multicast filter by index
|
|
+ */
|
|
+int ath5k_hw_set_mcast_filterindex(struct ath5k_hw *ah, u32 index)
|
|
+{
|
|
+
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+ if (index >= 64)
|
|
+ return -EINVAL;
|
|
+ else if (index >= 32)
|
|
+ AR5K_REG_ENABLE_BITS(ah, AR5K_MCAST_FILTER1,
|
|
+ (1 << (index - 32)));
|
|
+ else
|
|
+ AR5K_REG_ENABLE_BITS(ah, AR5K_MCAST_FILTER0, (1 << index));
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Clear Multicast filter by index
|
|
+ */
|
|
+int ath5k_hw_clear_mcast_filter_idx(struct ath5k_hw *ah, u32 index)
|
|
+{
|
|
+
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+ if (index >= 64)
|
|
+ return -EINVAL;
|
|
+ else if (index >= 32)
|
|
+ AR5K_REG_DISABLE_BITS(ah, AR5K_MCAST_FILTER1,
|
|
+ (1 << (index - 32)));
|
|
+ else
|
|
+ AR5K_REG_DISABLE_BITS(ah, AR5K_MCAST_FILTER0, (1 << index));
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Get current rx filter
|
|
+ */
|
|
+u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah)
|
|
+{
|
|
+ u32 data, filter = 0;
|
|
+
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+ filter = ath5k_hw_reg_read(ah, AR5K_RX_FILTER);
|
|
+
|
|
+ /*Radar detection for 5212*/
|
|
+ if (ah->ah_version == AR5K_AR5212) {
|
|
+ data = ath5k_hw_reg_read(ah, AR5K_PHY_ERR_FIL);
|
|
+
|
|
+ if (data & AR5K_PHY_ERR_FIL_RADAR)
|
|
+ filter |= AR5K_RX_FILTER_RADARERR;
|
|
+ if (data & (AR5K_PHY_ERR_FIL_OFDM | AR5K_PHY_ERR_FIL_CCK))
|
|
+ filter |= AR5K_RX_FILTER_PHYERR;
|
|
+ }
|
|
+
|
|
+ return filter;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Set rx filter
|
|
+ */
|
|
+void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter)
|
|
+{
|
|
+ u32 data = 0;
|
|
+
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+
|
|
+ /* Set PHY error filter register on 5212*/
|
|
+ if (ah->ah_version == AR5K_AR5212) {
|
|
+ if (filter & AR5K_RX_FILTER_RADARERR)
|
|
+ data |= AR5K_PHY_ERR_FIL_RADAR;
|
|
+ if (filter & AR5K_RX_FILTER_PHYERR)
|
|
+ data |= AR5K_PHY_ERR_FIL_OFDM | AR5K_PHY_ERR_FIL_CCK;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * The AR5210 uses promiscous mode to detect radar activity
|
|
+ */
|
|
+ if (ah->ah_version == AR5K_AR5210 &&
|
|
+ (filter & AR5K_RX_FILTER_RADARERR)) {
|
|
+ filter &= ~AR5K_RX_FILTER_RADARERR;
|
|
+ filter |= AR5K_RX_FILTER_PROM;
|
|
+ }
|
|
+
|
|
+ /*Zero length DMA*/
|
|
+ if (data)
|
|
+ AR5K_REG_ENABLE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_ZLFDMA);
|
|
+ else
|
|
+ AR5K_REG_DISABLE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_ZLFDMA);
|
|
+
|
|
+ /*Write RX Filter register*/
|
|
+ ath5k_hw_reg_write(ah, filter & 0xff, AR5K_RX_FILTER);
|
|
+
|
|
+ /*Write PHY error filter register on 5212*/
|
|
+ if (ah->ah_version == AR5K_AR5212)
|
|
+ ath5k_hw_reg_write(ah, data, AR5K_PHY_ERR_FIL);
|
|
+
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Beacon related functions
|
|
+ */
|
|
+
|
|
+/*
|
|
+ * Get a 32bit TSF
|
|
+ */
|
|
+u32 ath5k_hw_get_tsf32(struct ath5k_hw *ah)
|
|
+{
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+ return ath5k_hw_reg_read(ah, AR5K_TSF_L32);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Get the full 64bit TSF
|
|
+ */
|
|
+u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah)
|
|
+{
|
|
+ u64 tsf = ath5k_hw_reg_read(ah, AR5K_TSF_U32);
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+
|
|
+ return ath5k_hw_reg_read(ah, AR5K_TSF_L32) | (tsf << 32);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Force a TSF reset
|
|
+ */
|
|
+void ath5k_hw_reset_tsf(struct ath5k_hw *ah)
|
|
+{
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+ AR5K_REG_ENABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_RESET_TSF);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Initialize beacon timers
|
|
+ */
|
|
+void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval)
|
|
+{
|
|
+ u32 timer1, timer2, timer3;
|
|
+
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+ /*
|
|
+ * Set the additional timers by mode
|
|
+ */
|
|
+ switch (ah->ah_op_mode) {
|
|
+ case IEEE80211_IF_TYPE_STA:
|
|
+ if (ah->ah_version == AR5K_AR5210) {
|
|
+ timer1 = 0xffffffff;
|
|
+ timer2 = 0xffffffff;
|
|
+ } else {
|
|
+ timer1 = 0x0000ffff;
|
|
+ timer2 = 0x0007ffff;
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ timer1 = (next_beacon - AR5K_TUNE_DMA_BEACON_RESP) <<
|
|
+ 0x00000003;
|
|
+ timer2 = (next_beacon - AR5K_TUNE_SW_BEACON_RESP) <<
|
|
+ 0x00000003;
|
|
+ }
|
|
+
|
|
+ timer3 = next_beacon + (ah->ah_atim_window ? ah->ah_atim_window : 1);
|
|
+
|
|
+ /*
|
|
+ * Set the beacon register and enable all timers.
|
|
+ * (next beacon, DMA beacon, software beacon, ATIM window time)
|
|
+ */
|
|
+ ath5k_hw_reg_write(ah, next_beacon, AR5K_TIMER0);
|
|
+ ath5k_hw_reg_write(ah, timer1, AR5K_TIMER1);
|
|
+ ath5k_hw_reg_write(ah, timer2, AR5K_TIMER2);
|
|
+ ath5k_hw_reg_write(ah, timer3, AR5K_TIMER3);
|
|
+
|
|
+ ath5k_hw_reg_write(ah, interval & (AR5K_BEACON_PERIOD |
|
|
+ AR5K_BEACON_RESET_TSF | AR5K_BEACON_ENABLE),
|
|
+ AR5K_BEACON);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Set beacon timers
|
|
+ */
|
|
+int ath5k_hw_set_beacon_timers(struct ath5k_hw *ah,
|
|
+ const struct ath5k_beacon_state *state)
|
|
+{
|
|
+ u32 cfp_period, next_cfp, dtim, interval, next_beacon;
|
|
+
|
|
+ /*
|
|
+ * TODO: should be changed through *state
|
|
+ * review struct ath5k_beacon_state struct
|
|
+ *
|
|
+ * XXX: These are used for cfp period bellow, are they
|
|
+ * ok ? Is it O.K. for tsf here to be 0 or should we use
|
|
+ * get_tsf ?
|
|
+ */
|
|
+ u32 dtim_count = 0; /* XXX */
|
|
+ u32 cfp_count = 0; /* XXX */
|
|
+ u32 tsf = 0; /* XXX */
|
|
+
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+ /* Return on an invalid beacon state */
|
|
+ if (state->bs_interval < 1)
|
|
+ return -EINVAL;
|
|
+
|
|
+ interval = state->bs_interval;
|
|
+ dtim = state->bs_dtim_period;
|
|
+
|
|
+ /*
|
|
+ * PCF support?
|
|
+ */
|
|
+ if (state->bs_cfp_period > 0) {
|
|
+ /*
|
|
+ * Enable PCF mode and set the CFP
|
|
+ * (Contention Free Period) and timer registers
|
|
+ */
|
|
+ cfp_period = state->bs_cfp_period * state->bs_dtim_period *
|
|
+ state->bs_interval;
|
|
+ next_cfp = (cfp_count * state->bs_dtim_period + dtim_count) *
|
|
+ state->bs_interval;
|
|
+
|
|
+ AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1,
|
|
+ AR5K_STA_ID1_DEFAULT_ANTENNA |
|
|
+ AR5K_STA_ID1_PCF);
|
|
+ ath5k_hw_reg_write(ah, cfp_period, AR5K_CFP_PERIOD);
|
|
+ ath5k_hw_reg_write(ah, state->bs_cfp_max_duration,
|
|
+ AR5K_CFP_DUR);
|
|
+ ath5k_hw_reg_write(ah, (tsf + (next_cfp == 0 ? cfp_period :
|
|
+ next_cfp)) << 3, AR5K_TIMER2);
|
|
+ } else {
|
|
+ /* Disable PCF mode */
|
|
+ AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1,
|
|
+ AR5K_STA_ID1_DEFAULT_ANTENNA |
|
|
+ AR5K_STA_ID1_PCF);
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Enable the beacon timer register
|
|
+ */
|
|
+ ath5k_hw_reg_write(ah, state->bs_next_beacon, AR5K_TIMER0);
|
|
+
|
|
+ /*
|
|
+ * Start the beacon timers
|
|
+ */
|
|
+ ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, AR5K_BEACON) &~
|
|
+ (AR5K_BEACON_PERIOD | AR5K_BEACON_TIM)) |
|
|
+ AR5K_REG_SM(state->bs_tim_offset ? state->bs_tim_offset + 4 : 0,
|
|
+ AR5K_BEACON_TIM) | AR5K_REG_SM(state->bs_interval,
|
|
+ AR5K_BEACON_PERIOD), AR5K_BEACON);
|
|
+
|
|
+ /*
|
|
+ * Write new beacon miss threshold, if it appears to be valid
|
|
+ * XXX: Figure out right values for min <= bs_bmiss_threshold <= max
|
|
+ * and return if its not in range. We can test this by reading value and
|
|
+ * setting value to a largest value and seeing which values register.
|
|
+ */
|
|
+
|
|
+ AR5K_REG_WRITE_BITS(ah, AR5K_RSSI_THR, AR5K_RSSI_THR_BMISS,
|
|
+ state->bs_bmiss_threshold);
|
|
+
|
|
+ /*
|
|
+ * Set sleep control register
|
|
+ * XXX: Didn't find this in 5210 code but since this register
|
|
+ * exists also in ar5k's 5210 headers i leave it as common code.
|
|
+ */
|
|
+ AR5K_REG_WRITE_BITS(ah, AR5K_SLEEP_CTL, AR5K_SLEEP_CTL_SLDUR,
|
|
+ (state->bs_sleep_duration - 3) << 3);
|
|
+
|
|
+ /*
|
|
+ * Set enhanced sleep registers on 5212
|
|
+ */
|
|
+ if (ah->ah_version == AR5K_AR5212) {
|
|
+ if (state->bs_sleep_duration > state->bs_interval &&
|
|
+ roundup(state->bs_sleep_duration, interval) ==
|
|
+ state->bs_sleep_duration)
|
|
+ interval = state->bs_sleep_duration;
|
|
+
|
|
+ if (state->bs_sleep_duration > dtim && (dtim == 0 ||
|
|
+ roundup(state->bs_sleep_duration, dtim) ==
|
|
+ state->bs_sleep_duration))
|
|
+ dtim = state->bs_sleep_duration;
|
|
+
|
|
+ if (interval > dtim)
|
|
+ return -EINVAL;
|
|
+
|
|
+ next_beacon = interval == dtim ? state->bs_next_dtim :
|
|
+ state->bs_next_beacon;
|
|
+
|
|
+ ath5k_hw_reg_write(ah,
|
|
+ AR5K_REG_SM((state->bs_next_dtim - 3) << 3,
|
|
+ AR5K_SLEEP0_NEXT_DTIM) |
|
|
+ AR5K_REG_SM(10, AR5K_SLEEP0_CABTO) |
|
|
+ AR5K_SLEEP0_ENH_SLEEP_EN |
|
|
+ AR5K_SLEEP0_ASSUME_DTIM, AR5K_SLEEP0);
|
|
+
|
|
+ ath5k_hw_reg_write(ah, AR5K_REG_SM((next_beacon - 3) << 3,
|
|
+ AR5K_SLEEP1_NEXT_TIM) |
|
|
+ AR5K_REG_SM(10, AR5K_SLEEP1_BEACON_TO), AR5K_SLEEP1);
|
|
+
|
|
+ ath5k_hw_reg_write(ah,
|
|
+ AR5K_REG_SM(interval, AR5K_SLEEP2_TIM_PER) |
|
|
+ AR5K_REG_SM(dtim, AR5K_SLEEP2_DTIM_PER), AR5K_SLEEP2);
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Reset beacon timers
|
|
+ */
|
|
+void ath5k_hw_reset_beacon(struct ath5k_hw *ah)
|
|
+{
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+ /*
|
|
+ * Disable beacon timer
|
|
+ */
|
|
+ ath5k_hw_reg_write(ah, 0, AR5K_TIMER0);
|
|
+
|
|
+ /*
|
|
+ * Disable some beacon register values
|
|
+ */
|
|
+ AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1,
|
|
+ AR5K_STA_ID1_DEFAULT_ANTENNA | AR5K_STA_ID1_PCF);
|
|
+ ath5k_hw_reg_write(ah, AR5K_BEACON_PERIOD, AR5K_BEACON);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Wait for beacon queue to finish
|
|
+ * TODO: This function's name is misleading, rename
|
|
+ */
|
|
+int ath5k_hw_wait_for_beacon(struct ath5k_hw *ah, unsigned long phys_addr)
|
|
+{
|
|
+ unsigned int i;
|
|
+ int ret;
|
|
+
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+
|
|
+ /* 5210 doesn't have QCU*/
|
|
+ if (ah->ah_version == AR5K_AR5210) {
|
|
+ /*
|
|
+ * Wait for beaconn queue to finish by checking
|
|
+ * Control Register and Beacon Status Register.
|
|
+ */
|
|
+ for (i = AR5K_TUNE_BEACON_INTERVAL / 2; i > 0; i--) {
|
|
+ if (!(ath5k_hw_reg_read(ah, AR5K_BSR) & AR5K_BSR_TXQ1F)
|
|
+ ||
|
|
+ !(ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_BSR_TXQ1F))
|
|
+ break;
|
|
+ udelay(10);
|
|
+ }
|
|
+
|
|
+ /* Timeout... */
|
|
+ if (i <= 0) {
|
|
+ /*
|
|
+ * Re-schedule the beacon queue
|
|
+ */
|
|
+ ath5k_hw_reg_write(ah, phys_addr, AR5K_NOQCU_TXDP1);
|
|
+ ath5k_hw_reg_write(ah, AR5K_BCR_TQ1V | AR5K_BCR_BDMAE,
|
|
+ AR5K_BCR);
|
|
+
|
|
+ return -EIO;
|
|
+ }
|
|
+ ret = 0;
|
|
+ } else {
|
|
+ /*5211/5212*/
|
|
+ ret = ath5k_hw_register_timeout(ah,
|
|
+ AR5K_QUEUE_STATUS(AR5K_TX_QUEUE_ID_BEACON),
|
|
+ AR5K_QCU_STS_FRMPENDCNT, 0, false);
|
|
+
|
|
+ if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, AR5K_TX_QUEUE_ID_BEACON))
|
|
+ return -EIO;
|
|
+ }
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Update mib counters (statistics)
|
|
+ */
|
|
+void ath5k_hw_update_mib_counters(struct ath5k_hw *ah,
|
|
+ struct ath5k_mib_stats *statistics)
|
|
+{
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+ /* Read-And-Clear */
|
|
+ statistics->ackrcv_bad += ath5k_hw_reg_read(ah, AR5K_ACK_FAIL);
|
|
+ statistics->rts_bad += ath5k_hw_reg_read(ah, AR5K_RTS_FAIL);
|
|
+ statistics->rts_good += ath5k_hw_reg_read(ah, AR5K_RTS_OK);
|
|
+ statistics->fcs_bad += ath5k_hw_reg_read(ah, AR5K_FCS_FAIL);
|
|
+ statistics->beacons += ath5k_hw_reg_read(ah, AR5K_BEACON_CNT);
|
|
+
|
|
+ /* Reset profile count registers on 5212*/
|
|
+ if (ah->ah_version == AR5K_AR5212) {
|
|
+ ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_TX);
|
|
+ ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RX);
|
|
+ ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RXCLR);
|
|
+ ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_CYCLE);
|
|
+ }
|
|
+}
|
|
+
|
|
+/** ath5k_hw_set_ack_bitrate - set bitrate for ACKs
|
|
+ *
|
|
+ * @ah: the &struct ath5k_hw
|
|
+ * @high: determines if to use low bit rate or now
|
|
+ */
|
|
+void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high)
|
|
+{
|
|
+ if (ah->ah_version != AR5K_AR5212)
|
|
+ return;
|
|
+ else {
|
|
+ u32 val = AR5K_STA_ID1_BASE_RATE_11B | AR5K_STA_ID1_ACKCTS_6MB;
|
|
+ if (high)
|
|
+ AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, val);
|
|
+ else
|
|
+ AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, val);
|
|
+ }
|
|
+}
|
|
+
|
|
+
|
|
+/*
|
|
+ * ACK/CTS Timeouts
|
|
+ */
|
|
+
|
|
+/*
|
|
+ * Set ACK timeout on PCU
|
|
+ */
|
|
+int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout)
|
|
+{
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+ if (ath5k_hw_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_ACK),
|
|
+ ah->ah_turbo) <= timeout)
|
|
+ return -EINVAL;
|
|
+
|
|
+ AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_ACK,
|
|
+ ath5k_hw_htoclock(timeout, ah->ah_turbo));
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Read the ACK timeout from PCU
|
|
+ */
|
|
+unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah)
|
|
+{
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+
|
|
+ return ath5k_hw_clocktoh(AR5K_REG_MS(ath5k_hw_reg_read(ah,
|
|
+ AR5K_TIME_OUT), AR5K_TIME_OUT_ACK), ah->ah_turbo);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Set CTS timeout on PCU
|
|
+ */
|
|
+int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout)
|
|
+{
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+ if (ath5k_hw_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_CTS),
|
|
+ ah->ah_turbo) <= timeout)
|
|
+ return -EINVAL;
|
|
+
|
|
+ AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_CTS,
|
|
+ ath5k_hw_htoclock(timeout, ah->ah_turbo));
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Read CTS timeout from PCU
|
|
+ */
|
|
+unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah)
|
|
+{
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+ return ath5k_hw_clocktoh(AR5K_REG_MS(ath5k_hw_reg_read(ah,
|
|
+ AR5K_TIME_OUT), AR5K_TIME_OUT_CTS), ah->ah_turbo);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Key table (WEP) functions
|
|
+ */
|
|
+
|
|
+int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry)
|
|
+{
|
|
+ unsigned int i;
|
|
+
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+ AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE);
|
|
+
|
|
+ for (i = 0; i < AR5K_KEYCACHE_SIZE; i++)
|
|
+ ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_OFF(entry, i));
|
|
+
|
|
+ /* Set NULL encryption on non-5210*/
|
|
+ if (ah->ah_version != AR5K_AR5210)
|
|
+ ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL,
|
|
+ AR5K_KEYTABLE_TYPE(entry));
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int ath5k_hw_is_key_valid(struct ath5k_hw *ah, u16 entry)
|
|
+{
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+ AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE);
|
|
+
|
|
+ /* Check the validation flag at the end of the entry */
|
|
+ return ath5k_hw_reg_read(ah, AR5K_KEYTABLE_MAC1(entry)) &
|
|
+ AR5K_KEYTABLE_VALID;
|
|
+}
|
|
+
|
|
+int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry,
|
|
+ const struct ieee80211_key_conf *key, const u8 *mac)
|
|
+{
|
|
+ unsigned int i;
|
|
+ __le32 key_v[5] = {};
|
|
+ u32 keytype;
|
|
+
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+
|
|
+ /* key->keylen comes in from mac80211 in bytes */
|
|
+
|
|
+ if (key->keylen > AR5K_KEYTABLE_SIZE / 8)
|
|
+ return -EOPNOTSUPP;
|
|
+
|
|
+ switch (key->keylen) {
|
|
+ /* WEP 40-bit = 40-bit entered key + 24 bit IV = 64-bit */
|
|
+ case 40 / 8:
|
|
+ memcpy(&key_v[0], key->key, 5);
|
|
+ keytype = AR5K_KEYTABLE_TYPE_40;
|
|
+ break;
|
|
+
|
|
+ /* WEP 104-bit = 104-bit entered key + 24-bit IV = 128-bit */
|
|
+ case 104 / 8:
|
|
+ memcpy(&key_v[0], &key->key[0], 6);
|
|
+ memcpy(&key_v[2], &key->key[6], 6);
|
|
+ memcpy(&key_v[4], &key->key[12], 1);
|
|
+ keytype = AR5K_KEYTABLE_TYPE_104;
|
|
+ break;
|
|
+ /* WEP 128-bit = 128-bit entered key + 24 bit IV = 152-bit */
|
|
+ case 128 / 8:
|
|
+ memcpy(&key_v[0], &key->key[0], 6);
|
|
+ memcpy(&key_v[2], &key->key[6], 6);
|
|
+ memcpy(&key_v[4], &key->key[12], 4);
|
|
+ keytype = AR5K_KEYTABLE_TYPE_128;
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ return -EINVAL; /* shouldn't happen */
|
|
+ }
|
|
+
|
|
+ for (i = 0; i < ARRAY_SIZE(key_v); i++)
|
|
+ ath5k_hw_reg_write(ah, le32_to_cpu(key_v[i]),
|
|
+ AR5K_KEYTABLE_OFF(entry, i));
|
|
+
|
|
+ ath5k_hw_reg_write(ah, keytype, AR5K_KEYTABLE_TYPE(entry));
|
|
+
|
|
+ return ath5k_hw_set_key_lladdr(ah, entry, mac);
|
|
+}
|
|
+
|
|
+int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac)
|
|
+{
|
|
+ u32 low_id, high_id;
|
|
+
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+ /* Invalid entry (key table overflow) */
|
|
+ AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE);
|
|
+
|
|
+ /* MAC may be NULL if it's a broadcast key. In this case no need to
|
|
+ * to compute AR5K_LOW_ID and AR5K_HIGH_ID as we already know it. */
|
|
+ if (unlikely(mac == NULL)) {
|
|
+ low_id = 0xffffffff;
|
|
+ high_id = 0xffff | AR5K_KEYTABLE_VALID;
|
|
+ } else {
|
|
+ low_id = AR5K_LOW_ID(mac);
|
|
+ high_id = AR5K_HIGH_ID(mac) | AR5K_KEYTABLE_VALID;
|
|
+ }
|
|
+
|
|
+ ath5k_hw_reg_write(ah, low_id, AR5K_KEYTABLE_MAC0(entry));
|
|
+ ath5k_hw_reg_write(ah, high_id, AR5K_KEYTABLE_MAC1(entry));
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+
|
|
+/********************************************\
|
|
+Queue Control Unit, DFS Control Unit Functions
|
|
+\********************************************/
|
|
+
|
|
+/*
|
|
+ * Initialize a transmit queue
|
|
+ */
|
|
+int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type,
|
|
+ struct ath5k_txq_info *queue_info)
|
|
+{
|
|
+ unsigned int queue;
|
|
+ int ret;
|
|
+
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+
|
|
+ /*
|
|
+ * Get queue by type
|
|
+ */
|
|
+ /*5210 only has 2 queues*/
|
|
+ if (ah->ah_version == AR5K_AR5210) {
|
|
+ switch (queue_type) {
|
|
+ case AR5K_TX_QUEUE_DATA:
|
|
+ queue = AR5K_TX_QUEUE_ID_NOQCU_DATA;
|
|
+ break;
|
|
+ case AR5K_TX_QUEUE_BEACON:
|
|
+ case AR5K_TX_QUEUE_CAB:
|
|
+ queue = AR5K_TX_QUEUE_ID_NOQCU_BEACON;
|
|
+ break;
|
|
+ default:
|
|
+ return -EINVAL;
|
|
+ }
|
|
+ } else {
|
|
+ switch (queue_type) {
|
|
+ case AR5K_TX_QUEUE_DATA:
|
|
+ for (queue = AR5K_TX_QUEUE_ID_DATA_MIN;
|
|
+ ah->ah_txq[queue].tqi_type !=
|
|
+ AR5K_TX_QUEUE_INACTIVE; queue++) {
|
|
+
|
|
+ if (queue > AR5K_TX_QUEUE_ID_DATA_MAX)
|
|
+ return -EINVAL;
|
|
+ }
|
|
+ break;
|
|
+ case AR5K_TX_QUEUE_UAPSD:
|
|
+ queue = AR5K_TX_QUEUE_ID_UAPSD;
|
|
+ break;
|
|
+ case AR5K_TX_QUEUE_BEACON:
|
|
+ queue = AR5K_TX_QUEUE_ID_BEACON;
|
|
+ break;
|
|
+ case AR5K_TX_QUEUE_CAB:
|
|
+ queue = AR5K_TX_QUEUE_ID_CAB;
|
|
+ break;
|
|
+ case AR5K_TX_QUEUE_XR_DATA:
|
|
+ if (ah->ah_version != AR5K_AR5212)
|
|
+ ATH5K_ERR(ah->ah_sc,
|
|
+ "XR data queues only supported in"
|
|
+ " 5212!\n");
|
|
+ queue = AR5K_TX_QUEUE_ID_XR_DATA;
|
|
+ break;
|
|
+ default:
|
|
+ return -EINVAL;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Setup internal queue structure
|
|
+ */
|
|
+ memset(&ah->ah_txq[queue], 0, sizeof(struct ath5k_txq_info));
|
|
+ ah->ah_txq[queue].tqi_type = queue_type;
|
|
+
|
|
+ if (queue_info != NULL) {
|
|
+ queue_info->tqi_type = queue_type;
|
|
+ ret = ath5k_hw_setup_tx_queueprops(ah, queue, queue_info);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+ }
|
|
+ /*
|
|
+ * We use ah_txq_status to hold a temp value for
|
|
+ * the Secondary interrupt mask registers on 5211+
|
|
+ * check out ath5k_hw_reset_tx_queue
|
|
+ */
|
|
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_status, queue);
|
|
+
|
|
+ return queue;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Setup a transmit queue
|
|
+ */
|
|
+int ath5k_hw_setup_tx_queueprops(struct ath5k_hw *ah, int queue,
|
|
+ const struct ath5k_txq_info *queue_info)
|
|
+{
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+ AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
|
|
+
|
|
+ if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE)
|
|
+ return -EIO;
|
|
+
|
|
+ memcpy(&ah->ah_txq[queue], queue_info, sizeof(struct ath5k_txq_info));
|
|
+
|
|
+ /*XXX: Is this supported on 5210 ?*/
|
|
+ if ((queue_info->tqi_type == AR5K_TX_QUEUE_DATA &&
|
|
+ ((queue_info->tqi_subtype == AR5K_WME_AC_VI) ||
|
|
+ (queue_info->tqi_subtype == AR5K_WME_AC_VO))) ||
|
|
+ queue_info->tqi_type == AR5K_TX_QUEUE_UAPSD)
|
|
+ ah->ah_txq[queue].tqi_flags |= AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Get properties for a specific transmit queue
|
|
+ */
|
|
+int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue,
|
|
+ struct ath5k_txq_info *queue_info)
|
|
+{
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+ memcpy(queue_info, &ah->ah_txq[queue], sizeof(struct ath5k_txq_info));
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Set a transmit queue inactive
|
|
+ */
|
|
+void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue)
|
|
+{
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+ if (WARN_ON(queue >= ah->ah_capabilities.cap_queues.q_tx_num))
|
|
+ return;
|
|
+
|
|
+ /* This queue will be skipped in further operations */
|
|
+ ah->ah_txq[queue].tqi_type = AR5K_TX_QUEUE_INACTIVE;
|
|
+ /*For SIMR setup*/
|
|
+ AR5K_Q_DISABLE_BITS(ah->ah_txq_status, queue);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Set DFS params for a transmit queue
|
|
+ */
|
|
+int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
|
|
+{
|
|
+ u32 cw_min, cw_max, retry_lg, retry_sh;
|
|
+ struct ath5k_txq_info *tq = &ah->ah_txq[queue];
|
|
+
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+ AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
|
|
+
|
|
+ tq = &ah->ah_txq[queue];
|
|
+
|
|
+ if (tq->tqi_type == AR5K_TX_QUEUE_INACTIVE)
|
|
+ return 0;
|
|
+
|
|
+ if (ah->ah_version == AR5K_AR5210) {
|
|
+ /* Only handle data queues, others will be ignored */
|
|
+ if (tq->tqi_type != AR5K_TX_QUEUE_DATA)
|
|
+ return 0;
|
|
+
|
|
+ /* Set Slot time */
|
|
+ ath5k_hw_reg_write(ah, ah->ah_turbo == true ?
|
|
+ AR5K_INIT_SLOT_TIME_TURBO : AR5K_INIT_SLOT_TIME,
|
|
+ AR5K_SLOT_TIME);
|
|
+ /* Set ACK_CTS timeout */
|
|
+ ath5k_hw_reg_write(ah, ah->ah_turbo == true ?
|
|
+ AR5K_INIT_ACK_CTS_TIMEOUT_TURBO :
|
|
+ AR5K_INIT_ACK_CTS_TIMEOUT, AR5K_SLOT_TIME);
|
|
+ /* Set Transmit Latency */
|
|
+ ath5k_hw_reg_write(ah, ah->ah_turbo == true ?
|
|
+ AR5K_INIT_TRANSMIT_LATENCY_TURBO :
|
|
+ AR5K_INIT_TRANSMIT_LATENCY, AR5K_USEC_5210);
|
|
+ /* Set IFS0 */
|
|
+ if (ah->ah_turbo == true)
|
|
+ ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS_TURBO +
|
|
+ (ah->ah_aifs + tq->tqi_aifs) *
|
|
+ AR5K_INIT_SLOT_TIME_TURBO) <<
|
|
+ AR5K_IFS0_DIFS_S) | AR5K_INIT_SIFS_TURBO,
|
|
+ AR5K_IFS0);
|
|
+ else
|
|
+ ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS +
|
|
+ (ah->ah_aifs + tq->tqi_aifs) *
|
|
+ AR5K_INIT_SLOT_TIME) << AR5K_IFS0_DIFS_S) |
|
|
+ AR5K_INIT_SIFS, AR5K_IFS0);
|
|
+
|
|
+ /* Set IFS1 */
|
|
+ ath5k_hw_reg_write(ah, ah->ah_turbo == true ?
|
|
+ AR5K_INIT_PROTO_TIME_CNTRL_TURBO :
|
|
+ AR5K_INIT_PROTO_TIME_CNTRL, AR5K_IFS1);
|
|
+ /* Set PHY register 0x9844 (??) */
|
|
+ ath5k_hw_reg_write(ah, ah->ah_turbo == true ?
|
|
+ (ath5k_hw_reg_read(ah, AR5K_PHY(17)) & ~0x7F) | 0x38 :
|
|
+ (ath5k_hw_reg_read(ah, AR5K_PHY(17)) & ~0x7F) | 0x1C,
|
|
+ AR5K_PHY(17));
|
|
+ /* Set Frame Control Register */
|
|
+ ath5k_hw_reg_write(ah, ah->ah_turbo == true ?
|
|
+ (AR5K_PHY_FRAME_CTL_INI | AR5K_PHY_TURBO_MODE |
|
|
+ AR5K_PHY_TURBO_SHORT | 0x2020) :
|
|
+ (AR5K_PHY_FRAME_CTL_INI | 0x1020),
|
|
+ AR5K_PHY_FRAME_CTL_5210);
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Calculate cwmin/max by channel mode
|
|
+ */
|
|
+ cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN;
|
|
+ cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX;
|
|
+ ah->ah_aifs = AR5K_TUNE_AIFS;
|
|
+ /*XR is only supported on 5212*/
|
|
+ if (IS_CHAN_XR(ah->ah_current_channel) &&
|
|
+ ah->ah_version == AR5K_AR5212) {
|
|
+ cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN_XR;
|
|
+ cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX_XR;
|
|
+ ah->ah_aifs = AR5K_TUNE_AIFS_XR;
|
|
+ /*B mode is not supported on 5210*/
|
|
+ } else if (IS_CHAN_B(ah->ah_current_channel) &&
|
|
+ ah->ah_version != AR5K_AR5210) {
|
|
+ cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN_11B;
|
|
+ cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX_11B;
|
|
+ ah->ah_aifs = AR5K_TUNE_AIFS_11B;
|
|
+ }
|
|
+
|
|
+ cw_min = 1;
|
|
+ while (cw_min < ah->ah_cw_min)
|
|
+ cw_min = (cw_min << 1) | 1;
|
|
+
|
|
+ cw_min = tq->tqi_cw_min < 0 ? (cw_min >> (-tq->tqi_cw_min)) :
|
|
+ ((cw_min << tq->tqi_cw_min) + (1 << tq->tqi_cw_min) - 1);
|
|
+ cw_max = tq->tqi_cw_max < 0 ? (cw_max >> (-tq->tqi_cw_max)) :
|
|
+ ((cw_max << tq->tqi_cw_max) + (1 << tq->tqi_cw_max) - 1);
|
|
+
|
|
+ /*
|
|
+ * Calculate and set retry limits
|
|
+ */
|
|
+ if (ah->ah_software_retry == true) {
|
|
+ /* XXX Need to test this */
|
|
+ retry_lg = ah->ah_limit_tx_retries;
|
|
+ retry_sh = retry_lg = retry_lg > AR5K_DCU_RETRY_LMT_SH_RETRY ?
|
|
+ AR5K_DCU_RETRY_LMT_SH_RETRY : retry_lg;
|
|
+ } else {
|
|
+ retry_lg = AR5K_INIT_LG_RETRY;
|
|
+ retry_sh = AR5K_INIT_SH_RETRY;
|
|
+ }
|
|
+
|
|
+ /*No QCU/DCU [5210]*/
|
|
+ if (ah->ah_version == AR5K_AR5210) {
|
|
+ ath5k_hw_reg_write(ah,
|
|
+ (cw_min << AR5K_NODCU_RETRY_LMT_CW_MIN_S)
|
|
+ | AR5K_REG_SM(AR5K_INIT_SLG_RETRY,
|
|
+ AR5K_NODCU_RETRY_LMT_SLG_RETRY)
|
|
+ | AR5K_REG_SM(AR5K_INIT_SSH_RETRY,
|
|
+ AR5K_NODCU_RETRY_LMT_SSH_RETRY)
|
|
+ | AR5K_REG_SM(retry_lg, AR5K_NODCU_RETRY_LMT_LG_RETRY)
|
|
+ | AR5K_REG_SM(retry_sh, AR5K_NODCU_RETRY_LMT_SH_RETRY),
|
|
+ AR5K_NODCU_RETRY_LMT);
|
|
+ } else {
|
|
+ /*QCU/DCU [5211+]*/
|
|
+ ath5k_hw_reg_write(ah,
|
|
+ AR5K_REG_SM(AR5K_INIT_SLG_RETRY,
|
|
+ AR5K_DCU_RETRY_LMT_SLG_RETRY) |
|
|
+ AR5K_REG_SM(AR5K_INIT_SSH_RETRY,
|
|
+ AR5K_DCU_RETRY_LMT_SSH_RETRY) |
|
|
+ AR5K_REG_SM(retry_lg, AR5K_DCU_RETRY_LMT_LG_RETRY) |
|
|
+ AR5K_REG_SM(retry_sh, AR5K_DCU_RETRY_LMT_SH_RETRY),
|
|
+ AR5K_QUEUE_DFS_RETRY_LIMIT(queue));
|
|
+
|
|
+ /*===Rest is also for QCU/DCU only [5211+]===*/
|
|
+
|
|
+ /*
|
|
+ * Set initial content window (cw_min/cw_max)
|
|
+ * and arbitrated interframe space (aifs)...
|
|
+ */
|
|
+ ath5k_hw_reg_write(ah,
|
|
+ AR5K_REG_SM(cw_min, AR5K_DCU_LCL_IFS_CW_MIN) |
|
|
+ AR5K_REG_SM(cw_max, AR5K_DCU_LCL_IFS_CW_MAX) |
|
|
+ AR5K_REG_SM(ah->ah_aifs + tq->tqi_aifs,
|
|
+ AR5K_DCU_LCL_IFS_AIFS),
|
|
+ AR5K_QUEUE_DFS_LOCAL_IFS(queue));
|
|
+
|
|
+ /*
|
|
+ * Set misc registers
|
|
+ */
|
|
+ ath5k_hw_reg_write(ah, AR5K_QCU_MISC_DCU_EARLY,
|
|
+ AR5K_QUEUE_MISC(queue));
|
|
+
|
|
+ if (tq->tqi_cbr_period) {
|
|
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_cbr_period,
|
|
+ AR5K_QCU_CBRCFG_INTVAL) |
|
|
+ AR5K_REG_SM(tq->tqi_cbr_overflow_limit,
|
|
+ AR5K_QCU_CBRCFG_ORN_THRES),
|
|
+ AR5K_QUEUE_CBRCFG(queue));
|
|
+ AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
|
|
+ AR5K_QCU_MISC_FRSHED_CBR);
|
|
+ if (tq->tqi_cbr_overflow_limit)
|
|
+ AR5K_REG_ENABLE_BITS(ah,
|
|
+ AR5K_QUEUE_MISC(queue),
|
|
+ AR5K_QCU_MISC_CBR_THRES_ENABLE);
|
|
+ }
|
|
+
|
|
+ if (tq->tqi_ready_time)
|
|
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_ready_time,
|
|
+ AR5K_QCU_RDYTIMECFG_INTVAL) |
|
|
+ AR5K_QCU_RDYTIMECFG_ENABLE,
|
|
+ AR5K_QUEUE_RDYTIMECFG(queue));
|
|
+
|
|
+ if (tq->tqi_burst_time) {
|
|
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_burst_time,
|
|
+ AR5K_DCU_CHAN_TIME_DUR) |
|
|
+ AR5K_DCU_CHAN_TIME_ENABLE,
|
|
+ AR5K_QUEUE_DFS_CHANNEL_TIME(queue));
|
|
+
|
|
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE)
|
|
+ AR5K_REG_ENABLE_BITS(ah,
|
|
+ AR5K_QUEUE_MISC(queue),
|
|
+ AR5K_QCU_MISC_TXE);
|
|
+ }
|
|
+
|
|
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_BACKOFF_DISABLE)
|
|
+ ath5k_hw_reg_write(ah, AR5K_DCU_MISC_POST_FR_BKOFF_DIS,
|
|
+ AR5K_QUEUE_DFS_MISC(queue));
|
|
+
|
|
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE)
|
|
+ ath5k_hw_reg_write(ah, AR5K_DCU_MISC_BACKOFF_FRAG,
|
|
+ AR5K_QUEUE_DFS_MISC(queue));
|
|
+
|
|
+ /*
|
|
+ * Set registers by queue type
|
|
+ */
|
|
+ switch (tq->tqi_type) {
|
|
+ case AR5K_TX_QUEUE_BEACON:
|
|
+ AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
|
|
+ AR5K_QCU_MISC_FRSHED_DBA_GT |
|
|
+ AR5K_QCU_MISC_CBREXP_BCN |
|
|
+ AR5K_QCU_MISC_BCN_ENABLE);
|
|
+
|
|
+ AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
|
|
+ (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL <<
|
|
+ AR5K_DCU_MISC_ARBLOCK_CTL_S) |
|
|
+ AR5K_DCU_MISC_POST_FR_BKOFF_DIS |
|
|
+ AR5K_DCU_MISC_BCN_ENABLE);
|
|
+
|
|
+ ath5k_hw_reg_write(ah, ((AR5K_TUNE_BEACON_INTERVAL -
|
|
+ (AR5K_TUNE_SW_BEACON_RESP -
|
|
+ AR5K_TUNE_DMA_BEACON_RESP) -
|
|
+ AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF) * 1024) |
|
|
+ AR5K_QCU_RDYTIMECFG_ENABLE,
|
|
+ AR5K_QUEUE_RDYTIMECFG(queue));
|
|
+ break;
|
|
+
|
|
+ case AR5K_TX_QUEUE_CAB:
|
|
+ AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
|
|
+ AR5K_QCU_MISC_FRSHED_DBA_GT |
|
|
+ AR5K_QCU_MISC_CBREXP |
|
|
+ AR5K_QCU_MISC_CBREXP_BCN);
|
|
+
|
|
+ AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
|
|
+ (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL <<
|
|
+ AR5K_DCU_MISC_ARBLOCK_CTL_S));
|
|
+ break;
|
|
+
|
|
+ case AR5K_TX_QUEUE_UAPSD:
|
|
+ AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
|
|
+ AR5K_QCU_MISC_CBREXP);
|
|
+ break;
|
|
+
|
|
+ case AR5K_TX_QUEUE_DATA:
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Enable interrupts for this tx queue
|
|
+ * in the secondary interrupt mask registers
|
|
+ */
|
|
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_TXOKINT_ENABLE)
|
|
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txok, queue);
|
|
+
|
|
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_TXERRINT_ENABLE)
|
|
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txerr, queue);
|
|
+
|
|
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_TXURNINT_ENABLE)
|
|
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txurn, queue);
|
|
+
|
|
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_TXDESCINT_ENABLE)
|
|
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txdesc, queue);
|
|
+
|
|
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_TXEOLINT_ENABLE)
|
|
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txeol, queue);
|
|
+
|
|
+
|
|
+ /* Update secondary interrupt mask registers */
|
|
+ ah->ah_txq_imr_txok &= ah->ah_txq_status;
|
|
+ ah->ah_txq_imr_txerr &= ah->ah_txq_status;
|
|
+ ah->ah_txq_imr_txurn &= ah->ah_txq_status;
|
|
+ ah->ah_txq_imr_txdesc &= ah->ah_txq_status;
|
|
+ ah->ah_txq_imr_txeol &= ah->ah_txq_status;
|
|
+
|
|
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txok,
|
|
+ AR5K_SIMR0_QCU_TXOK) |
|
|
+ AR5K_REG_SM(ah->ah_txq_imr_txdesc,
|
|
+ AR5K_SIMR0_QCU_TXDESC), AR5K_SIMR0);
|
|
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txerr,
|
|
+ AR5K_SIMR1_QCU_TXERR) |
|
|
+ AR5K_REG_SM(ah->ah_txq_imr_txeol,
|
|
+ AR5K_SIMR1_QCU_TXEOL), AR5K_SIMR1);
|
|
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txurn,
|
|
+ AR5K_SIMR2_QCU_TXURN), AR5K_SIMR2);
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Get number of pending frames
|
|
+ * for a specific queue [5211+]
|
|
+ */
|
|
+u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue) {
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+ AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
|
|
+
|
|
+ /* Return if queue is declared inactive */
|
|
+ if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE)
|
|
+ return false;
|
|
+
|
|
+ /* XXX: How about AR5K_CFG_TXCNT ? */
|
|
+ if (ah->ah_version == AR5K_AR5210)
|
|
+ return false;
|
|
+
|
|
+ return AR5K_QUEUE_STATUS(queue) & AR5K_QCU_STS_FRMPENDCNT;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Set slot time
|
|
+ */
|
|
+int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time)
|
|
+{
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+ if (slot_time < AR5K_SLOT_TIME_9 || slot_time > AR5K_SLOT_TIME_MAX)
|
|
+ return -EINVAL;
|
|
+
|
|
+ if (ah->ah_version == AR5K_AR5210)
|
|
+ ath5k_hw_reg_write(ah, ath5k_hw_htoclock(slot_time,
|
|
+ ah->ah_turbo), AR5K_SLOT_TIME);
|
|
+ else
|
|
+ ath5k_hw_reg_write(ah, slot_time, AR5K_DCU_GBL_IFS_SLOT);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Get slot time
|
|
+ */
|
|
+unsigned int ath5k_hw_get_slot_time(struct ath5k_hw *ah)
|
|
+{
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+ if (ah->ah_version == AR5K_AR5210)
|
|
+ return ath5k_hw_clocktoh(ath5k_hw_reg_read(ah,
|
|
+ AR5K_SLOT_TIME) & 0xffff, ah->ah_turbo);
|
|
+ else
|
|
+ return ath5k_hw_reg_read(ah, AR5K_DCU_GBL_IFS_SLOT) & 0xffff;
|
|
+}
|
|
+
|
|
+
|
|
+/******************************\
|
|
+ Hardware Descriptor Functions
|
|
+\******************************/
|
|
+
|
|
+/*
|
|
+ * TX Descriptor
|
|
+ */
|
|
+
|
|
+/*
|
|
+ * Initialize the 2-word tx descriptor on 5210/5211
|
|
+ */
|
|
+static int
|
|
+ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
|
|
+ unsigned int pkt_len, unsigned int hdr_len, enum ath5k_pkt_type type,
|
|
+ unsigned int tx_power, unsigned int tx_rate0, unsigned int tx_tries0,
|
|
+ unsigned int key_index, unsigned int antenna_mode, unsigned int flags,
|
|
+ unsigned int rtscts_rate, unsigned int rtscts_duration)
|
|
+{
|
|
+ u32 frame_type;
|
|
+ struct ath5k_hw_2w_tx_desc *tx_desc;
|
|
+ unsigned int buff_len;
|
|
+
|
|
+ tx_desc = (struct ath5k_hw_2w_tx_desc *)&desc->ds_ctl0;
|
|
+
|
|
+ /*
|
|
+ * Validate input
|
|
+ * - Zero retries don't make sense.
|
|
+ * - A zero rate will put the HW into a mode where it continously sends
|
|
+ * noise on the channel, so it is important to avoid this.
|
|
+ */
|
|
+ if (unlikely(tx_tries0 == 0)) {
|
|
+ ATH5K_ERR(ah->ah_sc, "zero retries\n");
|
|
+ WARN_ON(1);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+ if (unlikely(tx_rate0 == 0)) {
|
|
+ ATH5K_ERR(ah->ah_sc, "zero rate\n");
|
|
+ WARN_ON(1);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ /* Clear status descriptor */
|
|
+ memset(desc->ds_hw, 0, sizeof(struct ath5k_hw_tx_status));
|
|
+
|
|
+ /* Initialize control descriptor */
|
|
+ tx_desc->tx_control_0 = 0;
|
|
+ tx_desc->tx_control_1 = 0;
|
|
+
|
|
+ /* Setup control descriptor */
|
|
+
|
|
+ /* Verify and set frame length */
|
|
+ if (pkt_len & ~AR5K_2W_TX_DESC_CTL0_FRAME_LEN)
|
|
+ return -EINVAL;
|
|
+
|
|
+ tx_desc->tx_control_0 = pkt_len & AR5K_2W_TX_DESC_CTL0_FRAME_LEN;
|
|
+
|
|
+ /* Verify and set buffer length */
|
|
+ buff_len = pkt_len - FCS_LEN;
|
|
+
|
|
+ /* NB: beacon's BufLen must be a multiple of 4 bytes */
|
|
+ if(type == AR5K_PKT_TYPE_BEACON)
|
|
+ buff_len = roundup(buff_len, 4);
|
|
+
|
|
+ if (buff_len & ~AR5K_2W_TX_DESC_CTL1_BUF_LEN)
|
|
+ return -EINVAL;
|
|
+
|
|
+ tx_desc->tx_control_1 = buff_len & AR5K_2W_TX_DESC_CTL1_BUF_LEN;
|
|
+
|
|
+ /*
|
|
+ * Verify and set header length
|
|
+ * XXX: I only found that on 5210 code, does it work on 5211 ?
|
|
+ */
|
|
+ if (ah->ah_version == AR5K_AR5210) {
|
|
+ if (hdr_len & ~AR5K_2W_TX_DESC_CTL0_HEADER_LEN)
|
|
+ return -EINVAL;
|
|
+ tx_desc->tx_control_0 |=
|
|
+ AR5K_REG_SM(hdr_len, AR5K_2W_TX_DESC_CTL0_HEADER_LEN);
|
|
+ }
|
|
+
|
|
+ /*Diferences between 5210-5211*/
|
|
+ if (ah->ah_version == AR5K_AR5210) {
|
|
+ switch (type) {
|
|
+ case AR5K_PKT_TYPE_BEACON:
|
|
+ case AR5K_PKT_TYPE_PROBE_RESP:
|
|
+ frame_type = AR5K_AR5210_TX_DESC_FRAME_TYPE_NO_DELAY;
|
|
+ case AR5K_PKT_TYPE_PIFS:
|
|
+ frame_type = AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS;
|
|
+ default:
|
|
+ frame_type = type /*<< 2 ?*/;
|
|
+ }
|
|
+
|
|
+ tx_desc->tx_control_0 |=
|
|
+ AR5K_REG_SM(frame_type, AR5K_2W_TX_DESC_CTL0_FRAME_TYPE) |
|
|
+ AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE);
|
|
+ } else {
|
|
+ tx_desc->tx_control_0 |=
|
|
+ AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE) |
|
|
+ AR5K_REG_SM(antenna_mode, AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT);
|
|
+ tx_desc->tx_control_1 |=
|
|
+ AR5K_REG_SM(type, AR5K_2W_TX_DESC_CTL1_FRAME_TYPE);
|
|
+ }
|
|
+#define _TX_FLAGS(_c, _flag) \
|
|
+ if (flags & AR5K_TXDESC_##_flag) \
|
|
+ tx_desc->tx_control_##_c |= \
|
|
+ AR5K_2W_TX_DESC_CTL##_c##_##_flag
|
|
+
|
|
+ _TX_FLAGS(0, CLRDMASK);
|
|
+ _TX_FLAGS(0, VEOL);
|
|
+ _TX_FLAGS(0, INTREQ);
|
|
+ _TX_FLAGS(0, RTSENA);
|
|
+ _TX_FLAGS(1, NOACK);
|
|
+
|
|
+#undef _TX_FLAGS
|
|
+
|
|
+ /*
|
|
+ * WEP crap
|
|
+ */
|
|
+ if (key_index != AR5K_TXKEYIX_INVALID) {
|
|
+ tx_desc->tx_control_0 |=
|
|
+ AR5K_2W_TX_DESC_CTL0_ENCRYPT_KEY_VALID;
|
|
+ tx_desc->tx_control_1 |=
|
|
+ AR5K_REG_SM(key_index,
|
|
+ AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX);
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * RTS/CTS Duration [5210 ?]
|
|
+ */
|
|
+ if ((ah->ah_version == AR5K_AR5210) &&
|
|
+ (flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA)))
|
|
+ tx_desc->tx_control_1 |= rtscts_duration &
|
|
+ AR5K_2W_TX_DESC_CTL1_RTS_DURATION;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Initialize the 4-word tx descriptor on 5212
|
|
+ */
|
|
+static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
|
|
+ struct ath5k_desc *desc, unsigned int pkt_len, unsigned int hdr_len,
|
|
+ enum ath5k_pkt_type type, unsigned int tx_power, unsigned int tx_rate0,
|
|
+ unsigned int tx_tries0, unsigned int key_index,
|
|
+ unsigned int antenna_mode, unsigned int flags, unsigned int rtscts_rate,
|
|
+ unsigned int rtscts_duration)
|
|
+{
|
|
+ struct ath5k_hw_4w_tx_desc *tx_desc;
|
|
+ struct ath5k_hw_tx_status *tx_status;
|
|
+ unsigned int buff_len;
|
|
+
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+ tx_desc = (struct ath5k_hw_4w_tx_desc *)&desc->ds_ctl0;
|
|
+ tx_status = (struct ath5k_hw_tx_status *)&desc->ds_hw[2];
|
|
+
|
|
+ /*
|
|
+ * Validate input
|
|
+ * - Zero retries don't make sense.
|
|
+ * - A zero rate will put the HW into a mode where it continously sends
|
|
+ * noise on the channel, so it is important to avoid this.
|
|
+ */
|
|
+ if (unlikely(tx_tries0 == 0)) {
|
|
+ ATH5K_ERR(ah->ah_sc, "zero retries\n");
|
|
+ WARN_ON(1);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+ if (unlikely(tx_rate0 == 0)) {
|
|
+ ATH5K_ERR(ah->ah_sc, "zero rate\n");
|
|
+ WARN_ON(1);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ /* Clear status descriptor */
|
|
+ memset(tx_status, 0, sizeof(struct ath5k_hw_tx_status));
|
|
+
|
|
+ /* Initialize control descriptor */
|
|
+ tx_desc->tx_control_0 = 0;
|
|
+ tx_desc->tx_control_1 = 0;
|
|
+ tx_desc->tx_control_2 = 0;
|
|
+ tx_desc->tx_control_3 = 0;
|
|
+
|
|
+ /* Setup control descriptor */
|
|
+
|
|
+ /* Verify and set frame length */
|
|
+ if (pkt_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN)
|
|
+ return -EINVAL;
|
|
+
|
|
+ tx_desc->tx_control_0 = pkt_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN;
|
|
+
|
|
+ /* Verify and set buffer length */
|
|
+ buff_len = pkt_len - FCS_LEN;
|
|
+
|
|
+ /* NB: beacon's BufLen must be a multiple of 4 bytes */
|
|
+ if(type == AR5K_PKT_TYPE_BEACON)
|
|
+ buff_len = roundup(buff_len, 4);
|
|
+
|
|
+ if (buff_len & ~AR5K_4W_TX_DESC_CTL1_BUF_LEN)
|
|
+ return -EINVAL;
|
|
+
|
|
+ tx_desc->tx_control_1 = buff_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN;
|
|
+
|
|
+ tx_desc->tx_control_0 |=
|
|
+ AR5K_REG_SM(tx_power, AR5K_4W_TX_DESC_CTL0_XMIT_POWER) |
|
|
+ AR5K_REG_SM(antenna_mode, AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT);
|
|
+ tx_desc->tx_control_1 |= AR5K_REG_SM(type,
|
|
+ AR5K_4W_TX_DESC_CTL1_FRAME_TYPE);
|
|
+ tx_desc->tx_control_2 = AR5K_REG_SM(tx_tries0 + AR5K_TUNE_HWTXTRIES,
|
|
+ AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0);
|
|
+ tx_desc->tx_control_3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
|
|
+
|
|
+#define _TX_FLAGS(_c, _flag) \
|
|
+ if (flags & AR5K_TXDESC_##_flag) \
|
|
+ tx_desc->tx_control_##_c |= \
|
|
+ AR5K_4W_TX_DESC_CTL##_c##_##_flag
|
|
+
|
|
+ _TX_FLAGS(0, CLRDMASK);
|
|
+ _TX_FLAGS(0, VEOL);
|
|
+ _TX_FLAGS(0, INTREQ);
|
|
+ _TX_FLAGS(0, RTSENA);
|
|
+ _TX_FLAGS(0, CTSENA);
|
|
+ _TX_FLAGS(1, NOACK);
|
|
+
|
|
+#undef _TX_FLAGS
|
|
+
|
|
+ /*
|
|
+ * WEP crap
|
|
+ */
|
|
+ if (key_index != AR5K_TXKEYIX_INVALID) {
|
|
+ tx_desc->tx_control_0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID;
|
|
+ tx_desc->tx_control_1 |= AR5K_REG_SM(key_index,
|
|
+ AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX);
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * RTS/CTS
|
|
+ */
|
|
+ if (flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA)) {
|
|
+ if ((flags & AR5K_TXDESC_RTSENA) &&
|
|
+ (flags & AR5K_TXDESC_CTSENA))
|
|
+ return -EINVAL;
|
|
+ tx_desc->tx_control_2 |= rtscts_duration &
|
|
+ AR5K_4W_TX_DESC_CTL2_RTS_DURATION;
|
|
+ tx_desc->tx_control_3 |= AR5K_REG_SM(rtscts_rate,
|
|
+ AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE);
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Initialize a 4-word multirate tx descriptor on 5212
|
|
+ */
|
|
+static bool
|
|
+ath5k_hw_setup_xr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
|
|
+ unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2, u_int tx_tries2,
|
|
+ unsigned int tx_rate3, u_int tx_tries3)
|
|
+{
|
|
+ struct ath5k_hw_4w_tx_desc *tx_desc;
|
|
+
|
|
+ /*
|
|
+ * Rates can be 0 as long as the retry count is 0 too.
|
|
+ * A zero rate and nonzero retry count will put the HW into a mode where
|
|
+ * it continously sends noise on the channel, so it is important to
|
|
+ * avoid this.
|
|
+ */
|
|
+ if (unlikely((tx_rate1 == 0 && tx_tries1 != 0) ||
|
|
+ (tx_rate2 == 0 && tx_tries2 != 0) ||
|
|
+ (tx_rate3 == 0 && tx_tries3 != 0))) {
|
|
+ ATH5K_ERR(ah->ah_sc, "zero rate\n");
|
|
+ WARN_ON(1);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ if (ah->ah_version == AR5K_AR5212) {
|
|
+ tx_desc = (struct ath5k_hw_4w_tx_desc *)&desc->ds_ctl0;
|
|
+
|
|
+#define _XTX_TRIES(_n) \
|
|
+ if (tx_tries##_n) { \
|
|
+ tx_desc->tx_control_2 |= \
|
|
+ AR5K_REG_SM(tx_tries##_n, \
|
|
+ AR5K_4W_TX_DESC_CTL2_XMIT_TRIES##_n); \
|
|
+ tx_desc->tx_control_3 |= \
|
|
+ AR5K_REG_SM(tx_rate##_n, \
|
|
+ AR5K_4W_TX_DESC_CTL3_XMIT_RATE##_n); \
|
|
+ }
|
|
+
|
|
+ _XTX_TRIES(1);
|
|
+ _XTX_TRIES(2);
|
|
+ _XTX_TRIES(3);
|
|
+
|
|
+#undef _XTX_TRIES
|
|
+
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ return false;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Proccess the tx status descriptor on 5210/5211
|
|
+ */
|
|
+static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah,
|
|
+ struct ath5k_desc *desc)
|
|
+{
|
|
+ struct ath5k_hw_tx_status *tx_status;
|
|
+ struct ath5k_hw_2w_tx_desc *tx_desc;
|
|
+
|
|
+ tx_desc = (struct ath5k_hw_2w_tx_desc *)&desc->ds_ctl0;
|
|
+ tx_status = (struct ath5k_hw_tx_status *)&desc->ds_hw[0];
|
|
+
|
|
+ /* No frame has been send or error */
|
|
+ if (unlikely((tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE) == 0))
|
|
+ return -EINPROGRESS;
|
|
+
|
|
+ /*
|
|
+ * Get descriptor status
|
|
+ */
|
|
+ desc->ds_us.tx.ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0,
|
|
+ AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP);
|
|
+ desc->ds_us.tx.ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
|
|
+ AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT);
|
|
+ desc->ds_us.tx.ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
|
|
+ AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT);
|
|
+ /*TODO: desc->ds_us.tx.ts_virtcol + test*/
|
|
+ desc->ds_us.tx.ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
|
|
+ AR5K_DESC_TX_STATUS1_SEQ_NUM);
|
|
+ desc->ds_us.tx.ts_rssi = AR5K_REG_MS(tx_status->tx_status_1,
|
|
+ AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
|
|
+ desc->ds_us.tx.ts_antenna = 1;
|
|
+ desc->ds_us.tx.ts_status = 0;
|
|
+ desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_desc->tx_control_0,
|
|
+ AR5K_2W_TX_DESC_CTL0_XMIT_RATE);
|
|
+
|
|
+ if ((tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK) == 0){
|
|
+ if (tx_status->tx_status_0 &
|
|
+ AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES)
|
|
+ desc->ds_us.tx.ts_status |= AR5K_TXERR_XRETRY;
|
|
+
|
|
+ if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN)
|
|
+ desc->ds_us.tx.ts_status |= AR5K_TXERR_FIFO;
|
|
+
|
|
+ if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED)
|
|
+ desc->ds_us.tx.ts_status |= AR5K_TXERR_FILT;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Proccess a tx descriptor on 5212
|
|
+ */
|
|
+static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah,
|
|
+ struct ath5k_desc *desc)
|
|
+{
|
|
+ struct ath5k_hw_tx_status *tx_status;
|
|
+ struct ath5k_hw_4w_tx_desc *tx_desc;
|
|
+
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+ tx_desc = (struct ath5k_hw_4w_tx_desc *)&desc->ds_ctl0;
|
|
+ tx_status = (struct ath5k_hw_tx_status *)&desc->ds_hw[2];
|
|
+
|
|
+ /* No frame has been send or error */
|
|
+ if (unlikely((tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE) == 0))
|
|
+ return -EINPROGRESS;
|
|
+
|
|
+ /*
|
|
+ * Get descriptor status
|
|
+ */
|
|
+ desc->ds_us.tx.ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0,
|
|
+ AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP);
|
|
+ desc->ds_us.tx.ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
|
|
+ AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT);
|
|
+ desc->ds_us.tx.ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
|
|
+ AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT);
|
|
+ desc->ds_us.tx.ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
|
|
+ AR5K_DESC_TX_STATUS1_SEQ_NUM);
|
|
+ desc->ds_us.tx.ts_rssi = AR5K_REG_MS(tx_status->tx_status_1,
|
|
+ AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
|
|
+ desc->ds_us.tx.ts_antenna = (tx_status->tx_status_1 &
|
|
+ AR5K_DESC_TX_STATUS1_XMIT_ANTENNA) ? 2 : 1;
|
|
+ desc->ds_us.tx.ts_status = 0;
|
|
+
|
|
+ switch (AR5K_REG_MS(tx_status->tx_status_1,
|
|
+ AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX)) {
|
|
+ case 0:
|
|
+ desc->ds_us.tx.ts_rate = tx_desc->tx_control_3 &
|
|
+ AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
|
|
+ break;
|
|
+ case 1:
|
|
+ desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_desc->tx_control_3,
|
|
+ AR5K_4W_TX_DESC_CTL3_XMIT_RATE1);
|
|
+ desc->ds_us.tx.ts_longretry +=AR5K_REG_MS(tx_desc->tx_control_2,
|
|
+ AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1);
|
|
+ break;
|
|
+ case 2:
|
|
+ desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_desc->tx_control_3,
|
|
+ AR5K_4W_TX_DESC_CTL3_XMIT_RATE2);
|
|
+ desc->ds_us.tx.ts_longretry +=AR5K_REG_MS(tx_desc->tx_control_2,
|
|
+ AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2);
|
|
+ break;
|
|
+ case 3:
|
|
+ desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_desc->tx_control_3,
|
|
+ AR5K_4W_TX_DESC_CTL3_XMIT_RATE3);
|
|
+ desc->ds_us.tx.ts_longretry +=AR5K_REG_MS(tx_desc->tx_control_2,
|
|
+ AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3);
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if ((tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK) == 0){
|
|
+ if (tx_status->tx_status_0 &
|
|
+ AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES)
|
|
+ desc->ds_us.tx.ts_status |= AR5K_TXERR_XRETRY;
|
|
+
|
|
+ if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN)
|
|
+ desc->ds_us.tx.ts_status |= AR5K_TXERR_FIFO;
|
|
+
|
|
+ if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED)
|
|
+ desc->ds_us.tx.ts_status |= AR5K_TXERR_FILT;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * RX Descriptor
|
|
+ */
|
|
+
|
|
+/*
|
|
+ * Initialize an rx descriptor
|
|
+ */
|
|
+int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
|
|
+ u32 size, unsigned int flags)
|
|
+{
|
|
+ struct ath5k_rx_desc *rx_desc;
|
|
+
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+ rx_desc = (struct ath5k_rx_desc *)&desc->ds_ctl0;
|
|
+
|
|
+ /*
|
|
+ *Clear ds_hw
|
|
+ * If we don't clean the status descriptor,
|
|
+ * while scanning we get too many results,
|
|
+ * most of them virtual, after some secs
|
|
+ * of scanning system hangs. M.F.
|
|
+ */
|
|
+ memset(desc->ds_hw, 0, sizeof(desc->ds_hw));
|
|
+
|
|
+ /*Initialize rx descriptor*/
|
|
+ rx_desc->rx_control_0 = 0;
|
|
+ rx_desc->rx_control_1 = 0;
|
|
+
|
|
+ /* Setup descriptor */
|
|
+ rx_desc->rx_control_1 = size & AR5K_DESC_RX_CTL1_BUF_LEN;
|
|
+ if (unlikely(rx_desc->rx_control_1 != size))
|
|
+ return -EINVAL;
|
|
+
|
|
+ if (flags & AR5K_RXDESC_INTREQ)
|
|
+ rx_desc->rx_control_1 |= AR5K_DESC_RX_CTL1_INTREQ;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Proccess the rx status descriptor on 5210/5211
|
|
+ */
|
|
+static int ath5k_hw_proc_old_rx_status(struct ath5k_hw *ah,
|
|
+ struct ath5k_desc *desc)
|
|
+{
|
|
+ struct ath5k_hw_old_rx_status *rx_status;
|
|
+
|
|
+ rx_status = (struct ath5k_hw_old_rx_status *)&desc->ds_hw[0];
|
|
+
|
|
+ /* No frame received / not ready */
|
|
+ if (unlikely((rx_status->rx_status_1 & AR5K_OLD_RX_DESC_STATUS1_DONE)
|
|
+ == 0))
|
|
+ return -EINPROGRESS;
|
|
+
|
|
+ /*
|
|
+ * Frame receive status
|
|
+ */
|
|
+ desc->ds_us.rx.rs_datalen = rx_status->rx_status_0 &
|
|
+ AR5K_OLD_RX_DESC_STATUS0_DATA_LEN;
|
|
+ desc->ds_us.rx.rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
|
|
+ AR5K_OLD_RX_DESC_STATUS0_RECEIVE_SIGNAL);
|
|
+ desc->ds_us.rx.rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
|
|
+ AR5K_OLD_RX_DESC_STATUS0_RECEIVE_RATE);
|
|
+ desc->ds_us.rx.rs_antenna = rx_status->rx_status_0 &
|
|
+ AR5K_OLD_RX_DESC_STATUS0_RECEIVE_ANTENNA;
|
|
+ desc->ds_us.rx.rs_more = rx_status->rx_status_0 &
|
|
+ AR5K_OLD_RX_DESC_STATUS0_MORE;
|
|
+ desc->ds_us.rx.rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
|
|
+ AR5K_OLD_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
|
|
+ desc->ds_us.rx.rs_status = 0;
|
|
+
|
|
+ /*
|
|
+ * Key table status
|
|
+ */
|
|
+ if (rx_status->rx_status_1 & AR5K_OLD_RX_DESC_STATUS1_KEY_INDEX_VALID)
|
|
+ desc->ds_us.rx.rs_keyix = AR5K_REG_MS(rx_status->rx_status_1,
|
|
+ AR5K_OLD_RX_DESC_STATUS1_KEY_INDEX);
|
|
+ else
|
|
+ desc->ds_us.rx.rs_keyix = AR5K_RXKEYIX_INVALID;
|
|
+
|
|
+ /*
|
|
+ * Receive/descriptor errors
|
|
+ */
|
|
+ if ((rx_status->rx_status_1 & AR5K_OLD_RX_DESC_STATUS1_FRAME_RECEIVE_OK)
|
|
+ == 0) {
|
|
+ if (rx_status->rx_status_1 & AR5K_OLD_RX_DESC_STATUS1_CRC_ERROR)
|
|
+ desc->ds_us.rx.rs_status |= AR5K_RXERR_CRC;
|
|
+
|
|
+ if (rx_status->rx_status_1 &
|
|
+ AR5K_OLD_RX_DESC_STATUS1_FIFO_OVERRUN)
|
|
+ desc->ds_us.rx.rs_status |= AR5K_RXERR_FIFO;
|
|
+
|
|
+ if (rx_status->rx_status_1 &
|
|
+ AR5K_OLD_RX_DESC_STATUS1_PHY_ERROR) {
|
|
+ desc->ds_us.rx.rs_status |= AR5K_RXERR_PHY;
|
|
+ desc->ds_us.rx.rs_phyerr =
|
|
+ AR5K_REG_MS(rx_status->rx_status_1,
|
|
+ AR5K_OLD_RX_DESC_STATUS1_PHY_ERROR);
|
|
+ }
|
|
+
|
|
+ if (rx_status->rx_status_1 &
|
|
+ AR5K_OLD_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
|
|
+ desc->ds_us.rx.rs_status |= AR5K_RXERR_DECRYPT;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Proccess the rx status descriptor on 5212
|
|
+ */
|
|
+static int ath5k_hw_proc_new_rx_status(struct ath5k_hw *ah,
|
|
+ struct ath5k_desc *desc)
|
|
+{
|
|
+ struct ath5k_hw_new_rx_status *rx_status;
|
|
+ struct ath5k_hw_rx_error *rx_err;
|
|
+
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+ rx_status = (struct ath5k_hw_new_rx_status *)&desc->ds_hw[0];
|
|
+
|
|
+ /* Overlay on error */
|
|
+ rx_err = (struct ath5k_hw_rx_error *)&desc->ds_hw[0];
|
|
+
|
|
+ /* No frame received / not ready */
|
|
+ if (unlikely((rx_status->rx_status_1 & AR5K_NEW_RX_DESC_STATUS1_DONE)
|
|
+ == 0))
|
|
+ return -EINPROGRESS;
|
|
+
|
|
+ /*
|
|
+ * Frame receive status
|
|
+ */
|
|
+ desc->ds_us.rx.rs_datalen = rx_status->rx_status_0 &
|
|
+ AR5K_NEW_RX_DESC_STATUS0_DATA_LEN;
|
|
+ desc->ds_us.rx.rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
|
|
+ AR5K_NEW_RX_DESC_STATUS0_RECEIVE_SIGNAL);
|
|
+ desc->ds_us.rx.rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
|
|
+ AR5K_NEW_RX_DESC_STATUS0_RECEIVE_RATE);
|
|
+ desc->ds_us.rx.rs_antenna = rx_status->rx_status_0 &
|
|
+ AR5K_NEW_RX_DESC_STATUS0_RECEIVE_ANTENNA;
|
|
+ desc->ds_us.rx.rs_more = rx_status->rx_status_0 &
|
|
+ AR5K_NEW_RX_DESC_STATUS0_MORE;
|
|
+ desc->ds_us.rx.rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
|
|
+ AR5K_NEW_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
|
|
+ desc->ds_us.rx.rs_status = 0;
|
|
+
|
|
+ /*
|
|
+ * Key table status
|
|
+ */
|
|
+ if (rx_status->rx_status_1 & AR5K_NEW_RX_DESC_STATUS1_KEY_INDEX_VALID)
|
|
+ desc->ds_us.rx.rs_keyix = AR5K_REG_MS(rx_status->rx_status_1,
|
|
+ AR5K_NEW_RX_DESC_STATUS1_KEY_INDEX);
|
|
+ else
|
|
+ desc->ds_us.rx.rs_keyix = AR5K_RXKEYIX_INVALID;
|
|
+
|
|
+ /*
|
|
+ * Receive/descriptor errors
|
|
+ */
|
|
+ if ((rx_status->rx_status_1 &
|
|
+ AR5K_NEW_RX_DESC_STATUS1_FRAME_RECEIVE_OK) == 0) {
|
|
+ if (rx_status->rx_status_1 & AR5K_NEW_RX_DESC_STATUS1_CRC_ERROR)
|
|
+ desc->ds_us.rx.rs_status |= AR5K_RXERR_CRC;
|
|
+
|
|
+ if (rx_status->rx_status_1 &
|
|
+ AR5K_NEW_RX_DESC_STATUS1_PHY_ERROR) {
|
|
+ desc->ds_us.rx.rs_status |= AR5K_RXERR_PHY;
|
|
+ desc->ds_us.rx.rs_phyerr =
|
|
+ AR5K_REG_MS(rx_err->rx_error_1,
|
|
+ AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE);
|
|
+ }
|
|
+
|
|
+ if (rx_status->rx_status_1 &
|
|
+ AR5K_NEW_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
|
|
+ desc->ds_us.rx.rs_status |= AR5K_RXERR_DECRYPT;
|
|
+
|
|
+ if (rx_status->rx_status_1 & AR5K_NEW_RX_DESC_STATUS1_MIC_ERROR)
|
|
+ desc->ds_us.rx.rs_status |= AR5K_RXERR_MIC;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+
|
|
+/****************\
|
|
+ GPIO Functions
|
|
+\****************/
|
|
+
|
|
+/*
|
|
+ * Set led state
|
|
+ */
|
|
+void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state)
|
|
+{
|
|
+ u32 led;
|
|
+ /*5210 has different led mode handling*/
|
|
+ u32 led_5210;
|
|
+
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+
|
|
+ /*Reset led status*/
|
|
+ if (ah->ah_version != AR5K_AR5210)
|
|
+ AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG,
|
|
+ AR5K_PCICFG_LEDMODE | AR5K_PCICFG_LED);
|
|
+ else
|
|
+ AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG, AR5K_PCICFG_LED);
|
|
+
|
|
+ /*
|
|
+ * Some blinking values, define at your wish
|
|
+ */
|
|
+ switch (state) {
|
|
+ case AR5K_LED_SCAN:
|
|
+ case AR5K_LED_AUTH:
|
|
+ led = AR5K_PCICFG_LEDMODE_PROP | AR5K_PCICFG_LED_PEND;
|
|
+ led_5210 = AR5K_PCICFG_LED_PEND | AR5K_PCICFG_LED_BCTL;
|
|
+ break;
|
|
+
|
|
+ case AR5K_LED_INIT:
|
|
+ led = AR5K_PCICFG_LEDMODE_PROP | AR5K_PCICFG_LED_NONE;
|
|
+ led_5210 = AR5K_PCICFG_LED_PEND;
|
|
+ break;
|
|
+
|
|
+ case AR5K_LED_ASSOC:
|
|
+ case AR5K_LED_RUN:
|
|
+ led = AR5K_PCICFG_LEDMODE_PROP | AR5K_PCICFG_LED_ASSOC;
|
|
+ led_5210 = AR5K_PCICFG_LED_ASSOC;
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ led = AR5K_PCICFG_LEDMODE_PROM | AR5K_PCICFG_LED_NONE;
|
|
+ led_5210 = AR5K_PCICFG_LED_PEND;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ /*Write new status to the register*/
|
|
+ if (ah->ah_version != AR5K_AR5210)
|
|
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, led);
|
|
+ else
|
|
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, led_5210);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Set GPIO outputs
|
|
+ */
|
|
+int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio)
|
|
+{
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+ if (gpio > AR5K_NUM_GPIO)
|
|
+ return -EINVAL;
|
|
+
|
|
+ ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, AR5K_GPIOCR) &~
|
|
+ AR5K_GPIOCR_OUT(gpio)) | AR5K_GPIOCR_OUT(gpio), AR5K_GPIOCR);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Set GPIO inputs
|
|
+ */
|
|
+int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio)
|
|
+{
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+ if (gpio > AR5K_NUM_GPIO)
|
|
+ return -EINVAL;
|
|
+
|
|
+ ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, AR5K_GPIOCR) &~
|
|
+ AR5K_GPIOCR_OUT(gpio)) | AR5K_GPIOCR_IN(gpio), AR5K_GPIOCR);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Get GPIO state
|
|
+ */
|
|
+u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio)
|
|
+{
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+ if (gpio > AR5K_NUM_GPIO)
|
|
+ return 0xffffffff;
|
|
+
|
|
+ /* GPIO input magic */
|
|
+ return ((ath5k_hw_reg_read(ah, AR5K_GPIODI) & AR5K_GPIODI_M) >> gpio) &
|
|
+ 0x1;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Set GPIO state
|
|
+ */
|
|
+int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val)
|
|
+{
|
|
+ u32 data;
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+
|
|
+ if (gpio > AR5K_NUM_GPIO)
|
|
+ return -EINVAL;
|
|
+
|
|
+ /* GPIO output magic */
|
|
+ data = ath5k_hw_reg_read(ah, AR5K_GPIODO);
|
|
+
|
|
+ data &= ~(1 << gpio);
|
|
+ data |= (val & 1) << gpio;
|
|
+
|
|
+ ath5k_hw_reg_write(ah, data, AR5K_GPIODO);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Initialize the GPIO interrupt (RFKill switch)
|
|
+ */
|
|
+void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio,
|
|
+ u32 interrupt_level)
|
|
+{
|
|
+ u32 data;
|
|
+
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+ if (gpio > AR5K_NUM_GPIO)
|
|
+ return;
|
|
+
|
|
+ /*
|
|
+ * Set the GPIO interrupt
|
|
+ */
|
|
+ data = (ath5k_hw_reg_read(ah, AR5K_GPIOCR) &
|
|
+ ~(AR5K_GPIOCR_INT_SEL(gpio) | AR5K_GPIOCR_INT_SELH |
|
|
+ AR5K_GPIOCR_INT_ENA | AR5K_GPIOCR_OUT(gpio))) |
|
|
+ (AR5K_GPIOCR_INT_SEL(gpio) | AR5K_GPIOCR_INT_ENA);
|
|
+
|
|
+ ath5k_hw_reg_write(ah, interrupt_level ? data :
|
|
+ (data | AR5K_GPIOCR_INT_SELH), AR5K_GPIOCR);
|
|
+
|
|
+ ah->ah_imr |= AR5K_IMR_GPIO;
|
|
+
|
|
+ /* Enable GPIO interrupts */
|
|
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PIMR, AR5K_IMR_GPIO);
|
|
+}
|
|
+
|
|
+
|
|
+/*********************************\
|
|
+ Regulatory Domain/Channels Setup
|
|
+\*********************************/
|
|
+
|
|
+u16 ath5k_get_regdomain(struct ath5k_hw *ah)
|
|
+{
|
|
+ u16 regdomain;
|
|
+ enum ath5k_regdom ieee_regdomain;
|
|
+#ifdef COUNTRYCODE
|
|
+ u16 code;
|
|
+#endif
|
|
+
|
|
+ ath5k_eeprom_regulation_domain(ah, false, &ieee_regdomain);
|
|
+ ah->ah_capabilities.cap_regdomain.reg_hw = ieee_regdomain;
|
|
+
|
|
+#ifdef COUNTRYCODE
|
|
+ /*
|
|
+ * Get the regulation domain by country code. This will ignore
|
|
+ * the settings found in the EEPROM.
|
|
+ */
|
|
+ code = ieee80211_name2countrycode(COUNTRYCODE);
|
|
+ ieee_regdomain = ieee80211_countrycode2regdomain(code);
|
|
+#endif
|
|
+
|
|
+ regdomain = ath5k_regdom_from_ieee(ieee_regdomain);
|
|
+ ah->ah_capabilities.cap_regdomain.reg_current = regdomain;
|
|
+
|
|
+ return regdomain;
|
|
+}
|
|
+
|
|
+
|
|
+/****************\
|
|
+ Misc functions
|
|
+\****************/
|
|
+
|
|
+int ath5k_hw_get_capability(struct ath5k_hw *ah,
|
|
+ enum ath5k_capability_type cap_type,
|
|
+ u32 capability, u32 *result)
|
|
+{
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+
|
|
+ switch (cap_type) {
|
|
+ case AR5K_CAP_NUM_TXQUEUES:
|
|
+ if (result) {
|
|
+ if (ah->ah_version == AR5K_AR5210)
|
|
+ *result = AR5K_NUM_TX_QUEUES_NOQCU;
|
|
+ else
|
|
+ *result = AR5K_NUM_TX_QUEUES;
|
|
+ goto yes;
|
|
+ }
|
|
+ case AR5K_CAP_VEOL:
|
|
+ goto yes;
|
|
+ case AR5K_CAP_COMPRESSION:
|
|
+ if (ah->ah_version == AR5K_AR5212)
|
|
+ goto yes;
|
|
+ else
|
|
+ goto no;
|
|
+ case AR5K_CAP_BURST:
|
|
+ goto yes;
|
|
+ case AR5K_CAP_TPC:
|
|
+ goto yes;
|
|
+ case AR5K_CAP_BSSIDMASK:
|
|
+ if (ah->ah_version == AR5K_AR5212)
|
|
+ goto yes;
|
|
+ else
|
|
+ goto no;
|
|
+ case AR5K_CAP_XR:
|
|
+ if (ah->ah_version == AR5K_AR5212)
|
|
+ goto yes;
|
|
+ else
|
|
+ goto no;
|
|
+ default:
|
|
+ goto no;
|
|
+ }
|
|
+
|
|
+no:
|
|
+ return -EINVAL;
|
|
+yes:
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int ath5k_hw_enable_pspoll(struct ath5k_hw *ah, u8 *bssid,
|
|
+ u16 assoc_id)
|
|
+{
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+
|
|
+ if (ah->ah_version == AR5K_AR5210) {
|
|
+ AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1,
|
|
+ AR5K_STA_ID1_NO_PSPOLL | AR5K_STA_ID1_DEFAULT_ANTENNA);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ return -EIO;
|
|
+}
|
|
+
|
|
+static int ath5k_hw_disable_pspoll(struct ath5k_hw *ah)
|
|
+{
|
|
+ ATH5K_TRACE(ah->ah_sc);
|
|
+
|
|
+ if (ah->ah_version == AR5K_AR5210) {
|
|
+ AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1,
|
|
+ AR5K_STA_ID1_NO_PSPOLL | AR5K_STA_ID1_DEFAULT_ANTENNA);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ return -EIO;
|
|
+}
|
|
diff -up /dev/null linux-2.6.23.noarch/drivers/net/wireless/ath5k/hw.h
|
|
--- /dev/null 2007-12-21 08:33:07.834165456 -0500
|
|
+++ linux-2.6.23.noarch/drivers/net/wireless/ath5k/hw.h 2007-12-21 12:18:50.000000000 -0500
|
|
@@ -0,0 +1,588 @@
|
|
+/*
|
|
+ * Copyright (c) 2004-2007 Reyk Floeter <reyk@openbsd.org>
|
|
+ * Copyright (c) 2006-2007 Nick Kossifidis <mickflemm@gmail.com>
|
|
+ * Copyright (c) 2007 Matthew W. S. Bell <mentor@madwifi.org>
|
|
+ * Copyright (c) 2007 Luis Rodriguez <mcgrof@winlab.rutgers.edu>
|
|
+ *
|
|
+ * Permission to use, copy, modify, and distribute this software for any
|
|
+ * purpose with or without fee is hereby granted, provided that the above
|
|
+ * copyright notice and this permission notice appear in all copies.
|
|
+ *
|
|
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
+ */
|
|
+
|
|
+#include <linux/delay.h>
|
|
+
|
|
+/*
|
|
+ * Gain settings
|
|
+ */
|
|
+
|
|
+enum ath5k_rfgain {
|
|
+ AR5K_RFGAIN_INACTIVE = 0,
|
|
+ AR5K_RFGAIN_READ_REQUESTED,
|
|
+ AR5K_RFGAIN_NEED_CHANGE,
|
|
+};
|
|
+
|
|
+#define AR5K_GAIN_CRN_FIX_BITS_5111 4
|
|
+#define AR5K_GAIN_CRN_FIX_BITS_5112 7
|
|
+#define AR5K_GAIN_CRN_MAX_FIX_BITS AR5K_GAIN_CRN_FIX_BITS_5112
|
|
+#define AR5K_GAIN_DYN_ADJUST_HI_MARGIN 15
|
|
+#define AR5K_GAIN_DYN_ADJUST_LO_MARGIN 20
|
|
+#define AR5K_GAIN_CCK_PROBE_CORR 5
|
|
+#define AR5K_GAIN_CCK_OFDM_GAIN_DELTA 15
|
|
+#define AR5K_GAIN_STEP_COUNT 10
|
|
+#define AR5K_GAIN_PARAM_TX_CLIP 0
|
|
+#define AR5K_GAIN_PARAM_PD_90 1
|
|
+#define AR5K_GAIN_PARAM_PD_84 2
|
|
+#define AR5K_GAIN_PARAM_GAIN_SEL 3
|
|
+#define AR5K_GAIN_PARAM_MIX_ORN 0
|
|
+#define AR5K_GAIN_PARAM_PD_138 1
|
|
+#define AR5K_GAIN_PARAM_PD_137 2
|
|
+#define AR5K_GAIN_PARAM_PD_136 3
|
|
+#define AR5K_GAIN_PARAM_PD_132 4
|
|
+#define AR5K_GAIN_PARAM_PD_131 5
|
|
+#define AR5K_GAIN_PARAM_PD_130 6
|
|
+#define AR5K_GAIN_CHECK_ADJUST(_g) \
|
|
+ ((_g)->g_current <= (_g)->g_low || (_g)->g_current >= (_g)->g_high)
|
|
+
|
|
+struct ath5k_gain_opt_step {
|
|
+ s16 gos_param[AR5K_GAIN_CRN_MAX_FIX_BITS];
|
|
+ s32 gos_gain;
|
|
+};
|
|
+
|
|
+struct ath5k_gain {
|
|
+ u32 g_step_idx;
|
|
+ u32 g_current;
|
|
+ u32 g_target;
|
|
+ u32 g_low;
|
|
+ u32 g_high;
|
|
+ u32 g_f_corr;
|
|
+ u32 g_active;
|
|
+ const struct ath5k_gain_opt_step *g_step;
|
|
+};
|
|
+
|
|
+
|
|
+/*
|
|
+ * HW SPECIFIC STRUCTS
|
|
+ */
|
|
+
|
|
+/* Some EEPROM defines */
|
|
+#define AR5K_EEPROM_EEP_SCALE 100
|
|
+#define AR5K_EEPROM_EEP_DELTA 10
|
|
+#define AR5K_EEPROM_N_MODES 3
|
|
+#define AR5K_EEPROM_N_5GHZ_CHAN 10
|
|
+#define AR5K_EEPROM_N_2GHZ_CHAN 3
|
|
+#define AR5K_EEPROM_MAX_CHAN 10
|
|
+#define AR5K_EEPROM_N_PCDAC 11
|
|
+#define AR5K_EEPROM_N_TEST_FREQ 8
|
|
+#define AR5K_EEPROM_N_EDGES 8
|
|
+#define AR5K_EEPROM_N_INTERCEPTS 11
|
|
+#define AR5K_EEPROM_FREQ_M(_v) AR5K_EEPROM_OFF(_v, 0x7f, 0xff)
|
|
+#define AR5K_EEPROM_PCDAC_M 0x3f
|
|
+#define AR5K_EEPROM_PCDAC_START 1
|
|
+#define AR5K_EEPROM_PCDAC_STOP 63
|
|
+#define AR5K_EEPROM_PCDAC_STEP 1
|
|
+#define AR5K_EEPROM_NON_EDGE_M 0x40
|
|
+#define AR5K_EEPROM_CHANNEL_POWER 8
|
|
+#define AR5K_EEPROM_N_OBDB 4
|
|
+#define AR5K_EEPROM_OBDB_DIS 0xffff
|
|
+#define AR5K_EEPROM_CHANNEL_DIS 0xff
|
|
+#define AR5K_EEPROM_SCALE_OC_DELTA(_x) (((_x) * 2) / 10)
|
|
+#define AR5K_EEPROM_N_CTLS(_v) AR5K_EEPROM_OFF(_v, 16, 32)
|
|
+#define AR5K_EEPROM_MAX_CTLS 32
|
|
+#define AR5K_EEPROM_N_XPD_PER_CHANNEL 4
|
|
+#define AR5K_EEPROM_N_XPD0_POINTS 4
|
|
+#define AR5K_EEPROM_N_XPD3_POINTS 3
|
|
+#define AR5K_EEPROM_N_INTERCEPT_10_2GHZ 35
|
|
+#define AR5K_EEPROM_N_INTERCEPT_10_5GHZ 55
|
|
+#define AR5K_EEPROM_POWER_M 0x3f
|
|
+#define AR5K_EEPROM_POWER_MIN 0
|
|
+#define AR5K_EEPROM_POWER_MAX 3150
|
|
+#define AR5K_EEPROM_POWER_STEP 50
|
|
+#define AR5K_EEPROM_POWER_TABLE_SIZE 64
|
|
+#define AR5K_EEPROM_N_POWER_LOC_11B 4
|
|
+#define AR5K_EEPROM_N_POWER_LOC_11G 6
|
|
+#define AR5K_EEPROM_I_GAIN 10
|
|
+#define AR5K_EEPROM_CCK_OFDM_DELTA 15
|
|
+#define AR5K_EEPROM_N_IQ_CAL 2
|
|
+
|
|
+/* Struct to hold EEPROM calibration data */
|
|
+struct ath5k_eeprom_info {
|
|
+ u16 ee_magic;
|
|
+ u16 ee_protect;
|
|
+ u16 ee_regdomain;
|
|
+ u16 ee_version;
|
|
+ u16 ee_header;
|
|
+ u16 ee_ant_gain;
|
|
+ u16 ee_misc0;
|
|
+ u16 ee_misc1;
|
|
+ u16 ee_cck_ofdm_gain_delta;
|
|
+ u16 ee_cck_ofdm_power_delta;
|
|
+ u16 ee_scaled_cck_delta;
|
|
+
|
|
+ /* Used for tx thermal adjustment (eeprom_init, rfregs) */
|
|
+ u16 ee_tx_clip;
|
|
+ u16 ee_pwd_84;
|
|
+ u16 ee_pwd_90;
|
|
+ u16 ee_gain_select;
|
|
+
|
|
+ /* RF Calibration settings (reset, rfregs) */
|
|
+ u16 ee_i_cal[AR5K_EEPROM_N_MODES];
|
|
+ u16 ee_q_cal[AR5K_EEPROM_N_MODES];
|
|
+ u16 ee_fixed_bias[AR5K_EEPROM_N_MODES];
|
|
+ u16 ee_turbo_max_power[AR5K_EEPROM_N_MODES];
|
|
+ u16 ee_xr_power[AR5K_EEPROM_N_MODES];
|
|
+ u16 ee_switch_settling[AR5K_EEPROM_N_MODES];
|
|
+ u16 ee_ant_tx_rx[AR5K_EEPROM_N_MODES];
|
|
+ u16 ee_ant_control[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_PCDAC];
|
|
+ u16 ee_ob[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_OBDB];
|
|
+ u16 ee_db[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_OBDB];
|
|
+ u16 ee_tx_end2xlna_enable[AR5K_EEPROM_N_MODES];
|
|
+ u16 ee_tx_end2xpa_disable[AR5K_EEPROM_N_MODES];
|
|
+ u16 ee_tx_frm2xpa_enable[AR5K_EEPROM_N_MODES];
|
|
+ u16 ee_thr_62[AR5K_EEPROM_N_MODES];
|
|
+ u16 ee_xlna_gain[AR5K_EEPROM_N_MODES];
|
|
+ u16 ee_xpd[AR5K_EEPROM_N_MODES];
|
|
+ u16 ee_x_gain[AR5K_EEPROM_N_MODES];
|
|
+ u16 ee_i_gain[AR5K_EEPROM_N_MODES];
|
|
+ u16 ee_margin_tx_rx[AR5K_EEPROM_N_MODES];
|
|
+
|
|
+ /* Unused */
|
|
+ u16 ee_false_detect[AR5K_EEPROM_N_MODES];
|
|
+ u16 ee_cal_pier[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_2GHZ_CHAN];
|
|
+ u16 ee_channel[AR5K_EEPROM_N_MODES][AR5K_EEPROM_MAX_CHAN]; /*empty*/
|
|
+
|
|
+ /* Conformance test limits (Unused) */
|
|
+ u16 ee_ctls;
|
|
+ u16 ee_ctl[AR5K_EEPROM_MAX_CTLS];
|
|
+
|
|
+ /* Noise Floor Calibration settings */
|
|
+ s16 ee_noise_floor_thr[AR5K_EEPROM_N_MODES];
|
|
+ s8 ee_adc_desired_size[AR5K_EEPROM_N_MODES];
|
|
+ s8 ee_pga_desired_size[AR5K_EEPROM_N_MODES];
|
|
+};
|
|
+
|
|
+/*
|
|
+ * Internal RX/TX descriptor structures
|
|
+ * (rX: reserved fields possibily used by future versions of the ar5k chipset)
|
|
+ */
|
|
+
|
|
+struct ath5k_rx_desc {
|
|
+ u32 rx_control_0; /* RX control word 0 */
|
|
+
|
|
+#define AR5K_DESC_RX_CTL0 0x00000000
|
|
+
|
|
+ u32 rx_control_1; /* RX control word 1 */
|
|
+
|
|
+#define AR5K_DESC_RX_CTL1_BUF_LEN 0x00000fff
|
|
+#define AR5K_DESC_RX_CTL1_INTREQ 0x00002000
|
|
+} __packed;
|
|
+
|
|
+/*
|
|
+ * 5210/5211 rx status descriptor
|
|
+ */
|
|
+struct ath5k_hw_old_rx_status {
|
|
+ u32 rx_status_0; /* RX status word 0 */
|
|
+
|
|
+#define AR5K_OLD_RX_DESC_STATUS0_DATA_LEN 0x00000fff
|
|
+#define AR5K_OLD_RX_DESC_STATUS0_MORE 0x00001000
|
|
+#define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_RATE 0x00078000
|
|
+#define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_RATE_S 15
|
|
+#define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_SIGNAL 0x07f80000
|
|
+#define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_SIGNAL_S 19
|
|
+#define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_ANTENNA 0x38000000
|
|
+#define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_ANTENNA_S 27
|
|
+
|
|
+ u32 rx_status_1; /* RX status word 1 */
|
|
+
|
|
+#define AR5K_OLD_RX_DESC_STATUS1_DONE 0x00000001
|
|
+#define AR5K_OLD_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002
|
|
+#define AR5K_OLD_RX_DESC_STATUS1_CRC_ERROR 0x00000004
|
|
+#define AR5K_OLD_RX_DESC_STATUS1_FIFO_OVERRUN 0x00000008
|
|
+#define AR5K_OLD_RX_DESC_STATUS1_DECRYPT_CRC_ERROR 0x00000010
|
|
+#define AR5K_OLD_RX_DESC_STATUS1_PHY_ERROR 0x000000e0
|
|
+#define AR5K_OLD_RX_DESC_STATUS1_PHY_ERROR_S 5
|
|
+#define AR5K_OLD_RX_DESC_STATUS1_KEY_INDEX_VALID 0x00000100
|
|
+#define AR5K_OLD_RX_DESC_STATUS1_KEY_INDEX 0x00007e00
|
|
+#define AR5K_OLD_RX_DESC_STATUS1_KEY_INDEX_S 9
|
|
+#define AR5K_OLD_RX_DESC_STATUS1_RECEIVE_TIMESTAMP 0x0fff8000
|
|
+#define AR5K_OLD_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S 15
|
|
+#define AR5K_OLD_RX_DESC_STATUS1_KEY_CACHE_MISS 0x10000000
|
|
+} __packed;
|
|
+
|
|
+/*
|
|
+ * 5212 rx status descriptor
|
|
+ */
|
|
+struct ath5k_hw_new_rx_status {
|
|
+ u32 rx_status_0; /* RX status word 0 */
|
|
+
|
|
+#define AR5K_NEW_RX_DESC_STATUS0_DATA_LEN 0x00000fff
|
|
+#define AR5K_NEW_RX_DESC_STATUS0_MORE 0x00001000
|
|
+#define AR5K_NEW_RX_DESC_STATUS0_DECOMP_CRC_ERROR 0x00002000
|
|
+#define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_RATE 0x000f8000
|
|
+#define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_RATE_S 15
|
|
+#define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_SIGNAL 0x0ff00000
|
|
+#define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_SIGNAL_S 20
|
|
+#define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_ANTENNA 0xf0000000
|
|
+#define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_ANTENNA_S 28
|
|
+
|
|
+ u32 rx_status_1; /* RX status word 1 */
|
|
+
|
|
+#define AR5K_NEW_RX_DESC_STATUS1_DONE 0x00000001
|
|
+#define AR5K_NEW_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002
|
|
+#define AR5K_NEW_RX_DESC_STATUS1_CRC_ERROR 0x00000004
|
|
+#define AR5K_NEW_RX_DESC_STATUS1_DECRYPT_CRC_ERROR 0x00000008
|
|
+#define AR5K_NEW_RX_DESC_STATUS1_PHY_ERROR 0x00000010
|
|
+#define AR5K_NEW_RX_DESC_STATUS1_MIC_ERROR 0x00000020
|
|
+#define AR5K_NEW_RX_DESC_STATUS1_KEY_INDEX_VALID 0x00000100
|
|
+#define AR5K_NEW_RX_DESC_STATUS1_KEY_INDEX 0x0000fe00
|
|
+#define AR5K_NEW_RX_DESC_STATUS1_KEY_INDEX_S 9
|
|
+#define AR5K_NEW_RX_DESC_STATUS1_RECEIVE_TIMESTAMP 0x7fff0000
|
|
+#define AR5K_NEW_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S 16
|
|
+#define AR5K_NEW_RX_DESC_STATUS1_KEY_CACHE_MISS 0x80000000
|
|
+} __packed;
|
|
+
|
|
+struct ath5k_hw_rx_error {
|
|
+ u32 rx_error_0; /* RX error word 0 */
|
|
+
|
|
+#define AR5K_RX_DESC_ERROR0 0x00000000
|
|
+
|
|
+ u32 rx_error_1; /* RX error word 1 */
|
|
+
|
|
+#define AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE 0x0000ff00
|
|
+#define AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE_S 8
|
|
+} __packed;
|
|
+
|
|
+#define AR5K_DESC_RX_PHY_ERROR_NONE 0x00
|
|
+#define AR5K_DESC_RX_PHY_ERROR_TIMING 0x20
|
|
+#define AR5K_DESC_RX_PHY_ERROR_PARITY 0x40
|
|
+#define AR5K_DESC_RX_PHY_ERROR_RATE 0x60
|
|
+#define AR5K_DESC_RX_PHY_ERROR_LENGTH 0x80
|
|
+#define AR5K_DESC_RX_PHY_ERROR_64QAM 0xa0
|
|
+#define AR5K_DESC_RX_PHY_ERROR_SERVICE 0xc0
|
|
+#define AR5K_DESC_RX_PHY_ERROR_TRANSMITOVR 0xe0
|
|
+
|
|
+struct ath5k_hw_2w_tx_desc {
|
|
+ u32 tx_control_0; /* TX control word 0 */
|
|
+
|
|
+#define AR5K_2W_TX_DESC_CTL0_FRAME_LEN 0x00000fff
|
|
+#define AR5K_2W_TX_DESC_CTL0_HEADER_LEN 0x0003f000 /*[5210 ?]*/
|
|
+#define AR5K_2W_TX_DESC_CTL0_HEADER_LEN_S 12
|
|
+#define AR5K_2W_TX_DESC_CTL0_XMIT_RATE 0x003c0000
|
|
+#define AR5K_2W_TX_DESC_CTL0_XMIT_RATE_S 18
|
|
+#define AR5K_2W_TX_DESC_CTL0_RTSENA 0x00400000
|
|
+#define AR5K_2W_TX_DESC_CTL0_CLRDMASK 0x01000000
|
|
+#define AR5K_2W_TX_DESC_CTL0_LONG_PACKET 0x00800000 /*[5210]*/
|
|
+#define AR5K_2W_TX_DESC_CTL0_VEOL 0x00800000 /*[5211]*/
|
|
+#define AR5K_2W_TX_DESC_CTL0_FRAME_TYPE 0x1c000000 /*[5210]*/
|
|
+#define AR5K_2W_TX_DESC_CTL0_FRAME_TYPE_S 26
|
|
+#define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5210 0x02000000
|
|
+#define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5211 0x1e000000
|
|
+#define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT (ah->ah_version == AR5K_AR5210 ? \
|
|
+ AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5210 : \
|
|
+ AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5211)
|
|
+#define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_S 25
|
|
+#define AR5K_2W_TX_DESC_CTL0_INTREQ 0x20000000
|
|
+#define AR5K_2W_TX_DESC_CTL0_ENCRYPT_KEY_VALID 0x40000000
|
|
+
|
|
+ u32 tx_control_1; /* TX control word 1 */
|
|
+
|
|
+#define AR5K_2W_TX_DESC_CTL1_BUF_LEN 0x00000fff
|
|
+#define AR5K_2W_TX_DESC_CTL1_MORE 0x00001000
|
|
+#define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5210 0x0007e000
|
|
+#define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5211 0x000fe000
|
|
+#define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX (ah->ah_version == AR5K_AR5210 ? \
|
|
+ AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5210 : \
|
|
+ AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5211)
|
|
+#define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_S 13
|
|
+#define AR5K_2W_TX_DESC_CTL1_FRAME_TYPE 0x00700000 /*[5211]*/
|
|
+#define AR5K_2W_TX_DESC_CTL1_FRAME_TYPE_S 20
|
|
+#define AR5K_2W_TX_DESC_CTL1_NOACK 0x00800000 /*[5211]*/
|
|
+#define AR5K_2W_TX_DESC_CTL1_RTS_DURATION 0xfff80000 /*[5210 ?]*/
|
|
+} __packed;
|
|
+
|
|
+#define AR5K_AR5210_TX_DESC_FRAME_TYPE_NORMAL 0x00
|
|
+#define AR5K_AR5210_TX_DESC_FRAME_TYPE_ATIM 0x04
|
|
+#define AR5K_AR5210_TX_DESC_FRAME_TYPE_PSPOLL 0x08
|
|
+#define AR5K_AR5210_TX_DESC_FRAME_TYPE_NO_DELAY 0x0c
|
|
+#define AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS 0x10
|
|
+
|
|
+/*
|
|
+ * 5212 4-word tx control descriptor
|
|
+ */
|
|
+struct ath5k_hw_4w_tx_desc {
|
|
+ u32 tx_control_0; /* TX control word 0 */
|
|
+
|
|
+#define AR5K_4W_TX_DESC_CTL0_FRAME_LEN 0x00000fff
|
|
+#define AR5K_4W_TX_DESC_CTL0_XMIT_POWER 0x003f0000
|
|
+#define AR5K_4W_TX_DESC_CTL0_XMIT_POWER_S 16
|
|
+#define AR5K_4W_TX_DESC_CTL0_RTSENA 0x00400000
|
|
+#define AR5K_4W_TX_DESC_CTL0_VEOL 0x00800000
|
|
+#define AR5K_4W_TX_DESC_CTL0_CLRDMASK 0x01000000
|
|
+#define AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT 0x1e000000
|
|
+#define AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT_S 25
|
|
+#define AR5K_4W_TX_DESC_CTL0_INTREQ 0x20000000
|
|
+#define AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID 0x40000000
|
|
+#define AR5K_4W_TX_DESC_CTL0_CTSENA 0x80000000
|
|
+
|
|
+ u32 tx_control_1; /* TX control word 1 */
|
|
+
|
|
+#define AR5K_4W_TX_DESC_CTL1_BUF_LEN 0x00000fff
|
|
+#define AR5K_4W_TX_DESC_CTL1_MORE 0x00001000
|
|
+#define AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX 0x000fe000
|
|
+#define AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_S 13
|
|
+#define AR5K_4W_TX_DESC_CTL1_FRAME_TYPE 0x00f00000
|
|
+#define AR5K_4W_TX_DESC_CTL1_FRAME_TYPE_S 20
|
|
+#define AR5K_4W_TX_DESC_CTL1_NOACK 0x01000000
|
|
+#define AR5K_4W_TX_DESC_CTL1_COMP_PROC 0x06000000
|
|
+#define AR5K_4W_TX_DESC_CTL1_COMP_PROC_S 25
|
|
+#define AR5K_4W_TX_DESC_CTL1_COMP_IV_LEN 0x18000000
|
|
+#define AR5K_4W_TX_DESC_CTL1_COMP_IV_LEN_S 27
|
|
+#define AR5K_4W_TX_DESC_CTL1_COMP_ICV_LEN 0x60000000
|
|
+#define AR5K_4W_TX_DESC_CTL1_COMP_ICV_LEN_S 29
|
|
+
|
|
+ u32 tx_control_2; /* TX control word 2 */
|
|
+
|
|
+#define AR5K_4W_TX_DESC_CTL2_RTS_DURATION 0x00007fff
|
|
+#define AR5K_4W_TX_DESC_CTL2_DURATION_UPDATE_ENABLE 0x00008000
|
|
+#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0 0x000f0000
|
|
+#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0_S 16
|
|
+#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1 0x00f00000
|
|
+#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1_S 20
|
|
+#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2 0x0f000000
|
|
+#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2_S 24
|
|
+#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3 0xf0000000
|
|
+#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3_S 28
|
|
+
|
|
+ u32 tx_control_3; /* TX control word 3 */
|
|
+
|
|
+#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE0 0x0000001f
|
|
+#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE1 0x000003e0
|
|
+#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE1_S 5
|
|
+#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE2 0x00007c00
|
|
+#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE2_S 10
|
|
+#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE3 0x000f8000
|
|
+#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE3_S 15
|
|
+#define AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE 0x01f00000
|
|
+#define AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE_S 20
|
|
+} __packed;
|
|
+
|
|
+/*
|
|
+ * Common tx status descriptor
|
|
+ */
|
|
+struct ath5k_hw_tx_status {
|
|
+ u32 tx_status_0; /* TX status word 0 */
|
|
+
|
|
+#define AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK 0x00000001
|
|
+#define AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES 0x00000002
|
|
+#define AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN 0x00000004
|
|
+#define AR5K_DESC_TX_STATUS0_FILTERED 0x00000008
|
|
+/*???
|
|
+#define AR5K_DESC_TX_STATUS0_RTS_FAIL_COUNT 0x000000f0
|
|
+#define AR5K_DESC_TX_STATUS0_RTS_FAIL_COUNT_S 4
|
|
+*/
|
|
+#define AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT 0x000000f0
|
|
+#define AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT_S 4
|
|
+/*???
|
|
+#define AR5K_DESC_TX_STATUS0_DATA_FAIL_COUNT 0x00000f00
|
|
+#define AR5K_DESC_TX_STATUS0_DATA_FAIL_COUNT_S 8
|
|
+*/
|
|
+#define AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT 0x00000f00
|
|
+#define AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT_S 8
|
|
+#define AR5K_DESC_TX_STATUS0_VIRT_COLL_COUNT 0x0000f000
|
|
+#define AR5K_DESC_TX_STATUS0_VIRT_COLL_COUNT_S 12
|
|
+#define AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP 0xffff0000
|
|
+#define AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP_S 16
|
|
+
|
|
+ u32 tx_status_1; /* TX status word 1 */
|
|
+
|
|
+#define AR5K_DESC_TX_STATUS1_DONE 0x00000001
|
|
+#define AR5K_DESC_TX_STATUS1_SEQ_NUM 0x00001ffe
|
|
+#define AR5K_DESC_TX_STATUS1_SEQ_NUM_S 1
|
|
+#define AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH 0x001fe000
|
|
+#define AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH_S 13
|
|
+#define AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX 0x00600000
|
|
+#define AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX_S 21
|
|
+#define AR5K_DESC_TX_STATUS1_COMP_SUCCESS 0x00800000
|
|
+#define AR5K_DESC_TX_STATUS1_XMIT_ANTENNA 0x01000000
|
|
+} __packed;
|
|
+
|
|
+
|
|
+/*
|
|
+ * AR5K REGISTER ACCESS
|
|
+ */
|
|
+
|
|
+/*Swap RX/TX Descriptor for big endian archs*/
|
|
+#if defined(__BIG_ENDIAN)
|
|
+#define AR5K_INIT_CFG ( \
|
|
+ AR5K_CFG_SWTD | AR5K_CFG_SWRD \
|
|
+)
|
|
+#else
|
|
+#define AR5K_INIT_CFG 0x00000000
|
|
+#endif
|
|
+
|
|
+/*#define AR5K_REG_READ(_reg) ath5k_hw_reg_read(ah, _reg)
|
|
+
|
|
+#define AR5K_REG_WRITE(_reg, _val) ath5k_hw_reg_write(ah, _val, _reg)*/
|
|
+
|
|
+#define AR5K_REG_SM(_val, _flags) \
|
|
+ (((_val) << _flags##_S) & (_flags))
|
|
+
|
|
+#define AR5K_REG_MS(_val, _flags) \
|
|
+ (((_val) & (_flags)) >> _flags##_S)
|
|
+
|
|
+/* Some registers can hold multiple values of interest. For this
|
|
+ * reason when we want to write to these registers we must first
|
|
+ * retrieve the values which we do not want to clear (lets call this
|
|
+ * old_data) and then set the register with this and our new_value:
|
|
+ * ( old_data | new_value) */
|
|
+#define AR5K_REG_WRITE_BITS(ah, _reg, _flags, _val) \
|
|
+ ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, _reg) & ~(_flags)) | \
|
|
+ (((_val) << _flags##_S) & (_flags)), _reg)
|
|
+
|
|
+#define AR5K_REG_MASKED_BITS(ah, _reg, _flags, _mask) \
|
|
+ ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, _reg) & \
|
|
+ (_mask)) | (_flags), _reg)
|
|
+
|
|
+#define AR5K_REG_ENABLE_BITS(ah, _reg, _flags) \
|
|
+ ath5k_hw_reg_write(ah, ath5k_hw_reg_read(ah, _reg) | (_flags), _reg)
|
|
+
|
|
+#define AR5K_REG_DISABLE_BITS(ah, _reg, _flags) \
|
|
+ ath5k_hw_reg_write(ah, ath5k_hw_reg_read(ah, _reg) & ~(_flags), _reg)
|
|
+
|
|
+#define AR5K_PHY_WRITE(ah, _reg, _val) \
|
|
+ ath5k_hw_reg_write(ah, _val, (ah)->ah_phy + ((_reg) << 2))
|
|
+
|
|
+#define AR5K_PHY_READ(ah, _reg) \
|
|
+ ath5k_hw_reg_read(ah, (ah)->ah_phy + ((_reg) << 2))
|
|
+
|
|
+#define AR5K_REG_WAIT(_i) do { \
|
|
+ if (_i % 64) \
|
|
+ udelay(1); \
|
|
+} while (0)
|
|
+
|
|
+#define AR5K_EEPROM_READ(_o, _v) do { \
|
|
+ if ((ret = ath5k_hw_eeprom_read(ah, (_o), &(_v))) != 0) \
|
|
+ return (ret); \
|
|
+} while (0)
|
|
+
|
|
+#define AR5K_EEPROM_READ_HDR(_o, _v) \
|
|
+ AR5K_EEPROM_READ(_o, ah->ah_capabilities.cap_eeprom._v); \
|
|
+
|
|
+/* Read status of selected queue */
|
|
+#define AR5K_REG_READ_Q(ah, _reg, _queue) \
|
|
+ (ath5k_hw_reg_read(ah, _reg) & (1 << _queue)) \
|
|
+
|
|
+#define AR5K_REG_WRITE_Q(ah, _reg, _queue) \
|
|
+ ath5k_hw_reg_write(ah, (1 << _queue), _reg)
|
|
+
|
|
+#define AR5K_Q_ENABLE_BITS(_reg, _queue) do { \
|
|
+ _reg |= 1 << _queue; \
|
|
+} while (0)
|
|
+
|
|
+#define AR5K_Q_DISABLE_BITS(_reg, _queue) do { \
|
|
+ _reg &= ~(1 << _queue); \
|
|
+} while (0)
|
|
+
|
|
+#define AR5K_LOW_ID(_a)( \
|
|
+(_a)[0] | (_a)[1] << 8 | (_a)[2] << 16 | (_a)[3] << 24 \
|
|
+)
|
|
+
|
|
+#define AR5K_HIGH_ID(_a) ((_a)[4] | (_a)[5] << 8)
|
|
+
|
|
+/*
|
|
+ * Initial register values
|
|
+ */
|
|
+
|
|
+/*
|
|
+ * Common initial register values
|
|
+ */
|
|
+#define AR5K_INIT_MODE CHANNEL_B
|
|
+
|
|
+#define AR5K_INIT_TX_LATENCY 502
|
|
+#define AR5K_INIT_USEC 39
|
|
+#define AR5K_INIT_USEC_TURBO 79
|
|
+#define AR5K_INIT_USEC_32 31
|
|
+#define AR5K_INIT_CARR_SENSE_EN 1
|
|
+#define AR5K_INIT_PROG_IFS 920
|
|
+#define AR5K_INIT_PROG_IFS_TURBO 960
|
|
+#define AR5K_INIT_EIFS 3440
|
|
+#define AR5K_INIT_EIFS_TURBO 6880
|
|
+#define AR5K_INIT_SLOT_TIME 396
|
|
+#define AR5K_INIT_SLOT_TIME_TURBO 480
|
|
+#define AR5K_INIT_ACK_CTS_TIMEOUT 1024
|
|
+#define AR5K_INIT_ACK_CTS_TIMEOUT_TURBO 0x08000800
|
|
+#define AR5K_INIT_SIFS 560
|
|
+#define AR5K_INIT_SIFS_TURBO 480
|
|
+#define AR5K_INIT_SH_RETRY 10
|
|
+#define AR5K_INIT_LG_RETRY AR5K_INIT_SH_RETRY
|
|
+#define AR5K_INIT_SSH_RETRY 32
|
|
+#define AR5K_INIT_SLG_RETRY AR5K_INIT_SSH_RETRY
|
|
+#define AR5K_INIT_TX_RETRY 10
|
|
+#define AR5K_INIT_TOPS 8
|
|
+#define AR5K_INIT_RXNOFRM 8
|
|
+#define AR5K_INIT_RPGTO 0
|
|
+#define AR5K_INIT_TXNOFRM 0
|
|
+#define AR5K_INIT_BEACON_PERIOD 65535
|
|
+#define AR5K_INIT_TIM_OFFSET 0
|
|
+#define AR5K_INIT_BEACON_EN 0
|
|
+#define AR5K_INIT_RESET_TSF 0
|
|
+
|
|
+#define AR5K_INIT_TRANSMIT_LATENCY ( \
|
|
+ (AR5K_INIT_TX_LATENCY << 14) | (AR5K_INIT_USEC_32 << 7) | \
|
|
+ (AR5K_INIT_USEC) \
|
|
+)
|
|
+#define AR5K_INIT_TRANSMIT_LATENCY_TURBO ( \
|
|
+ (AR5K_INIT_TX_LATENCY << 14) | (AR5K_INIT_USEC_32 << 7) | \
|
|
+ (AR5K_INIT_USEC_TURBO) \
|
|
+)
|
|
+#define AR5K_INIT_PROTO_TIME_CNTRL ( \
|
|
+ (AR5K_INIT_CARR_SENSE_EN << 26) | (AR5K_INIT_EIFS << 12) | \
|
|
+ (AR5K_INIT_PROG_IFS) \
|
|
+)
|
|
+#define AR5K_INIT_PROTO_TIME_CNTRL_TURBO ( \
|
|
+ (AR5K_INIT_CARR_SENSE_EN << 26) | (AR5K_INIT_EIFS_TURBO << 12) | \
|
|
+ (AR5K_INIT_PROG_IFS_TURBO) \
|
|
+)
|
|
+#define AR5K_INIT_BEACON_CONTROL ( \
|
|
+ (AR5K_INIT_RESET_TSF << 24) | (AR5K_INIT_BEACON_EN << 23) | \
|
|
+ (AR5K_INIT_TIM_OFFSET << 16) | (AR5K_INIT_BEACON_PERIOD) \
|
|
+)
|
|
+
|
|
+/*
|
|
+ * Non-common initial register values which have to be loaded into the
|
|
+ * card at boot time and after each reset.
|
|
+ */
|
|
+
|
|
+/* Register dumps are done per operation mode */
|
|
+#define AR5K_INI_RFGAIN_5GHZ 0
|
|
+#define AR5K_INI_RFGAIN_2GHZ 1
|
|
+
|
|
+#define AR5K_INI_VAL_11A 0
|
|
+#define AR5K_INI_VAL_11A_TURBO 1
|
|
+#define AR5K_INI_VAL_11B 2
|
|
+#define AR5K_INI_VAL_11G 3
|
|
+#define AR5K_INI_VAL_11G_TURBO 4
|
|
+#define AR5K_INI_VAL_XR 0
|
|
+#define AR5K_INI_VAL_MAX 5
|
|
+
|
|
+#define AR5K_RF5111_INI_RF_MAX_BANKS AR5K_MAX_RF_BANKS
|
|
+#define AR5K_RF5112_INI_RF_MAX_BANKS AR5K_MAX_RF_BANKS
|
|
+
|
|
+static inline u32 ath5k_hw_bitswap(u32 val, unsigned int bits)
|
|
+{
|
|
+ u32 retval = 0, bit, i;
|
|
+
|
|
+ for (i = 0; i < bits; i++) {
|
|
+ bit = (val >> i) & 1;
|
|
+ retval = (retval << 1) | bit;
|
|
+ }
|
|
+
|
|
+ return retval;
|
|
+}
|
|
diff -up /dev/null linux-2.6.23.noarch/drivers/net/wireless/ath5k/initvals.c
|
|
--- /dev/null 2007-12-21 08:33:07.834165456 -0500
|
|
+++ linux-2.6.23.noarch/drivers/net/wireless/ath5k/initvals.c 2007-12-21 12:18:50.000000000 -0500
|
|
@@ -0,0 +1,1347 @@
|
|
+/*
|
|
+ * Initial register settings functions
|
|
+ *
|
|
+ * Copyright (c) 2004, 2005, 2006, 2007 Reyk Floeter <reyk@openbsd.org>
|
|
+ * Copyright (c) 2006, 2007 Nick Kossifidis <mickflemm@gmail.com>
|
|
+ * Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com>
|
|
+ *
|
|
+ * Permission to use, copy, modify, and distribute this software for any
|
|
+ * purpose with or without fee is hereby granted, provided that the above
|
|
+ * copyright notice and this permission notice appear in all copies.
|
|
+ *
|
|
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
+ *
|
|
+ */
|
|
+
|
|
+#include "ath5k.h"
|
|
+#include "base.h"
|
|
+#include "reg.h"
|
|
+
|
|
+/*
|
|
+ * MAC/PHY REGISTERS
|
|
+ */
|
|
+
|
|
+
|
|
+/*
|
|
+ * Mode-independent initial register writes
|
|
+ */
|
|
+
|
|
+struct ath5k_ini {
|
|
+ u16 ini_register;
|
|
+ u32 ini_value;
|
|
+
|
|
+ enum {
|
|
+ AR5K_INI_WRITE = 0, /* Default */
|
|
+ AR5K_INI_READ = 1, /* Cleared on read */
|
|
+ } ini_mode;
|
|
+};
|
|
+
|
|
+/*
|
|
+ * Mode specific initial register values
|
|
+ */
|
|
+
|
|
+struct ath5k_ini_mode {
|
|
+ u16 mode_register;
|
|
+ u32 mode_value[5];
|
|
+};
|
|
+
|
|
+/* Initial register settings for AR5210 */
|
|
+static const struct ath5k_ini ar5210_ini[] = {
|
|
+ /* PCU and MAC registers */
|
|
+ { AR5K_NOQCU_TXDP0, 0 },
|
|
+ { AR5K_NOQCU_TXDP1, 0 },
|
|
+ { AR5K_RXDP, 0 },
|
|
+ { AR5K_CR, 0 },
|
|
+ { AR5K_ISR, 0, AR5K_INI_READ },
|
|
+ { AR5K_IMR, 0 },
|
|
+ { AR5K_IER, AR5K_IER_DISABLE },
|
|
+ { AR5K_BSR, 0, AR5K_INI_READ },
|
|
+ { AR5K_TXCFG, AR5K_DMASIZE_128B },
|
|
+ { AR5K_RXCFG, AR5K_DMASIZE_128B },
|
|
+ { AR5K_CFG, AR5K_INIT_CFG },
|
|
+ { AR5K_TOPS, AR5K_INIT_TOPS },
|
|
+ { AR5K_RXNOFRM, AR5K_INIT_RXNOFRM },
|
|
+ { AR5K_RPGTO, AR5K_INIT_RPGTO },
|
|
+ { AR5K_TXNOFRM, AR5K_INIT_TXNOFRM },
|
|
+ { AR5K_SFR, 0 },
|
|
+ { AR5K_MIBC, 0 },
|
|
+ { AR5K_MISC, 0 },
|
|
+ { AR5K_RX_FILTER_5210, 0 },
|
|
+ { AR5K_MCAST_FILTER0_5210, 0 },
|
|
+ { AR5K_MCAST_FILTER1_5210, 0 },
|
|
+ { AR5K_TX_MASK0, 0 },
|
|
+ { AR5K_TX_MASK1, 0 },
|
|
+ { AR5K_CLR_TMASK, 0 },
|
|
+ { AR5K_TRIG_LVL, AR5K_TUNE_MIN_TX_FIFO_THRES },
|
|
+ { AR5K_DIAG_SW_5210, 0 },
|
|
+ { AR5K_RSSI_THR, AR5K_TUNE_RSSI_THRES },
|
|
+ { AR5K_TSF_L32_5210, 0 },
|
|
+ { AR5K_TIMER0_5210, 0 },
|
|
+ { AR5K_TIMER1_5210, 0xffffffff },
|
|
+ { AR5K_TIMER2_5210, 0xffffffff },
|
|
+ { AR5K_TIMER3_5210, 1 },
|
|
+ { AR5K_CFP_DUR_5210, 0 },
|
|
+ { AR5K_CFP_PERIOD_5210, 0 },
|
|
+ /* PHY registers */
|
|
+ { AR5K_PHY(0), 0x00000047 },
|
|
+ { AR5K_PHY_AGC, 0x00000000 },
|
|
+ { AR5K_PHY(3), 0x09848ea6 },
|
|
+ { AR5K_PHY(4), 0x3d32e000 },
|
|
+ { AR5K_PHY(5), 0x0000076b },
|
|
+ { AR5K_PHY_ACT, AR5K_PHY_ACT_DISABLE },
|
|
+ { AR5K_PHY(8), 0x02020200 },
|
|
+ { AR5K_PHY(9), 0x00000e0e },
|
|
+ { AR5K_PHY(10), 0x0a020201 },
|
|
+ { AR5K_PHY(11), 0x00036ffc },
|
|
+ { AR5K_PHY(12), 0x00000000 },
|
|
+ { AR5K_PHY(13), 0x00000e0e },
|
|
+ { AR5K_PHY(14), 0x00000007 },
|
|
+ { AR5K_PHY(15), 0x00020100 },
|
|
+ { AR5K_PHY(16), 0x89630000 },
|
|
+ { AR5K_PHY(17), 0x1372169c },
|
|
+ { AR5K_PHY(18), 0x0018b633 },
|
|
+ { AR5K_PHY(19), 0x1284613c },
|
|
+ { AR5K_PHY(20), 0x0de8b8e0 },
|
|
+ { AR5K_PHY(21), 0x00074859 },
|
|
+ { AR5K_PHY(22), 0x7e80beba },
|
|
+ { AR5K_PHY(23), 0x313a665e },
|
|
+ { AR5K_PHY_AGCCTL, 0x00001d08 },
|
|
+ { AR5K_PHY(25), 0x0001ce00 },
|
|
+ { AR5K_PHY(26), 0x409a4190 },
|
|
+ { AR5K_PHY(28), 0x0000000f },
|
|
+ { AR5K_PHY(29), 0x00000080 },
|
|
+ { AR5K_PHY(30), 0x00000004 },
|
|
+ { AR5K_PHY(31), 0x00000018 }, /* 0x987c */
|
|
+ { AR5K_PHY(64), 0x00000000 }, /* 0x9900 */
|
|
+ { AR5K_PHY(65), 0x00000000 },
|
|
+ { AR5K_PHY(66), 0x00000000 },
|
|
+ { AR5K_PHY(67), 0x00800000 },
|
|
+ { AR5K_PHY(68), 0x00000003 },
|
|
+ /* BB gain table (64bytes) */
|
|
+ { AR5K_BB_GAIN(0), 0x00000000 },
|
|
+ { AR5K_BB_GAIN(1), 0x00000020 },
|
|
+ { AR5K_BB_GAIN(2), 0x00000010 },
|
|
+ { AR5K_BB_GAIN(3), 0x00000030 },
|
|
+ { AR5K_BB_GAIN(4), 0x00000008 },
|
|
+ { AR5K_BB_GAIN(5), 0x00000028 },
|
|
+ { AR5K_BB_GAIN(6), 0x00000028 },
|
|
+ { AR5K_BB_GAIN(7), 0x00000004 },
|
|
+ { AR5K_BB_GAIN(8), 0x00000024 },
|
|
+ { AR5K_BB_GAIN(9), 0x00000014 },
|
|
+ { AR5K_BB_GAIN(10), 0x00000034 },
|
|
+ { AR5K_BB_GAIN(11), 0x0000000c },
|
|
+ { AR5K_BB_GAIN(12), 0x0000002c },
|
|
+ { AR5K_BB_GAIN(13), 0x00000002 },
|
|
+ { AR5K_BB_GAIN(14), 0x00000022 },
|
|
+ { AR5K_BB_GAIN(15), 0x00000012 },
|
|
+ { AR5K_BB_GAIN(16), 0x00000032 },
|
|
+ { AR5K_BB_GAIN(17), 0x0000000a },
|
|
+ { AR5K_BB_GAIN(18), 0x0000002a },
|
|
+ { AR5K_BB_GAIN(19), 0x00000001 },
|
|
+ { AR5K_BB_GAIN(20), 0x00000021 },
|
|
+ { AR5K_BB_GAIN(21), 0x00000011 },
|
|
+ { AR5K_BB_GAIN(22), 0x00000031 },
|
|
+ { AR5K_BB_GAIN(23), 0x00000009 },
|
|
+ { AR5K_BB_GAIN(24), 0x00000029 },
|
|
+ { AR5K_BB_GAIN(25), 0x00000005 },
|
|
+ { AR5K_BB_GAIN(26), 0x00000025 },
|
|
+ { AR5K_BB_GAIN(27), 0x00000015 },
|
|
+ { AR5K_BB_GAIN(28), 0x00000035 },
|
|
+ { AR5K_BB_GAIN(29), 0x0000000d },
|
|
+ { AR5K_BB_GAIN(30), 0x0000002d },
|
|
+ { AR5K_BB_GAIN(31), 0x00000003 },
|
|
+ { AR5K_BB_GAIN(32), 0x00000023 },
|
|
+ { AR5K_BB_GAIN(33), 0x00000013 },
|
|
+ { AR5K_BB_GAIN(34), 0x00000033 },
|
|
+ { AR5K_BB_GAIN(35), 0x0000000b },
|
|
+ { AR5K_BB_GAIN(36), 0x0000002b },
|
|
+ { AR5K_BB_GAIN(37), 0x00000007 },
|
|
+ { AR5K_BB_GAIN(38), 0x00000027 },
|
|
+ { AR5K_BB_GAIN(39), 0x00000017 },
|
|
+ { AR5K_BB_GAIN(40), 0x00000037 },
|
|
+ { AR5K_BB_GAIN(41), 0x0000000f },
|
|
+ { AR5K_BB_GAIN(42), 0x0000002f },
|
|
+ { AR5K_BB_GAIN(43), 0x0000002f },
|
|
+ { AR5K_BB_GAIN(44), 0x0000002f },
|
|
+ { AR5K_BB_GAIN(45), 0x0000002f },
|
|
+ { AR5K_BB_GAIN(46), 0x0000002f },
|
|
+ { AR5K_BB_GAIN(47), 0x0000002f },
|
|
+ { AR5K_BB_GAIN(48), 0x0000002f },
|
|
+ { AR5K_BB_GAIN(49), 0x0000002f },
|
|
+ { AR5K_BB_GAIN(50), 0x0000002f },
|
|
+ { AR5K_BB_GAIN(51), 0x0000002f },
|
|
+ { AR5K_BB_GAIN(52), 0x0000002f },
|
|
+ { AR5K_BB_GAIN(53), 0x0000002f },
|
|
+ { AR5K_BB_GAIN(54), 0x0000002f },
|
|
+ { AR5K_BB_GAIN(55), 0x0000002f },
|
|
+ { AR5K_BB_GAIN(56), 0x0000002f },
|
|
+ { AR5K_BB_GAIN(57), 0x0000002f },
|
|
+ { AR5K_BB_GAIN(58), 0x0000002f },
|
|
+ { AR5K_BB_GAIN(59), 0x0000002f },
|
|
+ { AR5K_BB_GAIN(60), 0x0000002f },
|
|
+ { AR5K_BB_GAIN(61), 0x0000002f },
|
|
+ { AR5K_BB_GAIN(62), 0x0000002f },
|
|
+ { AR5K_BB_GAIN(63), 0x0000002f },
|
|
+ /* 5110 RF gain table (64btes) */
|
|
+ { AR5K_RF_GAIN(0), 0x0000001d },
|
|
+ { AR5K_RF_GAIN(1), 0x0000005d },
|
|
+ { AR5K_RF_GAIN(2), 0x0000009d },
|
|
+ { AR5K_RF_GAIN(3), 0x000000dd },
|
|
+ { AR5K_RF_GAIN(4), 0x0000011d },
|
|
+ { AR5K_RF_GAIN(5), 0x00000021 },
|
|
+ { AR5K_RF_GAIN(6), 0x00000061 },
|
|
+ { AR5K_RF_GAIN(7), 0x000000a1 },
|
|
+ { AR5K_RF_GAIN(8), 0x000000e1 },
|
|
+ { AR5K_RF_GAIN(9), 0x00000031 },
|
|
+ { AR5K_RF_GAIN(10), 0x00000071 },
|
|
+ { AR5K_RF_GAIN(11), 0x000000b1 },
|
|
+ { AR5K_RF_GAIN(12), 0x0000001c },
|
|
+ { AR5K_RF_GAIN(13), 0x0000005c },
|
|
+ { AR5K_RF_GAIN(14), 0x00000029 },
|
|
+ { AR5K_RF_GAIN(15), 0x00000069 },
|
|
+ { AR5K_RF_GAIN(16), 0x000000a9 },
|
|
+ { AR5K_RF_GAIN(17), 0x00000020 },
|
|
+ { AR5K_RF_GAIN(18), 0x00000019 },
|
|
+ { AR5K_RF_GAIN(19), 0x00000059 },
|
|
+ { AR5K_RF_GAIN(20), 0x00000099 },
|
|
+ { AR5K_RF_GAIN(21), 0x00000030 },
|
|
+ { AR5K_RF_GAIN(22), 0x00000005 },
|
|
+ { AR5K_RF_GAIN(23), 0x00000025 },
|
|
+ { AR5K_RF_GAIN(24), 0x00000065 },
|
|
+ { AR5K_RF_GAIN(25), 0x000000a5 },
|
|
+ { AR5K_RF_GAIN(26), 0x00000028 },
|
|
+ { AR5K_RF_GAIN(27), 0x00000068 },
|
|
+ { AR5K_RF_GAIN(28), 0x0000001f },
|
|
+ { AR5K_RF_GAIN(29), 0x0000001e },
|
|
+ { AR5K_RF_GAIN(30), 0x00000018 },
|
|
+ { AR5K_RF_GAIN(31), 0x00000058 },
|
|
+ { AR5K_RF_GAIN(32), 0x00000098 },
|
|
+ { AR5K_RF_GAIN(33), 0x00000003 },
|
|
+ { AR5K_RF_GAIN(34), 0x00000004 },
|
|
+ { AR5K_RF_GAIN(35), 0x00000044 },
|
|
+ { AR5K_RF_GAIN(36), 0x00000084 },
|
|
+ { AR5K_RF_GAIN(37), 0x00000013 },
|
|
+ { AR5K_RF_GAIN(38), 0x00000012 },
|
|
+ { AR5K_RF_GAIN(39), 0x00000052 },
|
|
+ { AR5K_RF_GAIN(40), 0x00000092 },
|
|
+ { AR5K_RF_GAIN(41), 0x000000d2 },
|
|
+ { AR5K_RF_GAIN(42), 0x0000002b },
|
|
+ { AR5K_RF_GAIN(43), 0x0000002a },
|
|
+ { AR5K_RF_GAIN(44), 0x0000006a },
|
|
+ { AR5K_RF_GAIN(45), 0x000000aa },
|
|
+ { AR5K_RF_GAIN(46), 0x0000001b },
|
|
+ { AR5K_RF_GAIN(47), 0x0000001a },
|
|
+ { AR5K_RF_GAIN(48), 0x0000005a },
|
|
+ { AR5K_RF_GAIN(49), 0x0000009a },
|
|
+ { AR5K_RF_GAIN(50), 0x000000da },
|
|
+ { AR5K_RF_GAIN(51), 0x00000006 },
|
|
+ { AR5K_RF_GAIN(52), 0x00000006 },
|
|
+ { AR5K_RF_GAIN(53), 0x00000006 },
|
|
+ { AR5K_RF_GAIN(54), 0x00000006 },
|
|
+ { AR5K_RF_GAIN(55), 0x00000006 },
|
|
+ { AR5K_RF_GAIN(56), 0x00000006 },
|
|
+ { AR5K_RF_GAIN(57), 0x00000006 },
|
|
+ { AR5K_RF_GAIN(58), 0x00000006 },
|
|
+ { AR5K_RF_GAIN(59), 0x00000006 },
|
|
+ { AR5K_RF_GAIN(60), 0x00000006 },
|
|
+ { AR5K_RF_GAIN(61), 0x00000006 },
|
|
+ { AR5K_RF_GAIN(62), 0x00000006 },
|
|
+ { AR5K_RF_GAIN(63), 0x00000006 },
|
|
+ /* PHY activation */
|
|
+ { AR5K_PHY(53), 0x00000020 },
|
|
+ { AR5K_PHY(51), 0x00000004 },
|
|
+ { AR5K_PHY(50), 0x00060106 },
|
|
+ { AR5K_PHY(39), 0x0000006d },
|
|
+ { AR5K_PHY(48), 0x00000000 },
|
|
+ { AR5K_PHY(52), 0x00000014 },
|
|
+ { AR5K_PHY_ACT, AR5K_PHY_ACT_ENABLE },
|
|
+};
|
|
+
|
|
+/* Initial register settings for AR5211 */
|
|
+static const struct ath5k_ini ar5211_ini[] = {
|
|
+ { AR5K_RXDP, 0x00000000 },
|
|
+ { AR5K_RTSD0, 0x84849c9c },
|
|
+ { AR5K_RTSD1, 0x7c7c7c7c },
|
|
+ { AR5K_RXCFG, 0x00000005 },
|
|
+ { AR5K_MIBC, 0x00000000 },
|
|
+ { AR5K_TOPS, 0x00000008 },
|
|
+ { AR5K_RXNOFRM, 0x00000008 },
|
|
+ { AR5K_TXNOFRM, 0x00000010 },
|
|
+ { AR5K_RPGTO, 0x00000000 },
|
|
+ { AR5K_RFCNT, 0x0000001f },
|
|
+ { AR5K_QUEUE_TXDP(0), 0x00000000 },
|
|
+ { AR5K_QUEUE_TXDP(1), 0x00000000 },
|
|
+ { AR5K_QUEUE_TXDP(2), 0x00000000 },
|
|
+ { AR5K_QUEUE_TXDP(3), 0x00000000 },
|
|
+ { AR5K_QUEUE_TXDP(4), 0x00000000 },
|
|
+ { AR5K_QUEUE_TXDP(5), 0x00000000 },
|
|
+ { AR5K_QUEUE_TXDP(6), 0x00000000 },
|
|
+ { AR5K_QUEUE_TXDP(7), 0x00000000 },
|
|
+ { AR5K_QUEUE_TXDP(8), 0x00000000 },
|
|
+ { AR5K_QUEUE_TXDP(9), 0x00000000 },
|
|
+ { AR5K_DCU_FP, 0x00000000 },
|
|
+ { AR5K_STA_ID1, 0x00000000 },
|
|
+ { AR5K_BSS_ID0, 0x00000000 },
|
|
+ { AR5K_BSS_ID1, 0x00000000 },
|
|
+ { AR5K_RSSI_THR, 0x00000000 },
|
|
+ { AR5K_CFP_PERIOD_5211, 0x00000000 },
|
|
+ { AR5K_TIMER0_5211, 0x00000030 },
|
|
+ { AR5K_TIMER1_5211, 0x0007ffff },
|
|
+ { AR5K_TIMER2_5211, 0x01ffffff },
|
|
+ { AR5K_TIMER3_5211, 0x00000031 },
|
|
+ { AR5K_CFP_DUR_5211, 0x00000000 },
|
|
+ { AR5K_RX_FILTER_5211, 0x00000000 },
|
|
+ { AR5K_MCAST_FILTER0_5211, 0x00000000 },
|
|
+ { AR5K_MCAST_FILTER1_5211, 0x00000002 },
|
|
+ { AR5K_DIAG_SW_5211, 0x00000000 },
|
|
+ { AR5K_ADDAC_TEST, 0x00000000 },
|
|
+ { AR5K_DEFAULT_ANTENNA, 0x00000000 },
|
|
+ /* PHY registers */
|
|
+ { AR5K_PHY_AGC, 0x00000000 },
|
|
+ { AR5K_PHY(3), 0x2d849093 },
|
|
+ { AR5K_PHY(4), 0x7d32e000 },
|
|
+ { AR5K_PHY(5), 0x00000f6b },
|
|
+ { AR5K_PHY_ACT, 0x00000000 },
|
|
+ { AR5K_PHY(11), 0x00026ffe },
|
|
+ { AR5K_PHY(12), 0x00000000 },
|
|
+ { AR5K_PHY(15), 0x00020100 },
|
|
+ { AR5K_PHY(16), 0x206a017a },
|
|
+ { AR5K_PHY(19), 0x1284613c },
|
|
+ { AR5K_PHY(21), 0x00000859 },
|
|
+ { AR5K_PHY(26), 0x409a4190 }, /* 0x9868 */
|
|
+ { AR5K_PHY(27), 0x050cb081 },
|
|
+ { AR5K_PHY(28), 0x0000000f },
|
|
+ { AR5K_PHY(29), 0x00000080 },
|
|
+ { AR5K_PHY(30), 0x0000000c },
|
|
+ { AR5K_PHY(64), 0x00000000 },
|
|
+ { AR5K_PHY(65), 0x00000000 },
|
|
+ { AR5K_PHY(66), 0x00000000 },
|
|
+ { AR5K_PHY(67), 0x00800000 },
|
|
+ { AR5K_PHY(68), 0x00000001 },
|
|
+ { AR5K_PHY(71), 0x0000092a },
|
|
+ { AR5K_PHY_IQ, 0x00000000 },
|
|
+ { AR5K_PHY(73), 0x00058a05 },
|
|
+ { AR5K_PHY(74), 0x00000001 },
|
|
+ { AR5K_PHY(75), 0x00000000 },
|
|
+ { AR5K_PHY_PAPD_PROBE, 0x00000000 },
|
|
+ { AR5K_PHY(77), 0x00000000 }, /* 0x9934 */
|
|
+ { AR5K_PHY(78), 0x00000000 }, /* 0x9938 */
|
|
+ { AR5K_PHY(79), 0x0000003f }, /* 0x993c */
|
|
+ { AR5K_PHY(80), 0x00000004 },
|
|
+ { AR5K_PHY(82), 0x00000000 },
|
|
+ { AR5K_PHY(83), 0x00000000 },
|
|
+ { AR5K_PHY(84), 0x00000000 },
|
|
+ { AR5K_PHY_RADAR, 0x5d50f14c },
|
|
+ { AR5K_PHY(86), 0x00000018 },
|
|
+ { AR5K_PHY(87), 0x004b6a8e },
|
|
+ /* Initial Power table (32bytes)
|
|
+ * common on all cards/modes.
|
|
+ * Note: Table is rewritten during
|
|
+ * txpower setup later using calibration
|
|
+ * data etc. so next write is non-common
|
|
+ { AR5K_PHY_PCDAC_TXPOWER(1), 0x06ff05ff },
|
|
+ { AR5K_PHY_PCDAC_TXPOWER(2), 0x07ff07ff },
|
|
+ { AR5K_PHY_PCDAC_TXPOWER(3), 0x08ff08ff },
|
|
+ { AR5K_PHY_PCDAC_TXPOWER(4), 0x09ff09ff },
|
|
+ { AR5K_PHY_PCDAC_TXPOWER(5), 0x0aff0aff },
|
|
+ { AR5K_PHY_PCDAC_TXPOWER(6), 0x0bff0bff },
|
|
+ { AR5K_PHY_PCDAC_TXPOWER(7), 0x0cff0cff },
|
|
+ { AR5K_PHY_PCDAC_TXPOWER(8), 0x0dff0dff },
|
|
+ { AR5K_PHY_PCDAC_TXPOWER(9), 0x0fff0eff },
|
|
+ { AR5K_PHY_PCDAC_TXPOWER(10), 0x12ff12ff },
|
|
+ { AR5K_PHY_PCDAC_TXPOWER(11), 0x14ff13ff },
|
|
+ { AR5K_PHY_PCDAC_TXPOWER(12), 0x16ff15ff },
|
|
+ { AR5K_PHY_PCDAC_TXPOWER(13), 0x19ff17ff },
|
|
+ { AR5K_PHY_PCDAC_TXPOWER(14), 0x1bff1aff },
|
|
+ { AR5K_PHY_PCDAC_TXPOWER(15), 0x1eff1dff },
|
|
+ { AR5K_PHY_PCDAC_TXPOWER(16), 0x23ff20ff },
|
|
+ { AR5K_PHY_PCDAC_TXPOWER(17), 0x27ff25ff },
|
|
+ { AR5K_PHY_PCDAC_TXPOWER(18), 0x2cff29ff },
|
|
+ { AR5K_PHY_PCDAC_TXPOWER(19), 0x31ff2fff },
|
|
+ { AR5K_PHY_PCDAC_TXPOWER(20), 0x37ff34ff },
|
|
+ { AR5K_PHY_PCDAC_TXPOWER(21), 0x3aff3aff },
|
|
+ { AR5K_PHY_PCDAC_TXPOWER(22), 0x3aff3aff },
|
|
+ { AR5K_PHY_PCDAC_TXPOWER(23), 0x3aff3aff },
|
|
+ { AR5K_PHY_PCDAC_TXPOWER(24), 0x3aff3aff },
|
|
+ { AR5K_PHY_PCDAC_TXPOWER(25), 0x3aff3aff },
|
|
+ { AR5K_PHY_PCDAC_TXPOWER(26), 0x3aff3aff },
|
|
+ { AR5K_PHY_PCDAC_TXPOWER(27), 0x3aff3aff },
|
|
+ { AR5K_PHY_PCDAC_TXPOWER(28), 0x3aff3aff },
|
|
+ { AR5K_PHY_PCDAC_TXPOWER(29), 0x3aff3aff },
|
|
+ { AR5K_PHY_PCDAC_TXPOWER(30), 0x3aff3aff },
|
|
+ { AR5K_PHY_PCDAC_TXPOWER(31), 0x3aff3aff },*/
|
|
+ { AR5K_PHY_CCKTXCTL, 0x00000000 },
|
|
+ { AR5K_PHY(642), 0x503e4646 },
|
|
+ { AR5K_PHY_GAIN_2GHZ, 0x6480416c },
|
|
+ { AR5K_PHY(644), 0x0199a003 },
|
|
+ { AR5K_PHY(645), 0x044cd610 },
|
|
+ { AR5K_PHY(646), 0x13800040 },
|
|
+ { AR5K_PHY(647), 0x1be00060 },
|
|
+ { AR5K_PHY(648), 0x0c53800a },
|
|
+ { AR5K_PHY(649), 0x0014df3b },
|
|
+ { AR5K_PHY(650), 0x000001b5 },
|
|
+ { AR5K_PHY(651), 0x00000020 },
|
|
+};
|
|
+
|
|
+/* Initial mode-specific settings for AR5211
|
|
+ * XXX: how about g / gTurbo ? RF5111 supports it, how about AR5211 ?
|
|
+ * Maybe 5211 supports OFDM-only g but we need to test it !
|
|
+ */
|
|
+static const struct ath5k_ini_mode ar5211_ini_mode[] = {
|
|
+ { AR5K_TXCFG,
|
|
+ /* a aTurbo b */
|
|
+ { 0x00000015, 0x00000015, 0x0000001d } },
|
|
+ { AR5K_QUEUE_DFS_LOCAL_IFS(0),
|
|
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f } },
|
|
+ { AR5K_QUEUE_DFS_LOCAL_IFS(1),
|
|
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f } },
|
|
+ { AR5K_QUEUE_DFS_LOCAL_IFS(2),
|
|
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f } },
|
|
+ { AR5K_QUEUE_DFS_LOCAL_IFS(3),
|
|
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f } },
|
|
+ { AR5K_QUEUE_DFS_LOCAL_IFS(4),
|
|
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f } },
|
|
+ { AR5K_QUEUE_DFS_LOCAL_IFS(5),
|
|
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f } },
|
|
+ { AR5K_QUEUE_DFS_LOCAL_IFS(6),
|
|
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f } },
|
|
+ { AR5K_QUEUE_DFS_LOCAL_IFS(7),
|
|
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f } },
|
|
+ { AR5K_QUEUE_DFS_LOCAL_IFS(8),
|
|
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f } },
|
|
+ { AR5K_QUEUE_DFS_LOCAL_IFS(9),
|
|
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f } },
|
|
+ { AR5K_DCU_GBL_IFS_SLOT,
|
|
+ { 0x00000168, 0x000001e0, 0x000001b8 } },
|
|
+ { AR5K_DCU_GBL_IFS_SIFS,
|
|
+ { 0x00000230, 0x000001e0, 0x000000b0 } },
|
|
+ { AR5K_DCU_GBL_IFS_EIFS,
|
|
+ { 0x00000d98, 0x00001180, 0x00001f48 } },
|
|
+ { AR5K_DCU_GBL_IFS_MISC,
|
|
+ { 0x0000a0e0, 0x00014068, 0x00005880 } },
|
|
+ { AR5K_TIME_OUT,
|
|
+ { 0x04000400, 0x08000800, 0x20003000 } },
|
|
+ { AR5K_USEC_5211,
|
|
+ { 0x0e8d8fa7, 0x0e8d8fcf, 0x01608f95 } },
|
|
+ { AR5K_PHY_TURBO,
|
|
+ { 0x00000000, 0x00000003, 0x00000000 } },
|
|
+ { AR5K_PHY(8),
|
|
+ { 0x02020200, 0x02020200, 0x02010200 } },
|
|
+ { AR5K_PHY(9),
|
|
+ { 0x00000e0e, 0x00000e0e, 0x00000707 } },
|
|
+ { AR5K_PHY(10),
|
|
+ { 0x0a020001, 0x0a020001, 0x05010000 } },
|
|
+ { AR5K_PHY(13),
|
|
+ { 0x00000e0e, 0x00000e0e, 0x00000e0e } },
|
|
+ { AR5K_PHY(14),
|
|
+ { 0x00000007, 0x00000007, 0x0000000b } },
|
|
+ { AR5K_PHY(17),
|
|
+ { 0x1372169c, 0x137216a5, 0x137216a8 } },
|
|
+ { AR5K_PHY(18),
|
|
+ { 0x0018ba67, 0x0018ba67, 0x0018ba69 } },
|
|
+ { AR5K_PHY(20),
|
|
+ { 0x0c28b4e0, 0x0c28b4e0, 0x0c28b4e0 } },
|
|
+ { AR5K_PHY_SIG,
|
|
+ { 0x7e800d2e, 0x7e800d2e, 0x7ec00d2e } },
|
|
+ { AR5K_PHY_AGCCOARSE,
|
|
+ { 0x31375d5e, 0x31375d5e, 0x313a5d5e } },
|
|
+ { AR5K_PHY_AGCCTL,
|
|
+ { 0x0000bd10, 0x0000bd10, 0x0000bd38 } },
|
|
+ { AR5K_PHY_NF,
|
|
+ { 0x0001ce00, 0x0001ce00, 0x0001ce00 } },
|
|
+ { AR5K_PHY_RX_DELAY,
|
|
+ { 0x00002710, 0x00002710, 0x0000157c } },
|
|
+ { AR5K_PHY(70),
|
|
+ { 0x00000190, 0x00000190, 0x00000084 } },
|
|
+ { AR5K_PHY_FRAME_CTL_5211,
|
|
+ { 0x6fe01020, 0x6fe01020, 0x6fe00920 } },
|
|
+ { AR5K_PHY_PCDAC_TXPOWER_BASE_5211,
|
|
+ { 0x05ff14ff, 0x05ff14ff, 0x05ff14ff } },
|
|
+ { AR5K_RF_BUFFER_CONTROL_4,
|
|
+ { 0x00000010, 0x00000014, 0x00000010 } },
|
|
+};
|
|
+
|
|
+/* Initial register settings for AR5212 */
|
|
+static const struct ath5k_ini ar5212_ini[] = {
|
|
+ { AR5K_RXDP, 0x00000000 },
|
|
+ { AR5K_RXCFG, 0x00000005 },
|
|
+ { AR5K_MIBC, 0x00000000 },
|
|
+ { AR5K_TOPS, 0x00000008 },
|
|
+ { AR5K_RXNOFRM, 0x00000008 },
|
|
+ { AR5K_TXNOFRM, 0x00000010 },
|
|
+ { AR5K_RPGTO, 0x00000000 },
|
|
+ { AR5K_RFCNT, 0x0000001f },
|
|
+ { AR5K_QUEUE_TXDP(0), 0x00000000 },
|
|
+ { AR5K_QUEUE_TXDP(1), 0x00000000 },
|
|
+ { AR5K_QUEUE_TXDP(2), 0x00000000 },
|
|
+ { AR5K_QUEUE_TXDP(3), 0x00000000 },
|
|
+ { AR5K_QUEUE_TXDP(4), 0x00000000 },
|
|
+ { AR5K_QUEUE_TXDP(5), 0x00000000 },
|
|
+ { AR5K_QUEUE_TXDP(6), 0x00000000 },
|
|
+ { AR5K_QUEUE_TXDP(7), 0x00000000 },
|
|
+ { AR5K_QUEUE_TXDP(8), 0x00000000 },
|
|
+ { AR5K_QUEUE_TXDP(9), 0x00000000 },
|
|
+ { AR5K_DCU_FP, 0x00000000 },
|
|
+ { AR5K_DCU_TXP, 0x00000000 },
|
|
+ { AR5K_DCU_TX_FILTER, 0x00000000 },
|
|
+ /* Unknown table */
|
|
+ { 0x1078, 0x00000000 },
|
|
+ { 0x10b8, 0x00000000 },
|
|
+ { 0x10f8, 0x00000000 },
|
|
+ { 0x1138, 0x00000000 },
|
|
+ { 0x1178, 0x00000000 },
|
|
+ { 0x11b8, 0x00000000 },
|
|
+ { 0x11f8, 0x00000000 },
|
|
+ { 0x1238, 0x00000000 },
|
|
+ { 0x1278, 0x00000000 },
|
|
+ { 0x12b8, 0x00000000 },
|
|
+ { 0x12f8, 0x00000000 },
|
|
+ { 0x1338, 0x00000000 },
|
|
+ { 0x1378, 0x00000000 },
|
|
+ { 0x13b8, 0x00000000 },
|
|
+ { 0x13f8, 0x00000000 },
|
|
+ { 0x1438, 0x00000000 },
|
|
+ { 0x1478, 0x00000000 },
|
|
+ { 0x14b8, 0x00000000 },
|
|
+ { 0x14f8, 0x00000000 },
|
|
+ { 0x1538, 0x00000000 },
|
|
+ { 0x1578, 0x00000000 },
|
|
+ { 0x15b8, 0x00000000 },
|
|
+ { 0x15f8, 0x00000000 },
|
|
+ { 0x1638, 0x00000000 },
|
|
+ { 0x1678, 0x00000000 },
|
|
+ { 0x16b8, 0x00000000 },
|
|
+ { 0x16f8, 0x00000000 },
|
|
+ { 0x1738, 0x00000000 },
|
|
+ { 0x1778, 0x00000000 },
|
|
+ { 0x17b8, 0x00000000 },
|
|
+ { 0x17f8, 0x00000000 },
|
|
+ { 0x103c, 0x00000000 },
|
|
+ { 0x107c, 0x00000000 },
|
|
+ { 0x10bc, 0x00000000 },
|
|
+ { 0x10fc, 0x00000000 },
|
|
+ { 0x113c, 0x00000000 },
|
|
+ { 0x117c, 0x00000000 },
|
|
+ { 0x11bc, 0x00000000 },
|
|
+ { 0x11fc, 0x00000000 },
|
|
+ { 0x123c, 0x00000000 },
|
|
+ { 0x127c, 0x00000000 },
|
|
+ { 0x12bc, 0x00000000 },
|
|
+ { 0x12fc, 0x00000000 },
|
|
+ { 0x133c, 0x00000000 },
|
|
+ { 0x137c, 0x00000000 },
|
|
+ { 0x13bc, 0x00000000 },
|
|
+ { 0x13fc, 0x00000000 },
|
|
+ { 0x143c, 0x00000000 },
|
|
+ { 0x147c, 0x00000000 },
|
|
+ { AR5K_DCU_TX_FILTER_CLR, 0x00000000 },
|
|
+ { AR5K_DCU_TX_FILTER_SET, 0x00000000 },
|
|
+ { AR5K_STA_ID1, 0x00000000 },
|
|
+ { AR5K_BSS_ID0, 0x00000000 },
|
|
+ { AR5K_BSS_ID1, 0x00000000 },
|
|
+ /*{ AR5K_RSSI_THR, 0x00000000 },*/ /* Found on SuperAG cards */
|
|
+ { AR5K_BEACON_5211, 0x00000000 }, /* Found on SuperAG cards */
|
|
+ { AR5K_CFP_PERIOD_5211, 0x00000000 }, /* Found on SuperAG cards */
|
|
+ { AR5K_TIMER0_5211, 0x00000030 }, /* Found on SuperAG cards */
|
|
+ { AR5K_TIMER1_5211, 0x0007ffff }, /* Found on SuperAG cards */
|
|
+ { AR5K_TIMER2_5211, 0x01ffffff }, /* Found on SuperAG cards */
|
|
+ { AR5K_TIMER3_5211, 0x00000031 }, /* Found on SuperAG cards */
|
|
+ { AR5K_CFP_DUR_5211, 0x00000000 }, /* Found on SuperAG cards */
|
|
+ { AR5K_RX_FILTER_5211, 0x00000000 },
|
|
+ { AR5K_DIAG_SW_5211, 0x00000000 },
|
|
+ { AR5K_ADDAC_TEST, 0x00000000 },
|
|
+ { AR5K_DEFAULT_ANTENNA, 0x00000000 },
|
|
+ { 0x8080, 0x00000000 },
|
|
+ /*{ 0x805c, 0xffffc7ff },*/ /* Old value */
|
|
+ { 0x805c, 0x000fc78f },
|
|
+ { AR5K_NAV_5211, 0x00000000 }, /* Not found on recent */
|
|
+ { AR5K_RTS_OK_5211, 0x00000000 }, /* dumps but it makes */
|
|
+ { AR5K_RTS_FAIL_5211, 0x00000000 }, /* sense to reset counters */
|
|
+ { AR5K_ACK_FAIL_5211, 0x00000000 }, /* since pcu registers */
|
|
+ { AR5K_FCS_FAIL_5211, 0x00000000 }, /* are skiped during chan*/
|
|
+ { AR5K_BEACON_CNT_5211, 0x00000000 }, /* change */
|
|
+ { AR5K_XRMODE, 0x2a82301a },
|
|
+ { AR5K_XRDELAY, 0x05dc01e0 },
|
|
+ { AR5K_XRTIMEOUT, 0x1f402710 },
|
|
+ { AR5K_XRCHIRP, 0x01f40000 },
|
|
+ { AR5K_XRSTOMP, 0x00001e1c },
|
|
+ { AR5K_SLEEP0, 0x0002aaaa }, /* Found on SuperAG cards */
|
|
+ { AR5K_SLEEP1, 0x02005555 }, /* Found on SuperAG cards */
|
|
+ { AR5K_SLEEP2, 0x00000000 }, /* Found on SuperAG cards */
|
|
+ { AR5K_BSS_IDM0, 0xffffffff },
|
|
+ { AR5K_BSS_IDM1, 0x0000ffff },
|
|
+ { AR5K_TXPC, 0x00000000 },
|
|
+ { AR5K_PROFCNT_TX, 0x00000000 },
|
|
+ { AR5K_PROFCNT_RX, 0x00000000 },
|
|
+ { AR5K_PROFCNT_RXCLR, 0x00000000 },
|
|
+ { AR5K_PROFCNT_CYCLE, 0x00000000 },
|
|
+ { 0x80fc, 0x00000088 },
|
|
+ { AR5K_RATE_DUR(0), 0x00000000 },
|
|
+ { AR5K_RATE_DUR(1), 0x0000008c },
|
|
+ { AR5K_RATE_DUR(2), 0x000000e4 },
|
|
+ { AR5K_RATE_DUR(3), 0x000002d5 },
|
|
+ { AR5K_RATE_DUR(4), 0x00000000 },
|
|
+ { AR5K_RATE_DUR(5), 0x00000000 },
|
|
+ { AR5K_RATE_DUR(6), 0x000000a0 },
|
|
+ { AR5K_RATE_DUR(7), 0x000001c9 },
|
|
+ { AR5K_RATE_DUR(8), 0x0000002c },
|
|
+ { AR5K_RATE_DUR(9), 0x0000002c },
|
|
+ { AR5K_RATE_DUR(10), 0x00000030 },
|
|
+ { AR5K_RATE_DUR(11), 0x0000003c },
|
|
+ { AR5K_RATE_DUR(12), 0x0000002c },
|
|
+ { AR5K_RATE_DUR(13), 0x0000002c },
|
|
+ { AR5K_RATE_DUR(14), 0x00000030 },
|
|
+ { AR5K_RATE_DUR(15), 0x0000003c },
|
|
+ { AR5K_RATE_DUR(16), 0x00000000 },
|
|
+ { AR5K_RATE_DUR(17), 0x00000000 },
|
|
+ { AR5K_RATE_DUR(18), 0x00000000 },
|
|
+ { AR5K_RATE_DUR(19), 0x00000000 },
|
|
+ { AR5K_RATE_DUR(20), 0x00000000 },
|
|
+ { AR5K_RATE_DUR(21), 0x00000000 },
|
|
+ { AR5K_RATE_DUR(22), 0x00000000 },
|
|
+ { AR5K_RATE_DUR(23), 0x00000000 },
|
|
+ { AR5K_RATE_DUR(24), 0x000000d5 },
|
|
+ { AR5K_RATE_DUR(25), 0x000000df },
|
|
+ { AR5K_RATE_DUR(26), 0x00000102 },
|
|
+ { AR5K_RATE_DUR(27), 0x0000013a },
|
|
+ { AR5K_RATE_DUR(28), 0x00000075 },
|
|
+ { AR5K_RATE_DUR(29), 0x0000007f },
|
|
+ { AR5K_RATE_DUR(30), 0x000000a2 },
|
|
+ { AR5K_RATE_DUR(31), 0x00000000 },
|
|
+ { 0x8100, 0x00010002},
|
|
+ { AR5K_TSF_PARM, 0x00000001 },
|
|
+ { 0x8108, 0x000000c0 },
|
|
+ { AR5K_PHY_ERR_FIL, 0x00000000 },
|
|
+ { 0x8110, 0x00000168 },
|
|
+ { 0x8114, 0x00000000 },
|
|
+ /* Some kind of table
|
|
+ * also notice ...03<-02<-01<-00) */
|
|
+ { 0x87c0, 0x03020100 },
|
|
+ { 0x87c4, 0x07060504 },
|
|
+ { 0x87c8, 0x0b0a0908 },
|
|
+ { 0x87cc, 0x0f0e0d0c },
|
|
+ { 0x87d0, 0x13121110 },
|
|
+ { 0x87d4, 0x17161514 },
|
|
+ { 0x87d8, 0x1b1a1918 },
|
|
+ { 0x87dc, 0x1f1e1d1c },
|
|
+ /* loop ? */
|
|
+ { 0x87e0, 0x03020100 },
|
|
+ { 0x87e4, 0x07060504 },
|
|
+ { 0x87e8, 0x0b0a0908 },
|
|
+ { 0x87ec, 0x0f0e0d0c },
|
|
+ { 0x87f0, 0x13121110 },
|
|
+ { 0x87f4, 0x17161514 },
|
|
+ { 0x87f8, 0x1b1a1918 },
|
|
+ { 0x87fc, 0x1f1e1d1c },
|
|
+ /* PHY registers */
|
|
+ /*{ AR5K_PHY_AGC, 0x00000000 },*/
|
|
+ { AR5K_PHY(3), 0xad848e19 },
|
|
+ { AR5K_PHY(4), 0x7d28e000 },
|
|
+ { AR5K_PHY_TIMING_3, 0x9c0a9f6b },
|
|
+ { AR5K_PHY_ACT, 0x00000000 },
|
|
+ /*{ AR5K_PHY(11), 0x00022ffe },*/
|
|
+ /*{ AR5K_PHY(15), 0x00020100 },*/
|
|
+ { AR5K_PHY(16), 0x206a017a },
|
|
+ /*{ AR5K_PHY(19), 0x1284613c },*/
|
|
+ { AR5K_PHY(21), 0x00000859 },
|
|
+ { AR5K_PHY(64), 0x00000000 },
|
|
+ { AR5K_PHY(65), 0x00000000 },
|
|
+ { AR5K_PHY(66), 0x00000000 },
|
|
+ { AR5K_PHY(67), 0x00800000 },
|
|
+ { AR5K_PHY(68), 0x00000001 },
|
|
+ /*{ AR5K_PHY(71), 0x0000092a },*/ /* Old value */
|
|
+ { AR5K_PHY(71), 0x00000c80 },
|
|
+ { AR5K_PHY_IQ, 0x05100000 },
|
|
+ { AR5K_PHY(74), 0x00000001 },
|
|
+ { AR5K_PHY(75), 0x00000004 },
|
|
+ { AR5K_PHY_TXPOWER_RATE1, 0x1e1f2022 },
|
|
+ { AR5K_PHY_TXPOWER_RATE2, 0x0a0b0c0d },
|
|
+ { AR5K_PHY_TXPOWER_RATE_MAX, 0x0000003f },
|
|
+ /*{ AR5K_PHY(80), 0x00000004 },*/
|
|
+ { AR5K_PHY(82), 0x9280b212 },
|
|
+ { AR5K_PHY_RADAR, 0x5d50e188 },
|
|
+ /*{ AR5K_PHY(86), 0x000000ff },*/
|
|
+ { AR5K_PHY(87), 0x004b6a8e },
|
|
+ { AR5K_PHY(90), 0x000003ce },
|
|
+ { AR5K_PHY(92), 0x192fb515 },
|
|
+ /*{ AR5K_PHY(93), 0x00000000 },*/
|
|
+ { AR5K_PHY(94), 0x00000001 },
|
|
+ { AR5K_PHY(95), 0x00000000 },
|
|
+ /*{ AR5K_PHY(644), 0x0080a333 },*/ /* Old value */
|
|
+ /*{ AR5K_PHY(645), 0x00206c10 },*/ /* Old value */
|
|
+ { AR5K_PHY(644), 0x00806333 },
|
|
+ { AR5K_PHY(645), 0x00106c10 },
|
|
+ { AR5K_PHY(646), 0x009c4060 },
|
|
+ /*{ AR5K_PHY(647), 0x1483800a },*/ /* Old value */
|
|
+ { AR5K_PHY(647), 0x1483800a },
|
|
+ { AR5K_PHY(648), 0x01831061 },
|
|
+ { AR5K_PHY(649), 0x00000400 },
|
|
+ /*{ AR5K_PHY(650), 0x000001b5 },*/
|
|
+ { AR5K_PHY(651), 0x00000000 },
|
|
+ { AR5K_PHY_TXPOWER_RATE3, 0x20202020 },
|
|
+ { AR5K_PHY_TXPOWER_RATE2, 0x20202020 },
|
|
+ /*{ AR5K_PHY(655), 0x13c889af },*/
|
|
+ { AR5K_PHY(656), 0x38490a20 },
|
|
+ { AR5K_PHY(657), 0x00007bb6 },
|
|
+ { AR5K_PHY(658), 0x0fff3ffc },
|
|
+ /*{ AR5K_PHY_CCKTXCTL, 0x00000000 },*/
|
|
+};
|
|
+
|
|
+/* Initial mode-specific settings for AR5212 (Written before ar5212_ini) */
|
|
+static const struct ath5k_ini_mode ar5212_ini_mode_start[] = {
|
|
+ { AR5K_PHY(640),
|
|
+ /* a/XR aTurbo b g (DYN) gTurbo */
|
|
+ { 0x00000008, 0x00000008, 0x0000000b, 0x0000000e, 0x0000000e } },
|
|
+ { AR5K_PHY(0),
|
|
+ { 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 } },
|
|
+ { AR5K_QUEUE_DFS_LOCAL_IFS(0),
|
|
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
|
|
+ { AR5K_QUEUE_DFS_LOCAL_IFS(1),
|
|
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
|
|
+ { AR5K_QUEUE_DFS_LOCAL_IFS(2),
|
|
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
|
|
+ { AR5K_QUEUE_DFS_LOCAL_IFS(3),
|
|
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
|
|
+ { AR5K_QUEUE_DFS_LOCAL_IFS(4),
|
|
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
|
|
+ { AR5K_QUEUE_DFS_LOCAL_IFS(5),
|
|
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
|
|
+ { AR5K_QUEUE_DFS_LOCAL_IFS(6),
|
|
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
|
|
+ { AR5K_QUEUE_DFS_LOCAL_IFS(7),
|
|
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
|
|
+ { AR5K_QUEUE_DFS_LOCAL_IFS(8),
|
|
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
|
|
+ { AR5K_QUEUE_DFS_LOCAL_IFS(9),
|
|
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
|
|
+ { AR5K_DCU_GBL_IFS_SIFS,
|
|
+ { 0x00000230, 0x000001e0, 0x000000b0, 0x00000160, 0x000001e0 } },
|
|
+ { AR5K_DCU_GBL_IFS_SLOT,
|
|
+ { 0x00000168, 0x000001e0, 0x000001b8, 0x0000018c, 0x000001e0 } },
|
|
+ { AR5K_DCU_GBL_IFS_EIFS,
|
|
+ { 0x00000e60, 0x00001180, 0x00001f1c, 0x00003e38, 0x00001180 } },
|
|
+ { AR5K_DCU_GBL_IFS_MISC,
|
|
+ { 0x0000a0e0, 0x00014068, 0x00005880, 0x0000b0e0, 0x00014068 } },
|
|
+ { AR5K_TIME_OUT,
|
|
+ { 0x03e803e8, 0x06e006e0, 0x04200420, 0x08400840, 0x06e006e0 } },
|
|
+ { AR5K_PHY_TURBO,
|
|
+ { 0x00000000, 0x00000003, 0x00000000, 0x00000000, 0x00000003 } },
|
|
+ { AR5K_PHY(8),
|
|
+ { 0x02020200, 0x02020200, 0x02010200, 0x02020200, 0x02020200 } },
|
|
+ { AR5K_PHY(9),
|
|
+ { 0x00000e0e, 0x00000e0e, 0x00000707, 0x00000e0e, 0x00000e0e } },
|
|
+ { AR5K_PHY(17),
|
|
+ { 0x1372161c, 0x13721c25, 0x13721722, 0x137216a2, 0x13721c25 } },
|
|
+ { AR5K_PHY_AGCCTL,
|
|
+ { 0x00009d10, 0x00009d10, 0x00009d18, 0x00009d18, 0x00009d18 } },
|
|
+ { AR5K_PHY_NF,
|
|
+ { 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 } },
|
|
+ { AR5K_PHY(26),
|
|
+ { 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190 } },
|
|
+ { AR5K_PHY(70),
|
|
+ { 0x000001b8, 0x000001b8, 0x00000084, 0x00000108, 0x000001b8 } },
|
|
+ { AR5K_PHY(73),
|
|
+ { 0x10058a05, 0x10058a05, 0x10058a05, 0x10058a05, 0x10058a05 } },
|
|
+ { 0xa230,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000108, 0x00000000 } },
|
|
+};
|
|
+
|
|
+/* Initial mode-specific settings for AR5212 + RF5111 (Written after ar5212_ini) */
|
|
+/* New dump pending */
|
|
+static const struct ath5k_ini_mode ar5212_rf5111_ini_mode_end[] = {
|
|
+ { AR5K_PHY(640), /* This one differs from ar5212_ini_mode_start ! */
|
|
+ /* a/XR aTurbo b g (DYN) gTurbo */
|
|
+ { 0x00000000, 0x00000000, 0x00000003, 0x00000006, 0x00000006 } },
|
|
+ { AR5K_TXCFG,
|
|
+ { 0x00008015, 0x00008015, 0x00008015, 0x00008015, 0x00008015 } },
|
|
+ { AR5K_USEC_5211,
|
|
+ { 0x128d8fa7, 0x09880fcf, 0x04e00f95, 0x12e00fab, 0x09880fcf } },
|
|
+ { AR5K_PHY(10),
|
|
+ { 0x0a020001, 0x0a020001, 0x05010100, 0x0a020001, 0x0a020001 } },
|
|
+ { AR5K_PHY(13),
|
|
+ { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } },
|
|
+ { AR5K_PHY(14),
|
|
+ { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b } },
|
|
+ { AR5K_PHY(18),
|
|
+ { 0x0018da5a, 0x0018da5a, 0x0018ca69, 0x0018ca69, 0x0018ca69 } },
|
|
+ { AR5K_PHY(20),
|
|
+ { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0 } },
|
|
+ { AR5K_PHY_SIG,
|
|
+ { 0x7e800d2e, 0x7e800d2e, 0x7ee84d2e, 0x7ee84d2e, 0x7e800d2e } },
|
|
+ { AR5K_PHY_AGCCOARSE,
|
|
+ { 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e, 0x3137615e } },
|
|
+ { AR5K_PHY(27),
|
|
+ { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb080, 0x050cb080 } },
|
|
+ { AR5K_PHY_RX_DELAY,
|
|
+ { 0x00002710, 0x00002710, 0x0000157c, 0x00002af8, 0x00002710 } },
|
|
+ { AR5K_PHY_FRAME_CTL_5211,
|
|
+ { 0xf7b81020, 0xf7b81020, 0xf7b80d20, 0xf7b81020, 0xf7b81020 } },
|
|
+ { AR5K_PHY_GAIN_2GHZ,
|
|
+ { 0x642c416a, 0x642c416a, 0x6440416a, 0x6440416a, 0x6440416a } },
|
|
+ { 0xa21c,
|
|
+ { 0x1883800a, 0x1883800a, 0x1873800a, 0x1883800a, 0x1883800a } },
|
|
+ { AR5K_DCU_FP,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { AR5K_PHY_AGC,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { AR5K_PHY(11),
|
|
+ { 0x00022ffe, 0x00022ffe, 0x00022ffe, 0x00022ffe, 0x00022ffe } },
|
|
+ { AR5K_PHY(15),
|
|
+ { 0x00020100, 0x00020100, 0x00020100, 0x00020100, 0x00020100 } },
|
|
+ { AR5K_PHY(19),
|
|
+ { 0x1284613c, 0x1284613c, 0x1284613c, 0x1284613c, 0x1284613c } },
|
|
+ { AR5K_PHY_PAPD_PROBE,
|
|
+ { 0x00004883, 0x00004883, 0x00004883, 0x00004883, 0x00004883 } },
|
|
+ { AR5K_PHY(80),
|
|
+ { 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x00000004 } },
|
|
+ { AR5K_PHY(86),
|
|
+ { 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff } },
|
|
+ { AR5K_PHY(93),
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { AR5K_PHY_SPENDING,
|
|
+ { 0x00000018, 0x00000018, 0x00000018, 0x00000018, 0x00000018 } },
|
|
+ { AR5K_PHY_CCKTXCTL,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { AR5K_PHY(642),
|
|
+ { 0xd03e6788, 0xd03e6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } },
|
|
+ { 0xa23c,
|
|
+ { 0x13c889af, 0x13c889af, 0x13c889af, 0x13c889af, 0x13c889af } },
|
|
+};
|
|
+
|
|
+/* Initial mode-specific settings for AR5212 + RF5112 (Written after ar5212_ini) */
|
|
+/* XXX: No dumps for turbog yet, but i found settings from old values so it should be ok */
|
|
+static const struct ath5k_ini_mode ar5212_rf5112_ini_mode_end[] = {
|
|
+ { AR5K_TXCFG,
|
|
+ /* a/XR aTurbo b g (DYN) gTurbo */
|
|
+ { 0x00008015, 0x00008015, 0x00008015, 0x00008015, 0x00008015 } },
|
|
+ { AR5K_USEC_5211,
|
|
+ { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } },
|
|
+ { AR5K_PHY(10),
|
|
+ { 0x0a020001, 0x0a020001, 0x05020100, 0x0a020001, 0x0a020001 } },
|
|
+ { AR5K_PHY(13),
|
|
+ { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } },
|
|
+ { AR5K_PHY(14),
|
|
+ { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b } },
|
|
+ { AR5K_PHY(18),
|
|
+ { 0x0018da6d, 0x0018da6d, 0x0018ca75, 0x0018ca75, 0x0018ca75 } },
|
|
+ { AR5K_PHY(20),
|
|
+ { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0 } },
|
|
+ { AR5K_PHY_SIG,
|
|
+ { 0x7e800d2e, 0x7e800d2e, 0x7ee80d2e, 0x7ee80d2e, 0x7ee80d2e } },
|
|
+ { AR5K_PHY_AGCCOARSE,
|
|
+ { 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e } },
|
|
+ { AR5K_PHY(27),
|
|
+ { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } },
|
|
+ { AR5K_PHY_RX_DELAY,
|
|
+ { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } },
|
|
+ { AR5K_PHY_FRAME_CTL_5211,
|
|
+ { 0xf7b81020, 0xf7b81020, 0xf7b80d10, 0xf7b81010, 0xf7b81010 } },
|
|
+ { AR5K_PHY_CCKTXCTL,
|
|
+ { 0x00000000, 0x00000000, 0x00000008, 0x00000008, 0x00000008 } },
|
|
+ { AR5K_PHY(642),
|
|
+ { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } },
|
|
+ { AR5K_PHY_GAIN_2GHZ,
|
|
+ { 0x642c0140, 0x642c0140, 0x6442c160, 0x6442c160, 0x6442c160 } },
|
|
+ { 0xa21c,
|
|
+ { 0x1883800a, 0x1883800a, 0x1873800a, 0x1883800a, 0x1883800a } },
|
|
+ { AR5K_DCU_FP,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { AR5K_PHY_AGC,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { AR5K_PHY(11),
|
|
+ { 0x00022ffe, 0x00022ffe, 0x00022ffe, 0x00022ffe, 0x00022ffe } },
|
|
+ { AR5K_PHY(15),
|
|
+ { 0x00020100, 0x00020100, 0x00020100, 0x00020100, 0x00020100 } },
|
|
+ { AR5K_PHY(19),
|
|
+ { 0x1284613c, 0x1284613c, 0x1284613c, 0x1284613c, 0x1284613c } },
|
|
+ { AR5K_PHY_PAPD_PROBE,
|
|
+ { 0x00004882, 0x00004882, 0x00004882, 0x00004882, 0x00004882 } },
|
|
+ { AR5K_PHY(80),
|
|
+ { 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x00000004 } },
|
|
+ { AR5K_PHY(86),
|
|
+ { 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff } },
|
|
+ { AR5K_PHY(93),
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 0xa228,
|
|
+ { 0x000001b5, 0x000001b5, 0x000001b5, 0x000001b5, 0x000001b5 } },
|
|
+ { 0xa23c,
|
|
+ { 0x13c889af, 0x13c889af, 0x13c889af, 0x13c889af, 0x13c889af } },
|
|
+};
|
|
+
|
|
+/* Initial mode-specific settings for RF5413/5414 (Written after ar5212_ini) */
|
|
+/* XXX: No dumps for turbog yet, so turbog is the same with g here with some
|
|
+ * minor tweaking based on dumps from other chips */
|
|
+static const struct ath5k_ini_mode rf5413_ini_mode_end[] = {
|
|
+ { AR5K_TXCFG,
|
|
+ /* a/XR aTurbo b g gTurbo */
|
|
+ { 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0x00000015 } },
|
|
+ { AR5K_USEC_5211,
|
|
+ { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } },
|
|
+ { AR5K_PHY(10),
|
|
+ { 0x0a020001, 0x0a020001, 0x05020100, 0x0a020001, 0x0a020001 } },
|
|
+ { AR5K_PHY(13),
|
|
+ { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } },
|
|
+ { AR5K_PHY(14),
|
|
+ { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b } },
|
|
+ { AR5K_PHY(18),
|
|
+ { 0x0018fa61, 0x0018fa61, 0x001a1a63, 0x001a1a63, 0x001a1a63 } },
|
|
+ { AR5K_PHY(20),
|
|
+ { 0x0c98b4e0, 0x0c98b4e0, 0x0c98b0da, 0x0c98b0da, 0x0c98b0da } },
|
|
+ { AR5K_PHY_SIG,
|
|
+ { 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e } },
|
|
+ { AR5K_PHY_AGCCOARSE,
|
|
+ { 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e } },
|
|
+ { AR5K_PHY(27),
|
|
+ { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } },
|
|
+ { AR5K_PHY_RX_DELAY,
|
|
+ { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } },
|
|
+ { AR5K_PHY_FRAME_CTL_5211,
|
|
+ { 0xf7b81000, 0xf7b81000, 0xf7b80d00, 0xf7b81000, 0xf7b81000 } },
|
|
+ { AR5K_PHY_CCKTXCTL,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { AR5K_PHY(642),
|
|
+ { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } },
|
|
+ { AR5K_PHY_GAIN_2GHZ,
|
|
+ { 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 } },
|
|
+ { 0xa21c,
|
|
+ { 0x1883800a, 0x1883800a, 0x1863800a, 0x1883800a, 0x1883800a } },
|
|
+ { 0xa300,
|
|
+ { 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 } },
|
|
+ { 0xa304,
|
|
+ { 0x30032602, 0x30032602, 0x30032602, 0x30032602, 0x30032602 } },
|
|
+ { 0xa308,
|
|
+ { 0x48073e06, 0x48073e06, 0x48073e06, 0x48073e06, 0x48073e06 } },
|
|
+ { 0xa30c,
|
|
+ { 0x560b4c0a, 0x560b4c0a, 0x560b4c0a, 0x560b4c0a, 0x560b4c0a } },
|
|
+ { 0xa310,
|
|
+ { 0x641a600f, 0x641a600f, 0x641a600f, 0x641a600f, 0x641a600f } },
|
|
+ { 0xa314,
|
|
+ { 0x784f6e1b, 0x784f6e1b, 0x784f6e1b, 0x784f6e1b, 0x784f6e1b } },
|
|
+ { 0xa318,
|
|
+ { 0x868f7c5a, 0x868f7c5a, 0x868f7c5a, 0x868f7c5a, 0x868f7c5a } },
|
|
+ { 0xa31c,
|
|
+ { 0x90cf865b, 0x90cf865b, 0x8ecf865b, 0x8ecf865b, 0x8ecf865b } },
|
|
+ { 0xa320,
|
|
+ { 0x9d4f970f, 0x9d4f970f, 0x9b4f970f, 0x9b4f970f, 0x9b4f970f } },
|
|
+ { 0xa324,
|
|
+ { 0xa7cfa38f, 0xa7cfa38f, 0xa3cf9f8f, 0xa3cf9f8f, 0xa3cf9f8f } },
|
|
+ { 0xa328,
|
|
+ { 0xb55faf1f, 0xb55faf1f, 0xb35faf1f, 0xb35faf1f, 0xb35faf1f } },
|
|
+ { 0xa32c,
|
|
+ { 0xbddfb99f, 0xbddfb99f, 0xbbdfb99f, 0xbbdfb99f, 0xbbdfb99f } },
|
|
+ { 0xa330,
|
|
+ { 0xcb7fc53f, 0xcb7fc53f, 0xcb7fc73f, 0xcb7fc73f, 0xcb7fc73f } },
|
|
+ { 0xa334,
|
|
+ { 0xd5ffd1bf, 0xd5ffd1bf, 0xd3ffd1bf, 0xd3ffd1bf, 0xd3ffd1bf } },
|
|
+ { AR5K_DCU_FP,
|
|
+ { 0x000003e0, 0x000003e0, 0x000003e0, 0x000003e0, 0x000003e0 } },
|
|
+ { 0x4068,
|
|
+ { 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 } },
|
|
+ { 0x8060,
|
|
+ { 0x0000000f, 0x0000000f, 0x0000000f, 0x0000000f, 0x0000000f } },
|
|
+ { 0x809c,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 0x80a0,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 0x8118,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 0x811c,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 0x8120,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 0x8124,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 0x8128,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 0x812c,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 0x8130,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 0x8134,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 0x8138,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 0x813c,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 0x8140,
|
|
+ { 0x800003f9, 0x800003f9, 0x800003f9, 0x800003f9, 0x800003f9 } },
|
|
+ { 0x8144,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { AR5K_PHY_AGC,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { AR5K_PHY(11),
|
|
+ { 0x0000a000, 0x0000a000, 0x0000a000, 0x0000a000, 0x0000a000 } },
|
|
+ { AR5K_PHY(15),
|
|
+ { 0x00200400, 0x00200400, 0x00200400, 0x00200400, 0x00200400 } },
|
|
+ { AR5K_PHY(19),
|
|
+ { 0x1284233c, 0x1284233c, 0x1284233c, 0x1284233c, 0x1284233c } },
|
|
+ { AR5K_PHY_SCR,
|
|
+ { 0x0000001f, 0x0000001f, 0x0000001f, 0x0000001f, 0x0000001f } },
|
|
+ { AR5K_PHY_SLMT,
|
|
+ { 0x00000080, 0x00000080, 0x00000080, 0x00000080, 0x00000080 } },
|
|
+ { AR5K_PHY_SCAL,
|
|
+ { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } },
|
|
+ { AR5K_PHY(86),
|
|
+ { 0x00081fff, 0x00081fff, 0x00081fff, 0x00081fff, 0x00081fff } },
|
|
+ { AR5K_PHY(96),
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { AR5K_PHY(97),
|
|
+ { 0x02800000, 0x02800000, 0x02800000, 0x02800000, 0x02800000 } },
|
|
+ { AR5K_PHY(104),
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { AR5K_PHY(120),
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { AR5K_PHY(121),
|
|
+ { 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa } },
|
|
+ { AR5K_PHY(122),
|
|
+ { 0x3c466478, 0x3c466478, 0x3c466478, 0x3c466478, 0x3c466478 } },
|
|
+ { AR5K_PHY(123),
|
|
+ { 0x000000aa, 0x000000aa, 0x000000aa, 0x000000aa, 0x000000aa } },
|
|
+ { AR5K_PHY_SCLOCK,
|
|
+ { 0x0000000c, 0x0000000c, 0x0000000c, 0x0000000c, 0x0000000c } },
|
|
+ { AR5K_PHY_SDELAY,
|
|
+ { 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff } },
|
|
+ { AR5K_PHY_SPENDING,
|
|
+ { 0x00000014, 0x00000014, 0x00000014, 0x00000014, 0x00000014 } },
|
|
+ { 0xa228,
|
|
+ { 0x000009b5, 0x000009b5, 0x000009b5, 0x000009b5, 0x000009b5 } },
|
|
+ { 0xa23c,
|
|
+ { 0x93c889af, 0x93c889af, 0x93c889af, 0x93c889af, 0x93c889af } },
|
|
+ { 0xa24c,
|
|
+ { 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 } },
|
|
+ { 0xa250,
|
|
+ { 0x0000a000, 0x0000a000, 0x0000a000, 0x0000a000, 0x0000a000 } },
|
|
+ { 0xa254,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 0xa258,
|
|
+ { 0x0cc75380, 0x0cc75380, 0x0cc75380, 0x0cc75380, 0x0cc75380 } },
|
|
+ { 0xa25c,
|
|
+ { 0x0f0f0f01, 0x0f0f0f01, 0x0f0f0f01, 0x0f0f0f01, 0x0f0f0f01 } },
|
|
+ { 0xa260,
|
|
+ { 0x5f690f01, 0x5f690f01, 0x5f690f01, 0x5f690f01, 0x5f690f01 } },
|
|
+ { 0xa264,
|
|
+ { 0x00418a11, 0x00418a11, 0x00418a11, 0x00418a11, 0x00418a11 } },
|
|
+ { 0xa268,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 0xa26c,
|
|
+ { 0x0c30c16a, 0x0c30c16a, 0x0c30c16a, 0x0c30c16a, 0x0c30c16a } },
|
|
+ { 0xa270,
|
|
+ { 0x00820820, 0x00820820, 0x00820820, 0x00820820, 0x00820820 } },
|
|
+ { 0xa274,
|
|
+ { 0x081b7caa, 0x081b7caa, 0x081b7caa, 0x081b7caa, 0x081b7caa } },
|
|
+ { 0xa278,
|
|
+ { 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce } },
|
|
+ { 0xa27c,
|
|
+ { 0x051701ce, 0x051701ce, 0x051701ce, 0x051701ce, 0x051701ce } },
|
|
+ { 0xa338,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 0xa33c,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 0xa340,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 0xa344,
|
|
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
|
|
+ { 0xa348,
|
|
+ { 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff } },
|
|
+ { 0xa34c,
|
|
+ { 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff } },
|
|
+ { 0xa350,
|
|
+ { 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff } },
|
|
+ { 0xa354,
|
|
+ { 0x0003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff } },
|
|
+ { 0xa358,
|
|
+ { 0x79a8aa1f, 0x79a8aa1f, 0x79a8aa1f, 0x79a8aa1f, 0x79a8aa1f } },
|
|
+ { 0xa35c,
|
|
+ { 0x066c420f, 0x066c420f, 0x066c420f, 0x066c420f, 0x066c420f } },
|
|
+ { 0xa360,
|
|
+ { 0x0f282207, 0x0f282207, 0x0f282207, 0x0f282207, 0x0f282207 } },
|
|
+ { 0xa364,
|
|
+ { 0x17601685, 0x17601685, 0x17601685, 0x17601685, 0x17601685 } },
|
|
+ { 0xa368,
|
|
+ { 0x1f801104, 0x1f801104, 0x1f801104, 0x1f801104, 0x1f801104 } },
|
|
+ { 0xa36c,
|
|
+ { 0x37a00c03, 0x37a00c03, 0x37a00c03, 0x37a00c03, 0x37a00c03 } },
|
|
+ { 0xa370,
|
|
+ { 0x3fc40883, 0x3fc40883, 0x3fc40883, 0x3fc40883, 0x3fc40883 } },
|
|
+ { 0xa374,
|
|
+ { 0x57c00803, 0x57c00803, 0x57c00803, 0x57c00803, 0x57c00803 } },
|
|
+ { 0xa378,
|
|
+ { 0x5fd80682, 0x5fd80682, 0x5fd80682, 0x5fd80682, 0x5fd80682 } },
|
|
+ { 0xa37c,
|
|
+ { 0x7fe00482, 0x7fe00482, 0x7fe00482, 0x7fe00482, 0x7fe00482 } },
|
|
+ { 0xa380,
|
|
+ { 0x7f3c7bba, 0x7f3c7bba, 0x7f3c7bba, 0x7f3c7bba, 0x7f3c7bba } },
|
|
+ { 0xa384,
|
|
+ { 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0 } },
|
|
+};
|
|
+
|
|
+/*
|
|
+ * Initial BaseBand Gain settings for RF5111/5112 (AR5210 comes with
|
|
+ * RF5110 only so initial BB Gain settings are included in AR5K_AR5210_INI)
|
|
+ */
|
|
+
|
|
+/* RF5111 Initial BaseBand Gain settings */
|
|
+static const struct ath5k_ini rf5111_ini_bbgain[] = {
|
|
+ { AR5K_BB_GAIN(0), 0x00000000 },
|
|
+ { AR5K_BB_GAIN(1), 0x00000020 },
|
|
+ { AR5K_BB_GAIN(2), 0x00000010 },
|
|
+ { AR5K_BB_GAIN(3), 0x00000030 },
|
|
+ { AR5K_BB_GAIN(4), 0x00000008 },
|
|
+ { AR5K_BB_GAIN(5), 0x00000028 },
|
|
+ { AR5K_BB_GAIN(6), 0x00000004 },
|
|
+ { AR5K_BB_GAIN(7), 0x00000024 },
|
|
+ { AR5K_BB_GAIN(8), 0x00000014 },
|
|
+ { AR5K_BB_GAIN(9), 0x00000034 },
|
|
+ { AR5K_BB_GAIN(10), 0x0000000c },
|
|
+ { AR5K_BB_GAIN(11), 0x0000002c },
|
|
+ { AR5K_BB_GAIN(12), 0x00000002 },
|
|
+ { AR5K_BB_GAIN(13), 0x00000022 },
|
|
+ { AR5K_BB_GAIN(14), 0x00000012 },
|
|
+ { AR5K_BB_GAIN(15), 0x00000032 },
|
|
+ { AR5K_BB_GAIN(16), 0x0000000a },
|
|
+ { AR5K_BB_GAIN(17), 0x0000002a },
|
|
+ { AR5K_BB_GAIN(18), 0x00000006 },
|
|
+ { AR5K_BB_GAIN(19), 0x00000026 },
|
|
+ { AR5K_BB_GAIN(20), 0x00000016 },
|
|
+ { AR5K_BB_GAIN(21), 0x00000036 },
|
|
+ { AR5K_BB_GAIN(22), 0x0000000e },
|
|
+ { AR5K_BB_GAIN(23), 0x0000002e },
|
|
+ { AR5K_BB_GAIN(24), 0x00000001 },
|
|
+ { AR5K_BB_GAIN(25), 0x00000021 },
|
|
+ { AR5K_BB_GAIN(26), 0x00000011 },
|
|
+ { AR5K_BB_GAIN(27), 0x00000031 },
|
|
+ { AR5K_BB_GAIN(28), 0x00000009 },
|
|
+ { AR5K_BB_GAIN(29), 0x00000029 },
|
|
+ { AR5K_BB_GAIN(30), 0x00000005 },
|
|
+ { AR5K_BB_GAIN(31), 0x00000025 },
|
|
+ { AR5K_BB_GAIN(32), 0x00000015 },
|
|
+ { AR5K_BB_GAIN(33), 0x00000035 },
|
|
+ { AR5K_BB_GAIN(34), 0x0000000d },
|
|
+ { AR5K_BB_GAIN(35), 0x0000002d },
|
|
+ { AR5K_BB_GAIN(36), 0x00000003 },
|
|
+ { AR5K_BB_GAIN(37), 0x00000023 },
|
|
+ { AR5K_BB_GAIN(38), 0x00000013 },
|
|
+ { AR5K_BB_GAIN(39), 0x00000033 },
|
|
+ { AR5K_BB_GAIN(40), 0x0000000b },
|
|
+ { AR5K_BB_GAIN(41), 0x0000002b },
|
|
+ { AR5K_BB_GAIN(42), 0x0000002b },
|
|
+ { AR5K_BB_GAIN(43), 0x0000002b },
|
|
+ { AR5K_BB_GAIN(44), 0x0000002b },
|
|
+ { AR5K_BB_GAIN(45), 0x0000002b },
|
|
+ { AR5K_BB_GAIN(46), 0x0000002b },
|
|
+ { AR5K_BB_GAIN(47), 0x0000002b },
|
|
+ { AR5K_BB_GAIN(48), 0x0000002b },
|
|
+ { AR5K_BB_GAIN(49), 0x0000002b },
|
|
+ { AR5K_BB_GAIN(50), 0x0000002b },
|
|
+ { AR5K_BB_GAIN(51), 0x0000002b },
|
|
+ { AR5K_BB_GAIN(52), 0x0000002b },
|
|
+ { AR5K_BB_GAIN(53), 0x0000002b },
|
|
+ { AR5K_BB_GAIN(54), 0x0000002b },
|
|
+ { AR5K_BB_GAIN(55), 0x0000002b },
|
|
+ { AR5K_BB_GAIN(56), 0x0000002b },
|
|
+ { AR5K_BB_GAIN(57), 0x0000002b },
|
|
+ { AR5K_BB_GAIN(58), 0x0000002b },
|
|
+ { AR5K_BB_GAIN(59), 0x0000002b },
|
|
+ { AR5K_BB_GAIN(60), 0x0000002b },
|
|
+ { AR5K_BB_GAIN(61), 0x0000002b },
|
|
+ { AR5K_BB_GAIN(62), 0x00000002 },
|
|
+ { AR5K_BB_GAIN(63), 0x00000016 },
|
|
+};
|
|
+
|
|
+/* RF5112 Initial BaseBand Gain settings (Same for RF5413/5414) */
|
|
+static const struct ath5k_ini rf5112_ini_bbgain[] = {
|
|
+ { AR5K_BB_GAIN(0), 0x00000000 },
|
|
+ { AR5K_BB_GAIN(1), 0x00000001 },
|
|
+ { AR5K_BB_GAIN(2), 0x00000002 },
|
|
+ { AR5K_BB_GAIN(3), 0x00000003 },
|
|
+ { AR5K_BB_GAIN(4), 0x00000004 },
|
|
+ { AR5K_BB_GAIN(5), 0x00000005 },
|
|
+ { AR5K_BB_GAIN(6), 0x00000008 },
|
|
+ { AR5K_BB_GAIN(7), 0x00000009 },
|
|
+ { AR5K_BB_GAIN(8), 0x0000000a },
|
|
+ { AR5K_BB_GAIN(9), 0x0000000b },
|
|
+ { AR5K_BB_GAIN(10), 0x0000000c },
|
|
+ { AR5K_BB_GAIN(11), 0x0000000d },
|
|
+ { AR5K_BB_GAIN(12), 0x00000010 },
|
|
+ { AR5K_BB_GAIN(13), 0x00000011 },
|
|
+ { AR5K_BB_GAIN(14), 0x00000012 },
|
|
+ { AR5K_BB_GAIN(15), 0x00000013 },
|
|
+ { AR5K_BB_GAIN(16), 0x00000014 },
|
|
+ { AR5K_BB_GAIN(17), 0x00000015 },
|
|
+ { AR5K_BB_GAIN(18), 0x00000018 },
|
|
+ { AR5K_BB_GAIN(19), 0x00000019 },
|
|
+ { AR5K_BB_GAIN(20), 0x0000001a },
|
|
+ { AR5K_BB_GAIN(21), 0x0000001b },
|
|
+ { AR5K_BB_GAIN(22), 0x0000001c },
|
|
+ { AR5K_BB_GAIN(23), 0x0000001d },
|
|
+ { AR5K_BB_GAIN(24), 0x00000020 },
|
|
+ { AR5K_BB_GAIN(25), 0x00000021 },
|
|
+ { AR5K_BB_GAIN(26), 0x00000022 },
|
|
+ { AR5K_BB_GAIN(27), 0x00000023 },
|
|
+ { AR5K_BB_GAIN(28), 0x00000024 },
|
|
+ { AR5K_BB_GAIN(29), 0x00000025 },
|
|
+ { AR5K_BB_GAIN(30), 0x00000028 },
|
|
+ { AR5K_BB_GAIN(31), 0x00000029 },
|
|
+ { AR5K_BB_GAIN(32), 0x0000002a },
|
|
+ { AR5K_BB_GAIN(33), 0x0000002b },
|
|
+ { AR5K_BB_GAIN(34), 0x0000002c },
|
|
+ { AR5K_BB_GAIN(35), 0x0000002d },
|
|
+ { AR5K_BB_GAIN(36), 0x00000030 },
|
|
+ { AR5K_BB_GAIN(37), 0x00000031 },
|
|
+ { AR5K_BB_GAIN(38), 0x00000032 },
|
|
+ { AR5K_BB_GAIN(39), 0x00000033 },
|
|
+ { AR5K_BB_GAIN(40), 0x00000034 },
|
|
+ { AR5K_BB_GAIN(41), 0x00000035 },
|
|
+ { AR5K_BB_GAIN(42), 0x00000035 },
|
|
+ { AR5K_BB_GAIN(43), 0x00000035 },
|
|
+ { AR5K_BB_GAIN(44), 0x00000035 },
|
|
+ { AR5K_BB_GAIN(45), 0x00000035 },
|
|
+ { AR5K_BB_GAIN(46), 0x00000035 },
|
|
+ { AR5K_BB_GAIN(47), 0x00000035 },
|
|
+ { AR5K_BB_GAIN(48), 0x00000035 },
|
|
+ { AR5K_BB_GAIN(49), 0x00000035 },
|
|
+ { AR5K_BB_GAIN(50), 0x00000035 },
|
|
+ { AR5K_BB_GAIN(51), 0x00000035 },
|
|
+ { AR5K_BB_GAIN(52), 0x00000035 },
|
|
+ { AR5K_BB_GAIN(53), 0x00000035 },
|
|
+ { AR5K_BB_GAIN(54), 0x00000035 },
|
|
+ { AR5K_BB_GAIN(55), 0x00000035 },
|
|
+ { AR5K_BB_GAIN(56), 0x00000035 },
|
|
+ { AR5K_BB_GAIN(57), 0x00000035 },
|
|
+ { AR5K_BB_GAIN(58), 0x00000035 },
|
|
+ { AR5K_BB_GAIN(59), 0x00000035 },
|
|
+ { AR5K_BB_GAIN(60), 0x00000035 },
|
|
+ { AR5K_BB_GAIN(61), 0x00000035 },
|
|
+ { AR5K_BB_GAIN(62), 0x00000010 },
|
|
+ { AR5K_BB_GAIN(63), 0x0000001a },
|
|
+};
|
|
+
|
|
+
|
|
+/*
|
|
+ * Write initial register dump
|
|
+ */
|
|
+static void ath5k_hw_ini_registers(struct ath5k_hw *ah, unsigned int size,
|
|
+ const struct ath5k_ini *ini_regs, bool change_channel)
|
|
+{
|
|
+ unsigned int i;
|
|
+
|
|
+ /* Write initial registers */
|
|
+ for (i = 0; i < size; i++) {
|
|
+ /* On channel change there is
|
|
+ * no need to mess with PCU */
|
|
+ if (change_channel &&
|
|
+ ini_regs[i].ini_register >= AR5K_PCU_MIN &&
|
|
+ ini_regs[i].ini_register <= AR5K_PCU_MAX)
|
|
+ continue;
|
|
+
|
|
+ switch (ini_regs[i].ini_mode) {
|
|
+ case AR5K_INI_READ:
|
|
+ /* Cleared on read */
|
|
+ ath5k_hw_reg_read(ah, ini_regs[i].ini_register);
|
|
+ break;
|
|
+ case AR5K_INI_WRITE:
|
|
+ default:
|
|
+ AR5K_REG_WAIT(i);
|
|
+ ath5k_hw_reg_write(ah, ini_regs[i].ini_value,
|
|
+ ini_regs[i].ini_register);
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+static void ath5k_hw_ini_mode_registers(struct ath5k_hw *ah,
|
|
+ unsigned int size, const struct ath5k_ini_mode *ini_mode,
|
|
+ u8 mode)
|
|
+{
|
|
+ unsigned int i;
|
|
+
|
|
+ for (i = 0; i < size; i++) {
|
|
+ AR5K_REG_WAIT(i);
|
|
+ ath5k_hw_reg_write(ah, ini_mode[i].mode_value[mode],
|
|
+ (u32)ini_mode[i].mode_register);
|
|
+ }
|
|
+
|
|
+}
|
|
+
|
|
+int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel)
|
|
+{
|
|
+ /*
|
|
+ * Write initial register settings
|
|
+ */
|
|
+
|
|
+ /* For AR5212 and combatible */
|
|
+ if (ah->ah_version == AR5K_AR5212){
|
|
+
|
|
+ /* First set of mode-specific settings */
|
|
+ ath5k_hw_ini_mode_registers(ah,
|
|
+ ARRAY_SIZE(ar5212_ini_mode_start),
|
|
+ ar5212_ini_mode_start, mode);
|
|
+
|
|
+ /*
|
|
+ * Write initial settings common for all modes
|
|
+ */
|
|
+ ath5k_hw_ini_registers(ah, ARRAY_SIZE(ar5212_ini),
|
|
+ ar5212_ini, change_channel);
|
|
+
|
|
+ /* Second set of mode-specific settings */
|
|
+ if (ah->ah_radio == AR5K_RF5111){
|
|
+ ath5k_hw_ini_mode_registers(ah,
|
|
+ ARRAY_SIZE(ar5212_rf5111_ini_mode_end),
|
|
+ ar5212_rf5111_ini_mode_end, mode);
|
|
+ /* Baseband gain table */
|
|
+ ath5k_hw_ini_registers(ah,
|
|
+ ARRAY_SIZE(rf5111_ini_bbgain),
|
|
+ rf5111_ini_bbgain, change_channel);
|
|
+ } else if (ah->ah_radio == AR5K_RF5112){
|
|
+ ath5k_hw_ini_mode_registers(ah,
|
|
+ ARRAY_SIZE(ar5212_rf5112_ini_mode_end),
|
|
+ ar5212_rf5112_ini_mode_end, mode);
|
|
+ /* Baseband gain table */
|
|
+ ath5k_hw_ini_registers(ah,
|
|
+ ARRAY_SIZE(rf5112_ini_bbgain),
|
|
+ rf5112_ini_bbgain, change_channel);
|
|
+ } else if (ah->ah_radio == AR5K_RF5413){
|
|
+ ath5k_hw_ini_mode_registers(ah,
|
|
+ ARRAY_SIZE(rf5413_ini_mode_end),
|
|
+ rf5413_ini_mode_end, mode);
|
|
+ /* Baseband gain table */
|
|
+ ath5k_hw_ini_registers(ah,
|
|
+ ARRAY_SIZE(rf5112_ini_bbgain),
|
|
+ rf5112_ini_bbgain, change_channel);
|
|
+ }
|
|
+ /* For AR5211 */
|
|
+ } else if (ah->ah_version == AR5K_AR5211) {
|
|
+
|
|
+ if(mode > 2){ /* AR5K_INI_VAL_11B */
|
|
+ ATH5K_ERR(ah->ah_sc,"unsupported channel mode: %d\n", mode);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ /* Mode-specific settings */
|
|
+ ath5k_hw_ini_mode_registers(ah, ARRAY_SIZE(ar5211_ini_mode),
|
|
+ ar5211_ini_mode, mode);
|
|
+
|
|
+ /*
|
|
+ * Write initial settings common for all modes
|
|
+ */
|
|
+ ath5k_hw_ini_registers(ah, ARRAY_SIZE(ar5211_ini),
|
|
+ ar5211_ini, change_channel);
|
|
+
|
|
+ /* AR5211 only comes with 5111 */
|
|
+
|
|
+ /* Baseband gain table */
|
|
+ ath5k_hw_ini_registers(ah, ARRAY_SIZE(rf5111_ini_bbgain),
|
|
+ rf5111_ini_bbgain, change_channel);
|
|
+ /* For AR5210 (for mode settings check out ath5k_hw_reset_tx_queue) */
|
|
+ } else if (ah->ah_version == AR5K_AR5210) {
|
|
+ ath5k_hw_ini_registers(ah, ARRAY_SIZE(ar5210_ini),
|
|
+ ar5210_ini, change_channel);
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
diff -up /dev/null linux-2.6.23.noarch/drivers/net/wireless/ath5k/base.c
|
|
--- /dev/null 2007-12-21 08:33:07.834165456 -0500
|
|
+++ linux-2.6.23.noarch/drivers/net/wireless/ath5k/base.c 2007-12-21 12:18:50.000000000 -0500
|
|
@@ -0,0 +1,2822 @@
|
|
+/*-
|
|
+ * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
|
|
+ * Copyright (c) 2004-2005 Atheros Communications, Inc.
|
|
+ * Copyright (c) 2006 Devicescape Software, Inc.
|
|
+ * Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com>
|
|
+ * Copyright (c) 2007 Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
|
|
+ *
|
|
+ * All rights reserved.
|
|
+ *
|
|
+ * Redistribution and use in source and binary forms, with or without
|
|
+ * modification, are permitted provided that the following conditions
|
|
+ * are met:
|
|
+ * 1. Redistributions of source code must retain the above copyright
|
|
+ * notice, this list of conditions and the following disclaimer,
|
|
+ * without modification.
|
|
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
|
+ * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
|
|
+ * redistribution must be conditioned upon including a substantially
|
|
+ * similar Disclaimer requirement for further binary redistribution.
|
|
+ * 3. Neither the names of the above-listed copyright holders nor the names
|
|
+ * of any contributors may be used to endorse or promote products derived
|
|
+ * from this software without specific prior written permission.
|
|
+ *
|
|
+ * Alternatively, this software may be distributed under the terms of the
|
|
+ * GNU General Public License ("GPL") version 2 as published by the Free
|
|
+ * Software Foundation.
|
|
+ *
|
|
+ * NO WARRANTY
|
|
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
|
|
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
|
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
|
|
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
|
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
|
+ * THE POSSIBILITY OF SUCH DAMAGES.
|
|
+ *
|
|
+ */
|
|
+
|
|
+#include <linux/version.h>
|
|
+#include <linux/module.h>
|
|
+#include <linux/delay.h>
|
|
+#include <linux/if.h>
|
|
+#include <linux/netdevice.h>
|
|
+#include <linux/cache.h>
|
|
+#include <linux/pci.h>
|
|
+#include <linux/ethtool.h>
|
|
+#include <linux/uaccess.h>
|
|
+
|
|
+#include <net/ieee80211_radiotap.h>
|
|
+
|
|
+#include <asm/unaligned.h>
|
|
+
|
|
+#include "base.h"
|
|
+#include "reg.h"
|
|
+#include "debug.h"
|
|
+
|
|
+/* unaligned little endian access */
|
|
+#define LE_READ_2(_p) (le16_to_cpu(get_unaligned((__le16 *)(_p))))
|
|
+#define LE_READ_4(_p) (le32_to_cpu(get_unaligned((__le32 *)(_p))))
|
|
+
|
|
+enum {
|
|
+ ATH_LED_TX,
|
|
+ ATH_LED_RX,
|
|
+};
|
|
+
|
|
+static int ath5k_calinterval = 10; /* Calibrate PHY every 10 secs (TODO: Fixme) */
|
|
+
|
|
+
|
|
+/******************\
|
|
+* Internal defines *
|
|
+\******************/
|
|
+
|
|
+/* Module info */
|
|
+MODULE_AUTHOR("Jiri Slaby");
|
|
+MODULE_AUTHOR("Nick Kossifidis");
|
|
+MODULE_DESCRIPTION("Support for 5xxx series of Atheros 802.11 wireless LAN cards.");
|
|
+MODULE_SUPPORTED_DEVICE("Atheros 5xxx WLAN cards");
|
|
+MODULE_LICENSE("Dual BSD/GPL");
|
|
+MODULE_VERSION("0.1.1 (EXPERIMENTAL)");
|
|
+
|
|
+
|
|
+/* Known PCI ids */
|
|
+static struct pci_device_id ath5k_pci_id_table[] __devinitdata = {
|
|
+ { PCI_VDEVICE(ATHEROS, 0x0207), .driver_data = AR5K_AR5210 }, /* 5210 early */
|
|
+ { PCI_VDEVICE(ATHEROS, 0x0007), .driver_data = AR5K_AR5210 }, /* 5210 */
|
|
+ { PCI_VDEVICE(ATHEROS, 0x0011), .driver_data = AR5K_AR5211 }, /* 5311 - this is on AHB bus !*/
|
|
+ { PCI_VDEVICE(ATHEROS, 0x0012), .driver_data = AR5K_AR5211 }, /* 5211 */
|
|
+ { PCI_VDEVICE(ATHEROS, 0x0013), .driver_data = AR5K_AR5212 }, /* 5212 */
|
|
+ { PCI_VDEVICE(3COM_2, 0x0013), .driver_data = AR5K_AR5212 }, /* 3com 5212 */
|
|
+ { PCI_VDEVICE(3COM, 0x0013), .driver_data = AR5K_AR5212 }, /* 3com 3CRDAG675 5212 */
|
|
+ { PCI_VDEVICE(ATHEROS, 0x1014), .driver_data = AR5K_AR5212 }, /* IBM minipci 5212 */
|
|
+ { PCI_VDEVICE(ATHEROS, 0x0014), .driver_data = AR5K_AR5212 }, /* 5212 combatible */
|
|
+ { PCI_VDEVICE(ATHEROS, 0x0015), .driver_data = AR5K_AR5212 }, /* 5212 combatible */
|
|
+ { PCI_VDEVICE(ATHEROS, 0x0016), .driver_data = AR5K_AR5212 }, /* 5212 combatible */
|
|
+ { PCI_VDEVICE(ATHEROS, 0x0017), .driver_data = AR5K_AR5212 }, /* 5212 combatible */
|
|
+ { PCI_VDEVICE(ATHEROS, 0x0018), .driver_data = AR5K_AR5212 }, /* 5212 combatible */
|
|
+ { PCI_VDEVICE(ATHEROS, 0x0019), .driver_data = AR5K_AR5212 }, /* 5212 combatible */
|
|
+ { PCI_VDEVICE(ATHEROS, 0x001a), .driver_data = AR5K_AR5212 }, /* 2413 Griffin-lite */
|
|
+ { PCI_VDEVICE(ATHEROS, 0x001b), .driver_data = AR5K_AR5212 }, /* 5413 Eagle */
|
|
+ { PCI_VDEVICE(ATHEROS, 0x001c), .driver_data = AR5K_AR5212 }, /* 5424 Condor (PCI-E)*/
|
|
+ { PCI_VDEVICE(ATHEROS, 0x0023), .driver_data = AR5K_AR5212 }, /* 5416 */
|
|
+ { PCI_VDEVICE(ATHEROS, 0x0024), .driver_data = AR5K_AR5212 }, /* 5418 */
|
|
+ { 0 }
|
|
+};
|
|
+MODULE_DEVICE_TABLE(pci, ath5k_pci_id_table);
|
|
+
|
|
+/* Known SREVs */
|
|
+static struct ath5k_srev_name srev_names[] = {
|
|
+ { "5210", AR5K_VERSION_VER, AR5K_SREV_VER_AR5210 },
|
|
+ { "5311", AR5K_VERSION_VER, AR5K_SREV_VER_AR5311 },
|
|
+ { "5311A", AR5K_VERSION_VER, AR5K_SREV_VER_AR5311A },
|
|
+ { "5311B", AR5K_VERSION_VER, AR5K_SREV_VER_AR5311B },
|
|
+ { "5211", AR5K_VERSION_VER, AR5K_SREV_VER_AR5211 },
|
|
+ { "5212", AR5K_VERSION_VER, AR5K_SREV_VER_AR5212 },
|
|
+ { "5213", AR5K_VERSION_VER, AR5K_SREV_VER_AR5213 },
|
|
+ { "5213A", AR5K_VERSION_VER, AR5K_SREV_VER_AR5213A },
|
|
+ { "2424", AR5K_VERSION_VER, AR5K_SREV_VER_AR2424 },
|
|
+ { "5424", AR5K_VERSION_VER, AR5K_SREV_VER_AR5424 },
|
|
+ { "5413", AR5K_VERSION_VER, AR5K_SREV_VER_AR5413 },
|
|
+ { "5414", AR5K_VERSION_VER, AR5K_SREV_VER_AR5414 },
|
|
+ { "5416", AR5K_VERSION_VER, AR5K_SREV_VER_AR5416 },
|
|
+ { "5418", AR5K_VERSION_VER, AR5K_SREV_VER_AR5418 },
|
|
+ { "xxxxx", AR5K_VERSION_VER, AR5K_SREV_UNKNOWN },
|
|
+ { "5110", AR5K_VERSION_RAD, AR5K_SREV_RAD_5110 },
|
|
+ { "5111", AR5K_VERSION_RAD, AR5K_SREV_RAD_5111 },
|
|
+ { "2111", AR5K_VERSION_RAD, AR5K_SREV_RAD_2111 },
|
|
+ { "5112", AR5K_VERSION_RAD, AR5K_SREV_RAD_5112 },
|
|
+ { "5112A", AR5K_VERSION_RAD, AR5K_SREV_RAD_5112A },
|
|
+ { "2112", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112 },
|
|
+ { "2112A", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112A },
|
|
+ { "SChip", AR5K_VERSION_RAD, AR5K_SREV_RAD_SC1 },
|
|
+ { "SChip", AR5K_VERSION_RAD, AR5K_SREV_RAD_SC2 },
|
|
+ { "5133", AR5K_VERSION_RAD, AR5K_SREV_RAD_5133 },
|
|
+ { "xxxxx", AR5K_VERSION_RAD, AR5K_SREV_UNKNOWN },
|
|
+};
|
|
+
|
|
+/*
|
|
+ * Prototypes - PCI stack related functions
|
|
+ */
|
|
+static int __devinit ath5k_pci_probe(struct pci_dev *pdev,
|
|
+ const struct pci_device_id *id);
|
|
+static void __devexit ath5k_pci_remove(struct pci_dev *pdev);
|
|
+#ifdef CONFIG_PM
|
|
+static int ath5k_pci_suspend(struct pci_dev *pdev,
|
|
+ pm_message_t state);
|
|
+static int ath5k_pci_resume(struct pci_dev *pdev);
|
|
+#else
|
|
+#define ath5k_pci_suspend NULL
|
|
+#define ath5k_pci_resume NULL
|
|
+#endif /* CONFIG_PM */
|
|
+
|
|
+static struct pci_driver ath5k_pci_drv_id = {
|
|
+ .name = "ath5k_pci",
|
|
+ .id_table = ath5k_pci_id_table,
|
|
+ .probe = ath5k_pci_probe,
|
|
+ .remove = __devexit_p(ath5k_pci_remove),
|
|
+ .suspend = ath5k_pci_suspend,
|
|
+ .resume = ath5k_pci_resume,
|
|
+};
|
|
+
|
|
+
|
|
+
|
|
+/*
|
|
+ * Prototypes - MAC 802.11 stack related functions
|
|
+ */
|
|
+static int ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
|
|
+ struct ieee80211_tx_control *ctl);
|
|
+static int ath5k_reset(struct ieee80211_hw *hw);
|
|
+static int ath5k_start(struct ieee80211_hw *hw);
|
|
+static void ath5k_stop(struct ieee80211_hw *hw);
|
|
+static int ath5k_add_interface(struct ieee80211_hw *hw,
|
|
+ struct ieee80211_if_init_conf *conf);
|
|
+static void ath5k_remove_interface(struct ieee80211_hw *hw,
|
|
+ struct ieee80211_if_init_conf *conf);
|
|
+static int ath5k_config(struct ieee80211_hw *hw,
|
|
+ struct ieee80211_conf *conf);
|
|
+static int ath5k_config_interface(struct ieee80211_hw *hw, int if_id,
|
|
+ struct ieee80211_if_conf *conf);
|
|
+static void ath5k_configure_filter(struct ieee80211_hw *hw,
|
|
+ unsigned int changed_flags,
|
|
+ unsigned int *new_flags,
|
|
+ int mc_count, struct dev_mc_list *mclist);
|
|
+static int ath5k_set_key(struct ieee80211_hw *hw,
|
|
+ enum set_key_cmd cmd,
|
|
+ const u8 *local_addr, const u8 *addr,
|
|
+ struct ieee80211_key_conf *key);
|
|
+static int ath5k_get_stats(struct ieee80211_hw *hw,
|
|
+ struct ieee80211_low_level_stats *stats);
|
|
+static int ath5k_get_tx_stats(struct ieee80211_hw *hw,
|
|
+ struct ieee80211_tx_queue_stats *stats);
|
|
+static u64 ath5k_get_tsf(struct ieee80211_hw *hw);
|
|
+static void ath5k_reset_tsf(struct ieee80211_hw *hw);
|
|
+static int ath5k_beacon_update(struct ieee80211_hw *hw,
|
|
+ struct sk_buff *skb,
|
|
+ struct ieee80211_tx_control *ctl);
|
|
+
|
|
+static struct ieee80211_ops ath5k_hw_ops = {
|
|
+ .tx = ath5k_tx,
|
|
+ .start = ath5k_start,
|
|
+ .stop = ath5k_stop,
|
|
+ .add_interface = ath5k_add_interface,
|
|
+ .remove_interface = ath5k_remove_interface,
|
|
+ .config = ath5k_config,
|
|
+ .config_interface = ath5k_config_interface,
|
|
+ .configure_filter = ath5k_configure_filter,
|
|
+ .set_key = ath5k_set_key,
|
|
+ .get_stats = ath5k_get_stats,
|
|
+ .conf_tx = NULL,
|
|
+ .get_tx_stats = ath5k_get_tx_stats,
|
|
+ .get_tsf = ath5k_get_tsf,
|
|
+ .reset_tsf = ath5k_reset_tsf,
|
|
+ .beacon_update = ath5k_beacon_update,
|
|
+};
|
|
+
|
|
+/*
|
|
+ * Prototypes - Internal functions
|
|
+ */
|
|
+/* Attach detach */
|
|
+static int ath5k_attach(struct pci_dev *pdev,
|
|
+ struct ieee80211_hw *hw);
|
|
+static void ath5k_detach(struct pci_dev *pdev,
|
|
+ struct ieee80211_hw *hw);
|
|
+/* Channel/mode setup */
|
|
+static inline short ath5k_ieee2mhz(short chan);
|
|
+static unsigned int ath5k_copy_rates(struct ieee80211_rate *rates,
|
|
+ const struct ath5k_rate_table *rt,
|
|
+ unsigned int max);
|
|
+static unsigned int ath5k_copy_channels(struct ath5k_hw *ah,
|
|
+ struct ieee80211_channel *channels,
|
|
+ unsigned int mode,
|
|
+ unsigned int max);
|
|
+static int ath5k_getchannels(struct ieee80211_hw *hw);
|
|
+static int ath5k_chan_set(struct ath5k_softc *sc,
|
|
+ struct ieee80211_channel *chan);
|
|
+static void ath5k_setcurmode(struct ath5k_softc *sc,
|
|
+ unsigned int mode);
|
|
+static void ath5k_mode_setup(struct ath5k_softc *sc);
|
|
+/* Descriptor setup */
|
|
+static int ath5k_desc_alloc(struct ath5k_softc *sc,
|
|
+ struct pci_dev *pdev);
|
|
+static void ath5k_desc_free(struct ath5k_softc *sc,
|
|
+ struct pci_dev *pdev);
|
|
+/* Buffers setup */
|
|
+static int ath5k_rxbuf_setup(struct ath5k_softc *sc,
|
|
+ struct ath5k_buf *bf);
|
|
+static int ath5k_txbuf_setup(struct ath5k_softc *sc,
|
|
+ struct ath5k_buf *bf,
|
|
+ struct ieee80211_tx_control *ctl);
|
|
+
|
|
+static inline void ath5k_txbuf_free(struct ath5k_softc *sc,
|
|
+ struct ath5k_buf *bf)
|
|
+{
|
|
+ BUG_ON(!bf);
|
|
+ if (!bf->skb)
|
|
+ return;
|
|
+ pci_unmap_single(sc->pdev, bf->skbaddr, bf->skb->len,
|
|
+ PCI_DMA_TODEVICE);
|
|
+ dev_kfree_skb(bf->skb);
|
|
+ bf->skb = NULL;
|
|
+}
|
|
+
|
|
+/* Queues setup */
|
|
+static struct ath5k_txq *ath5k_txq_setup(struct ath5k_softc *sc,
|
|
+ int qtype, int subtype);
|
|
+static int ath5k_beaconq_setup(struct ath5k_hw *ah);
|
|
+static int ath5k_beaconq_config(struct ath5k_softc *sc);
|
|
+static void ath5k_txq_drainq(struct ath5k_softc *sc,
|
|
+ struct ath5k_txq *txq);
|
|
+static void ath5k_txq_cleanup(struct ath5k_softc *sc);
|
|
+static void ath5k_txq_release(struct ath5k_softc *sc);
|
|
+/* Rx handling */
|
|
+static int ath5k_rx_start(struct ath5k_softc *sc);
|
|
+static void ath5k_rx_stop(struct ath5k_softc *sc);
|
|
+static unsigned int ath5k_rx_decrypted(struct ath5k_softc *sc,
|
|
+ struct ath5k_desc *ds,
|
|
+ struct sk_buff *skb);
|
|
+static void ath5k_tasklet_rx(unsigned long data);
|
|
+/* Tx handling */
|
|
+static void ath5k_tx_processq(struct ath5k_softc *sc,
|
|
+ struct ath5k_txq *txq);
|
|
+static void ath5k_tasklet_tx(unsigned long data);
|
|
+/* Beacon handling */
|
|
+static int ath5k_beacon_setup(struct ath5k_softc *sc,
|
|
+ struct ath5k_buf *bf,
|
|
+ struct ieee80211_tx_control *ctl);
|
|
+static void ath5k_beacon_send(struct ath5k_softc *sc);
|
|
+static void ath5k_beacon_config(struct ath5k_softc *sc);
|
|
+
|
|
+static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp)
|
|
+{
|
|
+ u64 tsf = ath5k_hw_get_tsf64(ah);
|
|
+
|
|
+ if ((tsf & 0x7fff) < rstamp)
|
|
+ tsf -= 0x8000;
|
|
+
|
|
+ return (tsf & ~0x7fff) | rstamp;
|
|
+}
|
|
+
|
|
+/* Interrupt handling */
|
|
+static int ath5k_init(struct ath5k_softc *sc);
|
|
+static int ath5k_stop_locked(struct ath5k_softc *sc);
|
|
+static int ath5k_stop_hw(struct ath5k_softc *sc);
|
|
+static irqreturn_t ath5k_intr(int irq, void *dev_id);
|
|
+static void ath5k_tasklet_reset(unsigned long data);
|
|
+
|
|
+static void ath5k_calibrate(unsigned long data);
|
|
+/* LED functions */
|
|
+static void ath5k_led_off(unsigned long data);
|
|
+static void ath5k_led_blink(struct ath5k_softc *sc,
|
|
+ unsigned int on,
|
|
+ unsigned int off);
|
|
+static void ath5k_led_event(struct ath5k_softc *sc,
|
|
+ int event);
|
|
+
|
|
+
|
|
+/*
|
|
+ * Module init/exit functions
|
|
+ */
|
|
+static int __init
|
|
+init_ath5k_pci(void)
|
|
+{
|
|
+ int ret;
|
|
+
|
|
+ ath5k_debug_init();
|
|
+
|
|
+ ret = pci_register_driver(&ath5k_pci_drv_id);
|
|
+ if (ret) {
|
|
+ printk(KERN_ERR "ath5k_pci: can't register pci driver\n");
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static void __exit
|
|
+exit_ath5k_pci(void)
|
|
+{
|
|
+ pci_unregister_driver(&ath5k_pci_drv_id);
|
|
+
|
|
+ ath5k_debug_finish();
|
|
+}
|
|
+
|
|
+module_init(init_ath5k_pci);
|
|
+module_exit(exit_ath5k_pci);
|
|
+
|
|
+
|
|
+/********************\
|
|
+* PCI Initialization *
|
|
+\********************/
|
|
+
|
|
+static const char *
|
|
+ath5k_chip_name(enum ath5k_srev_type type, u_int16_t val)
|
|
+{
|
|
+ const char *name = "xxxxx";
|
|
+ unsigned int i;
|
|
+
|
|
+ for (i = 0; i < ARRAY_SIZE(srev_names); i++) {
|
|
+ if (srev_names[i].sr_type != type)
|
|
+ continue;
|
|
+ if ((val & 0xff) < srev_names[i + 1].sr_val) {
|
|
+ name = srev_names[i].sr_name;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return name;
|
|
+}
|
|
+
|
|
+static int __devinit
|
|
+ath5k_pci_probe(struct pci_dev *pdev,
|
|
+ const struct pci_device_id *id)
|
|
+{
|
|
+ void __iomem *mem;
|
|
+ struct ath5k_softc *sc;
|
|
+ struct ieee80211_hw *hw;
|
|
+ int ret;
|
|
+ u8 csz;
|
|
+
|
|
+ ret = pci_enable_device(pdev);
|
|
+ if (ret) {
|
|
+ dev_err(&pdev->dev, "can't enable device\n");
|
|
+ goto err;
|
|
+ }
|
|
+
|
|
+ /* XXX 32-bit addressing only */
|
|
+ ret = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
|
|
+ if (ret) {
|
|
+ dev_err(&pdev->dev, "32-bit DMA not available\n");
|
|
+ goto err_dis;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Cache line size is used to size and align various
|
|
+ * structures used to communicate with the hardware.
|
|
+ */
|
|
+ pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &csz);
|
|
+ if (csz == 0) {
|
|
+ /*
|
|
+ * Linux 2.4.18 (at least) writes the cache line size
|
|
+ * register as a 16-bit wide register which is wrong.
|
|
+ * We must have this setup properly for rx buffer
|
|
+ * DMA to work so force a reasonable value here if it
|
|
+ * comes up zero.
|
|
+ */
|
|
+ csz = L1_CACHE_BYTES / sizeof(u32);
|
|
+ pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz);
|
|
+ }
|
|
+ /*
|
|
+ * The default setting of latency timer yields poor results,
|
|
+ * set it to the value used by other systems. It may be worth
|
|
+ * tweaking this setting more.
|
|
+ */
|
|
+ pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xa8);
|
|
+
|
|
+ /* Enable bus mastering */
|
|
+ pci_set_master(pdev);
|
|
+
|
|
+ /*
|
|
+ * Disable the RETRY_TIMEOUT register (0x41) to keep
|
|
+ * PCI Tx retries from interfering with C3 CPU state.
|
|
+ */
|
|
+ pci_write_config_byte(pdev, 0x41, 0);
|
|
+
|
|
+ ret = pci_request_region(pdev, 0, "ath5k");
|
|
+ if (ret) {
|
|
+ dev_err(&pdev->dev, "cannot reserve PCI memory region\n");
|
|
+ goto err_dis;
|
|
+ }
|
|
+
|
|
+ mem = pci_iomap(pdev, 0, 0);
|
|
+ if (!mem) {
|
|
+ dev_err(&pdev->dev, "cannot remap PCI memory region\n") ;
|
|
+ ret = -EIO;
|
|
+ goto err_reg;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Allocate hw (mac80211 main struct)
|
|
+ * and hw->priv (driver private data)
|
|
+ */
|
|
+ hw = ieee80211_alloc_hw(sizeof(*sc), &ath5k_hw_ops);
|
|
+ if (hw == NULL) {
|
|
+ dev_err(&pdev->dev, "cannot allocate ieee80211_hw\n");
|
|
+ ret = -ENOMEM;
|
|
+ goto err_map;
|
|
+ }
|
|
+
|
|
+ dev_info(&pdev->dev, "registered as '%s'\n", wiphy_name(hw->wiphy));
|
|
+
|
|
+ /* Initialize driver private data */
|
|
+ SET_IEEE80211_DEV(hw, &pdev->dev);
|
|
+ hw->flags = IEEE80211_HW_RX_INCLUDES_FCS;
|
|
+ hw->extra_tx_headroom = 2;
|
|
+ hw->channel_change_time = 5000;
|
|
+ /* these names are misleading */
|
|
+ hw->max_rssi = -110; /* signal in dBm */
|
|
+ hw->max_noise = -110; /* noise in dBm */
|
|
+ hw->max_signal = 100; /* we will provide a percentage based on rssi */
|
|
+ sc = hw->priv;
|
|
+ sc->hw = hw;
|
|
+ sc->pdev = pdev;
|
|
+
|
|
+ ath5k_debug_init_device(sc);
|
|
+
|
|
+ /*
|
|
+ * Mark the device as detached to avoid processing
|
|
+ * interrupts until setup is complete.
|
|
+ */
|
|
+ __set_bit(ATH_STAT_INVALID, sc->status);
|
|
+
|
|
+ sc->iobase = mem; /* So we can unmap it on detach */
|
|
+ sc->cachelsz = csz * sizeof(u32); /* convert to bytes */
|
|
+ sc->opmode = IEEE80211_IF_TYPE_STA;
|
|
+ mutex_init(&sc->lock);
|
|
+ spin_lock_init(&sc->rxbuflock);
|
|
+ spin_lock_init(&sc->txbuflock);
|
|
+
|
|
+ /* Set private data */
|
|
+ pci_set_drvdata(pdev, hw);
|
|
+
|
|
+ /* Enable msi for devices that support it */
|
|
+ pci_enable_msi(pdev);
|
|
+
|
|
+ /* Setup interrupt handler */
|
|
+ ret = request_irq(pdev->irq, ath5k_intr, IRQF_SHARED, "ath", sc);
|
|
+ if (ret) {
|
|
+ ATH5K_ERR(sc, "request_irq failed\n");
|
|
+ goto err_free;
|
|
+ }
|
|
+
|
|
+ /* Initialize device */
|
|
+ sc->ah = ath5k_hw_attach(sc, id->driver_data);
|
|
+ if (IS_ERR(sc->ah)) {
|
|
+ ret = PTR_ERR(sc->ah);
|
|
+ goto err_irq;
|
|
+ }
|
|
+
|
|
+ /* Finish private driver data initialization */
|
|
+ ret = ath5k_attach(pdev, hw);
|
|
+ if (ret)
|
|
+ goto err_ah;
|
|
+
|
|
+ ATH5K_INFO(sc, "Atheros AR%s chip found (MAC: 0x%x, PHY: 0x%x)\n",
|
|
+ ath5k_chip_name(AR5K_VERSION_VER,sc->ah->ah_mac_srev),
|
|
+ sc->ah->ah_mac_srev,
|
|
+ sc->ah->ah_phy_revision);
|
|
+
|
|
+ if(!sc->ah->ah_single_chip){
|
|
+ /* Single chip radio (!RF5111) */
|
|
+ if(sc->ah->ah_radio_5ghz_revision && !sc->ah->ah_radio_2ghz_revision) {
|
|
+ /* No 5GHz support -> report 2GHz radio */
|
|
+ if(!test_bit(MODE_IEEE80211A, sc->ah->ah_capabilities.cap_mode)){
|
|
+ ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n",
|
|
+ ath5k_chip_name(AR5K_VERSION_RAD,sc->ah->ah_radio_5ghz_revision),
|
|
+ sc->ah->ah_radio_5ghz_revision);
|
|
+ /* No 2GHz support (5110 and some 5Ghz only cards) -> report 5Ghz radio */
|
|
+ } else if(!test_bit(MODE_IEEE80211B, sc->ah->ah_capabilities.cap_mode)){
|
|
+ ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n",
|
|
+ ath5k_chip_name(AR5K_VERSION_RAD,sc->ah->ah_radio_5ghz_revision),
|
|
+ sc->ah->ah_radio_5ghz_revision);
|
|
+ /* Multiband radio */
|
|
+ } else {
|
|
+ ATH5K_INFO(sc, "RF%s multiband radio found"
|
|
+ " (0x%x)\n",
|
|
+ ath5k_chip_name(AR5K_VERSION_RAD,sc->ah->ah_radio_5ghz_revision),
|
|
+ sc->ah->ah_radio_5ghz_revision);
|
|
+ }
|
|
+ }
|
|
+ /* Multi chip radio (RF5111 - RF2111) -> report both 2GHz/5GHz radios */
|
|
+ else if(sc->ah->ah_radio_5ghz_revision && sc->ah->ah_radio_2ghz_revision){
|
|
+ ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n",
|
|
+ ath5k_chip_name(AR5K_VERSION_RAD,sc->ah->ah_radio_5ghz_revision),
|
|
+ sc->ah->ah_radio_5ghz_revision);
|
|
+ ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n",
|
|
+ ath5k_chip_name(AR5K_VERSION_RAD,sc->ah->ah_radio_2ghz_revision),
|
|
+ sc->ah->ah_radio_2ghz_revision);
|
|
+ }
|
|
+ }
|
|
+
|
|
+
|
|
+ /* ready to process interrupts */
|
|
+ __clear_bit(ATH_STAT_INVALID, sc->status);
|
|
+
|
|
+ return 0;
|
|
+err_ah:
|
|
+ ath5k_hw_detach(sc->ah);
|
|
+err_irq:
|
|
+ free_irq(pdev->irq, sc);
|
|
+err_free:
|
|
+ pci_disable_msi(pdev);
|
|
+ ieee80211_free_hw(hw);
|
|
+err_map:
|
|
+ pci_iounmap(pdev, mem);
|
|
+err_reg:
|
|
+ pci_release_region(pdev, 0);
|
|
+err_dis:
|
|
+ pci_disable_device(pdev);
|
|
+err:
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static void __devexit
|
|
+ath5k_pci_remove(struct pci_dev *pdev)
|
|
+{
|
|
+ struct ieee80211_hw *hw = pci_get_drvdata(pdev);
|
|
+ struct ath5k_softc *sc = hw->priv;
|
|
+
|
|
+ ath5k_debug_finish_device(sc);
|
|
+ ath5k_detach(pdev, hw);
|
|
+ ath5k_hw_detach(sc->ah);
|
|
+ free_irq(pdev->irq, sc);
|
|
+ pci_disable_msi(pdev);
|
|
+ pci_iounmap(pdev, sc->iobase);
|
|
+ pci_release_region(pdev, 0);
|
|
+ pci_disable_device(pdev);
|
|
+ ieee80211_free_hw(hw);
|
|
+}
|
|
+
|
|
+#ifdef CONFIG_PM
|
|
+static int
|
|
+ath5k_pci_suspend(struct pci_dev *pdev, pm_message_t state)
|
|
+{
|
|
+ struct ieee80211_hw *hw = pci_get_drvdata(pdev);
|
|
+ struct ath5k_softc *sc = hw->priv;
|
|
+
|
|
+ if (test_bit(ATH_STAT_LEDSOFT, sc->status))
|
|
+ ath5k_hw_set_gpio(sc->ah, sc->led_pin, 1);
|
|
+
|
|
+ ath5k_stop_hw(sc);
|
|
+ pci_save_state(pdev);
|
|
+ pci_disable_device(pdev);
|
|
+ pci_set_power_state(pdev, PCI_D3hot);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int
|
|
+ath5k_pci_resume(struct pci_dev *pdev)
|
|
+{
|
|
+ struct ieee80211_hw *hw = pci_get_drvdata(pdev);
|
|
+ struct ath5k_softc *sc = hw->priv;
|
|
+ int err;
|
|
+
|
|
+ err = pci_set_power_state(pdev, PCI_D0);
|
|
+ if (err)
|
|
+ return err;
|
|
+
|
|
+ err = pci_enable_device(pdev);
|
|
+ if (err)
|
|
+ return err;
|
|
+
|
|
+ pci_restore_state(pdev);
|
|
+ /*
|
|
+ * Suspend/Resume resets the PCI configuration space, so we have to
|
|
+ * re-disable the RETRY_TIMEOUT register (0x41) to keep
|
|
+ * PCI Tx retries from interfering with C3 CPU state
|
|
+ */
|
|
+ pci_write_config_byte(pdev, 0x41, 0);
|
|
+
|
|
+ ath5k_init(sc);
|
|
+ if (test_bit(ATH_STAT_LEDSOFT, sc->status)) {
|
|
+ ath5k_hw_set_gpio_output(sc->ah, sc->led_pin);
|
|
+ ath5k_hw_set_gpio(sc->ah, sc->led_pin, 0);
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+#endif /* CONFIG_PM */
|
|
+
|
|
+
|
|
+
|
|
+/***********************\
|
|
+* Driver Initialization *
|
|
+\***********************/
|
|
+
|
|
+static int
|
|
+ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
|
|
+{
|
|
+ struct ath5k_softc *sc = hw->priv;
|
|
+ struct ath5k_hw *ah = sc->ah;
|
|
+ u8 mac[ETH_ALEN];
|
|
+ unsigned int i;
|
|
+ int ret;
|
|
+
|
|
+ ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "devid 0x%x\n", pdev->device);
|
|
+
|
|
+ /*
|
|
+ * Check if the MAC has multi-rate retry support.
|
|
+ * We do this by trying to setup a fake extended
|
|
+ * descriptor. MAC's that don't have support will
|
|
+ * return false w/o doing anything. MAC's that do
|
|
+ * support it will return true w/o doing anything.
|
|
+ */
|
|
+ if (ah->ah_setup_xtx_desc(ah, NULL, 0, 0, 0, 0, 0, 0))
|
|
+ __set_bit(ATH_STAT_MRRETRY, sc->status);
|
|
+
|
|
+ /*
|
|
+ * Reset the key cache since some parts do not
|
|
+ * reset the contents on initial power up.
|
|
+ */
|
|
+ for (i = 0; i < AR5K_KEYCACHE_SIZE; i++)
|
|
+ ath5k_hw_reset_key(ah, i);
|
|
+
|
|
+ /*
|
|
+ * Collect the channel list. The 802.11 layer
|
|
+ * is resposible for filtering this list based
|
|
+ * on settings like the phy mode and regulatory
|
|
+ * domain restrictions.
|
|
+ */
|
|
+ ret = ath5k_getchannels(hw);
|
|
+ if (ret) {
|
|
+ ATH5K_ERR(sc, "can't get channels\n");
|
|
+ goto err;
|
|
+ }
|
|
+
|
|
+ /* NB: setup here so ath5k_rate_update is happy */
|
|
+ if (test_bit(MODE_IEEE80211A, ah->ah_modes))
|
|
+ ath5k_setcurmode(sc, MODE_IEEE80211A);
|
|
+ else
|
|
+ ath5k_setcurmode(sc, MODE_IEEE80211B);
|
|
+
|
|
+ /*
|
|
+ * Allocate tx+rx descriptors and populate the lists.
|
|
+ */
|
|
+ ret = ath5k_desc_alloc(sc, pdev);
|
|
+ if (ret) {
|
|
+ ATH5K_ERR(sc, "can't allocate descriptors\n");
|
|
+ goto err;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Allocate hardware transmit queues: one queue for
|
|
+ * beacon frames and one data queue for each QoS
|
|
+ * priority. Note that hw functions handle reseting
|
|
+ * these queues at the needed time.
|
|
+ */
|
|
+ ret = ath5k_beaconq_setup(ah);
|
|
+ if (ret < 0) {
|
|
+ ATH5K_ERR(sc, "can't setup a beacon xmit queue\n");
|
|
+ goto err_desc;
|
|
+ }
|
|
+ sc->bhalq = ret;
|
|
+
|
|
+ sc->txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BK);
|
|
+ if (IS_ERR(sc->txq)) {
|
|
+ ATH5K_ERR(sc, "can't setup xmit queue\n");
|
|
+ ret = PTR_ERR(sc->txq);
|
|
+ goto err_bhal;
|
|
+ }
|
|
+
|
|
+ tasklet_init(&sc->rxtq, ath5k_tasklet_rx, (unsigned long)sc);
|
|
+ tasklet_init(&sc->txtq, ath5k_tasklet_tx, (unsigned long)sc);
|
|
+ tasklet_init(&sc->restq, ath5k_tasklet_reset, (unsigned long)sc);
|
|
+ setup_timer(&sc->calib_tim, ath5k_calibrate, (unsigned long)sc);
|
|
+ setup_timer(&sc->led_tim, ath5k_led_off, (unsigned long)sc);
|
|
+
|
|
+ sc->led_on = 0; /* low true */
|
|
+ /*
|
|
+ * Auto-enable soft led processing for IBM cards and for
|
|
+ * 5211 minipci cards.
|
|
+ */
|
|
+ if (pdev->device == PCI_DEVICE_ID_ATHEROS_AR5212_IBM ||
|
|
+ pdev->device == PCI_DEVICE_ID_ATHEROS_AR5211) {
|
|
+ __set_bit(ATH_STAT_LEDSOFT, sc->status);
|
|
+ sc->led_pin = 0;
|
|
+ }
|
|
+ /* Enable softled on PIN1 on HP Compaq nc6xx, nc4000 & nx5000 laptops */
|
|
+ if (pdev->subsystem_vendor == PCI_VENDOR_ID_COMPAQ) {
|
|
+ __set_bit(ATH_STAT_LEDSOFT, sc->status);
|
|
+ sc->led_pin = 0;
|
|
+ }
|
|
+ if (test_bit(ATH_STAT_LEDSOFT, sc->status)) {
|
|
+ ath5k_hw_set_gpio_output(ah, sc->led_pin);
|
|
+ ath5k_hw_set_gpio(ah, sc->led_pin, !sc->led_on);
|
|
+ }
|
|
+
|
|
+ ath5k_hw_get_lladdr(ah, mac);
|
|
+ SET_IEEE80211_PERM_ADDR(hw, mac);
|
|
+ /* All MAC address bits matter for ACKs */
|
|
+ memset(sc->bssidmask, 0xff, ETH_ALEN);
|
|
+ ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask);
|
|
+
|
|
+ ret = ieee80211_register_hw(hw);
|
|
+ if (ret) {
|
|
+ ATH5K_ERR(sc, "can't register ieee80211 hw\n");
|
|
+ goto err_queues;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+err_queues:
|
|
+ ath5k_txq_release(sc);
|
|
+err_bhal:
|
|
+ ath5k_hw_release_tx_queue(ah, sc->bhalq);
|
|
+err_desc:
|
|
+ ath5k_desc_free(sc, pdev);
|
|
+err:
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static void
|
|
+ath5k_detach(struct pci_dev *pdev, struct ieee80211_hw *hw)
|
|
+{
|
|
+ struct ath5k_softc *sc = hw->priv;
|
|
+
|
|
+ /*
|
|
+ * NB: the order of these is important:
|
|
+ * o call the 802.11 layer before detaching ath5k_hw to
|
|
+ * insure callbacks into the driver to delete global
|
|
+ * key cache entries can be handled
|
|
+ * o reclaim the tx queue data structures after calling
|
|
+ * the 802.11 layer as we'll get called back to reclaim
|
|
+ * node state and potentially want to use them
|
|
+ * o to cleanup the tx queues the hal is called, so detach
|
|
+ * it last
|
|
+ * XXX: ??? detach ath5k_hw ???
|
|
+ * Other than that, it's straightforward...
|
|
+ */
|
|
+ ieee80211_unregister_hw(hw);
|
|
+ ath5k_desc_free(sc, pdev);
|
|
+ ath5k_txq_release(sc);
|
|
+ ath5k_hw_release_tx_queue(sc->ah, sc->bhalq);
|
|
+
|
|
+ /*
|
|
+ * NB: can't reclaim these until after ieee80211_ifdetach
|
|
+ * returns because we'll get called back to reclaim node
|
|
+ * state and potentially want to use them.
|
|
+ */
|
|
+}
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+/********************\
|
|
+* Channel/mode setup *
|
|
+\********************/
|
|
+
|
|
+/*
|
|
+ * Convert IEEE channel number to MHz frequency.
|
|
+ */
|
|
+static inline short
|
|
+ath5k_ieee2mhz(short chan)
|
|
+{
|
|
+ if (chan <= 14 || chan >= 27)
|
|
+ return ieee80211chan2mhz(chan);
|
|
+ else
|
|
+ return 2212 + chan * 20;
|
|
+}
|
|
+
|
|
+static unsigned int
|
|
+ath5k_copy_rates(struct ieee80211_rate *rates,
|
|
+ const struct ath5k_rate_table *rt,
|
|
+ unsigned int max)
|
|
+{
|
|
+ unsigned int i, count;
|
|
+
|
|
+ if (rt == NULL)
|
|
+ return 0;
|
|
+
|
|
+ for (i = 0, count = 0; i < rt->rate_count && max > 0; i++) {
|
|
+ if (!rt->rates[i].valid)
|
|
+ continue;
|
|
+ rates->rate = rt->rates[i].rate_kbps / 100;
|
|
+ rates->val = rt->rates[i].rate_code;
|
|
+ rates->flags = rt->rates[i].modulation;
|
|
+ rates++;
|
|
+ count++;
|
|
+ max--;
|
|
+ }
|
|
+
|
|
+ return count;
|
|
+}
|
|
+
|
|
+static unsigned int
|
|
+ath5k_copy_channels(struct ath5k_hw *ah,
|
|
+ struct ieee80211_channel *channels,
|
|
+ unsigned int mode,
|
|
+ unsigned int max)
|
|
+{
|
|
+ static const struct { unsigned int mode, mask, chan; } map[] = {
|
|
+ [MODE_IEEE80211A] = { CHANNEL_OFDM, CHANNEL_OFDM | CHANNEL_TURBO, CHANNEL_A },
|
|
+ [MODE_ATHEROS_TURBO] = { CHANNEL_OFDM|CHANNEL_TURBO, CHANNEL_OFDM | CHANNEL_TURBO, CHANNEL_T },
|
|
+ [MODE_IEEE80211B] = { CHANNEL_CCK, CHANNEL_CCK, CHANNEL_B },
|
|
+ [MODE_IEEE80211G] = { CHANNEL_OFDM, CHANNEL_OFDM, CHANNEL_G },
|
|
+ [MODE_ATHEROS_TURBOG] = { CHANNEL_OFDM | CHANNEL_TURBO, CHANNEL_OFDM | CHANNEL_TURBO, CHANNEL_TG },
|
|
+ };
|
|
+ static const struct ath5k_regchannel chans_2ghz[] =
|
|
+ IEEE80211_CHANNELS_2GHZ;
|
|
+ static const struct ath5k_regchannel chans_5ghz[] =
|
|
+ IEEE80211_CHANNELS_5GHZ;
|
|
+ const struct ath5k_regchannel *chans;
|
|
+ enum ath5k_regdom dmn;
|
|
+ unsigned int i, count, size, chfreq, all, f, ch;
|
|
+
|
|
+ if (!test_bit(mode, ah->ah_modes))
|
|
+ return 0;
|
|
+
|
|
+ all = ah->ah_regdomain == DMN_DEFAULT || CHAN_DEBUG == 1;
|
|
+
|
|
+ switch (mode) {
|
|
+ case MODE_IEEE80211A:
|
|
+ case MODE_ATHEROS_TURBO:
|
|
+ /* 1..220, but 2GHz frequencies are filtered by check_channel */
|
|
+ size = all ? 220 : ARRAY_SIZE(chans_5ghz);
|
|
+ chans = chans_5ghz;
|
|
+ dmn = ath5k_regdom2flag(ah->ah_regdomain,
|
|
+ IEEE80211_CHANNELS_5GHZ_MIN);
|
|
+ chfreq = CHANNEL_5GHZ;
|
|
+ break;
|
|
+ case MODE_IEEE80211B:
|
|
+ case MODE_IEEE80211G:
|
|
+ case MODE_ATHEROS_TURBOG:
|
|
+ size = all ? 26 : ARRAY_SIZE(chans_2ghz);
|
|
+ chans = chans_2ghz;
|
|
+ dmn = ath5k_regdom2flag(ah->ah_regdomain,
|
|
+ IEEE80211_CHANNELS_2GHZ_MIN);
|
|
+ chfreq = CHANNEL_2GHZ;
|
|
+ break;
|
|
+ default:
|
|
+ ATH5K_WARN(ah->ah_sc, "bad mode, not copying channels\n");
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ for (i = 0, count = 0; i < size && max > 0; i++) {
|
|
+ ch = all ? i + 1 : chans[i].chan;
|
|
+ f = ath5k_ieee2mhz(ch);
|
|
+ /* Check if channel is supported by the chipset */
|
|
+ if (!ath5k_channel_ok(ah, f, chfreq))
|
|
+ continue;
|
|
+
|
|
+ /* Match regulation domain */
|
|
+ if (!all && !(IEEE80211_DMN(chans[i].domain) &
|
|
+ IEEE80211_DMN(dmn)))
|
|
+ continue;
|
|
+
|
|
+ if (!all && (chans[i].mode & map[mode].mask) != map[mode].mode)
|
|
+ continue;
|
|
+
|
|
+ /* Write channel and increment counter */
|
|
+ channels->chan = ch;
|
|
+ channels->freq = f;
|
|
+ channels->val = map[mode].chan;
|
|
+ channels++;
|
|
+ count++;
|
|
+ max--;
|
|
+ }
|
|
+
|
|
+ return count;
|
|
+}
|
|
+
|
|
+/* Only tries to register modes our EEPROM says it can support */
|
|
+#define REGISTER_MODE(m) do { \
|
|
+ ret = ath5k_register_mode(hw, m); \
|
|
+ if (ret) \
|
|
+ return ret; \
|
|
+} while (0) \
|
|
+
|
|
+static inline int
|
|
+ath5k_register_mode(struct ieee80211_hw *hw, u8 m)
|
|
+{
|
|
+ struct ath5k_softc *sc = hw->priv;
|
|
+ struct ieee80211_hw_mode *modes = sc->modes;
|
|
+ unsigned int i;
|
|
+ int ret;
|
|
+
|
|
+ if (!test_bit(m, sc->ah->ah_capabilities.cap_mode))
|
|
+ return 0;
|
|
+
|
|
+ for (i = 0; i < NUM_DRIVER_MODES; i++) {
|
|
+ if (modes[i].mode != m || !modes[i].num_channels)
|
|
+ continue;
|
|
+ ret = ieee80211_register_hwmode(hw, &modes[i]);
|
|
+ if (ret) {
|
|
+ ATH5K_ERR(sc, "can't register hwmode %u\n", m);
|
|
+ return ret;
|
|
+ }
|
|
+ return 0;
|
|
+ }
|
|
+ BUG();
|
|
+}
|
|
+
|
|
+static int
|
|
+ath5k_getchannels(struct ieee80211_hw *hw)
|
|
+{
|
|
+ struct ath5k_softc *sc = hw->priv;
|
|
+ struct ath5k_hw *ah = sc->ah;
|
|
+ struct ieee80211_hw_mode *modes = sc->modes;
|
|
+ unsigned int i, max_r, max_c;
|
|
+ int ret;
|
|
+
|
|
+ BUILD_BUG_ON(ARRAY_SIZE(sc->modes) < 3);
|
|
+
|
|
+ /* The order here does not matter */
|
|
+ modes[0].mode = MODE_IEEE80211G;
|
|
+ modes[1].mode = MODE_IEEE80211B;
|
|
+ modes[2].mode = MODE_IEEE80211A;
|
|
+
|
|
+ max_r = ARRAY_SIZE(sc->rates);
|
|
+ max_c = ARRAY_SIZE(sc->channels);
|
|
+
|
|
+ for (i = 0; i < NUM_DRIVER_MODES; i++) {
|
|
+ struct ieee80211_hw_mode *mode = &modes[i];
|
|
+ const struct ath5k_rate_table *hw_rates;
|
|
+
|
|
+ if (i == 0) {
|
|
+ modes[0].rates = sc->rates;
|
|
+ modes->channels = sc->channels;
|
|
+ } else {
|
|
+ struct ieee80211_hw_mode *prev_mode = &modes[i-1];
|
|
+ int prev_num_r = prev_mode->num_rates;
|
|
+ int prev_num_c = prev_mode->num_channels;
|
|
+ mode->rates = &prev_mode->rates[prev_num_r];
|
|
+ mode->channels = &prev_mode->channels[prev_num_c];
|
|
+ }
|
|
+
|
|
+ hw_rates = ath5k_hw_get_rate_table(ah, mode->mode);
|
|
+ mode->num_rates = ath5k_copy_rates(mode->rates, hw_rates,
|
|
+ max_r);
|
|
+ mode->num_channels = ath5k_copy_channels(ah, mode->channels,
|
|
+ mode->mode, max_c);
|
|
+ max_r -= mode->num_rates;
|
|
+ max_c -= mode->num_channels;
|
|
+ }
|
|
+
|
|
+ /* We try to register all modes this driver supports. We don't bother
|
|
+ * with MODE_IEEE80211B for AR5212 as MODE_IEEE80211G already accounts
|
|
+ * for that as per mac80211. Then, REGISTER_MODE() will will actually
|
|
+ * check the eeprom reading for more reliable capability information.
|
|
+ * Order matters here as per mac80211's latest preference. This will
|
|
+ * all hopefullly soon go away. */
|
|
+
|
|
+ REGISTER_MODE(MODE_IEEE80211G);
|
|
+ if (ah->ah_version != AR5K_AR5212)
|
|
+ REGISTER_MODE(MODE_IEEE80211B);
|
|
+ REGISTER_MODE(MODE_IEEE80211A);
|
|
+
|
|
+ ath5k_debug_dump_modes(sc, modes);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Set/change channels. If the channel is really being changed,
|
|
+ * it's done by reseting the chip. To accomplish this we must
|
|
+ * first cleanup any pending DMA, then restart stuff after a la
|
|
+ * ath5k_init.
|
|
+ */
|
|
+static int
|
|
+ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan)
|
|
+{
|
|
+ struct ath5k_hw *ah = sc->ah;
|
|
+ int ret;
|
|
+
|
|
+ ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "%u (%u MHz) -> %u (%u MHz)\n",
|
|
+ sc->curchan->chan, sc->curchan->freq,
|
|
+ chan->chan, chan->freq);
|
|
+
|
|
+ if (chan->freq != sc->curchan->freq || chan->val != sc->curchan->val) {
|
|
+ /*
|
|
+ * To switch channels clear any pending DMA operations;
|
|
+ * wait long enough for the RX fifo to drain, reset the
|
|
+ * hardware at the new frequency, and then re-enable
|
|
+ * the relevant bits of the h/w.
|
|
+ */
|
|
+ ath5k_hw_set_intr(ah, 0); /* disable interrupts */
|
|
+ ath5k_txq_cleanup(sc); /* clear pending tx frames */
|
|
+ ath5k_rx_stop(sc); /* turn off frame recv */
|
|
+ ret = ath5k_hw_reset(ah, sc->opmode, chan, true);
|
|
+ if (ret) {
|
|
+ ATH5K_ERR(sc, "%s: unable to reset channel %u "
|
|
+ "(%u Mhz)\n", __func__, chan->chan, chan->freq);
|
|
+ return ret;
|
|
+ }
|
|
+ sc->curchan = chan;
|
|
+ ath5k_hw_set_txpower_limit(sc->ah, 0);
|
|
+
|
|
+ /*
|
|
+ * Re-enable rx framework.
|
|
+ */
|
|
+ ret = ath5k_rx_start(sc);
|
|
+ if (ret) {
|
|
+ ATH5K_ERR(sc, "%s: unable to restart recv logic\n",
|
|
+ __func__);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Change channels and update the h/w rate map
|
|
+ * if we're switching; e.g. 11a to 11b/g.
|
|
+ *
|
|
+ * XXX needed?
|
|
+ */
|
|
+/* ath5k_chan_change(sc, chan); */
|
|
+
|
|
+ /*
|
|
+ * Re-enable interrupts.
|
|
+ */
|
|
+ ath5k_hw_set_intr(ah, sc->imask);
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static void
|
|
+ath5k_setcurmode(struct ath5k_softc *sc, unsigned int mode)
|
|
+{
|
|
+ if (unlikely(test_bit(ATH_STAT_LEDSOFT, sc->status))) {
|
|
+ /* from Atheros NDIS driver, w/ permission */
|
|
+ static const struct {
|
|
+ u16 rate; /* tx/rx 802.11 rate */
|
|
+ u16 timeOn; /* LED on time (ms) */
|
|
+ u16 timeOff; /* LED off time (ms) */
|
|
+ } blinkrates[] = {
|
|
+ { 108, 40, 10 },
|
|
+ { 96, 44, 11 },
|
|
+ { 72, 50, 13 },
|
|
+ { 48, 57, 14 },
|
|
+ { 36, 67, 16 },
|
|
+ { 24, 80, 20 },
|
|
+ { 22, 100, 25 },
|
|
+ { 18, 133, 34 },
|
|
+ { 12, 160, 40 },
|
|
+ { 10, 200, 50 },
|
|
+ { 6, 240, 58 },
|
|
+ { 4, 267, 66 },
|
|
+ { 2, 400, 100 },
|
|
+ { 0, 500, 130 }
|
|
+ };
|
|
+ const struct ath5k_rate_table *rt =
|
|
+ ath5k_hw_get_rate_table(sc->ah, mode);
|
|
+ unsigned int i, j;
|
|
+
|
|
+ BUG_ON(rt == NULL);
|
|
+
|
|
+ memset(sc->hwmap, 0, sizeof(sc->hwmap));
|
|
+ for (i = 0; i < 32; i++) {
|
|
+ u8 ix = rt->rate_code_to_index[i];
|
|
+ if (ix == 0xff) {
|
|
+ sc->hwmap[i].ledon = msecs_to_jiffies(500);
|
|
+ sc->hwmap[i].ledoff = msecs_to_jiffies(130);
|
|
+ continue;
|
|
+ }
|
|
+ sc->hwmap[i].txflags = IEEE80211_RADIOTAP_F_DATAPAD;
|
|
+ if (SHPREAMBLE_FLAG(ix) || rt->rates[ix].modulation ==
|
|
+ IEEE80211_RATE_OFDM)
|
|
+ sc->hwmap[i].txflags |=
|
|
+ IEEE80211_RADIOTAP_F_SHORTPRE;
|
|
+ /* receive frames include FCS */
|
|
+ sc->hwmap[i].rxflags = sc->hwmap[i].txflags |
|
|
+ IEEE80211_RADIOTAP_F_FCS;
|
|
+ /* setup blink rate table to avoid per-packet lookup */
|
|
+ for (j = 0; j < ARRAY_SIZE(blinkrates) - 1; j++)
|
|
+ if (blinkrates[j].rate == /* XXX why 7f? */
|
|
+ (rt->rates[ix].dot11_rate&0x7f))
|
|
+ break;
|
|
+
|
|
+ sc->hwmap[i].ledon = msecs_to_jiffies(blinkrates[j].
|
|
+ timeOn);
|
|
+ sc->hwmap[i].ledoff = msecs_to_jiffies(blinkrates[j].
|
|
+ timeOff);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ sc->curmode = mode;
|
|
+}
|
|
+
|
|
+static void
|
|
+ath5k_mode_setup(struct ath5k_softc *sc)
|
|
+{
|
|
+ struct ath5k_hw *ah = sc->ah;
|
|
+ u32 rfilt;
|
|
+
|
|
+ /* configure rx filter */
|
|
+ rfilt = sc->filter_flags;
|
|
+ ath5k_hw_set_rx_filter(ah, rfilt);
|
|
+
|
|
+ if (ath5k_hw_hasbssidmask(ah))
|
|
+ ath5k_hw_set_bssid_mask(ah, sc->bssidmask);
|
|
+
|
|
+ /* configure operational mode */
|
|
+ ath5k_hw_set_opmode(ah);
|
|
+
|
|
+ ath5k_hw_set_mcast_filter(ah, 0, 0);
|
|
+ ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "RX filter 0x%x\n", rfilt);
|
|
+}
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+/***************\
|
|
+* Buffers setup *
|
|
+\***************/
|
|
+
|
|
+static int
|
|
+ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
|
|
+{
|
|
+ struct ath5k_hw *ah = sc->ah;
|
|
+ struct sk_buff *skb = bf->skb;
|
|
+ struct ath5k_desc *ds;
|
|
+
|
|
+ if (likely(skb == NULL)) {
|
|
+ unsigned int off;
|
|
+
|
|
+ /*
|
|
+ * Allocate buffer with headroom_needed space for the
|
|
+ * fake physical layer header at the start.
|
|
+ */
|
|
+ skb = dev_alloc_skb(sc->rxbufsize + sc->cachelsz - 1);
|
|
+ if (unlikely(skb == NULL)) {
|
|
+ ATH5K_ERR(sc, "can't alloc skbuff of size %u\n",
|
|
+ sc->rxbufsize + sc->cachelsz - 1);
|
|
+ return -ENOMEM;
|
|
+ }
|
|
+ /*
|
|
+ * Cache-line-align. This is important (for the
|
|
+ * 5210 at least) as not doing so causes bogus data
|
|
+ * in rx'd frames.
|
|
+ */
|
|
+ off = ((unsigned long)skb->data) % sc->cachelsz;
|
|
+ if (off != 0)
|
|
+ skb_reserve(skb, sc->cachelsz - off);
|
|
+
|
|
+ bf->skb = skb;
|
|
+ bf->skbaddr = pci_map_single(sc->pdev,
|
|
+ skb->data, sc->rxbufsize, PCI_DMA_FROMDEVICE);
|
|
+ if (unlikely(pci_dma_mapping_error(bf->skbaddr))) {
|
|
+ ATH5K_ERR(sc, "%s: DMA mapping failed\n", __func__);
|
|
+ dev_kfree_skb(skb);
|
|
+ bf->skb = NULL;
|
|
+ return -ENOMEM;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Setup descriptors. For receive we always terminate
|
|
+ * the descriptor list with a self-linked entry so we'll
|
|
+ * not get overrun under high load (as can happen with a
|
|
+ * 5212 when ANI processing enables PHY error frames).
|
|
+ *
|
|
+ * To insure the last descriptor is self-linked we create
|
|
+ * each descriptor as self-linked and add it to the end. As
|
|
+ * each additional descriptor is added the previous self-linked
|
|
+ * entry is ``fixed'' naturally. This should be safe even
|
|
+ * if DMA is happening. When processing RX interrupts we
|
|
+ * never remove/process the last, self-linked, entry on the
|
|
+ * descriptor list. This insures the hardware always has
|
|
+ * someplace to write a new frame.
|
|
+ */
|
|
+ ds = bf->desc;
|
|
+ ds->ds_link = bf->daddr; /* link to self */
|
|
+ ds->ds_data = bf->skbaddr;
|
|
+ ath5k_hw_setup_rx_desc(ah, ds,
|
|
+ skb_tailroom(skb), /* buffer size */
|
|
+ 0);
|
|
+
|
|
+ if (sc->rxlink != NULL)
|
|
+ *sc->rxlink = bf->daddr;
|
|
+ sc->rxlink = &ds->ds_link;
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int
|
|
+ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,
|
|
+ struct ieee80211_tx_control *ctl)
|
|
+{
|
|
+ struct ath5k_hw *ah = sc->ah;
|
|
+ struct ath5k_txq *txq = sc->txq;
|
|
+ struct ath5k_desc *ds = bf->desc;
|
|
+ struct sk_buff *skb = bf->skb;
|
|
+ unsigned int pktlen, flags, keyidx = AR5K_TXKEYIX_INVALID;
|
|
+ int ret;
|
|
+
|
|
+ flags = AR5K_TXDESC_INTREQ | AR5K_TXDESC_CLRDMASK;
|
|
+ bf->ctl = *ctl;
|
|
+ /* XXX endianness */
|
|
+ bf->skbaddr = pci_map_single(sc->pdev, skb->data, skb->len,
|
|
+ PCI_DMA_TODEVICE);
|
|
+
|
|
+ if (ctl->flags & IEEE80211_TXCTL_NO_ACK)
|
|
+ flags |= AR5K_TXDESC_NOACK;
|
|
+
|
|
+ pktlen = skb->len + FCS_LEN;
|
|
+
|
|
+ if (!(ctl->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT)) {
|
|
+ keyidx = ctl->key_idx;
|
|
+ pktlen += ctl->icv_len;
|
|
+ }
|
|
+
|
|
+ ret = ah->ah_setup_tx_desc(ah, ds, pktlen,
|
|
+ ieee80211_get_hdrlen_from_skb(skb), AR5K_PKT_TYPE_NORMAL,
|
|
+ (ctl->power_level * 2), ctl->tx_rate, ctl->retry_limit, keyidx, 0, flags, 0, 0);
|
|
+ if (ret)
|
|
+ goto err_unmap;
|
|
+
|
|
+ ds->ds_link = 0;
|
|
+ ds->ds_data = bf->skbaddr;
|
|
+
|
|
+ spin_lock_bh(&txq->lock);
|
|
+ list_add_tail(&bf->list, &txq->q);
|
|
+ sc->tx_stats.data[txq->qnum].len++;
|
|
+ if (txq->link == NULL) /* is this first packet? */
|
|
+ ath5k_hw_put_tx_buf(ah, txq->qnum, bf->daddr);
|
|
+ else /* no, so only link it */
|
|
+ *txq->link = bf->daddr;
|
|
+
|
|
+ txq->link = &ds->ds_link;
|
|
+ ath5k_hw_tx_start(ah, txq->qnum);
|
|
+ spin_unlock_bh(&txq->lock);
|
|
+
|
|
+ return 0;
|
|
+err_unmap:
|
|
+ pci_unmap_single(sc->pdev, bf->skbaddr, skb->len, PCI_DMA_TODEVICE);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+/*******************\
|
|
+* Descriptors setup *
|
|
+\*******************/
|
|
+
|
|
+static int
|
|
+ath5k_desc_alloc(struct ath5k_softc *sc, struct pci_dev *pdev)
|
|
+{
|
|
+ struct ath5k_desc *ds;
|
|
+ struct ath5k_buf *bf;
|
|
+ dma_addr_t da;
|
|
+ unsigned int i;
|
|
+ int ret;
|
|
+
|
|
+ /* allocate descriptors */
|
|
+ sc->desc_len = sizeof(struct ath5k_desc) *
|
|
+ (ATH_TXBUF + ATH_RXBUF + ATH_BCBUF + 1);
|
|
+ sc->desc = pci_alloc_consistent(pdev, sc->desc_len, &sc->desc_daddr);
|
|
+ if (sc->desc == NULL) {
|
|
+ ATH5K_ERR(sc, "can't allocate descriptors\n");
|
|
+ ret = -ENOMEM;
|
|
+ goto err;
|
|
+ }
|
|
+ ds = sc->desc;
|
|
+ da = sc->desc_daddr;
|
|
+ ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "DMA map: %p (%zu) -> %llx\n",
|
|
+ ds, sc->desc_len, (unsigned long long)sc->desc_daddr);
|
|
+
|
|
+ bf = kcalloc(1 + ATH_TXBUF + ATH_RXBUF + ATH_BCBUF,
|
|
+ sizeof(struct ath5k_buf), GFP_KERNEL);
|
|
+ if (bf == NULL) {
|
|
+ ATH5K_ERR(sc, "can't allocate bufptr\n");
|
|
+ ret = -ENOMEM;
|
|
+ goto err_free;
|
|
+ }
|
|
+ sc->bufptr = bf;
|
|
+
|
|
+ INIT_LIST_HEAD(&sc->rxbuf);
|
|
+ for (i = 0; i < ATH_RXBUF; i++, bf++, ds++, da += sizeof(*ds)) {
|
|
+ bf->desc = ds;
|
|
+ bf->daddr = da;
|
|
+ list_add_tail(&bf->list, &sc->rxbuf);
|
|
+ }
|
|
+
|
|
+ INIT_LIST_HEAD(&sc->txbuf);
|
|
+ sc->txbuf_len = ATH_TXBUF;
|
|
+ for (i = 0; i < ATH_TXBUF; i++, bf++, ds++,
|
|
+ da += sizeof(*ds)) {
|
|
+ bf->desc = ds;
|
|
+ bf->daddr = da;
|
|
+ list_add_tail(&bf->list, &sc->txbuf);
|
|
+ }
|
|
+
|
|
+ /* beacon buffer */
|
|
+ bf->desc = ds;
|
|
+ bf->daddr = da;
|
|
+ sc->bbuf = bf;
|
|
+
|
|
+ return 0;
|
|
+err_free:
|
|
+ pci_free_consistent(pdev, sc->desc_len, sc->desc, sc->desc_daddr);
|
|
+err:
|
|
+ sc->desc = NULL;
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static void
|
|
+ath5k_desc_free(struct ath5k_softc *sc, struct pci_dev *pdev)
|
|
+{
|
|
+ struct ath5k_buf *bf;
|
|
+
|
|
+ ath5k_txbuf_free(sc, sc->bbuf);
|
|
+ list_for_each_entry(bf, &sc->txbuf, list)
|
|
+ ath5k_txbuf_free(sc, bf);
|
|
+ list_for_each_entry(bf, &sc->rxbuf, list)
|
|
+ ath5k_txbuf_free(sc, bf);
|
|
+
|
|
+ /* Free memory associated with all descriptors */
|
|
+ pci_free_consistent(pdev, sc->desc_len, sc->desc, sc->desc_daddr);
|
|
+
|
|
+ kfree(sc->bufptr);
|
|
+ sc->bufptr = NULL;
|
|
+}
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+/**************\
|
|
+* Queues setup *
|
|
+\**************/
|
|
+
|
|
+static struct ath5k_txq *
|
|
+ath5k_txq_setup(struct ath5k_softc *sc,
|
|
+ int qtype, int subtype)
|
|
+{
|
|
+ struct ath5k_hw *ah = sc->ah;
|
|
+ struct ath5k_txq *txq;
|
|
+ struct ath5k_txq_info qi = {
|
|
+ .tqi_subtype = subtype,
|
|
+ .tqi_aifs = AR5K_TXQ_USEDEFAULT,
|
|
+ .tqi_cw_min = AR5K_TXQ_USEDEFAULT,
|
|
+ .tqi_cw_max = AR5K_TXQ_USEDEFAULT
|
|
+ };
|
|
+ int qnum;
|
|
+
|
|
+ /*
|
|
+ * Enable interrupts only for EOL and DESC conditions.
|
|
+ * We mark tx descriptors to receive a DESC interrupt
|
|
+ * when a tx queue gets deep; otherwise waiting for the
|
|
+ * EOL to reap descriptors. Note that this is done to
|
|
+ * reduce interrupt load and this only defers reaping
|
|
+ * descriptors, never transmitting frames. Aside from
|
|
+ * reducing interrupts this also permits more concurrency.
|
|
+ * The only potential downside is if the tx queue backs
|
|
+ * up in which case the top half of the kernel may backup
|
|
+ * due to a lack of tx descriptors.
|
|
+ */
|
|
+ qi.tqi_flags = AR5K_TXQ_FLAG_TXEOLINT_ENABLE |
|
|
+ AR5K_TXQ_FLAG_TXDESCINT_ENABLE;
|
|
+ qnum = ath5k_hw_setup_tx_queue(ah, qtype, &qi);
|
|
+ if (qnum < 0) {
|
|
+ /*
|
|
+ * NB: don't print a message, this happens
|
|
+ * normally on parts with too few tx queues
|
|
+ */
|
|
+ return ERR_PTR(qnum);
|
|
+ }
|
|
+ if (qnum >= ARRAY_SIZE(sc->txqs)) {
|
|
+ ATH5K_ERR(sc, "hw qnum %u out of range, max %tu!\n",
|
|
+ qnum, ARRAY_SIZE(sc->txqs));
|
|
+ ath5k_hw_release_tx_queue(ah, qnum);
|
|
+ return ERR_PTR(-EINVAL);
|
|
+ }
|
|
+ txq = &sc->txqs[qnum];
|
|
+ if (!txq->setup) {
|
|
+ txq->qnum = qnum;
|
|
+ txq->link = NULL;
|
|
+ INIT_LIST_HEAD(&txq->q);
|
|
+ spin_lock_init(&txq->lock);
|
|
+ txq->setup = true;
|
|
+ }
|
|
+ return &sc->txqs[qnum];
|
|
+}
|
|
+
|
|
+static int
|
|
+ath5k_beaconq_setup(struct ath5k_hw *ah)
|
|
+{
|
|
+ struct ath5k_txq_info qi = {
|
|
+ .tqi_aifs = AR5K_TXQ_USEDEFAULT,
|
|
+ .tqi_cw_min = AR5K_TXQ_USEDEFAULT,
|
|
+ .tqi_cw_max = AR5K_TXQ_USEDEFAULT,
|
|
+ /* NB: for dynamic turbo, don't enable any other interrupts */
|
|
+ .tqi_flags = AR5K_TXQ_FLAG_TXDESCINT_ENABLE
|
|
+ };
|
|
+
|
|
+ return ath5k_hw_setup_tx_queue(ah, AR5K_TX_QUEUE_BEACON, &qi);
|
|
+}
|
|
+
|
|
+static int
|
|
+ath5k_beaconq_config(struct ath5k_softc *sc)
|
|
+{
|
|
+ struct ath5k_hw *ah = sc->ah;
|
|
+ struct ath5k_txq_info qi;
|
|
+ int ret;
|
|
+
|
|
+ ret = ath5k_hw_get_tx_queueprops(ah, sc->bhalq, &qi);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+ if (sc->opmode == IEEE80211_IF_TYPE_AP ||
|
|
+ sc->opmode == IEEE80211_IF_TYPE_IBSS) {
|
|
+ /*
|
|
+ * Always burst out beacon and CAB traffic
|
|
+ * (aifs = cwmin = cwmax = 0)
|
|
+ */
|
|
+ qi.tqi_aifs = 0;
|
|
+ qi.tqi_cw_min = 0;
|
|
+ qi.tqi_cw_max = 0;
|
|
+ }
|
|
+
|
|
+ ret = ath5k_hw_setup_tx_queueprops(ah, sc->bhalq, &qi);
|
|
+ if (ret) {
|
|
+ ATH5K_ERR(sc, "%s: unable to update parameters for beacon "
|
|
+ "hardware queue!\n", __func__);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ return ath5k_hw_reset_tx_queue(ah, sc->bhalq); /* push to h/w */;
|
|
+}
|
|
+
|
|
+static void
|
|
+ath5k_txq_drainq(struct ath5k_softc *sc, struct ath5k_txq *txq)
|
|
+{
|
|
+ struct ath5k_buf *bf, *bf0;
|
|
+
|
|
+ /*
|
|
+ * NB: this assumes output has been stopped and
|
|
+ * we do not need to block ath5k_tx_tasklet
|
|
+ */
|
|
+ spin_lock_bh(&txq->lock);
|
|
+ list_for_each_entry_safe(bf, bf0, &txq->q, list) {
|
|
+ ath5k_debug_printtxbuf(sc, bf, !sc->ah->ah_proc_tx_desc(sc->ah,
|
|
+ bf->desc));
|
|
+
|
|
+ ath5k_txbuf_free(sc, bf);
|
|
+
|
|
+ spin_lock_bh(&sc->txbuflock);
|
|
+ sc->tx_stats.data[txq->qnum].len--;
|
|
+ list_move_tail(&bf->list, &sc->txbuf);
|
|
+ sc->txbuf_len++;
|
|
+ spin_unlock_bh(&sc->txbuflock);
|
|
+ }
|
|
+ txq->link = NULL;
|
|
+ spin_unlock_bh(&txq->lock);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Drain the transmit queues and reclaim resources.
|
|
+ */
|
|
+static void
|
|
+ath5k_txq_cleanup(struct ath5k_softc *sc)
|
|
+{
|
|
+ struct ath5k_hw *ah = sc->ah;
|
|
+ unsigned int i;
|
|
+
|
|
+ /* XXX return value */
|
|
+ if (likely(!test_bit(ATH_STAT_INVALID, sc->status))) {
|
|
+ /* don't touch the hardware if marked invalid */
|
|
+ (void)ath5k_hw_stop_tx_dma(ah, sc->bhalq);
|
|
+ ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "beacon queue %x\n",
|
|
+ ath5k_hw_get_tx_buf(ah, sc->bhalq));
|
|
+ for (i = 0; i < ARRAY_SIZE(sc->txqs); i++)
|
|
+ if (sc->txqs[i].setup) {
|
|
+ ath5k_hw_stop_tx_dma(ah, sc->txqs[i].qnum);
|
|
+ ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "txq [%u] %x, "
|
|
+ "link %p\n",
|
|
+ sc->txqs[i].qnum,
|
|
+ ath5k_hw_get_tx_buf(ah,
|
|
+ sc->txqs[i].qnum),
|
|
+ sc->txqs[i].link);
|
|
+ }
|
|
+ }
|
|
+ ieee80211_start_queues(sc->hw); /* XXX move to callers */
|
|
+
|
|
+ for (i = 0; i < ARRAY_SIZE(sc->txqs); i++)
|
|
+ if (sc->txqs[i].setup)
|
|
+ ath5k_txq_drainq(sc, &sc->txqs[i]);
|
|
+}
|
|
+
|
|
+static void
|
|
+ath5k_txq_release(struct ath5k_softc *sc)
|
|
+{
|
|
+ struct ath5k_txq *txq = sc->txqs;
|
|
+ unsigned int i;
|
|
+
|
|
+ for (i = 0; i < ARRAY_SIZE(sc->txqs); i++, txq++)
|
|
+ if (txq->setup) {
|
|
+ ath5k_hw_release_tx_queue(sc->ah, txq->qnum);
|
|
+ txq->setup = false;
|
|
+ }
|
|
+}
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+/*************\
|
|
+* RX Handling *
|
|
+\*************/
|
|
+
|
|
+/*
|
|
+ * Enable the receive h/w following a reset.
|
|
+ */
|
|
+static int
|
|
+ath5k_rx_start(struct ath5k_softc *sc)
|
|
+{
|
|
+ struct ath5k_hw *ah = sc->ah;
|
|
+ struct ath5k_buf *bf;
|
|
+ int ret;
|
|
+
|
|
+ sc->rxbufsize = roundup(IEEE80211_MAX_LEN, sc->cachelsz);
|
|
+
|
|
+ ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "cachelsz %u rxbufsize %u\n",
|
|
+ sc->cachelsz, sc->rxbufsize);
|
|
+
|
|
+ sc->rxlink = NULL;
|
|
+
|
|
+ spin_lock_bh(&sc->rxbuflock);
|
|
+ list_for_each_entry(bf, &sc->rxbuf, list) {
|
|
+ ret = ath5k_rxbuf_setup(sc, bf);
|
|
+ if (ret != 0) {
|
|
+ spin_unlock_bh(&sc->rxbuflock);
|
|
+ goto err;
|
|
+ }
|
|
+ }
|
|
+ bf = list_first_entry(&sc->rxbuf, struct ath5k_buf, list);
|
|
+ spin_unlock_bh(&sc->rxbuflock);
|
|
+
|
|
+ ath5k_hw_put_rx_buf(ah, bf->daddr);
|
|
+ ath5k_hw_start_rx(ah); /* enable recv descriptors */
|
|
+ ath5k_mode_setup(sc); /* set filters, etc. */
|
|
+ ath5k_hw_start_rx_pcu(ah); /* re-enable PCU/DMA engine */
|
|
+
|
|
+ return 0;
|
|
+err:
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Disable the receive h/w in preparation for a reset.
|
|
+ */
|
|
+static void
|
|
+ath5k_rx_stop(struct ath5k_softc *sc)
|
|
+{
|
|
+ struct ath5k_hw *ah = sc->ah;
|
|
+
|
|
+ ath5k_hw_stop_pcu_recv(ah); /* disable PCU */
|
|
+ ath5k_hw_set_rx_filter(ah, 0); /* clear recv filter */
|
|
+ ath5k_hw_stop_rx_dma(ah); /* disable DMA engine */
|
|
+ mdelay(3); /* 3ms is long enough for 1 frame */
|
|
+
|
|
+ ath5k_debug_printrxbuffs(sc, ah);
|
|
+
|
|
+ sc->rxlink = NULL; /* just in case */
|
|
+}
|
|
+
|
|
+static unsigned int
|
|
+ath5k_rx_decrypted(struct ath5k_softc *sc, struct ath5k_desc *ds,
|
|
+ struct sk_buff *skb)
|
|
+{
|
|
+ struct ieee80211_hdr *hdr = (void *)skb->data;
|
|
+ unsigned int keyix, hlen = ieee80211_get_hdrlen_from_skb(skb);
|
|
+
|
|
+ if (!(ds->ds_rxstat.rs_status & AR5K_RXERR_DECRYPT) &&
|
|
+ ds->ds_rxstat.rs_keyix != AR5K_RXKEYIX_INVALID)
|
|
+ return RX_FLAG_DECRYPTED;
|
|
+
|
|
+ /* Apparently when a default key is used to decrypt the packet
|
|
+ the hw does not set the index used to decrypt. In such cases
|
|
+ get the index from the packet. */
|
|
+ if ((le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_PROTECTED) &&
|
|
+ !(ds->ds_rxstat.rs_status & AR5K_RXERR_DECRYPT) &&
|
|
+ skb->len >= hlen + 4) {
|
|
+ keyix = skb->data[hlen + 3] >> 6;
|
|
+
|
|
+ if (test_bit(keyix, sc->keymap))
|
|
+ return RX_FLAG_DECRYPTED;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static void
|
|
+ath5k_tasklet_rx(unsigned long data)
|
|
+{
|
|
+ struct ieee80211_rx_status rxs = {};
|
|
+ struct sk_buff *skb;
|
|
+ struct ath5k_softc *sc = (void *)data;
|
|
+ struct ath5k_buf *bf;
|
|
+ struct ath5k_desc *ds;
|
|
+ u16 len;
|
|
+ u8 stat;
|
|
+ int ret;
|
|
+ int hdrlen;
|
|
+ int pad;
|
|
+
|
|
+ spin_lock(&sc->rxbuflock);
|
|
+ do {
|
|
+ if (unlikely(list_empty(&sc->rxbuf))) {
|
|
+ ATH5K_WARN(sc, "empty rx buf pool\n");
|
|
+ break;
|
|
+ }
|
|
+ bf = list_first_entry(&sc->rxbuf, struct ath5k_buf, list);
|
|
+ BUG_ON(bf->skb == NULL);
|
|
+ skb = bf->skb;
|
|
+ ds = bf->desc;
|
|
+
|
|
+ /* TODO only one segment */
|
|
+ pci_dma_sync_single_for_cpu(sc->pdev, sc->desc_daddr,
|
|
+ sc->desc_len, PCI_DMA_FROMDEVICE);
|
|
+
|
|
+ if (unlikely(ds->ds_link == bf->daddr)) /* this is the end */
|
|
+ break;
|
|
+
|
|
+ ret = sc->ah->ah_proc_rx_desc(sc->ah, ds);
|
|
+ if (unlikely(ret == -EINPROGRESS))
|
|
+ break;
|
|
+ else if (unlikely(ret)) {
|
|
+ ATH5K_ERR(sc, "error in processing rx descriptor\n");
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ if (unlikely(ds->ds_rxstat.rs_more)) {
|
|
+ ATH5K_WARN(sc, "unsupported jumbo\n");
|
|
+ goto next;
|
|
+ }
|
|
+
|
|
+ stat = ds->ds_rxstat.rs_status;
|
|
+ if (unlikely(stat)) {
|
|
+ if (stat & AR5K_RXERR_PHY)
|
|
+ goto next;
|
|
+ if (stat & AR5K_RXERR_DECRYPT) {
|
|
+ /*
|
|
+ * Decrypt error. If the error occurred
|
|
+ * because there was no hardware key, then
|
|
+ * let the frame through so the upper layers
|
|
+ * can process it. This is necessary for 5210
|
|
+ * parts which have no way to setup a ``clear''
|
|
+ * key cache entry.
|
|
+ *
|
|
+ * XXX do key cache faulting
|
|
+ */
|
|
+ if (ds->ds_rxstat.rs_keyix ==
|
|
+ AR5K_RXKEYIX_INVALID &&
|
|
+ !(stat & AR5K_RXERR_CRC))
|
|
+ goto accept;
|
|
+ }
|
|
+ if (stat & AR5K_RXERR_MIC) {
|
|
+ rxs.flag |= RX_FLAG_MMIC_ERROR;
|
|
+ goto accept;
|
|
+ }
|
|
+
|
|
+ /* let crypto-error packets fall through in MNTR */
|
|
+ if ((stat & ~(AR5K_RXERR_DECRYPT|AR5K_RXERR_MIC)) ||
|
|
+ sc->opmode != IEEE80211_IF_TYPE_MNTR)
|
|
+ goto next;
|
|
+ }
|
|
+accept:
|
|
+ len = ds->ds_rxstat.rs_datalen;
|
|
+ pci_dma_sync_single_for_cpu(sc->pdev, bf->skbaddr, len,
|
|
+ PCI_DMA_FROMDEVICE);
|
|
+ pci_unmap_single(sc->pdev, bf->skbaddr, sc->rxbufsize,
|
|
+ PCI_DMA_FROMDEVICE);
|
|
+ bf->skb = NULL;
|
|
+
|
|
+ skb_put(skb, len);
|
|
+
|
|
+ /*
|
|
+ * the hardware adds a padding to 4 byte boundaries between
|
|
+ * the header and the payload data if the header length is
|
|
+ * not multiples of 4 - remove it
|
|
+ */
|
|
+ hdrlen = ieee80211_get_hdrlen_from_skb(skb);
|
|
+ if (hdrlen & 3) {
|
|
+ pad = hdrlen % 4;
|
|
+ memmove(skb->data + pad, skb->data, hdrlen);
|
|
+ skb_pull(skb, pad);
|
|
+ }
|
|
+
|
|
+ if (sc->opmode == IEEE80211_IF_TYPE_MNTR)
|
|
+ rxs.mactime = ath5k_extend_tsf(sc->ah,
|
|
+ ds->ds_rxstat.rs_tstamp);
|
|
+ else
|
|
+ rxs.mactime = ds->ds_rxstat.rs_tstamp;
|
|
+ rxs.freq = sc->curchan->freq;
|
|
+ rxs.channel = sc->curchan->chan;
|
|
+ rxs.phymode = sc->curmode;
|
|
+
|
|
+ /*
|
|
+ * signal quality:
|
|
+ * the names here are misleading and the usage of these
|
|
+ * values by iwconfig makes it even worse
|
|
+ */
|
|
+ /* noise floor in dBm, from the last noise calibration */
|
|
+ rxs.noise = sc->ah->ah_noise_floor;
|
|
+ /* signal level in dBm */
|
|
+ rxs.ssi = rxs.noise + ds->ds_rxstat.rs_rssi;
|
|
+ /*
|
|
+ * "signal" is actually displayed as Link Quality by iwconfig
|
|
+ * we provide a percentage based on rssi (assuming max rssi 64)
|
|
+ */
|
|
+ rxs.signal = ds->ds_rxstat.rs_rssi * 100 / 64;
|
|
+
|
|
+ rxs.antenna = ds->ds_rxstat.rs_antenna;
|
|
+ rxs.rate = ds->ds_rxstat.rs_rate;
|
|
+ rxs.flag |= ath5k_rx_decrypted(sc, ds, skb);
|
|
+
|
|
+ ath5k_debug_dump_skb(sc, skb, "RX ", 0);
|
|
+
|
|
+ __ieee80211_rx(sc->hw, skb, &rxs);
|
|
+ sc->led_rxrate = ds->ds_rxstat.rs_rate;
|
|
+ ath5k_led_event(sc, ATH_LED_RX);
|
|
+next:
|
|
+ list_move_tail(&bf->list, &sc->rxbuf);
|
|
+ } while (ath5k_rxbuf_setup(sc, bf) == 0);
|
|
+ spin_unlock(&sc->rxbuflock);
|
|
+}
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+/*************\
|
|
+* TX Handling *
|
|
+\*************/
|
|
+
|
|
+static void
|
|
+ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
|
|
+{
|
|
+ struct ieee80211_tx_status txs = {};
|
|
+ struct ath5k_buf *bf, *bf0;
|
|
+ struct ath5k_desc *ds;
|
|
+ struct sk_buff *skb;
|
|
+ int ret;
|
|
+
|
|
+ spin_lock(&txq->lock);
|
|
+ list_for_each_entry_safe(bf, bf0, &txq->q, list) {
|
|
+ ds = bf->desc;
|
|
+
|
|
+ /* TODO only one segment */
|
|
+ pci_dma_sync_single_for_cpu(sc->pdev, sc->desc_daddr,
|
|
+ sc->desc_len, PCI_DMA_FROMDEVICE);
|
|
+ ret = sc->ah->ah_proc_tx_desc(sc->ah, ds);
|
|
+ if (unlikely(ret == -EINPROGRESS))
|
|
+ break;
|
|
+ else if (unlikely(ret)) {
|
|
+ ATH5K_ERR(sc, "error %d while processing queue %u\n",
|
|
+ ret, txq->qnum);
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ skb = bf->skb;
|
|
+ bf->skb = NULL;
|
|
+ pci_unmap_single(sc->pdev, bf->skbaddr, skb->len,
|
|
+ PCI_DMA_TODEVICE);
|
|
+
|
|
+ txs.control = bf->ctl;
|
|
+ txs.retry_count = ds->ds_txstat.ts_shortretry +
|
|
+ ds->ds_txstat.ts_longretry / 6;
|
|
+ if (unlikely(ds->ds_txstat.ts_status)) {
|
|
+ sc->ll_stats.dot11ACKFailureCount++;
|
|
+ if (ds->ds_txstat.ts_status & AR5K_TXERR_XRETRY)
|
|
+ txs.excessive_retries = 1;
|
|
+ else if (ds->ds_txstat.ts_status & AR5K_TXERR_FILT)
|
|
+ txs.flags |= IEEE80211_TX_STATUS_TX_FILTERED;
|
|
+ } else {
|
|
+ txs.flags |= IEEE80211_TX_STATUS_ACK;
|
|
+ txs.ack_signal = ds->ds_txstat.ts_rssi;
|
|
+ }
|
|
+
|
|
+ ieee80211_tx_status(sc->hw, skb, &txs);
|
|
+ sc->tx_stats.data[txq->qnum].count++;
|
|
+
|
|
+ spin_lock(&sc->txbuflock);
|
|
+ sc->tx_stats.data[txq->qnum].len--;
|
|
+ list_move_tail(&bf->list, &sc->txbuf);
|
|
+ sc->txbuf_len++;
|
|
+ spin_unlock(&sc->txbuflock);
|
|
+ }
|
|
+ if (likely(list_empty(&txq->q)))
|
|
+ txq->link = NULL;
|
|
+ spin_unlock(&txq->lock);
|
|
+ if (sc->txbuf_len > ATH_TXBUF / 5)
|
|
+ ieee80211_wake_queues(sc->hw);
|
|
+}
|
|
+
|
|
+static void
|
|
+ath5k_tasklet_tx(unsigned long data)
|
|
+{
|
|
+ struct ath5k_softc *sc = (void *)data;
|
|
+
|
|
+ ath5k_tx_processq(sc, sc->txq);
|
|
+
|
|
+ ath5k_led_event(sc, ATH_LED_TX);
|
|
+}
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+/*****************\
|
|
+* Beacon handling *
|
|
+\*****************/
|
|
+
|
|
+/*
|
|
+ * Setup the beacon frame for transmit.
|
|
+ */
|
|
+static int
|
|
+ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,
|
|
+ struct ieee80211_tx_control *ctl)
|
|
+{
|
|
+ struct sk_buff *skb = bf->skb;
|
|
+ struct ath5k_hw *ah = sc->ah;
|
|
+ struct ath5k_desc *ds;
|
|
+ int ret, antenna = 0;
|
|
+ u32 flags;
|
|
+
|
|
+ bf->skbaddr = pci_map_single(sc->pdev, skb->data, skb->len,
|
|
+ PCI_DMA_TODEVICE);
|
|
+ ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "skb %p [data %p len %u] "
|
|
+ "skbaddr %llx\n", skb, skb->data, skb->len,
|
|
+ (unsigned long long)bf->skbaddr);
|
|
+ if (pci_dma_mapping_error(bf->skbaddr)) {
|
|
+ ATH5K_ERR(sc, "beacon DMA mapping failed\n");
|
|
+ return -EIO;
|
|
+ }
|
|
+
|
|
+ ds = bf->desc;
|
|
+
|
|
+ flags = AR5K_TXDESC_NOACK;
|
|
+ if (sc->opmode == IEEE80211_IF_TYPE_IBSS && ath5k_hw_hasveol(ah)) {
|
|
+ ds->ds_link = bf->daddr; /* self-linked */
|
|
+ flags |= AR5K_TXDESC_VEOL;
|
|
+ /*
|
|
+ * Let hardware handle antenna switching if txantenna is not set
|
|
+ */
|
|
+ } else {
|
|
+ ds->ds_link = 0;
|
|
+ /*
|
|
+ * Switch antenna every 4 beacons if txantenna is not set
|
|
+ * XXX assumes two antennas
|
|
+ */
|
|
+ if (antenna == 0)
|
|
+ antenna = sc->bsent & 4 ? 2 : 1;
|
|
+ }
|
|
+
|
|
+ ds->ds_data = bf->skbaddr;
|
|
+ ret = ah->ah_setup_tx_desc(ah, ds, skb->len + FCS_LEN,
|
|
+ ieee80211_get_hdrlen_from_skb(skb),
|
|
+ AR5K_PKT_TYPE_BEACON, (ctl->power_level * 2), ctl->tx_rate, 1,
|
|
+ AR5K_TXKEYIX_INVALID, antenna, flags, 0, 0);
|
|
+ if (ret)
|
|
+ goto err_unmap;
|
|
+
|
|
+ return 0;
|
|
+err_unmap:
|
|
+ pci_unmap_single(sc->pdev, bf->skbaddr, skb->len, PCI_DMA_TODEVICE);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Transmit a beacon frame at SWBA. Dynamic updates to the
|
|
+ * frame contents are done as needed and the slot time is
|
|
+ * also adjusted based on current state.
|
|
+ *
|
|
+ * this is usually called from interrupt context (ath5k_intr())
|
|
+ * but also from ath5k_beacon_config() in IBSS mode which in turn
|
|
+ * can be called from a tasklet and user context
|
|
+ */
|
|
+static void
|
|
+ath5k_beacon_send(struct ath5k_softc *sc)
|
|
+{
|
|
+ struct ath5k_buf *bf = sc->bbuf;
|
|
+ struct ath5k_hw *ah = sc->ah;
|
|
+
|
|
+ ATH5K_DBG(sc, ATH5K_DEBUG_BEACON_PROC, "in beacon_send\n");
|
|
+
|
|
+ if (unlikely(bf->skb == NULL || sc->opmode == IEEE80211_IF_TYPE_STA ||
|
|
+ sc->opmode == IEEE80211_IF_TYPE_MNTR)) {
|
|
+ ATH5K_WARN(sc, "bf=%p bf_skb=%p\n", bf, bf ? bf->skb : NULL);
|
|
+ return;
|
|
+ }
|
|
+ /*
|
|
+ * Check if the previous beacon has gone out. If
|
|
+ * not don't don't try to post another, skip this
|
|
+ * period and wait for the next. Missed beacons
|
|
+ * indicate a problem and should not occur. If we
|
|
+ * miss too many consecutive beacons reset the device.
|
|
+ */
|
|
+ if (unlikely(ath5k_hw_num_tx_pending(ah, sc->bhalq) != 0)) {
|
|
+ sc->bmisscount++;
|
|
+ ATH5K_DBG(sc, ATH5K_DEBUG_BEACON_PROC,
|
|
+ "missed %u consecutive beacons\n", sc->bmisscount);
|
|
+ if (sc->bmisscount > 3) { /* NB: 3 is a guess */
|
|
+ ATH5K_DBG(sc, ATH5K_DEBUG_BEACON_PROC,
|
|
+ "stuck beacon time (%u missed)\n",
|
|
+ sc->bmisscount);
|
|
+ tasklet_schedule(&sc->restq);
|
|
+ }
|
|
+ return;
|
|
+ }
|
|
+ if (unlikely(sc->bmisscount != 0)) {
|
|
+ ATH5K_DBG(sc, ATH5K_DEBUG_BEACON_PROC,
|
|
+ "resume beacon xmit after %u misses\n",
|
|
+ sc->bmisscount);
|
|
+ sc->bmisscount = 0;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Stop any current dma and put the new frame on the queue.
|
|
+ * This should never fail since we check above that no frames
|
|
+ * are still pending on the queue.
|
|
+ */
|
|
+ if (unlikely(ath5k_hw_stop_tx_dma(ah, sc->bhalq))) {
|
|
+ ATH5K_WARN(sc, "beacon queue %u didn't stop?\n", sc->bhalq);
|
|
+ /* NB: hw still stops DMA, so proceed */
|
|
+ }
|
|
+ pci_dma_sync_single_for_cpu(sc->pdev, bf->skbaddr, bf->skb->len,
|
|
+ PCI_DMA_TODEVICE);
|
|
+
|
|
+ ath5k_hw_put_tx_buf(ah, sc->bhalq, bf->daddr);
|
|
+ ath5k_hw_tx_start(ah, sc->bhalq);
|
|
+ ATH5K_DBG(sc, ATH5K_DEBUG_BEACON_PROC, "TXDP[%u] = %llx (%p)\n",
|
|
+ sc->bhalq, (unsigned long long)bf->daddr, bf->desc);
|
|
+
|
|
+ sc->bsent++;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Configure the beacon and sleep timers.
|
|
+ *
|
|
+ * When operating as an AP this resets the TSF and sets
|
|
+ * up the hardware to notify us when we need to issue beacons.
|
|
+ *
|
|
+ * When operating in station mode this sets up the beacon
|
|
+ * timers according to the timestamp of the last received
|
|
+ * beacon and the current TSF, configures PCF and DTIM
|
|
+ * handling, programs the sleep registers so the hardware
|
|
+ * will wakeup in time to receive beacons, and configures
|
|
+ * the beacon miss handling so we'll receive a BMISS
|
|
+ * interrupt when we stop seeing beacons from the AP
|
|
+ * we've associated with.
|
|
+ */
|
|
+static void
|
|
+ath5k_beacon_config(struct ath5k_softc *sc)
|
|
+{
|
|
+#define TSF_TO_TU(_h, _l) (((_h) << 22) | ((_l) >> 10))
|
|
+ struct ath5k_hw *ah = sc->ah;
|
|
+ u32 uninitialized_var(nexttbtt), intval, tsftu;
|
|
+ u64 tsf;
|
|
+
|
|
+ intval = sc->bintval & AR5K_BEACON_PERIOD;
|
|
+ if (WARN_ON(!intval))
|
|
+ return;
|
|
+
|
|
+ /* current TSF converted to TU */
|
|
+ tsf = ath5k_hw_get_tsf64(ah);
|
|
+ tsftu = TSF_TO_TU((u32)(tsf >> 32), (u32)tsf);
|
|
+
|
|
+ ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "intval %u hw tsftu %u\n",
|
|
+ intval, tsftu);
|
|
+
|
|
+ if (sc->opmode == IEEE80211_IF_TYPE_STA ||
|
|
+ (sc->opmode == IEEE80211_IF_TYPE_IBSS &&
|
|
+ !sc->bbuf->skb)) {
|
|
+ ath5k_hw_set_intr(ah, 0);
|
|
+ sc->imask |= AR5K_INT_BMISS;
|
|
+ sc->bmisscount = 0;
|
|
+ ath5k_hw_set_intr(ah, sc->imask);
|
|
+ } else if (sc->opmode == IEEE80211_IF_TYPE_IBSS /* TODO || AP */) {
|
|
+ ath5k_hw_set_intr(ah, 0);
|
|
+ if (sc->opmode == IEEE80211_IF_TYPE_IBSS) {
|
|
+ /*
|
|
+ * Pull nexttbtt forward to reflect the current
|
|
+ * TSF. Add one intval otherwise the timespan
|
|
+ * can be too short for ibss merges.
|
|
+ */
|
|
+ nexttbtt = tsftu + 2 * intval;
|
|
+
|
|
+ ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "nexttbtt %u "
|
|
+ "intval %u\n", nexttbtt, intval);
|
|
+
|
|
+ /*
|
|
+ * In IBSS mode enable the beacon timers but only
|
|
+ * enable SWBA interrupts if we need to manually
|
|
+ * prepare beacon frames. Otherwise we use a
|
|
+ * self-linked tx descriptor and let the hardware
|
|
+ * deal with things.
|
|
+ */
|
|
+ if (!ath5k_hw_hasveol(ah))
|
|
+ sc->imask |= AR5K_INT_SWBA;
|
|
+ } /* TODO else AP */
|
|
+
|
|
+ intval |= AR5K_BEACON_ENA;
|
|
+
|
|
+ ath5k_beaconq_config(sc);
|
|
+ ath5k_hw_init_beacon(ah, nexttbtt, intval);
|
|
+
|
|
+ sc->bmisscount = 0;
|
|
+ ath5k_hw_set_intr(ah, sc->imask);
|
|
+ /*
|
|
+ * When using a self-linked beacon descriptor in
|
|
+ * ibss mode load it once here.
|
|
+ */
|
|
+ if (sc->opmode == IEEE80211_IF_TYPE_IBSS &&
|
|
+ ath5k_hw_hasveol(ah))
|
|
+ ath5k_beacon_send(sc);
|
|
+ }
|
|
+#undef TSF_TO_TU
|
|
+}
|
|
+
|
|
+/********************\
|
|
+* Interrupt handling *
|
|
+\********************/
|
|
+
|
|
+static int
|
|
+ath5k_init(struct ath5k_softc *sc)
|
|
+{
|
|
+ int ret;
|
|
+
|
|
+ mutex_lock(&sc->lock);
|
|
+
|
|
+ ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "mode %d\n", sc->opmode);
|
|
+
|
|
+ /*
|
|
+ * Stop anything previously setup. This is safe
|
|
+ * no matter this is the first time through or not.
|
|
+ */
|
|
+ ath5k_stop_locked(sc);
|
|
+
|
|
+ /*
|
|
+ * The basic interface to setting the hardware in a good
|
|
+ * state is ``reset''. On return the hardware is known to
|
|
+ * be powered up and with interrupts disabled. This must
|
|
+ * be followed by initialization of the appropriate bits
|
|
+ * and then setup of the interrupt mask.
|
|
+ */
|
|
+ sc->curchan = sc->hw->conf.chan;
|
|
+ ret = ath5k_hw_reset(sc->ah, sc->opmode, sc->curchan, false);
|
|
+ if (ret) {
|
|
+ ATH5K_ERR(sc, "unable to reset hardware: %d\n", ret);
|
|
+ goto done;
|
|
+ }
|
|
+ /*
|
|
+ * This is needed only to setup initial state
|
|
+ * but it's best done after a reset.
|
|
+ */
|
|
+ ath5k_hw_set_txpower_limit(sc->ah, 0);
|
|
+
|
|
+ /*
|
|
+ * Setup the hardware after reset: the key cache
|
|
+ * is filled as needed and the receive engine is
|
|
+ * set going. Frame transmit is handled entirely
|
|
+ * in the frame output path; there's nothing to do
|
|
+ * here except setup the interrupt mask.
|
|
+ */
|
|
+ ret = ath5k_rx_start(sc);
|
|
+ if (ret)
|
|
+ goto done;
|
|
+
|
|
+ /*
|
|
+ * Enable interrupts.
|
|
+ */
|
|
+ sc->imask = AR5K_INT_RX | AR5K_INT_TX | AR5K_INT_RXEOL |
|
|
+ AR5K_INT_RXORN | AR5K_INT_FATAL | AR5K_INT_GLOBAL;
|
|
+
|
|
+ ath5k_hw_set_intr(sc->ah, sc->imask);
|
|
+ /* Set ack to be sent at low bit-rates */
|
|
+ ath5k_hw_set_ack_bitrate_high(sc->ah, false);
|
|
+
|
|
+ mod_timer(&sc->calib_tim, round_jiffies(jiffies +
|
|
+ msecs_to_jiffies(ath5k_calinterval * 1000)));
|
|
+
|
|
+ ret = 0;
|
|
+done:
|
|
+ mutex_unlock(&sc->lock);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static int
|
|
+ath5k_stop_locked(struct ath5k_softc *sc)
|
|
+{
|
|
+ struct ath5k_hw *ah = sc->ah;
|
|
+
|
|
+ ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "invalid %u\n",
|
|
+ test_bit(ATH_STAT_INVALID, sc->status));
|
|
+
|
|
+ /*
|
|
+ * Shutdown the hardware and driver:
|
|
+ * stop output from above
|
|
+ * disable interrupts
|
|
+ * turn off timers
|
|
+ * turn off the radio
|
|
+ * clear transmit machinery
|
|
+ * clear receive machinery
|
|
+ * drain and release tx queues
|
|
+ * reclaim beacon resources
|
|
+ * power down hardware
|
|
+ *
|
|
+ * Note that some of this work is not possible if the
|
|
+ * hardware is gone (invalid).
|
|
+ */
|
|
+ ieee80211_stop_queues(sc->hw);
|
|
+
|
|
+ if (!test_bit(ATH_STAT_INVALID, sc->status)) {
|
|
+ if (test_bit(ATH_STAT_LEDSOFT, sc->status)) {
|
|
+ del_timer_sync(&sc->led_tim);
|
|
+ ath5k_hw_set_gpio(ah, sc->led_pin, !sc->led_on);
|
|
+ __clear_bit(ATH_STAT_LEDBLINKING, sc->status);
|
|
+ }
|
|
+ ath5k_hw_set_intr(ah, 0);
|
|
+ }
|
|
+ ath5k_txq_cleanup(sc);
|
|
+ if (!test_bit(ATH_STAT_INVALID, sc->status)) {
|
|
+ ath5k_rx_stop(sc);
|
|
+ ath5k_hw_phy_disable(ah);
|
|
+ } else
|
|
+ sc->rxlink = NULL;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Stop the device, grabbing the top-level lock to protect
|
|
+ * against concurrent entry through ath5k_init (which can happen
|
|
+ * if another thread does a system call and the thread doing the
|
|
+ * stop is preempted).
|
|
+ */
|
|
+static int
|
|
+ath5k_stop_hw(struct ath5k_softc *sc)
|
|
+{
|
|
+ int ret;
|
|
+
|
|
+ mutex_lock(&sc->lock);
|
|
+ ret = ath5k_stop_locked(sc);
|
|
+ if (ret == 0 && !test_bit(ATH_STAT_INVALID, sc->status)) {
|
|
+ /*
|
|
+ * Set the chip in full sleep mode. Note that we are
|
|
+ * careful to do this only when bringing the interface
|
|
+ * completely to a stop. When the chip is in this state
|
|
+ * it must be carefully woken up or references to
|
|
+ * registers in the PCI clock domain may freeze the bus
|
|
+ * (and system). This varies by chip and is mostly an
|
|
+ * issue with newer parts that go to sleep more quickly.
|
|
+ */
|
|
+ if (sc->ah->ah_mac_srev >= 0x78) {
|
|
+ /*
|
|
+ * XXX
|
|
+ * don't put newer MAC revisions > 7.8 to sleep because
|
|
+ * of the above mentioned problems
|
|
+ */
|
|
+ ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "mac version > 7.8, "
|
|
+ "not putting device to sleep\n");
|
|
+ } else {
|
|
+ ATH5K_DBG(sc, ATH5K_DEBUG_RESET,
|
|
+ "putting device to full sleep\n");
|
|
+ ath5k_hw_set_power(sc->ah, AR5K_PM_FULL_SLEEP, true, 0);
|
|
+ }
|
|
+ }
|
|
+ ath5k_txbuf_free(sc, sc->bbuf);
|
|
+ mutex_unlock(&sc->lock);
|
|
+
|
|
+ del_timer_sync(&sc->calib_tim);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static irqreturn_t
|
|
+ath5k_intr(int irq, void *dev_id)
|
|
+{
|
|
+ struct ath5k_softc *sc = dev_id;
|
|
+ struct ath5k_hw *ah = sc->ah;
|
|
+ enum ath5k_int status;
|
|
+ unsigned int counter = 1000;
|
|
+
|
|
+ if (unlikely(test_bit(ATH_STAT_INVALID, sc->status) ||
|
|
+ !ath5k_hw_is_intr_pending(ah)))
|
|
+ return IRQ_NONE;
|
|
+
|
|
+ do {
|
|
+ /*
|
|
+ * Figure out the reason(s) for the interrupt. Note
|
|
+ * that get_isr returns a pseudo-ISR that may include
|
|
+ * bits we haven't explicitly enabled so we mask the
|
|
+ * value to insure we only process bits we requested.
|
|
+ */
|
|
+ ath5k_hw_get_isr(ah, &status); /* NB: clears IRQ too */
|
|
+ ATH5K_DBG(sc, ATH5K_DEBUG_INTR, "status 0x%x/0x%x\n",
|
|
+ status, sc->imask);
|
|
+ status &= sc->imask; /* discard unasked for bits */
|
|
+ if (unlikely(status & AR5K_INT_FATAL)) {
|
|
+ /*
|
|
+ * Fatal errors are unrecoverable.
|
|
+ * Typically these are caused by DMA errors.
|
|
+ */
|
|
+ tasklet_schedule(&sc->restq);
|
|
+ } else if (unlikely(status & AR5K_INT_RXORN)) {
|
|
+ tasklet_schedule(&sc->restq);
|
|
+ } else {
|
|
+ if (status & AR5K_INT_SWBA) {
|
|
+ /*
|
|
+ * Software beacon alert--time to send a beacon.
|
|
+ * Handle beacon transmission directly; deferring
|
|
+ * this is too slow to meet timing constraints
|
|
+ * under load.
|
|
+ */
|
|
+ ath5k_beacon_send(sc);
|
|
+ }
|
|
+ if (status & AR5K_INT_RXEOL) {
|
|
+ /*
|
|
+ * NB: the hardware should re-read the link when
|
|
+ * RXE bit is written, but it doesn't work at
|
|
+ * least on older hardware revs.
|
|
+ */
|
|
+ sc->rxlink = NULL;
|
|
+ }
|
|
+ if (status & AR5K_INT_TXURN) {
|
|
+ /* bump tx trigger level */
|
|
+ ath5k_hw_update_tx_triglevel(ah, true);
|
|
+ }
|
|
+ if (status & AR5K_INT_RX)
|
|
+ tasklet_schedule(&sc->rxtq);
|
|
+ if (status & AR5K_INT_TX)
|
|
+ tasklet_schedule(&sc->txtq);
|
|
+ if (status & AR5K_INT_BMISS) {
|
|
+ }
|
|
+ if (status & AR5K_INT_MIB) {
|
|
+ /* TODO */
|
|
+ }
|
|
+ }
|
|
+ } while (ath5k_hw_is_intr_pending(ah) && counter-- > 0);
|
|
+
|
|
+ if (unlikely(!counter))
|
|
+ ATH5K_WARN(sc, "too many interrupts, giving up for now\n");
|
|
+
|
|
+ return IRQ_HANDLED;
|
|
+}
|
|
+
|
|
+static void
|
|
+ath5k_tasklet_reset(unsigned long data)
|
|
+{
|
|
+ struct ath5k_softc *sc = (void *)data;
|
|
+
|
|
+ ath5k_reset(sc->hw);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Periodically recalibrate the PHY to account
|
|
+ * for temperature/environment changes.
|
|
+ */
|
|
+static void
|
|
+ath5k_calibrate(unsigned long data)
|
|
+{
|
|
+ struct ath5k_softc *sc = (void *)data;
|
|
+ struct ath5k_hw *ah = sc->ah;
|
|
+
|
|
+ ATH5K_DBG(sc, ATH5K_DEBUG_CALIBRATE, "channel %u/%x\n",
|
|
+ sc->curchan->chan, sc->curchan->val);
|
|
+
|
|
+ if (ath5k_hw_get_rf_gain(ah) == AR5K_RFGAIN_NEED_CHANGE) {
|
|
+ /*
|
|
+ * Rfgain is out of bounds, reset the chip
|
|
+ * to load new gain values.
|
|
+ */
|
|
+ ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "calibration, resetting\n");
|
|
+ ath5k_reset(sc->hw);
|
|
+ }
|
|
+ if (ath5k_hw_phy_calibrate(ah, sc->curchan))
|
|
+ ATH5K_ERR(sc, "calibration of channel %u failed\n",
|
|
+ sc->curchan->chan);
|
|
+
|
|
+ mod_timer(&sc->calib_tim, round_jiffies(jiffies +
|
|
+ msecs_to_jiffies(ath5k_calinterval * 1000)));
|
|
+}
|
|
+
|
|
+
|
|
+
|
|
+/***************\
|
|
+* LED functions *
|
|
+\***************/
|
|
+
|
|
+static void
|
|
+ath5k_led_off(unsigned long data)
|
|
+{
|
|
+ struct ath5k_softc *sc = (void *)data;
|
|
+
|
|
+ if (test_bit(ATH_STAT_LEDENDBLINK, sc->status))
|
|
+ __clear_bit(ATH_STAT_LEDBLINKING, sc->status);
|
|
+ else {
|
|
+ __set_bit(ATH_STAT_LEDENDBLINK, sc->status);
|
|
+ ath5k_hw_set_gpio(sc->ah, sc->led_pin, !sc->led_on);
|
|
+ mod_timer(&sc->led_tim, jiffies + sc->led_off);
|
|
+ }
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Blink the LED according to the specified on/off times.
|
|
+ */
|
|
+static void
|
|
+ath5k_led_blink(struct ath5k_softc *sc, unsigned int on,
|
|
+ unsigned int off)
|
|
+{
|
|
+ ATH5K_DBG(sc, ATH5K_DEBUG_LED, "on %u off %u\n", on, off);
|
|
+ ath5k_hw_set_gpio(sc->ah, sc->led_pin, sc->led_on);
|
|
+ __set_bit(ATH_STAT_LEDBLINKING, sc->status);
|
|
+ __clear_bit(ATH_STAT_LEDENDBLINK, sc->status);
|
|
+ sc->led_off = off;
|
|
+ mod_timer(&sc->led_tim, jiffies + on);
|
|
+}
|
|
+
|
|
+static void
|
|
+ath5k_led_event(struct ath5k_softc *sc, int event)
|
|
+{
|
|
+ if (likely(!test_bit(ATH_STAT_LEDSOFT, sc->status)))
|
|
+ return;
|
|
+ if (unlikely(test_bit(ATH_STAT_LEDBLINKING, sc->status)))
|
|
+ return; /* don't interrupt active blink */
|
|
+ switch (event) {
|
|
+ case ATH_LED_TX:
|
|
+ ath5k_led_blink(sc, sc->hwmap[sc->led_txrate].ledon,
|
|
+ sc->hwmap[sc->led_txrate].ledoff);
|
|
+ break;
|
|
+ case ATH_LED_RX:
|
|
+ ath5k_led_blink(sc, sc->hwmap[sc->led_rxrate].ledon,
|
|
+ sc->hwmap[sc->led_rxrate].ledoff);
|
|
+ break;
|
|
+ }
|
|
+}
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+/********************\
|
|
+* Mac80211 functions *
|
|
+\********************/
|
|
+
|
|
+static int
|
|
+ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
|
|
+ struct ieee80211_tx_control *ctl)
|
|
+{
|
|
+ struct ath5k_softc *sc = hw->priv;
|
|
+ struct ath5k_buf *bf;
|
|
+ unsigned long flags;
|
|
+ int hdrlen;
|
|
+ int pad;
|
|
+
|
|
+ ath5k_debug_dump_skb(sc, skb, "TX ", 1);
|
|
+
|
|
+ if (sc->opmode == IEEE80211_IF_TYPE_MNTR)
|
|
+ ATH5K_DBG(sc, ATH5K_DEBUG_XMIT, "tx in monitor (scan?)\n");
|
|
+
|
|
+ /*
|
|
+ * the hardware expects the header padded to 4 byte boundaries
|
|
+ * if this is not the case we add the padding after the header
|
|
+ */
|
|
+ hdrlen = ieee80211_get_hdrlen_from_skb(skb);
|
|
+ if (hdrlen & 3) {
|
|
+ pad = hdrlen % 4;
|
|
+ if (skb_headroom(skb) < pad) {
|
|
+ ATH5K_ERR(sc, "tx hdrlen not %%4: %d not enough"
|
|
+ " headroom to pad %d\n", hdrlen, pad);
|
|
+ return -1;
|
|
+ }
|
|
+ skb_push(skb, pad);
|
|
+ memmove(skb->data, skb->data+pad, hdrlen);
|
|
+ }
|
|
+
|
|
+ sc->led_txrate = ctl->tx_rate;
|
|
+
|
|
+ spin_lock_irqsave(&sc->txbuflock, flags);
|
|
+ if (list_empty(&sc->txbuf)) {
|
|
+ ATH5K_ERR(sc, "no further txbuf available, dropping packet\n");
|
|
+ spin_unlock_irqrestore(&sc->txbuflock, flags);
|
|
+ ieee80211_stop_queue(hw, ctl->queue);
|
|
+ return -1;
|
|
+ }
|
|
+ bf = list_first_entry(&sc->txbuf, struct ath5k_buf, list);
|
|
+ list_del(&bf->list);
|
|
+ sc->txbuf_len--;
|
|
+ if (list_empty(&sc->txbuf))
|
|
+ ieee80211_stop_queues(hw);
|
|
+ spin_unlock_irqrestore(&sc->txbuflock, flags);
|
|
+
|
|
+ bf->skb = skb;
|
|
+
|
|
+ if (ath5k_txbuf_setup(sc, bf, ctl)) {
|
|
+ bf->skb = NULL;
|
|
+ spin_lock_irqsave(&sc->txbuflock, flags);
|
|
+ list_add_tail(&bf->list, &sc->txbuf);
|
|
+ sc->txbuf_len++;
|
|
+ spin_unlock_irqrestore(&sc->txbuflock, flags);
|
|
+ dev_kfree_skb_any(skb);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int
|
|
+ath5k_reset(struct ieee80211_hw *hw)
|
|
+{
|
|
+ struct ath5k_softc *sc = hw->priv;
|
|
+ struct ath5k_hw *ah = sc->ah;
|
|
+ int ret;
|
|
+
|
|
+ ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "resetting\n");
|
|
+ /*
|
|
+ * Convert to a hw channel description with the flags
|
|
+ * constrained to reflect the current operating mode.
|
|
+ */
|
|
+ sc->curchan = hw->conf.chan;
|
|
+
|
|
+ ath5k_hw_set_intr(ah, 0);
|
|
+ ath5k_txq_cleanup(sc);
|
|
+ ath5k_rx_stop(sc);
|
|
+
|
|
+ ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, true);
|
|
+ if (unlikely(ret)) {
|
|
+ ATH5K_ERR(sc, "can't reset hardware (%d)\n", ret);
|
|
+ goto err;
|
|
+ }
|
|
+ ath5k_hw_set_txpower_limit(sc->ah, 0);
|
|
+
|
|
+ ret = ath5k_rx_start(sc);
|
|
+ if (unlikely(ret)) {
|
|
+ ATH5K_ERR(sc, "can't start recv logic\n");
|
|
+ goto err;
|
|
+ }
|
|
+ /*
|
|
+ * We may be doing a reset in response to an ioctl
|
|
+ * that changes the channel so update any state that
|
|
+ * might change as a result.
|
|
+ *
|
|
+ * XXX needed?
|
|
+ */
|
|
+/* ath5k_chan_change(sc, c); */
|
|
+ ath5k_beacon_config(sc);
|
|
+ /* intrs are started by ath5k_beacon_config */
|
|
+
|
|
+ ieee80211_wake_queues(hw);
|
|
+
|
|
+ return 0;
|
|
+err:
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static int ath5k_start(struct ieee80211_hw *hw)
|
|
+{
|
|
+ return ath5k_init(hw->priv);
|
|
+}
|
|
+
|
|
+static void ath5k_stop(struct ieee80211_hw *hw)
|
|
+{
|
|
+ ath5k_stop_hw(hw->priv);
|
|
+}
|
|
+
|
|
+static int ath5k_add_interface(struct ieee80211_hw *hw,
|
|
+ struct ieee80211_if_init_conf *conf)
|
|
+{
|
|
+ struct ath5k_softc *sc = hw->priv;
|
|
+ int ret;
|
|
+
|
|
+ mutex_lock(&sc->lock);
|
|
+ if (sc->iface_id) {
|
|
+ ret = 0;
|
|
+ goto end;
|
|
+ }
|
|
+
|
|
+ sc->iface_id = conf->if_id;
|
|
+
|
|
+ switch (conf->type) {
|
|
+ case IEEE80211_IF_TYPE_STA:
|
|
+ case IEEE80211_IF_TYPE_IBSS:
|
|
+ case IEEE80211_IF_TYPE_MNTR:
|
|
+ sc->opmode = conf->type;
|
|
+ break;
|
|
+ default:
|
|
+ ret = -EOPNOTSUPP;
|
|
+ goto end;
|
|
+ }
|
|
+ ret = 0;
|
|
+end:
|
|
+ mutex_unlock(&sc->lock);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static void
|
|
+ath5k_remove_interface(struct ieee80211_hw *hw,
|
|
+ struct ieee80211_if_init_conf *conf)
|
|
+{
|
|
+ struct ath5k_softc *sc = hw->priv;
|
|
+
|
|
+ mutex_lock(&sc->lock);
|
|
+ if (sc->iface_id != conf->if_id)
|
|
+ goto end;
|
|
+
|
|
+ sc->iface_id = 0;
|
|
+end:
|
|
+ mutex_unlock(&sc->lock);
|
|
+}
|
|
+
|
|
+static int
|
|
+ath5k_config(struct ieee80211_hw *hw,
|
|
+ struct ieee80211_conf *conf)
|
|
+{
|
|
+ struct ath5k_softc *sc = hw->priv;
|
|
+
|
|
+ sc->bintval = conf->beacon_int * 1000 / 1024;
|
|
+ ath5k_setcurmode(sc, conf->phymode);
|
|
+
|
|
+ return ath5k_chan_set(sc, conf->chan);
|
|
+}
|
|
+
|
|
+static int
|
|
+ath5k_config_interface(struct ieee80211_hw *hw, int if_id,
|
|
+ struct ieee80211_if_conf *conf)
|
|
+{
|
|
+ struct ath5k_softc *sc = hw->priv;
|
|
+ struct ath5k_hw *ah = sc->ah;
|
|
+ int ret;
|
|
+
|
|
+ /* Set to a reasonable value. Note that this will
|
|
+ * be set to mac80211's value at ath5k_config(). */
|
|
+ sc->bintval = 1000 * 1000 / 1024;
|
|
+ mutex_lock(&sc->lock);
|
|
+ if (sc->iface_id != if_id) {
|
|
+ ret = -EIO;
|
|
+ goto unlock;
|
|
+ }
|
|
+ if (conf->bssid) {
|
|
+ /* Cache for later use during resets */
|
|
+ memcpy(ah->bssid, conf->bssid, ETH_ALEN);
|
|
+ /* XXX: assoc id is set to 0 for now, mac80211 doesn't have
|
|
+ * a clean way of letting us retrieve this yet. */
|
|
+ ath5k_hw_set_associd(ah, ah->bssid, 0);
|
|
+ }
|
|
+ mutex_unlock(&sc->lock);
|
|
+
|
|
+ return ath5k_reset(hw);
|
|
+unlock:
|
|
+ mutex_unlock(&sc->lock);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+#define SUPPORTED_FIF_FLAGS \
|
|
+ FIF_PROMISC_IN_BSS | FIF_ALLMULTI | FIF_FCSFAIL | \
|
|
+ FIF_PLCPFAIL | FIF_CONTROL | FIF_OTHER_BSS | \
|
|
+ FIF_BCN_PRBRESP_PROMISC
|
|
+/*
|
|
+ * o always accept unicast, broadcast, and multicast traffic
|
|
+ * o multicast traffic for all BSSIDs will be enabled if mac80211
|
|
+ * says it should be
|
|
+ * o maintain current state of phy ofdm or phy cck error reception.
|
|
+ * If the hardware detects any of these type of errors then
|
|
+ * ath5k_hw_get_rx_filter() will pass to us the respective
|
|
+ * hardware filters to be able to receive these type of frames.
|
|
+ * o probe request frames are accepted only when operating in
|
|
+ * hostap, adhoc, or monitor modes
|
|
+ * o enable promiscuous mode according to the interface state
|
|
+ * o accept beacons:
|
|
+ * - when operating in adhoc mode so the 802.11 layer creates
|
|
+ * node table entries for peers,
|
|
+ * - when operating in station mode for collecting rssi data when
|
|
+ * the station is otherwise quiet, or
|
|
+ * - when scanning
|
|
+ */
|
|
+static void ath5k_configure_filter(struct ieee80211_hw *hw,
|
|
+ unsigned int changed_flags,
|
|
+ unsigned int *new_flags,
|
|
+ int mc_count, struct dev_mc_list *mclist)
|
|
+{
|
|
+ struct ath5k_softc *sc = hw->priv;
|
|
+ struct ath5k_hw *ah = sc->ah;
|
|
+ u32 mfilt[2], val, rfilt;
|
|
+ u8 pos;
|
|
+ int i;
|
|
+
|
|
+ mfilt[0] = 0;
|
|
+ mfilt[1] = 0;
|
|
+
|
|
+ /* Only deal with supported flags */
|
|
+ changed_flags &= SUPPORTED_FIF_FLAGS;
|
|
+ *new_flags &= SUPPORTED_FIF_FLAGS;
|
|
+
|
|
+ /* If HW detects any phy or radar errors, leave those filters on.
|
|
+ * Also, always enable Unicast, Broadcasts and Multicast
|
|
+ * XXX: move unicast, bssid broadcasts and multicast to mac80211 */
|
|
+ rfilt = (ath5k_hw_get_rx_filter(ah) & (AR5K_RX_FILTER_PHYERR)) |
|
|
+ (AR5K_RX_FILTER_UCAST | AR5K_RX_FILTER_BCAST |
|
|
+ AR5K_RX_FILTER_MCAST);
|
|
+
|
|
+ if (changed_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) {
|
|
+ if (*new_flags & FIF_PROMISC_IN_BSS) {
|
|
+ rfilt |= AR5K_RX_FILTER_PROM;
|
|
+ __set_bit(ATH_STAT_PROMISC, sc->status);
|
|
+ }
|
|
+ else
|
|
+ __clear_bit(ATH_STAT_PROMISC, sc->status);
|
|
+ }
|
|
+
|
|
+ /* Note, AR5K_RX_FILTER_MCAST is already enabled */
|
|
+ if (*new_flags & FIF_ALLMULTI) {
|
|
+ mfilt[0] = ~0;
|
|
+ mfilt[1] = ~0;
|
|
+ } else {
|
|
+ for (i = 0; i < mc_count; i++) {
|
|
+ if (!mclist)
|
|
+ break;
|
|
+ /* calculate XOR of eight 6-bit values */
|
|
+ val = LE_READ_4(mclist->dmi_addr + 0);
|
|
+ pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
|
|
+ val = LE_READ_4(mclist->dmi_addr + 3);
|
|
+ pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
|
|
+ pos &= 0x3f;
|
|
+ mfilt[pos / 32] |= (1 << (pos % 32));
|
|
+ /* XXX: we might be able to just do this instead,
|
|
+ * but not sure, needs testing, if we do use this we'd
|
|
+ * neet to inform below to not reset the mcast */
|
|
+ /* ath5k_hw_set_mcast_filterindex(ah,
|
|
+ * mclist->dmi_addr[5]); */
|
|
+ mclist = mclist->next;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /* This is the best we can do */
|
|
+ if (*new_flags & (FIF_FCSFAIL | FIF_PLCPFAIL))
|
|
+ rfilt |= AR5K_RX_FILTER_PHYERR;
|
|
+
|
|
+ /* FIF_BCN_PRBRESP_PROMISC really means to enable beacons
|
|
+ * and probes for any BSSID, this needs testing */
|
|
+ if (*new_flags & FIF_BCN_PRBRESP_PROMISC)
|
|
+ rfilt |= AR5K_RX_FILTER_BEACON | AR5K_RX_FILTER_PROBEREQ;
|
|
+
|
|
+ /* FIF_CONTROL doc says that if FIF_PROMISC_IN_BSS is not
|
|
+ * set we should only pass on control frames for this
|
|
+ * station. This needs testing. I believe right now this
|
|
+ * enables *all* control frames, which is OK.. but
|
|
+ * but we should see if we can improve on granularity */
|
|
+ if (*new_flags & FIF_CONTROL)
|
|
+ rfilt |= AR5K_RX_FILTER_CONTROL;
|
|
+
|
|
+ /* Additional settings per mode -- this is per ath5k */
|
|
+
|
|
+ /* XXX move these to mac80211, and add a beacon IFF flag to mac80211 */
|
|
+
|
|
+ if (sc->opmode == IEEE80211_IF_TYPE_MNTR)
|
|
+ rfilt |= AR5K_RX_FILTER_CONTROL | AR5K_RX_FILTER_BEACON |
|
|
+ AR5K_RX_FILTER_PROBEREQ | AR5K_RX_FILTER_PROM;
|
|
+ if (sc->opmode != IEEE80211_IF_TYPE_STA)
|
|
+ rfilt |= AR5K_RX_FILTER_PROBEREQ;
|
|
+ if (sc->opmode != IEEE80211_IF_TYPE_AP &&
|
|
+ test_bit(ATH_STAT_PROMISC, sc->status))
|
|
+ rfilt |= AR5K_RX_FILTER_PROM;
|
|
+ if (sc->opmode == IEEE80211_IF_TYPE_STA ||
|
|
+ sc->opmode == IEEE80211_IF_TYPE_IBSS) {
|
|
+ rfilt |= AR5K_RX_FILTER_BEACON;
|
|
+ }
|
|
+
|
|
+ /* Set filters */
|
|
+ ath5k_hw_set_rx_filter(ah,rfilt);
|
|
+
|
|
+ /* Set multicast bits */
|
|
+ ath5k_hw_set_mcast_filter(ah, mfilt[0], mfilt[1]);
|
|
+ /* Set the cached hw filter flags, this will alter actually
|
|
+ * be set in HW */
|
|
+ sc->filter_flags = rfilt;
|
|
+}
|
|
+
|
|
+static int
|
|
+ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
|
+ const u8 *local_addr, const u8 *addr,
|
|
+ struct ieee80211_key_conf *key)
|
|
+{
|
|
+ struct ath5k_softc *sc = hw->priv;
|
|
+ int ret = 0;
|
|
+
|
|
+ switch(key->alg) {
|
|
+ case ALG_WEP:
|
|
+ break;
|
|
+ case ALG_TKIP:
|
|
+ case ALG_CCMP:
|
|
+ return -EOPNOTSUPP;
|
|
+ default:
|
|
+ WARN_ON(1);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ mutex_lock(&sc->lock);
|
|
+
|
|
+ switch (cmd) {
|
|
+ case SET_KEY:
|
|
+ ret = ath5k_hw_set_key(sc->ah, key->keyidx, key, addr);
|
|
+ if (ret) {
|
|
+ ATH5K_ERR(sc, "can't set the key\n");
|
|
+ goto unlock;
|
|
+ }
|
|
+ __set_bit(key->keyidx, sc->keymap);
|
|
+ key->hw_key_idx = key->keyidx;
|
|
+ break;
|
|
+ case DISABLE_KEY:
|
|
+ ath5k_hw_reset_key(sc->ah, key->keyidx);
|
|
+ __clear_bit(key->keyidx, sc->keymap);
|
|
+ break;
|
|
+ default:
|
|
+ ret = -EINVAL;
|
|
+ goto unlock;
|
|
+ }
|
|
+
|
|
+unlock:
|
|
+ mutex_unlock(&sc->lock);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static int
|
|
+ath5k_get_stats(struct ieee80211_hw *hw,
|
|
+ struct ieee80211_low_level_stats *stats)
|
|
+{
|
|
+ struct ath5k_softc *sc = hw->priv;
|
|
+
|
|
+ memcpy(stats, &sc->ll_stats, sizeof(sc->ll_stats));
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int
|
|
+ath5k_get_tx_stats(struct ieee80211_hw *hw,
|
|
+ struct ieee80211_tx_queue_stats *stats)
|
|
+{
|
|
+ struct ath5k_softc *sc = hw->priv;
|
|
+
|
|
+ memcpy(stats, &sc->tx_stats, sizeof(sc->tx_stats));
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static u64
|
|
+ath5k_get_tsf(struct ieee80211_hw *hw)
|
|
+{
|
|
+ struct ath5k_softc *sc = hw->priv;
|
|
+
|
|
+ return ath5k_hw_get_tsf64(sc->ah);
|
|
+}
|
|
+
|
|
+static void
|
|
+ath5k_reset_tsf(struct ieee80211_hw *hw)
|
|
+{
|
|
+ struct ath5k_softc *sc = hw->priv;
|
|
+
|
|
+ ath5k_hw_reset_tsf(sc->ah);
|
|
+}
|
|
+
|
|
+static int
|
|
+ath5k_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
|
|
+ struct ieee80211_tx_control *ctl)
|
|
+{
|
|
+ struct ath5k_softc *sc = hw->priv;
|
|
+ int ret;
|
|
+
|
|
+ ath5k_debug_dump_skb(sc, skb, "BC ", 1);
|
|
+
|
|
+ mutex_lock(&sc->lock);
|
|
+
|
|
+ if (sc->opmode != IEEE80211_IF_TYPE_IBSS) {
|
|
+ ret = -EIO;
|
|
+ goto end;
|
|
+ }
|
|
+
|
|
+ ath5k_txbuf_free(sc, sc->bbuf);
|
|
+ sc->bbuf->skb = skb;
|
|
+ ret = ath5k_beacon_setup(sc, sc->bbuf, ctl);
|
|
+ if (ret)
|
|
+ sc->bbuf->skb = NULL;
|
|
+
|
|
+end:
|
|
+ mutex_unlock(&sc->lock);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
diff -up /dev/null linux-2.6.23.noarch/drivers/net/wireless/ath5k/debug.c
|
|
--- /dev/null 2007-12-21 08:33:07.834165456 -0500
|
|
+++ linux-2.6.23.noarch/drivers/net/wireless/ath5k/debug.c 2007-12-21 12:18:50.000000000 -0500
|
|
@@ -0,0 +1,469 @@
|
|
+/*
|
|
+ * Copyright (c) 2007 Bruno Randolf <bruno@thinktube.com>
|
|
+ *
|
|
+ * This file is free software: you may copy, redistribute 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 file is distributed in the hope that it will be useful, but
|
|
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ * General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU General Public License
|
|
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
+ *
|
|
+ *
|
|
+ * This file incorporates work covered by the following copyright and
|
|
+ * permission notice:
|
|
+ *
|
|
+ * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
|
|
+ * Copyright (c) 2004-2005 Atheros Communications, Inc.
|
|
+ * Copyright (c) 2006 Devicescape Software, Inc.
|
|
+ * Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com>
|
|
+ * Copyright (c) 2007 Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
|
|
+ *
|
|
+ * All rights reserved.
|
|
+ *
|
|
+ * Redistribution and use in source and binary forms, with or without
|
|
+ * modification, are permitted provided that the following conditions
|
|
+ * are met:
|
|
+ * 1. Redistributions of source code must retain the above copyright
|
|
+ * notice, this list of conditions and the following disclaimer,
|
|
+ * without modification.
|
|
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
|
+ * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
|
|
+ * redistribution must be conditioned upon including a substantially
|
|
+ * similar Disclaimer requirement for further binary redistribution.
|
|
+ * 3. Neither the names of the above-listed copyright holders nor the names
|
|
+ * of any contributors may be used to endorse or promote products derived
|
|
+ * from this software without specific prior written permission.
|
|
+ *
|
|
+ * Alternatively, this software may be distributed under the terms of the
|
|
+ * GNU General Public License ("GPL") version 2 as published by the Free
|
|
+ * Software Foundation.
|
|
+ *
|
|
+ * NO WARRANTY
|
|
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
|
|
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
|
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
|
|
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
|
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
|
+ * THE POSSIBILITY OF SUCH DAMAGES.
|
|
+ */
|
|
+
|
|
+#include "debug.h"
|
|
+#include "base.h"
|
|
+
|
|
+static unsigned int ath5k_debug;
|
|
+module_param_named(debug, ath5k_debug, uint, 0);
|
|
+
|
|
+
|
|
+#if ATH5K_DEBUG
|
|
+
|
|
+#include <linux/seq_file.h>
|
|
+#include "reg.h"
|
|
+
|
|
+static struct dentry *ath5k_global_debugfs;
|
|
+
|
|
+static int ath5k_debugfs_open(struct inode *inode, struct file *file)
|
|
+{
|
|
+ file->private_data = inode->i_private;
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+
|
|
+/* debugfs: registers */
|
|
+
|
|
+struct reg {
|
|
+ char *name;
|
|
+ int addr;
|
|
+};
|
|
+
|
|
+#define REG_STRUCT_INIT(r) { #r, r }
|
|
+
|
|
+/* just a few random registers, might want to add more */
|
|
+static struct reg regs[] = {
|
|
+ REG_STRUCT_INIT(AR5K_CR),
|
|
+ REG_STRUCT_INIT(AR5K_RXDP),
|
|
+ REG_STRUCT_INIT(AR5K_CFG),
|
|
+ REG_STRUCT_INIT(AR5K_IER),
|
|
+ REG_STRUCT_INIT(AR5K_BCR),
|
|
+ REG_STRUCT_INIT(AR5K_RTSD0),
|
|
+ REG_STRUCT_INIT(AR5K_RTSD1),
|
|
+ REG_STRUCT_INIT(AR5K_TXCFG),
|
|
+ REG_STRUCT_INIT(AR5K_RXCFG),
|
|
+ REG_STRUCT_INIT(AR5K_RXJLA),
|
|
+ REG_STRUCT_INIT(AR5K_MIBC),
|
|
+ REG_STRUCT_INIT(AR5K_TOPS),
|
|
+ REG_STRUCT_INIT(AR5K_RXNOFRM),
|
|
+ REG_STRUCT_INIT(AR5K_TXNOFRM),
|
|
+ REG_STRUCT_INIT(AR5K_RPGTO),
|
|
+ REG_STRUCT_INIT(AR5K_RFCNT),
|
|
+ REG_STRUCT_INIT(AR5K_MISC),
|
|
+ REG_STRUCT_INIT(AR5K_QCUDCU_CLKGT),
|
|
+ REG_STRUCT_INIT(AR5K_ISR),
|
|
+ REG_STRUCT_INIT(AR5K_PISR),
|
|
+ REG_STRUCT_INIT(AR5K_SISR0),
|
|
+ REG_STRUCT_INIT(AR5K_SISR1),
|
|
+ REG_STRUCT_INIT(AR5K_SISR2),
|
|
+ REG_STRUCT_INIT(AR5K_SISR3),
|
|
+ REG_STRUCT_INIT(AR5K_SISR4),
|
|
+ REG_STRUCT_INIT(AR5K_IMR),
|
|
+ REG_STRUCT_INIT(AR5K_PIMR),
|
|
+ REG_STRUCT_INIT(AR5K_SIMR0),
|
|
+ REG_STRUCT_INIT(AR5K_SIMR1),
|
|
+ REG_STRUCT_INIT(AR5K_SIMR2),
|
|
+ REG_STRUCT_INIT(AR5K_SIMR3),
|
|
+ REG_STRUCT_INIT(AR5K_SIMR4),
|
|
+ REG_STRUCT_INIT(AR5K_DCM_ADDR),
|
|
+ REG_STRUCT_INIT(AR5K_DCCFG),
|
|
+ REG_STRUCT_INIT(AR5K_CCFG),
|
|
+ REG_STRUCT_INIT(AR5K_CPC0),
|
|
+ REG_STRUCT_INIT(AR5K_CPC1),
|
|
+ REG_STRUCT_INIT(AR5K_CPC2),
|
|
+ REG_STRUCT_INIT(AR5K_CPC3),
|
|
+ REG_STRUCT_INIT(AR5K_CPCORN),
|
|
+ REG_STRUCT_INIT(AR5K_RESET_CTL),
|
|
+ REG_STRUCT_INIT(AR5K_SLEEP_CTL),
|
|
+ REG_STRUCT_INIT(AR5K_INTPEND),
|
|
+ REG_STRUCT_INIT(AR5K_SFR),
|
|
+ REG_STRUCT_INIT(AR5K_PCICFG),
|
|
+ REG_STRUCT_INIT(AR5K_GPIOCR),
|
|
+ REG_STRUCT_INIT(AR5K_GPIODO),
|
|
+ REG_STRUCT_INIT(AR5K_SREV),
|
|
+};
|
|
+
|
|
+static void *reg_start(struct seq_file *seq, loff_t *pos)
|
|
+{
|
|
+ return *pos < ARRAY_SIZE(regs) ? ®s[*pos] : NULL;
|
|
+}
|
|
+
|
|
+static void reg_stop(struct seq_file *seq, void *p)
|
|
+{
|
|
+ /* nothing to do */
|
|
+}
|
|
+
|
|
+static void *reg_next(struct seq_file *seq, void *p, loff_t *pos)
|
|
+{
|
|
+ ++*pos;
|
|
+ return *pos < ARRAY_SIZE(regs) ? ®s[*pos] : NULL;
|
|
+}
|
|
+
|
|
+static int reg_show(struct seq_file *seq, void *p)
|
|
+{
|
|
+ struct ath5k_softc *sc = seq->private;
|
|
+ struct reg *r = p;
|
|
+ seq_printf(seq, "%-25s0x%08x\n", r->name,
|
|
+ ath5k_hw_reg_read(sc->ah, r->addr));
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static struct seq_operations register_seq_ops = {
|
|
+ .start = reg_start,
|
|
+ .next = reg_next,
|
|
+ .stop = reg_stop,
|
|
+ .show = reg_show
|
|
+};
|
|
+
|
|
+static int open_file_registers(struct inode *inode, struct file *file)
|
|
+{
|
|
+ struct seq_file *s;
|
|
+ int res;
|
|
+ res = seq_open(file, ®ister_seq_ops);
|
|
+ if (res == 0) {
|
|
+ s = file->private_data;
|
|
+ s->private = inode->i_private;
|
|
+ }
|
|
+ return res;
|
|
+}
|
|
+
|
|
+static const struct file_operations fops_registers = {
|
|
+ .open = open_file_registers,
|
|
+ .read = seq_read,
|
|
+ .llseek = seq_lseek,
|
|
+ .release = seq_release,
|
|
+ .owner = THIS_MODULE,
|
|
+};
|
|
+
|
|
+
|
|
+/* debugfs: TSF */
|
|
+
|
|
+static ssize_t read_file_tsf(struct file *file, char __user *user_buf,
|
|
+ size_t count, loff_t *ppos)
|
|
+{
|
|
+ struct ath5k_softc *sc = file->private_data;
|
|
+ char buf[100];
|
|
+ snprintf(buf, 100, "0x%016llx\n", ath5k_hw_get_tsf64(sc->ah));
|
|
+ return simple_read_from_buffer(user_buf, count, ppos, buf, 19);
|
|
+}
|
|
+
|
|
+static ssize_t write_file_tsf(struct file *file,
|
|
+ const char __user *userbuf,
|
|
+ size_t count, loff_t *ppos)
|
|
+{
|
|
+ struct ath5k_softc *sc = file->private_data;
|
|
+ if (strncmp(userbuf, "reset", 5) == 0) {
|
|
+ ath5k_hw_reset_tsf(sc->ah);
|
|
+ printk(KERN_INFO "debugfs reset TSF\n");
|
|
+ }
|
|
+ return count;
|
|
+}
|
|
+
|
|
+static const struct file_operations fops_tsf = {
|
|
+ .read = read_file_tsf,
|
|
+ .write = write_file_tsf,
|
|
+ .open = ath5k_debugfs_open,
|
|
+ .owner = THIS_MODULE,
|
|
+};
|
|
+
|
|
+
|
|
+/* debugfs: beacons */
|
|
+
|
|
+static ssize_t read_file_beacon(struct file *file, char __user *user_buf,
|
|
+ size_t count, loff_t *ppos)
|
|
+{
|
|
+ struct ath5k_softc *sc = file->private_data;
|
|
+ struct ath5k_hw *ah = sc->ah;
|
|
+ char buf[1000];
|
|
+ int len = 0;
|
|
+ unsigned int v;
|
|
+ u64 tsf;
|
|
+
|
|
+ v = ath5k_hw_reg_read(sc->ah, AR5K_BEACON);
|
|
+ len += snprintf(buf+len, sizeof(buf)-len,
|
|
+ "%-24s0x%08x\tintval: %d\tTIM: 0x%x\n",
|
|
+ "AR5K_BEACON", v, v & AR5K_BEACON_PERIOD,
|
|
+ (v & AR5K_BEACON_TIM) >> AR5K_BEACON_TIM_S);
|
|
+
|
|
+ len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\n",
|
|
+ "AR5K_LAST_TSTP", ath5k_hw_reg_read(sc->ah, AR5K_LAST_TSTP));
|
|
+
|
|
+ len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\n\n",
|
|
+ "AR5K_BEACON_CNT", ath5k_hw_reg_read(sc->ah, AR5K_BEACON_CNT));
|
|
+
|
|
+ v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER0);
|
|
+ len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n",
|
|
+ "AR5K_TIMER0 (TBTT)", v, v);
|
|
+
|
|
+ v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER1);
|
|
+ len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n",
|
|
+ "AR5K_TIMER1 (DMA)", v, v >> 3);
|
|
+
|
|
+ v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER2);
|
|
+ len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n",
|
|
+ "AR5K_TIMER2 (SWBA)", v, v >> 3);
|
|
+
|
|
+ v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER3);
|
|
+ len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n",
|
|
+ "AR5K_TIMER3 (ATIM)", v, v);
|
|
+
|
|
+ tsf = ath5k_hw_get_tsf64(sc->ah);
|
|
+ len += snprintf(buf+len, sizeof(buf)-len,
|
|
+ "TSF\t\t0x%016llx\tTU: %08x\n", tsf, (u32)(tsf >> 10));
|
|
+
|
|
+ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
|
+}
|
|
+
|
|
+static ssize_t write_file_beacon(struct file *file,
|
|
+ const char __user *userbuf,
|
|
+ size_t count, loff_t *ppos)
|
|
+{
|
|
+ struct ath5k_softc *sc = file->private_data;
|
|
+ struct ath5k_hw *ah = sc->ah;
|
|
+
|
|
+ if (strncmp(userbuf, "disable", 7) == 0) {
|
|
+ AR5K_REG_DISABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE);
|
|
+ printk(KERN_INFO "debugfs disable beacons\n");
|
|
+ } else if (strncmp(userbuf, "enable", 6) == 0) {
|
|
+ AR5K_REG_ENABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE);
|
|
+ printk(KERN_INFO "debugfs enable beacons\n");
|
|
+ }
|
|
+ return count;
|
|
+}
|
|
+
|
|
+static const struct file_operations fops_beacon = {
|
|
+ .read = read_file_beacon,
|
|
+ .write = write_file_beacon,
|
|
+ .open = ath5k_debugfs_open,
|
|
+ .owner = THIS_MODULE,
|
|
+};
|
|
+
|
|
+
|
|
+/* debugfs: reset */
|
|
+
|
|
+static ssize_t write_file_reset(struct file *file,
|
|
+ const char __user *userbuf,
|
|
+ size_t count, loff_t *ppos)
|
|
+{
|
|
+ struct ath5k_softc *sc = file->private_data;
|
|
+ tasklet_schedule(&sc->restq);
|
|
+ return count;
|
|
+}
|
|
+
|
|
+static const struct file_operations fops_reset = {
|
|
+ .write = write_file_reset,
|
|
+ .open = ath5k_debugfs_open,
|
|
+ .owner = THIS_MODULE,
|
|
+};
|
|
+
|
|
+
|
|
+/* init */
|
|
+
|
|
+void
|
|
+ath5k_debug_init(void)
|
|
+{
|
|
+ ath5k_global_debugfs = debugfs_create_dir("ath5k", NULL);
|
|
+}
|
|
+
|
|
+void
|
|
+ath5k_debug_init_device(struct ath5k_softc *sc)
|
|
+{
|
|
+ sc->debug.level = ath5k_debug;
|
|
+ sc->debug.debugfs_phydir = debugfs_create_dir(wiphy_name(sc->hw->wiphy),
|
|
+ ath5k_global_debugfs);
|
|
+ sc->debug.debugfs_debug = debugfs_create_u32("debug",
|
|
+ 0666, sc->debug.debugfs_phydir, &sc->debug.level);
|
|
+
|
|
+ sc->debug.debugfs_registers = debugfs_create_file("registers", 0444,
|
|
+ sc->debug.debugfs_phydir,
|
|
+ sc, &fops_registers);
|
|
+
|
|
+ sc->debug.debugfs_tsf = debugfs_create_file("tsf", 0666,
|
|
+ sc->debug.debugfs_phydir,
|
|
+ sc, &fops_tsf);
|
|
+
|
|
+ sc->debug.debugfs_beacon = debugfs_create_file("beacon", 0666,
|
|
+ sc->debug.debugfs_phydir,
|
|
+ sc, &fops_beacon);
|
|
+
|
|
+ sc->debug.debugfs_reset = debugfs_create_file("reset", 0222,
|
|
+ sc->debug.debugfs_phydir,
|
|
+ sc, &fops_reset);
|
|
+}
|
|
+
|
|
+void
|
|
+ath5k_debug_finish(void)
|
|
+{
|
|
+ debugfs_remove(ath5k_global_debugfs);
|
|
+}
|
|
+
|
|
+void
|
|
+ath5k_debug_finish_device(struct ath5k_softc *sc)
|
|
+{
|
|
+ debugfs_remove(sc->debug.debugfs_debug);
|
|
+ debugfs_remove(sc->debug.debugfs_registers);
|
|
+ debugfs_remove(sc->debug.debugfs_tsf);
|
|
+ debugfs_remove(sc->debug.debugfs_beacon);
|
|
+ debugfs_remove(sc->debug.debugfs_reset);
|
|
+ debugfs_remove(sc->debug.debugfs_phydir);
|
|
+}
|
|
+
|
|
+
|
|
+/* functions used in other places */
|
|
+
|
|
+void
|
|
+ath5k_debug_dump_modes(struct ath5k_softc *sc, struct ieee80211_hw_mode *modes)
|
|
+{
|
|
+ unsigned int m, i;
|
|
+
|
|
+ if (likely(!(sc->debug.level & ATH5K_DEBUG_DUMPMODES)))
|
|
+ return;
|
|
+
|
|
+ for (m = 0; m < NUM_DRIVER_MODES; m++) {
|
|
+ printk(KERN_DEBUG "Mode %u: channels %d, rates %d\n", m,
|
|
+ modes[m].num_channels, modes[m].num_rates);
|
|
+ printk(KERN_DEBUG " channels:\n");
|
|
+ for (i = 0; i < modes[m].num_channels; i++)
|
|
+ printk(KERN_DEBUG " %3d %d %.4x %.4x\n",
|
|
+ modes[m].channels[i].chan,
|
|
+ modes[m].channels[i].freq,
|
|
+ modes[m].channels[i].val,
|
|
+ modes[m].channels[i].flag);
|
|
+ printk(KERN_DEBUG " rates:\n");
|
|
+ for (i = 0; i < modes[m].num_rates; i++)
|
|
+ printk(KERN_DEBUG " %4d %.4x %.4x %.4x\n",
|
|
+ modes[m].rates[i].rate,
|
|
+ modes[m].rates[i].val,
|
|
+ modes[m].rates[i].flags,
|
|
+ modes[m].rates[i].val2);
|
|
+ }
|
|
+}
|
|
+
|
|
+static inline void
|
|
+ath5k_debug_printrxbuf(struct ath5k_buf *bf, int done)
|
|
+{
|
|
+ struct ath5k_desc *ds = bf->desc;
|
|
+
|
|
+ printk(KERN_DEBUG "R (%p %llx) %08x %08x %08x %08x %08x %08x %c\n",
|
|
+ ds, (unsigned long long)bf->daddr,
|
|
+ ds->ds_link, ds->ds_data, ds->ds_ctl0, ds->ds_ctl1,
|
|
+ ds->ds_hw[0], ds->ds_hw[1],
|
|
+ !done ? ' ' : (ds->ds_rxstat.rs_status == 0) ? '*' : '!');
|
|
+}
|
|
+
|
|
+void
|
|
+ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah)
|
|
+{
|
|
+ struct ath5k_desc *ds;
|
|
+ struct ath5k_buf *bf;
|
|
+ int status;
|
|
+
|
|
+ if (likely(!(sc->debug.level &
|
|
+ (ATH5K_DEBUG_RESET | ATH5K_DEBUG_FATAL))))
|
|
+ return;
|
|
+
|
|
+ printk(KERN_DEBUG "rx queue %x, link %p\n",
|
|
+ ath5k_hw_get_rx_buf(ah), sc->rxlink);
|
|
+
|
|
+ spin_lock_bh(&sc->rxbuflock);
|
|
+ list_for_each_entry(bf, &sc->rxbuf, list) {
|
|
+ ds = bf->desc;
|
|
+ status = ah->ah_proc_rx_desc(ah, ds);
|
|
+ if (!status || (sc->debug.level & ATH5K_DEBUG_FATAL))
|
|
+ ath5k_debug_printrxbuf(bf, status == 0);
|
|
+ }
|
|
+ spin_unlock_bh(&sc->rxbuflock);
|
|
+}
|
|
+
|
|
+void
|
|
+ath5k_debug_dump_skb(struct ath5k_softc *sc,
|
|
+ struct sk_buff *skb, const char *prefix, int tx)
|
|
+{
|
|
+ char buf[16];
|
|
+
|
|
+ if (likely(!((tx && (sc->debug.level & ATH5K_DEBUG_DUMP_TX)) ||
|
|
+ (!tx && (sc->debug.level & ATH5K_DEBUG_DUMP_RX)))))
|
|
+ return;
|
|
+
|
|
+ snprintf(buf, sizeof(buf), "%s %s", wiphy_name(sc->hw->wiphy), prefix);
|
|
+
|
|
+ print_hex_dump_bytes(buf, DUMP_PREFIX_NONE, skb->data,
|
|
+ min(200U, skb->len));
|
|
+
|
|
+ printk(KERN_DEBUG "\n");
|
|
+}
|
|
+
|
|
+void
|
|
+ath5k_debug_printtxbuf(struct ath5k_softc *sc,
|
|
+ struct ath5k_buf *bf, int done)
|
|
+{
|
|
+ struct ath5k_desc *ds = bf->desc;
|
|
+
|
|
+ if (likely(!(sc->debug.level & ATH5K_DEBUG_RESET)))
|
|
+ return;
|
|
+
|
|
+ printk(KERN_DEBUG "T (%p %llx) %08x %08x %08x %08x %08x %08x %08x "
|
|
+ "%08x %c\n", ds, (unsigned long long)bf->daddr, ds->ds_link,
|
|
+ ds->ds_data, ds->ds_ctl0, ds->ds_ctl1,
|
|
+ ds->ds_hw[0], ds->ds_hw[1], ds->ds_hw[2], ds->ds_hw[3],
|
|
+ !done ? ' ' : (ds->ds_txstat.ts_status == 0) ? '*' : '!');
|
|
+}
|
|
+
|
|
+#endif /* if ATH5K_DEBUG */
|
|
diff -up /dev/null linux-2.6.23.noarch/drivers/net/wireless/ath5k/base.h
|
|
--- /dev/null 2007-12-21 08:33:07.834165456 -0500
|
|
+++ linux-2.6.23.noarch/drivers/net/wireless/ath5k/base.h 2007-12-21 12:18:50.000000000 -0500
|
|
@@ -0,0 +1,178 @@
|
|
+/*-
|
|
+ * Copyright (c) 2002-2007 Sam Leffler, Errno Consulting
|
|
+ * All rights reserved.
|
|
+ *
|
|
+ * Redistribution and use in source and binary forms, with or without
|
|
+ * modification, are permitted provided that the following conditions
|
|
+ * are met:
|
|
+ * 1. Redistributions of source code must retain the above copyright
|
|
+ * notice, this list of conditions and the following disclaimer,
|
|
+ * without modification.
|
|
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
|
+ * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
|
|
+ * redistribution must be conditioned upon including a substantially
|
|
+ * similar Disclaimer requirement for further binary redistribution.
|
|
+ * 3. Neither the names of the above-listed copyright holders nor the names
|
|
+ * of any contributors may be used to endorse or promote products derived
|
|
+ * from this software without specific prior written permission.
|
|
+ *
|
|
+ * Alternatively, this software may be distributed under the terms of the
|
|
+ * GNU General Public License ("GPL") version 2 as published by the Free
|
|
+ * Software Foundation.
|
|
+ *
|
|
+ * NO WARRANTY
|
|
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
|
|
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
|
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
|
|
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
|
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
|
+ * THE POSSIBILITY OF SUCH DAMAGES.
|
|
+ *
|
|
+ */
|
|
+
|
|
+/*
|
|
+ * Defintions for the Atheros Wireless LAN controller driver.
|
|
+ */
|
|
+#ifndef _DEV_ATH_ATHVAR_H
|
|
+#define _DEV_ATH_ATHVAR_H
|
|
+
|
|
+#include <linux/interrupt.h>
|
|
+#include <linux/list.h>
|
|
+#include <linux/wireless.h>
|
|
+#include <linux/if_ether.h>
|
|
+
|
|
+#include "ath5k.h"
|
|
+#include "debug.h"
|
|
+
|
|
+#define ATH_RXBUF 40 /* number of RX buffers */
|
|
+#define ATH_TXBUF 200 /* number of TX buffers */
|
|
+#define ATH_BCBUF 1 /* number of beacon buffers */
|
|
+
|
|
+struct ath5k_buf {
|
|
+ struct list_head list;
|
|
+ unsigned int flags; /* tx descriptor flags */
|
|
+ struct ath5k_desc *desc; /* virtual addr of desc */
|
|
+ dma_addr_t daddr; /* physical addr of desc */
|
|
+ struct sk_buff *skb; /* skbuff for buf */
|
|
+ dma_addr_t skbaddr;/* physical addr of skb data */
|
|
+ struct ieee80211_tx_control ctl;
|
|
+};
|
|
+
|
|
+/*
|
|
+ * Data transmit queue state. One of these exists for each
|
|
+ * hardware transmit queue. Packets sent to us from above
|
|
+ * are assigned to queues based on their priority. Not all
|
|
+ * devices support a complete set of hardware transmit queues.
|
|
+ * For those devices the array sc_ac2q will map multiple
|
|
+ * priorities to fewer hardware queues (typically all to one
|
|
+ * hardware queue).
|
|
+ */
|
|
+struct ath5k_txq {
|
|
+ unsigned int qnum; /* hardware q number */
|
|
+ u32 *link; /* link ptr in last TX desc */
|
|
+ struct list_head q; /* transmit queue */
|
|
+ spinlock_t lock; /* lock on q and link */
|
|
+ bool setup;
|
|
+};
|
|
+
|
|
+#if CHAN_DEBUG
|
|
+#define ATH_CHAN_MAX (26+26+26+200+200)
|
|
+#else
|
|
+#define ATH_CHAN_MAX (14+14+14+252+20) /* XXX what's the max? */
|
|
+#endif
|
|
+
|
|
+/* Software Carrier, keeps track of the driver state
|
|
+ * associated with an instance of a device */
|
|
+struct ath5k_softc {
|
|
+ struct pci_dev *pdev; /* for dma mapping */
|
|
+ void __iomem *iobase; /* address of the device */
|
|
+ struct mutex lock; /* dev-level lock */
|
|
+ struct ieee80211_tx_queue_stats tx_stats;
|
|
+ struct ieee80211_low_level_stats ll_stats;
|
|
+ struct ieee80211_hw *hw; /* IEEE 802.11 common */
|
|
+ struct ieee80211_hw_mode modes[NUM_DRIVER_MODES];
|
|
+ struct ieee80211_channel channels[ATH_CHAN_MAX];
|
|
+ struct ieee80211_rate rates[AR5K_MAX_RATES * NUM_DRIVER_MODES];
|
|
+ enum ieee80211_if_types opmode;
|
|
+ struct ath5k_hw *ah; /* Atheros HW */
|
|
+
|
|
+#if ATH5K_DEBUG
|
|
+ struct ath5k_dbg_info debug; /* debug info */
|
|
+#endif
|
|
+
|
|
+ struct ath5k_buf *bufptr; /* allocated buffer ptr */
|
|
+ struct ath5k_desc *desc; /* TX/RX descriptors */
|
|
+ dma_addr_t desc_daddr; /* DMA (physical) address */
|
|
+ size_t desc_len; /* size of TX/RX descriptors */
|
|
+ u16 cachelsz; /* cache line size */
|
|
+
|
|
+ DECLARE_BITMAP(status, 6);
|
|
+#define ATH_STAT_INVALID 0 /* disable hardware accesses */
|
|
+#define ATH_STAT_MRRETRY 1 /* multi-rate retry support */
|
|
+#define ATH_STAT_PROMISC 2
|
|
+#define ATH_STAT_LEDBLINKING 3 /* LED blink operation active */
|
|
+#define ATH_STAT_LEDENDBLINK 4 /* finish LED blink operation */
|
|
+#define ATH_STAT_LEDSOFT 5 /* enable LED gpio status */
|
|
+
|
|
+ unsigned int filter_flags; /* HW flags, AR5K_RX_FILTER_* */
|
|
+ unsigned int curmode; /* current phy mode */
|
|
+ struct ieee80211_channel *curchan; /* current h/w channel */
|
|
+
|
|
+ int iface_id; /* add/remove_interface id */
|
|
+
|
|
+ struct {
|
|
+ u8 rxflags; /* radiotap rx flags */
|
|
+ u8 txflags; /* radiotap tx flags */
|
|
+ u16 ledon; /* softled on time */
|
|
+ u16 ledoff; /* softled off time */
|
|
+ } hwmap[32]; /* h/w rate ix mappings */
|
|
+
|
|
+ enum ath5k_int imask; /* interrupt mask copy */
|
|
+
|
|
+ DECLARE_BITMAP(keymap, AR5K_KEYCACHE_SIZE); /* key use bit map */
|
|
+
|
|
+ u8 bssidmask[ETH_ALEN];
|
|
+
|
|
+ unsigned int led_pin, /* GPIO pin for driving LED */
|
|
+ led_on, /* pin setting for LED on */
|
|
+ led_off; /* off time for current blink */
|
|
+ struct timer_list led_tim; /* led off timer */
|
|
+ u8 led_rxrate; /* current rx rate for LED */
|
|
+ u8 led_txrate; /* current tx rate for LED */
|
|
+
|
|
+ struct tasklet_struct restq; /* reset tasklet */
|
|
+
|
|
+ unsigned int rxbufsize; /* rx size based on mtu */
|
|
+ struct list_head rxbuf; /* receive buffer */
|
|
+ spinlock_t rxbuflock;
|
|
+ u32 *rxlink; /* link ptr in last RX desc */
|
|
+ struct tasklet_struct rxtq; /* rx intr tasklet */
|
|
+
|
|
+ struct list_head txbuf; /* transmit buffer */
|
|
+ spinlock_t txbuflock;
|
|
+ unsigned int txbuf_len; /* buf count in txbuf list */
|
|
+ struct ath5k_txq txqs[2]; /* beacon and tx */
|
|
+
|
|
+ struct ath5k_txq *txq; /* beacon and tx*/
|
|
+ struct tasklet_struct txtq; /* tx intr tasklet */
|
|
+
|
|
+ struct ath5k_buf *bbuf; /* beacon buffer */
|
|
+ unsigned int bhalq, /* SW q for outgoing beacons */
|
|
+ bmisscount, /* missed beacon transmits */
|
|
+ bintval, /* beacon interval */
|
|
+ bsent;
|
|
+
|
|
+ struct timer_list calib_tim; /* calibration timer */
|
|
+};
|
|
+
|
|
+#define ath5k_hw_hasbssidmask(_ah) \
|
|
+ (ath5k_hw_get_capability(_ah, AR5K_CAP_BSSIDMASK, 0, NULL) == 0)
|
|
+#define ath5k_hw_hasveol(_ah) \
|
|
+ (ath5k_hw_get_capability(_ah, AR5K_CAP_VEOL, 0, NULL) == 0)
|
|
+
|
|
+#endif
|
|
diff -up /dev/null linux-2.6.23.noarch/drivers/net/wireless/ath5k/regdom.c
|
|
--- /dev/null 2007-12-21 08:33:07.834165456 -0500
|
|
+++ linux-2.6.23.noarch/drivers/net/wireless/ath5k/regdom.c 2007-12-21 12:18:50.000000000 -0500
|
|
@@ -0,0 +1,121 @@
|
|
+/*
|
|
+ * Copyright (c) 2004, 2005 Reyk Floeter <reyk@vantronix.net>
|
|
+ *
|
|
+ * Permission to use, copy, modify, and distribute this software for any
|
|
+ * purpose with or without fee is hereby granted, provided that the above
|
|
+ * copyright notice and this permission notice appear in all copies.
|
|
+ *
|
|
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
+ */
|
|
+
|
|
+/*
|
|
+ * Basic regulation domain extensions for the IEEE 802.11 stack
|
|
+ */
|
|
+
|
|
+#include <linux/kernel.h>
|
|
+#include <linux/string.h>
|
|
+
|
|
+#include "regdom.h"
|
|
+
|
|
+static const struct ath5k_regdommap {
|
|
+ enum ath5k_regdom dmn;
|
|
+ enum ath5k_regdom dmn5;
|
|
+ enum ath5k_regdom dmn2;
|
|
+} r_map[] = {
|
|
+ { DMN_DEFAULT, DMN_DEBUG, DMN_DEBUG },
|
|
+ { DMN_NULL_WORLD, DMN_NULL, DMN_WORLD },
|
|
+ { DMN_NULL_ETSIB, DMN_NULL, DMN_ETSIB },
|
|
+ { DMN_NULL_ETSIC, DMN_NULL, DMN_ETSIC },
|
|
+ { DMN_FCC1_FCCA, DMN_FCC1, DMN_FCCA },
|
|
+ { DMN_FCC1_WORLD, DMN_FCC1, DMN_WORLD },
|
|
+ { DMN_FCC2_FCCA, DMN_FCC2, DMN_FCCA },
|
|
+ { DMN_FCC2_WORLD, DMN_FCC2, DMN_WORLD },
|
|
+ { DMN_FCC2_ETSIC, DMN_FCC2, DMN_ETSIC },
|
|
+ { DMN_FRANCE_NULL, DMN_ETSI3, DMN_ETSI3 },
|
|
+ { DMN_FCC3_FCCA, DMN_FCC3, DMN_WORLD },
|
|
+ { DMN_ETSI1_WORLD, DMN_ETSI1, DMN_WORLD },
|
|
+ { DMN_ETSI3_ETSIA, DMN_ETSI3, DMN_WORLD },
|
|
+ { DMN_ETSI2_WORLD, DMN_ETSI2, DMN_WORLD },
|
|
+ { DMN_ETSI3_WORLD, DMN_ETSI3, DMN_WORLD },
|
|
+ { DMN_ETSI4_WORLD, DMN_ETSI4, DMN_WORLD },
|
|
+ { DMN_ETSI4_ETSIC, DMN_ETSI4, DMN_ETSIC },
|
|
+ { DMN_ETSI5_WORLD, DMN_ETSI5, DMN_WORLD },
|
|
+ { DMN_ETSI6_WORLD, DMN_ETSI6, DMN_WORLD },
|
|
+ { DMN_ETSI_NULL, DMN_ETSI1, DMN_ETSI1 },
|
|
+ { DMN_MKK1_MKKA, DMN_MKK1, DMN_MKKA },
|
|
+ { DMN_MKK1_MKKB, DMN_MKK1, DMN_MKKA },
|
|
+ { DMN_APL4_WORLD, DMN_APL4, DMN_WORLD },
|
|
+ { DMN_MKK2_MKKA, DMN_MKK2, DMN_MKKA },
|
|
+ { DMN_APL_NULL, DMN_APL1, DMN_NULL },
|
|
+ { DMN_APL2_WORLD, DMN_APL2, DMN_WORLD },
|
|
+ { DMN_APL2_APLC, DMN_APL2, DMN_WORLD },
|
|
+ { DMN_APL3_WORLD, DMN_APL3, DMN_WORLD },
|
|
+ { DMN_MKK1_FCCA, DMN_MKK1, DMN_FCCA },
|
|
+ { DMN_APL2_APLD, DMN_APL2, DMN_APLD },
|
|
+ { DMN_MKK1_MKKA1, DMN_MKK1, DMN_MKKA },
|
|
+ { DMN_MKK1_MKKA2, DMN_MKK1, DMN_MKKA },
|
|
+ { DMN_APL1_WORLD, DMN_APL1, DMN_WORLD },
|
|
+ { DMN_APL1_FCCA, DMN_APL1, DMN_FCCA },
|
|
+ { DMN_APL1_APLA, DMN_APL1, DMN_WORLD },
|
|
+ { DMN_APL1_ETSIC, DMN_APL1, DMN_ETSIC },
|
|
+ { DMN_APL2_ETSIC, DMN_APL2, DMN_ETSIC },
|
|
+ { DMN_APL5_WORLD, DMN_APL5, DMN_WORLD },
|
|
+ { DMN_WOR0_WORLD, DMN_WORLD, DMN_WORLD },
|
|
+ { DMN_WOR1_WORLD, DMN_WORLD, DMN_WORLD },
|
|
+ { DMN_WOR2_WORLD, DMN_WORLD, DMN_WORLD },
|
|
+ { DMN_WOR3_WORLD, DMN_WORLD, DMN_WORLD },
|
|
+ { DMN_WOR4_WORLD, DMN_WORLD, DMN_WORLD },
|
|
+ { DMN_WOR5_ETSIC, DMN_WORLD, DMN_WORLD },
|
|
+ { DMN_WOR01_WORLD, DMN_WORLD, DMN_WORLD },
|
|
+ { DMN_WOR02_WORLD, DMN_WORLD, DMN_WORLD },
|
|
+ { DMN_EU1_WORLD, DMN_ETSI1, DMN_WORLD },
|
|
+ { DMN_WOR9_WORLD, DMN_WORLD, DMN_WORLD },
|
|
+ { DMN_WORA_WORLD, DMN_WORLD, DMN_WORLD },
|
|
+};
|
|
+
|
|
+enum ath5k_regdom ath5k_regdom2flag(enum ath5k_regdom dmn, u16 mhz)
|
|
+{
|
|
+ unsigned int i;
|
|
+
|
|
+ for (i = 0; i < ARRAY_SIZE(r_map); i++) {
|
|
+ if (r_map[i].dmn == dmn) {
|
|
+ if (mhz >= 2000 && mhz <= 3000)
|
|
+ return r_map[i].dmn2;
|
|
+ if (mhz >= IEEE80211_CHANNELS_5GHZ_MIN &&
|
|
+ mhz <= IEEE80211_CHANNELS_5GHZ_MAX)
|
|
+ return r_map[i].dmn5;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return DMN_DEBUG;
|
|
+}
|
|
+
|
|
+u16 ath5k_regdom_from_ieee(enum ath5k_regdom ieee)
|
|
+{
|
|
+ u32 regdomain = (u32)ieee;
|
|
+
|
|
+ /*
|
|
+ * Use the default regulation domain if the value is empty
|
|
+ * or not supported by the net80211 regulation code.
|
|
+ */
|
|
+ if (ath5k_regdom2flag(regdomain, IEEE80211_CHANNELS_5GHZ_MIN) ==
|
|
+ DMN_DEBUG)
|
|
+ return (u16)AR5K_TUNE_REGDOMAIN;
|
|
+
|
|
+ /* It is supported, just return the value */
|
|
+ return regdomain;
|
|
+}
|
|
+
|
|
+enum ath5k_regdom ath5k_regdom_to_ieee(u16 regdomain)
|
|
+{
|
|
+ enum ath5k_regdom ieee = (enum ath5k_regdom)regdomain;
|
|
+
|
|
+ return ieee;
|
|
+}
|
|
+
|