From 55315bf3c0a9f0c3073304fd77407941e98dc82b Mon Sep 17 00:00:00 2001 From: Sascha Wildner Date: Mon, 9 Mar 2015 03:06:04 +0100 Subject: [PATCH] kernel: Remove (unhooked) acx(4), bwi(4), iwl(4) and rtw(4). The first three were written by sephe and rtw(4) was ported from NetBSD by him. They were all never ported to the newer wlan(4) upgrades we got, starting with Rui Paulo's back in 2010. Approved-by: sephe --- Makefile_upgrade.inc | 26 +- share/man/man4/Makefile | 10 - share/man/man4/acx.4 | 168 - share/man/man4/bwi.4 | 126 - share/man/man4/bwn.4 | 7 - share/man/man4/iwl.4 | 105 - share/man/man4/rtw.4 | 264 -- share/man/man4/wlan.4 | 4 - share/man/man4/wlan_amrr.4 | 1 - sys/boot/dloader/loader-bootp.conf | 4 - sys/boot/dloader/loader.conf | 4 - sys/conf/files | 11 - sys/config/LINT | 3 - sys/config/LINT64 | 3 - sys/dev/netif/Makefile | 4 - sys/dev/netif/acx/Makefile | 6 - sys/dev/netif/acx/_acxcmd.h | 85 - sys/dev/netif/acx/acx100.c | 859 ------ sys/dev/netif/acx/acx111.c | 781 ----- sys/dev/netif/acx/acxcmd.c | 314 -- sys/dev/netif/acx/acxcmd.h | 333 -- sys/dev/netif/acx/if_acx.c | 2773 ----------------- sys/dev/netif/acx/if_acxreg.h | 161 - sys/dev/netif/acx/if_acxvar.h | 521 ---- sys/dev/netif/bwi/Makefile | 6 - sys/dev/netif/bwi/bwimac.c | 1953 ------------ sys/dev/netif/bwi/bwimac.h | 99 - sys/dev/netif/bwi/bwiphy.c | 1003 ------ sys/dev/netif/bwi/bwiphy.h | 223 -- sys/dev/netif/bwi/bwirf.c | 2664 ---------------- sys/dev/netif/bwi/bwirf.h | 153 - sys/dev/netif/bwi/if_bwi.c | 3959 ------------------------ sys/dev/netif/bwi/if_bwireg.h | 490 --- sys/dev/netif/bwi/if_bwivar.h | 684 ----- sys/dev/netif/iwl/Makefile | 5 - sys/dev/netif/iwl/if_iwl.c | 530 ---- sys/dev/netif/iwl/if_iwlreg.h | 49 - sys/dev/netif/iwl/if_iwlvar.h | 143 - sys/dev/netif/iwl/iwl2100.c | 3677 ---------------------- sys/dev/netif/iwl/iwl2100reg.h | 202 -- sys/dev/netif/iwl/iwl2100var.h | 363 --- sys/dev/netif/rtw/Makefile | 11 - sys/dev/netif/rtw/if_rtw_pci.c | 261 -- sys/dev/netif/rtw/max2820reg.h | 190 -- sys/dev/netif/rtw/rtw.c | 4545 ---------------------------- sys/dev/netif/rtw/rtwphy.c | 812 ----- sys/dev/netif/rtw/rtwphy.h | 44 - sys/dev/netif/rtw/rtwphyio.c | 361 --- sys/dev/netif/rtw/rtwphyio.h | 42 - sys/dev/netif/rtw/rtwreg.h | 1103 ------- sys/dev/netif/rtw/rtwvar.h | 534 ---- sys/dev/netif/rtw/sa2400reg.h | 284 -- sys/dev/netif/rtw/si4136reg.h | 88 - sys/dev/netif/rtw/smc93cx6.c | 181 -- sys/dev/netif/rtw/smc93cx6var.h | 107 - 55 files changed, 12 insertions(+), 31327 deletions(-) delete mode 100644 share/man/man4/acx.4 delete mode 100644 share/man/man4/bwi.4 delete mode 100644 share/man/man4/iwl.4 delete mode 100644 share/man/man4/rtw.4 delete mode 100644 sys/dev/netif/acx/Makefile delete mode 100644 sys/dev/netif/acx/_acxcmd.h delete mode 100644 sys/dev/netif/acx/acx100.c delete mode 100644 sys/dev/netif/acx/acx111.c delete mode 100644 sys/dev/netif/acx/acxcmd.c delete mode 100644 sys/dev/netif/acx/acxcmd.h delete mode 100644 sys/dev/netif/acx/if_acx.c delete mode 100644 sys/dev/netif/acx/if_acxreg.h delete mode 100644 sys/dev/netif/acx/if_acxvar.h delete mode 100644 sys/dev/netif/bwi/Makefile delete mode 100644 sys/dev/netif/bwi/bwimac.c delete mode 100644 sys/dev/netif/bwi/bwimac.h delete mode 100644 sys/dev/netif/bwi/bwiphy.c delete mode 100644 sys/dev/netif/bwi/bwiphy.h delete mode 100644 sys/dev/netif/bwi/bwirf.c delete mode 100644 sys/dev/netif/bwi/bwirf.h delete mode 100644 sys/dev/netif/bwi/if_bwi.c delete mode 100644 sys/dev/netif/bwi/if_bwireg.h delete mode 100644 sys/dev/netif/bwi/if_bwivar.h delete mode 100644 sys/dev/netif/iwl/Makefile delete mode 100644 sys/dev/netif/iwl/if_iwl.c delete mode 100644 sys/dev/netif/iwl/if_iwlreg.h delete mode 100644 sys/dev/netif/iwl/if_iwlvar.h delete mode 100644 sys/dev/netif/iwl/iwl2100.c delete mode 100644 sys/dev/netif/iwl/iwl2100reg.h delete mode 100644 sys/dev/netif/iwl/iwl2100var.h delete mode 100644 sys/dev/netif/rtw/Makefile delete mode 100644 sys/dev/netif/rtw/if_rtw_pci.c delete mode 100644 sys/dev/netif/rtw/max2820reg.h delete mode 100644 sys/dev/netif/rtw/rtw.c delete mode 100644 sys/dev/netif/rtw/rtwphy.c delete mode 100644 sys/dev/netif/rtw/rtwphy.h delete mode 100644 sys/dev/netif/rtw/rtwphyio.c delete mode 100644 sys/dev/netif/rtw/rtwphyio.h delete mode 100644 sys/dev/netif/rtw/rtwreg.h delete mode 100644 sys/dev/netif/rtw/rtwvar.h delete mode 100644 sys/dev/netif/rtw/sa2400reg.h delete mode 100644 sys/dev/netif/rtw/si4136reg.h delete mode 100644 sys/dev/netif/rtw/smc93cx6.c delete mode 100644 sys/dev/netif/rtw/smc93cx6var.h diff --git a/Makefile_upgrade.inc b/Makefile_upgrade.inc index 492af71c20..7ab2f3192c 100644 --- a/Makefile_upgrade.inc +++ b/Makefile_upgrade.inc @@ -2854,6 +2854,18 @@ TO_REMOVE+=/usr/share/man/man8/smrsh.8.gz TO_REMOVE+=/usr/share/sendmail TO_REMOVE+=/usr/share/libg++ TO_REMOVE+=/etc/mail/helpfile +TO_REMOVE+=/boot/kernel/if_acx.ko +TO_REMOVE+=/usr/share/man/cat4/acx.4.gz +TO_REMOVE+=/usr/share/man/man4/acx.4.gz +TO_REMOVE+=/boot/kernel/if_bwi.ko +TO_REMOVE+=/usr/share/man/cat4/bwi.4.gz +TO_REMOVE+=/usr/share/man/man4/bwi.4.gz +TO_REMOVE+=/boot/kernel/if_iwl.ko +TO_REMOVE+=/usr/share/man/cat4/iwl.4.gz +TO_REMOVE+=/usr/share/man/man4/iwl.4.gz +TO_REMOVE+=/boot/kernel/if_rtw.ko +TO_REMOVE+=/usr/share/man/cat4/rtw.4.gz +TO_REMOVE+=/usr/share/man/man4/rtw.4.gz .if ${MACHINE_ARCH} == "x86_64" TO_REMOVE+=/usr/sbin/stlstats @@ -2880,17 +2892,3 @@ TO_REMOVE+=/boot/kernel/ng_sync_sr.ko # XXX Remove when pfsync(4) has been fixed TO_REMOVE+=/usr/share/man/cat4/pfsync.4.gz TO_REMOVE+=/usr/share/man/man4/pfsync.4.gz - -# XXX Remove when adjusted to the new 802.11 framework -TO_REMOVE+=/boot/kernel/if_acx.ko -TO_REMOVE+=/usr/share/man/cat4/acx.4.gz -TO_REMOVE+=/usr/share/man/man4/acx.4.gz -TO_REMOVE+=/boot/kernel/if_bwi.ko -TO_REMOVE+=/usr/share/man/cat4/bwi.4.gz -TO_REMOVE+=/usr/share/man/man4/bwi.4.gz -TO_REMOVE+=/boot/kernel/if_iwl.ko -TO_REMOVE+=/usr/share/man/cat4/iwl.4.gz -TO_REMOVE+=/usr/share/man/man4/iwl.4.gz -TO_REMOVE+=/boot/kernel/if_rtw.ko -TO_REMOVE+=/usr/share/man/cat4/rtw.4.gz -TO_REMOVE+=/usr/share/man/man4/rtw.4.gz diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile index 6c7fd4e1b4..e977e74553 100644 --- a/share/man/man4/Makefile +++ b/share/man/man4/Makefile @@ -403,14 +403,7 @@ MAN= aac.4 \ # XXX re-add when pfsync(4) has been fixed # pfsync.4 \ -# XXX re-add when adjusted to the new 802.11 framework -# acx.4 \ -# bwi.4 \ -# iwl.4 \ -# rtw.4 \ - MLINKS= acpi_thermal.4 acpi_tz.4 -#MLINKS+=acx.4 if_acx.4 MLINKS+=ae.4 if_ae.4 MLINKS+=age.4 if_age.4 MLINKS+=agp.4 agpgart.4 @@ -427,7 +420,6 @@ MLINKS+=bge.4 if_bge.4 MLINKS+=bktr.4 brooktree.4 MLINKS+=bnx.4 if_bnx.4 MLINKS+=bridge.4 if_bridge.4 -#MLINKS+=bwi.4 if_bwi.4 MLINKS+=bwn.4 if_bwn.4 MLINKS+=crypto.4 cryptodev.4 MLINKS+=cue.4 if_cue.4 @@ -459,7 +451,6 @@ MLINKS+=ipfirewall.4 ipaccounting.4 \ ipfirewall.4 ipfw.4 MLINKS+=ipheth.4 if_ipheth.4 MLINKS+=iwi.4 if_iwi.4 -#MLINKS+=iwl.4 if_iwl.4 MLINKS+=iwn.4 if_iwn.4 MLINKS+=ix.4 if_ix.4 \ ix.4 ixgbe.4 \ @@ -492,7 +483,6 @@ MLINKS+=ral.4 if_ral.4 MLINKS+=random.4 urandom.4 MLINKS+=re.4 if_re.4 MLINKS+=rl.4 if_rl.4 -#MLINKS+=rtw.4 if_rtw.4 #MLINKS+=rue.4 if_rue.4 MLINKS+=rum.4 if_rum.4 MLINKS+=run.4 if_run.4 diff --git a/share/man/man4/acx.4 b/share/man/man4/acx.4 deleted file mode 100644 index 2437a8e762..0000000000 --- a/share/man/man4/acx.4 +++ /dev/null @@ -1,168 +0,0 @@ -.\" -.\" Copyright (c) 2006 The DragonFly Project. 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. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in -.\" the documentation and/or other materials provided with the -.\" distribution. -.\" 3. Neither the name of The DragonFly Project nor the names of its -.\" contributors may be used to endorse or promote products derived -.\" from this software without specific, prior written permission. -.\" -.\" 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 MERCHANTABILITY AND FITNESS -.\" FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -.\" COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -.\" INCIDENTAL, 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 DAMAGE. -.\" -.Dd November 28, 2014 -.Dt ACX 4 -.Os -.Sh NAME -.Nm acx -.Nd Texas Instruments ACX100/ACX111 IEEE 802.11a/b/g wireless network driver -.Sh SYNOPSIS -To compile this driver into the kernel, place the following lines in -your kernel configuration file: -.Bd -ragged -offset indent -.Cd "device acx" -.Cd "device wlan" -.Cd "device wlan_ratectl_onoe" -.Cd "device wlan_ratectl_amrr" -.Ed -.Pp -Alternatively, to load the driver as a module at boot time, place the -following line in -.Pa /boot/loader.conf : -.Bd -literal -offset indent -if_acx_load="YES" -.Ed -.Sh DESCRIPTION -The -.Nm -driver provides support for Texas Instruments TNETW1100/TNETW1100B (ACX100) -and TNETW1130 (ACX111) based PCI/CardBus network adapters. -.Pp -The ACX100A and ACX100B are first generation 802.11b devices -from TI. -The ACX111 is a second generation device which supports 802.11b/g -and in some cases 802.11a. -.Pp -By default, the -.Nm -driver configures the adapter for BSS operation (infrastructure mode). -This mode requires the use of an access point. -In addition, IBSS operation (adhoc mode) is also supported. -For more information on configuring this device, see -.Xr ifconfig 8 . -.Ss MIB Variables -The following per-interface variables are implemented in the -.Va dev.acx. Ns Em X -branch of the -.Xr sysctl 3 -MIB. -.Bl -tag -width ".Va combined_radio_fw" -.It Va msdu_lifetime -MSDU life time. -.It Va long_retry_limit -Long retry limit. -.It Va scan_dwell -Channel dwell time during scanning (unit: milliseconds) -.It Va combined_radio_fw -The base and radio firmwares are combined in one image file. -By default, -it is set to 1 for ACX111 parts and 0 for ACX100A and ACX100B parts. -.It Va free_fw -Set to non-zero value to free the loaded firmwares. -This does not affect a running device. -Firmwares will be reloaded from -.Pa /etc/firmware/acx -when device is brought up next time. -.El -.Sh HARDWARE -The following cards are among those supported by the -.Nm -driver: -.Pp -.Bl -column -compact "WESTELL A90-200WG-01" "ACX111" "CardBus" "a/b/g" -offset 6n -.It Em Card Ta Em Chip Ta Em Bus Ta Em Standard -.It "D-Link DWL-520+" Ta ACX100 Ta PCI Ta b -.It "D-Link DWL-650+" Ta ACX100 Ta CardBus Ta b -.It "D-Link DWL-G520+" Ta ACX111 Ta PCI Ta b/g -.It "D-Link DWL-G630+" Ta ACX111 Ta CardBus Ta b/g -.It "D-Link DWL-G650+" Ta ACX111 Ta CardBus Ta b/g -.It "Ergenic ERG WL-003" Ta ACX100 Ta CardBus Ta b -.It "Hamlet HNWP254" Ta ACX111 Ta CardBus Ta b/g -.It "Hawking HWP54G" Ta ACX111 Ta PCI Ta b/g -.It "Linksys WPC54Gv2" Ta ACX111 Ta CardBus Ta b/g -.It "Microcom Travelcard" Ta ACX111 Ta CardBus Ta b/g -.It "Netgear WG311v2" Ta ACX111 Ta PCI Ta b/g -.It "Sceptre SC254W+" Ta ACX111 Ta CardBus Ta b/g -.It "Tornado/ADT 211g" Ta ACX111 Ta PCI Ta b/g -.It "USR USR5410" Ta ACX111 Ta CardBus Ta b/g -.It "USR USR5416" Ta ACX111 Ta PCI Ta b/g -.It "WESTELL A90-200WG-01" Ta ACX111 Ta CardBus Ta b/g -.It "ZyXEL G-160" Ta ACX111 Ta CardBus Ta b/g -.It "ZyXEL G-360 EE" Ta ACX111 Ta PCI Ta b/g -.El -.Sh FILES -The firmware for the adapter is not shipped with -.Dx -and must be obtained separately. -An archive with firmware files that are known to work can be found at: -.Bd -literal -offset indent -http://leaf.dragonflybsd.org/~sephe/acx/acx_fw.tbz -.Ed -.Pp -The firmware files have to reside in -.Pa /etc/firmware/acx -and will be loaded when the interface is brought up. -.Sh EXAMPLES -Refer to the -.Sx EXAMPLES -section of -.Xr wlan 4 . -.Sh SEE ALSO -.Xr arp 4 , -.Xr cardbus 4 , -.Xr ifmedia 4 , -.Xr pci 4 , -.Xr wlan 4 , -.Xr wlan_ratectl 4 , -.Xr hostapd 8 , -.Xr ifconfig 8 , -.Xr sysctl 8 , -.Xr wpa_supplicant 8 -.Sh HISTORY -The -.Nm -driver first appeared in -.Dx 1.5 . -.Sh AUTHORS -.An -nosplit -The -.Nm -driver was written by -.An Sepherosa Ziehau . -The manual page was written by -.An Sascha Wildner . -Both are based on the -.Pa http://wlan.kewl.org -project team's original code. -.Pp -The hardware specification was reverse engineered by the good folks at -.Pa http://acx100.sourceforge.net . -Without them this driver would not have been possible. diff --git a/share/man/man4/bwi.4 b/share/man/man4/bwi.4 deleted file mode 100644 index 221e0b66e1..0000000000 --- a/share/man/man4/bwi.4 +++ /dev/null @@ -1,126 +0,0 @@ -.\" -.\" Copyright (c) 2007 The DragonFly Project. 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. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in -.\" the documentation and/or other materials provided with the -.\" distribution. -.\" 3. Neither the name of The DragonFly Project nor the names of its -.\" contributors may be used to endorse or promote products derived -.\" from this software without specific, prior written permission. -.\" -.\" 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 MERCHANTABILITY AND FITNESS -.\" FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -.\" COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -.\" INCIDENTAL, 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 DAMAGE. -.\" -.Dd November 28, 2014 -.Dt BWI 4 -.Os -.Sh NAME -.Nm bwi -.Nd Broadcom BCM430x/4318 IEEE 802.11b/g wireless network driver -.Sh SYNOPSIS -To load the driver as a module at boot time, place the -following line in -.Pa /boot/loader.conf : -.Bd -literal -offset indent -if_bwi_load="YES" -.Ed -.Sh DESCRIPTION -The -.Nm -driver provides support for Broadcom BCM430x/4318 wireless network adapters. -For more information on configuring this device, see -.Xr ifconfig 8 . -.Ss MIB Variables -The following per-interface variables are implemented in the -.Va dev.bwi. Ns Em X -branch of the -.Xr sysctl 3 -MIB. -.Bl -tag -width ".Va txpwr_calib" -.It Va debug -Debug flags. -.It Va dwell_time -Channel dwell time during scan (msec). -.It Va fw_version -Firmware version. -.It Va led_idle -Number of ticks before LED enters idle state. -.It Va led_blink -Allow LED to blink. -.It Va txpwr_calib -Enable software TX power calibration. -.El -.Sh HARDWARE -The following cards are among those supported by the -.Nm -driver: -.Pp -.Bl -column -compact "Buffalo WLI-PCI-G54S" "BCM4318" "CardBus" "b/g" -offset 6n -.It Em Card Ta Em Chip Ta Em Bus Ta Em Standard -.It "Linksys WPC54Gv3" Ta BCM4318 Ta CardBus Ta b/g -.It "Linksys WPC54GSv2" Ta BCM4318 Ta CardBus Ta b/g -.It "Buffalo WLI-CB-G54S" Ta BCM4318 Ta CardBus Ta b/g -.It "Buffalo WLI-PCI-G54S" Ta BCM4306 Ta PCI Ta b/g -.It "Dell Wireless 1470" Ta BCM4318 Ta Mini PCI Ta b/g -.It "Dell Truemobile 1400" Ta BCM4309 Ta Mini PCI Ta b/g -.El -.Sh FILES -The firmware for the adapter is not shipped with -.Dx -and must be obtained separately. -An archive with firmware files that are known to work can be found at: -.Bd -literal -offset indent -http://leaf.dragonflybsd.org/~sephe/bwi/v3.tbz -.Ed -.Pp -The firmware files have to reside in -.Pa /etc/firmware/bwi -and will be loaded when the interface is brought up. -.Sh EXAMPLES -Refer to the -.Sx EXAMPLES -section of -.Xr wlan 4 . -.Sh SEE ALSO -.Xr arp 4 , -.Xr cardbus 4 , -.Xr ifmedia 4 , -.Xr pci 4 , -.Xr wlan 4 , -.Xr wlan_ratectl 4 , -.Xr ifconfig 8 , -.Xr wpa_supplicant 8 -.Sh HISTORY -The -.Nm -driver first appeared in -.Dx 1.11 . -.Sh AUTHORS -.An -nosplit -The -.Nm -driver was written by -.An Sepherosa Ziehau . -.Pp -The hardware specification was reverse engineered by the people at -.Pa http://bcm-specs.sipsolutions.net . -Thanks go also to johill and mb on the #bcm-specs channel. -.Sh BUGS -BCM4306 and BCM4309 chips do not work properly on channel 1, 2 and 3. diff --git a/share/man/man4/bwn.4 b/share/man/man4/bwn.4 index 4c37b522b0..770b41db6a 100644 --- a/share/man/man4/bwn.4 +++ b/share/man/man4/bwn.4 @@ -88,12 +88,6 @@ driver supports Broadcom BCM43xx based wireless devices, including: .It "Linksys WPC54GS Ver 2 BCM4318 CardBus b/g" .It "US Robotics 5411 BCM4318 CardBus b/g" .El -.\".Pp -.\"Users of older Broadcom chipsets (BCM4301, BCM4303 and BCM4306 rev 2) -.\"must use -.\".Xr bwi 4 -.\"because the v4 version of the firmware does not support these chips. -.\"The newer firmware is too big to fit into these old chips. .Sh EXAMPLES Join an existing BSS network (i.e., connect to an access point): .Bd -literal -offset indent @@ -127,7 +121,6 @@ The default value is 1. .El .Sh SEE ALSO .Xr arp 4 , -.\".Xr bwi 4 , .Xr cardbus 4 , .Xr ifmedia 4 , .Xr intro 4 , diff --git a/share/man/man4/iwl.4 b/share/man/man4/iwl.4 deleted file mode 100644 index d47241039c..0000000000 --- a/share/man/man4/iwl.4 +++ /dev/null @@ -1,105 +0,0 @@ -.\" -.\" Copyright (c) 2008 -.\" The DragonFly Project. 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. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in -.\" the documentation and/or other materials provided with the -.\" distribution. -.\" 3. Neither the name of The DragonFly Project nor the names of its -.\" contributors may be used to endorse or promote products derived -.\" from this software without specific, prior written permission. -.\" -.\" 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 MERCHANTABILITY AND FITNESS -.\" FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -.\" COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -.\" INCIDENTAL, 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 DAMAGE. -.\" -.\" $DragonFly: src/share/man/man4/iwl.4,v 1.3 2008/07/26 16:25:40 swildner Exp $ -.\" -.Dd July 26, 2008 -.Os -.Dt IWL 4 -.Sh NAME -.Nm iwl -.Nd Intel(R) PRO/Wireless 2100 IEEE 802.11 driver -.Sh SYNOPSIS -To compile this driver into the kernel, -place the following lines in your -kernel configuration file: -.Bd -ragged -offset indent -.Cd "device iwl" -.Ed -.Pp -Alternatively, to load the driver as a -module at boot time, place the following line in -.Xr loader.conf 5 : -.Bd -literal -offset indent -if_iwl_load="YES" -.Ed -.Sh DESCRIPTION -The -.Nm -driver provides support for the Intel(R) PRO/Wireless 2100 MiniPCI network -adapter. -.Pp -By default, the -.Nm -driver configures the adapter for BSS operation (aka infrastructure mode). -This mode requires the use of an access point. -.Pp -For more information on configuring this device, see -.Xr ifconfig 8 . -.Sh FILES -The firmware for the adapter is not shipped with -.Dx -and must be obtained separately. -An archive with firmware files that are known to work can be found at: -.Bd -literal -offset indent -http://ipw2100.sourceforge.net/firmware.php?fid=4 -.Ed -.Pp -The firmware files have to reside in -.Pa /etc/firmware/iwl/2100/1.3 -and will be loaded when the interface is brought up. -.Sh EXAMPLES -Refer to the -.Sx EXAMPLES -section of -.Xr wlan 4 . -.\".Sh DIAGNOSTICS -.\".Bl -diag -.\".It "iwl%d: device timeout" -.\"The driver will reset the hardware. This should not happen. -.\".El -.Sh SEE ALSO -.Xr arp 4 , -.Xr ifmedia 4 , -.Xr pci 4 , -.Xr wlan 4 , -.Xr ifconfig 8 , -.Xr wpa_supplicant 8 -.Sh HISTORY -The -.Nm -first appeared in -.Dx 1.13 . -.Sh AUTHORS -The -.Nm -driver was written by -.An Sepherosa Ziehau . diff --git a/share/man/man4/rtw.4 b/share/man/man4/rtw.4 deleted file mode 100644 index 4a3eb2394e..0000000000 --- a/share/man/man4/rtw.4 +++ /dev/null @@ -1,264 +0,0 @@ -.\" $NetBSD: rtw.4,v 1.3 2005/09/09 14:11:39 drochner Exp $ -.\" $OpenBSD: rtw.4,v 1.18 2005/06/09 09:03:38 jmc Exp $ -.\" -.\" Copyright (c) 2004 Jonathan Gray -.\" -.\" 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. -.\" -.Dd July 26, 2008 -.Dt RTW 4 -.Os -.Sh NAME -.Nm rtw -.Nd Realtek RTL8180L IEEE 802.11b wireless network driver -.Sh SYNOPSIS -To compile this driver into the kernel, -place the following lines in your -kernel configuration file: -.Bd -ragged -offset indent -.Cd "device rtw" -.Cd "device wlan" -.Cd "device wlan_wep" -.Cd "device wlan_ratectl_onoe" -.Ed -.Pp -Alternatively, to load the driver as a -module at boot time, place the following line in -.Xr loader.conf 5 : -.Bd -literal -offset indent -if_rtw_load="YES" -.Ed -.Sh DESCRIPTION -The -.Nm -driver supports PCI/CardBus 802.11b wireless adapters based on the -Realtek RTL8180L. -.Pp -A variety of radio transceivers can be found in these devices, including -the Philips SA2400A, Maxim MAX2820, and GCT GRF5101, though not all of them -are currently supported. -.Pp -These are the modes the -.Nm -driver can operate in: -.Bl -tag -width "monitor mode" -.It BSS mode -Also known as -.Em infrastructure -mode, this is used when associating with an access point, through -which all traffic passes. -This mode is the default. -.It IBSS mode -Also known as -.Em IEEE ad-hoc -mode or -.Em peer-to-peer -mode. -This is the standardized method of operating without an access point. -Stations associate with a service set. -However, actual connections between stations are peer-to-peer. -.It Host AP -In this mode the driver acts as an access point (base station) -for other cards. -.It monitor mode -In this mode the driver is able to receive packets without -associating with an access point. -This disables the internal receive filter and enables the card to -capture packets from networks which it wouldn't normally have access to, -or to scan for access points. -.El -.Pp -.Nm -supports software WEP. -Wired Equivalent Privacy (WEP) is the de facto encryption standard -for wireless networks. -It can be typically configured in one of three modes: -no encryption; 40-bit encryption; or 104-bit encryption. -Unfortunately, due to serious weaknesses in WEP protocol -it is strongly recommended that it not be used as the -sole mechanism to secure wireless communication. -WEP is not enabled by default. -.Sh CONFIGURATION -The -.Nm -driver can be configured at runtime with -.Xr ifconfig 8 -using the following parameters: -.Bl -tag -width ".Fl mediaopt Ar opts" -.It Cm bssid Ar bssid -Set the desired BSSID. -.It Fl bssid -Unset the desired BSSID. -The interface will automatically select a BSSID in this mode, which is -the default. -.It Cm chan Ar n -Set the channel (radio frequency) to be used by the driver based on -the given channel ID -.Ar n . -.It Fl chan -Unset the desired channel to be used by the driver. -The driver will automatically select a channel in this mode, which is -the default. -.It Cm media Ar media -The -.Nm -driver supports the following -.Ar media -types: -.Pp -.Bl -tag -width ".Cm autoselect" -compact -.It Cm autoselect -Enable autoselection of the media type and options. -.It Cm DS1 -Set 802.11b DS 1Mbps operation. -.It Cm DS2 -Set 802.11b DS 2Mbps operation. -.It Cm DS5 -Set 802.11b DS 5.5Mbps operation. -.It Cm DS11 -Set 802.11b DS 11Mbps operation. -.El -.It Cm mediaopt Ar opts -The -.Nm -driver supports the following media options: -.Pp -.Bl -tag -width ".Cm monitor" -compact -.It Cm hostap -Select Host AP operation. -.It Cm ibss -Select IBSS operation. -.It Cm monitor -Select monitor mode. -.El -.It Fl mediaopt Ar opts -Disable the specified media options on the driver and return it to the -default mode of operation (BSS). -.It Cm ssid Ar id -Set the network ID. -The -.Ar id -can either be any text string up to 32 characters in length, -or a series of hexadecimal digits up to 64 digits. -An empty -.Ar id -string allows the interface to connect to any available access points. -By default the -.Nm -driver uses an empty string. -Note that network ID is synonymous with Extended Service Set ID (ESSID). -.It Cm nwkey Ar key -Enable WEP encryption using the specified -.Ar key . -The -.Ar key -can either be a string, a series of hexadecimal digits (preceded by -.Sq 0x ) , -or a set of keys of the form -.Dq n:k1,k2,k3,k4 , -where -.Sq n -specifies which of the keys will be used for transmitted packets, -and the four keys, -.Dq k1 -through -.Dq k4 , -are configured as WEP keys. -If a set of keys is specified, a comma -.Pq Sq \&, -within the key must be escaped with a backslash. -Note that if multiple keys are used, their order must be the same within -the network. -.Nm -is capable of using both 40-bit (5 characters or 10 hexadecimal digits) -or 104-bit (13 characters or 26 hexadecimal digits) keys. -.It Fl nwkey -Disable WEP encryption. -This is the default mode of operation. -.It Cm nwkey persist -Enable WEP encryption with the persistent key stored in the network card. -.El -.Sh HARDWARE -The following adapters should work: -.Pp -.Bl -column -compact ".Li Ovislink AirLive WL-1120PCM" "CardBus" -.It Em Card Ta Em Bus -.\".It Li "Acer Aspire 1357 LMi" Ta Mini PCI -.\".It Li "Belkin F5D6001 V3" Ta PCI -.It Li "Belkin F5D6020 V3" Ta CardBus -.It Li "Buffalo WLI-CB-B11" Ta CardBus -.It Li "Corega CG-WLCB11V3" Ta CardBus -.\".It Li "D-Link DWL-510" Ta PCI -.\".It Li "D-Link DWL-520 rev D" Ta PCI -.It Li "D-Link DWL-610" Ta CardBus -.\".It Li "Encore ENLWI-PCI1-NT" Ta PCI -.\".It Li "Gigabyte GN-WLMR101" Ta PCI -.It Li "Level-One WPC-0101" Ta CardBus -.It Li "Linksys WPC11 v4" Ta CardBus -.It Li "Netgear MA521" Ta CardBus -.It Li "Ovislink AirLive WL-1120PCM" Ta CardBus -.It Li "Planet WL-3553" Ta CardBus -.It Li "TrendNET TEW-266PC" Ta CardBus -.\".It Li "TrendNET TEW-288PI" Ta PCI -.It Li "VCTnet PC-11B1" Ta CardBus -.El -.Sh EXAMPLES -Refer to the -.Sx EXAMPLES -section of -.Xr wlan 4 . -.Sh SEE ALSO -.Xr arp 4 , -.Xr cardbus 4 , -.Xr ifmedia 4 , -.Xr intro 4 , -.Xr netintro 4 , -.Xr pci 4 , -.Xr wlan 4 , -.Xr wlan_ratectl 4 , -.Xr hostapd 8 , -.Xr ifconfig 8 -.Rs -.%T Realtek -.%O http://www.realtek.com.tw -.Re -.Sh HISTORY -The -.Nm -device driver first appeared in -.Nx 3.0 -and then in -.Ox 3.7 . -It was imported into -.Dx 1.7 . -.Sh AUTHORS -.An -nosplit -The -.Nm -driver was written by -.An David Young Aq Mt dyoung@NetBSD.org -and ported to -.Ox -by -.An Jonathan Gray Aq Mt jsg@openbsd.org , -who wrote this man page. -The -.Dx -port was done by -.An Sepherosa Ziehau Aq Mt sepherosa@gmail.com . -.Sh BUGS -Only the Philips SA2400A and Maxim MAX2820 RF transceivers are known to work. -Devices incorporating a GCT RF transceiver are not supported due to a lack of -documentation from GCT. -.Pp -While PCI devices will attach most of them are not able to transmit. diff --git a/share/man/man4/wlan.4 b/share/man/man4/wlan.4 index 2276b2430f..102c51fcc9 100644 --- a/share/man/man4/wlan.4 +++ b/share/man/man4/wlan.4 @@ -228,19 +228,15 @@ Beware that this specification is incompatible with earlier drafts; and stations implementing earlier drafts (e.g. Linux) may not interoperate. .Sh SEE ALSO -.\".Xr acx 4 , .Xr an 4 , .Xr ath 4 , -.\".Xr bwi 4 , .Xr bwn 4 , .\".Xr ipw 4 , .Xr iwi 4 , -.\".Xr iwl 4 , .Xr iwn 4 , .\".Xr malo 4 , .Xr netintro 4 , .Xr ral 4 , -.\".Xr rtw 4 , .Xr rum 4 , .Xr run 4 , .\".Xr uath 4 , diff --git a/share/man/man4/wlan_amrr.4 b/share/man/man4/wlan_amrr.4 index 723e59c674..707f6f7e67 100644 --- a/share/man/man4/wlan_amrr.4 +++ b/share/man/man4/wlan_amrr.4 @@ -39,7 +39,6 @@ The module implements the Adaptive Multi-Rate Retry tx rate control algorithm for use by 802.11 device drivers. .Sh SEE ALSO -.\".Xr bwi 4 , .Xr bwn 4 , .Xr iwn 4 , .Xr ral 4 , diff --git a/sys/boot/dloader/loader-bootp.conf b/sys/boot/dloader/loader-bootp.conf index 69c9c418c1..74b32300e6 100644 --- a/sys/boot/dloader/loader-bootp.conf +++ b/sys/boot/dloader/loader-bootp.conf @@ -171,14 +171,12 @@ pf_load="NO" # OpenBSD's packet filter # be able to mount the root filesystem via NFS. miibus_load="NO" # miibus support, needed for some drivers -if_acx_load="NO" # TI ACX100/ACX111 802.11 wireless NICs if_an_load="NO" # Aironet 4500/4800 802.11 wireless NICs if_ar_load="NO" # Digi SYNC/570i if_ath_load="NO" # Atheros 802.11 wireless NICs if_bce_load="NO" # Broadcom BCM5706/BCM5708 gigabit ethernet if_bfe_load="NO" # Broadcom BCM4401 PCI ethernet if_bge_load="NO" # Broadcom BCM570x PCI gigabit ethernet -if_bwi_load="NO" # Broadcom BCM430x/4318 IEEE 802.11b/g wireless if_dc_load="NO" # DEC/Intel 21143 and various workalikes if_ed_load="NO" # National Semiconductor DS8390/WD83C690 ethernet if_em_load="NO" # Intel(R) PRO/1000 gigabit ethernet @@ -187,7 +185,6 @@ if_et_load="NO" # Agere ET1310 10/100/Gigabit ethernet if_fwe_load="NO" # Ethernet emulation driver for FireWire if_fxp_load="NO" # Intel EtherExpress PRO/100B (82557, 82558) if_iwi_load="NO" # Intel(R) PRO/Wireless 2200BG/2915ABG MiniPCI -if_iwl_load="NO" # Intel(R) PRO/Wireless 2100 MiniPCI if_lge_load="NO" # Level 1 LXT1001 NetCellerator PCI gigabit ethernet if_lnc_load="NO" # AMD Lance/PCnet Ethernet if_msk_load="NO" # Marvell/SysKonnect Yukon II Gigabit Ethernet @@ -199,7 +196,6 @@ if_pcn_load="NO" # AMD PCnet PCI if_ral_load="NO" # Ralink Technology 802.11 wireless NICs if_re_load="NO" # RealTek 8139C+/8169/816xS/811xS/8101E if_rl_load="NO" # RealTek 8129/8139 -if_rtw_load="NO" # Realtek RTL8180L IEEE 802.11b wireless NICs if_sbni_load="NO" # Granch SBNI12 leased line adapters if_sbsh_load="NO" # Granch SBNI16 SHDSL modem if_sf_load="NO" # Adaptec Duralink PCI (AIC-6915 "starfire") diff --git a/sys/boot/dloader/loader.conf b/sys/boot/dloader/loader.conf index bae1eb532b..8dd8512c45 100644 --- a/sys/boot/dloader/loader.conf +++ b/sys/boot/dloader/loader.conf @@ -175,14 +175,12 @@ pf_load="NO" # OpenBSD's packet filter ############################################################## miibus_load="NO" # miibus support, needed for some drivers -if_acx_load="NO" # TI ACX100/ACX111 802.11 wireless NICs if_an_load="NO" # Aironet 4500/4800 802.11 wireless NICs if_ar_load="NO" # Digi SYNC/570i if_ath_load="NO" # Atheros 802.11 wireless NICs if_bce_load="NO" # Broadcom BCM5706/BCM5708 gigabit ethernet if_bfe_load="NO" # Broadcom BCM4401 PCI ethernet if_bge_load="NO" # Broadcom BCM570x PCI gigabit ethernet -if_bwi_load="NO" # Broadcom BCM430x/4318 IEEE 802.11b/g wireless if_dc_load="NO" # DEC/Intel 21143 and various workalikes if_ed_load="NO" # National Semiconductor DS8390/WD83C690 ethernet if_em_load="NO" # Intel(R) PRO/1000 gigabit ethernet @@ -191,7 +189,6 @@ if_et_load="NO" # Agere ET1310 10/100/Gigabit ethernet if_fwe_load="NO" # Ethernet emulation driver for FireWire if_fxp_load="NO" # Intel EtherExpress PRO/100B (82557, 82558) if_iwi_load="NO" # Intel(R) PRO/Wireless 2200BG/2915ABG MiniPCI -if_iwl_load="NO" # Intel(R) PRO/Wireless 2100 MiniPCI if_lge_load="NO" # Level 1 LXT1001 NetCellerator PCI gigabit ethernet if_lnc_load="NO" # AMD Lance/PCnet Ethernet if_msk_load="NO" # Marvell/SysKonnect Yukon II Gigabit Ethernet @@ -203,7 +200,6 @@ if_pcn_load="NO" # AMD PCnet PCI if_ral_load="NO" # Ralink Technology 802.11 wireless NICs if_re_load="NO" # RealTek 8139C+/8169/816xS/811xS/8101E if_rl_load="NO" # RealTek 8129/8139 -if_rtw_load="NO" # Realtek RTL8180L IEEE 802.11b wireless NICs if_sbni_load="NO" # Granch SBNI12 leased line adapters if_sbsh_load="NO" # Granch SBNI16 SHDSL modem if_sf_load="NO" # Adaptec Duralink PCI (AIC-6915 "starfire") diff --git a/sys/conf/files b/sys/conf/files index 7ae0174997..d2b8b18006 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -679,13 +679,7 @@ iwn6050.fw optional iwnfw \ compile-with "${NORMAL_FW}" \ no-obj no-implicit-rule \ clean "iwn6050.fw" -dev/netif/iwl/if_iwl.c optional iwl -dev/netif/iwl/iwl2100.c optional iwl dev/netif/jme/if_jme.c optional jme -dev/netif/acx/if_acx.c optional acx -dev/netif/acx/acxcmd.c optional acx -dev/netif/acx/acx100.c optional acx -dev/netif/acx/acx111.c optional acx dev/netif/ral/if_ral_pci.c optional ral dev/netif/ral/rt2560.c optional ral dev/netif/ral/rt2661.c optional ral @@ -959,11 +953,6 @@ wpi.fw optional wpifw \ compile-with "${NORMAL_FW}" \ no-obj no-implicit-rule \ clean "wpi.fw" -dev/netif/rtw/rtw.c optional rtw -dev/netif/rtw/rtwphy.c optional rtw -dev/netif/rtw/rtwphyio.c optional rtw -dev/netif/rtw/smc93cx6.c optional rtw -dev/netif/rtw/if_rtw_pci.c optional rtw pci dev/netif/xe/if_xe.c optional xe dev/netif/xe/if_xe_pccard.c optional xe pccard gnu/vfs/ext2fs/ext2_alloc.c optional ext2fs diff --git a/sys/config/LINT b/sys/config/LINT index 535032c2ad..1f6b691595 100644 --- a/sys/config/LINT +++ b/sys/config/LINT @@ -1307,13 +1307,10 @@ device bwn # Broadcom BCM43xx NICs using v4 firmware options BWN_DEBUG # turn on debugging output options BWN_RXRING_SLOTS=128 # number of RX slots to allocate options BWN_TXRING_SLOTS=128 # number of TX slots to allocate -#device iwl # Intel PRO/Wireless 2100 device iwi # Intel PRO/Wireless 2200BG/2915ABG device iwn # Intel WiFi Link 4965/1000/5000/5150/5300/6000/6050 options IWN_DEBUG # turn on debugging output device wi # WaveLAN/IEEE, PRISM-II, Spectrum24 802.11DS -#device rtw # RealTek 8180 -#device acx # TI ACX100/ACX111. device xe # Xircom PCMCIA device ral # Ralink Technology 802.11 wireless NIC device wpi diff --git a/sys/config/LINT64 b/sys/config/LINT64 index 57a4f6fb37..d6106476bd 100644 --- a/sys/config/LINT64 +++ b/sys/config/LINT64 @@ -1177,13 +1177,10 @@ device bwn # Broadcom BCM43xx NICs using v4 firmware options BWN_DEBUG # turn on debugging output options BWN_RXRING_SLOTS=128 # number of RX slots to allocate options BWN_TXRING_SLOTS=128 # number of TX slots to allocate -#device iwl # Intel PRO/Wireless 2100 device iwi # Intel PRO/Wireless 2200BG/2915ABG device iwn # Intel WiFi Link 4965/1000/5000/5150/5300/6000/6050 options IWN_DEBUG # turn on debugging output device wi # WaveLAN/IEEE, PRISM-II, Spectrum24 802.11DS -#device rtw # RealTek 8180 -#device acx # TI ACX100/ACX111. device xe # Xircom PCMCIA device ral # Ralink Technology 802.11 wireless NIC device wpi diff --git a/sys/dev/netif/Makefile b/sys/dev/netif/Makefile index d3ca2a7b86..7b94033ed2 100644 --- a/sys/dev/netif/Makefile +++ b/sys/dev/netif/Makefile @@ -9,8 +9,4 @@ SUBDIR= an age alc ale ath bce bfe bge bwn \ SUBDIR+=ar ed sbni sr .endif -# XXX need to be updated to the new net80211 stack -# SUBDIR+= acx bwi iwl rtw -# .endif - .include diff --git a/sys/dev/netif/acx/Makefile b/sys/dev/netif/acx/Makefile deleted file mode 100644 index dfdedc8599..0000000000 --- a/sys/dev/netif/acx/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -KMOD = if_acx - -SRCS = if_acx.c acxcmd.c acx100.c acx111.c -SRCS += device_if.h bus_if.h pci_if.h pcidevs.h - -.include diff --git a/sys/dev/netif/acx/_acxcmd.h b/sys/dev/netif/acx/_acxcmd.h deleted file mode 100644 index ed457e72fd..0000000000 --- a/sys/dev/netif/acx/_acxcmd.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2006 The DragonFly Project. All rights reserved. - * - * This code is derived from software contributed to The DragonFly Project - * by Sepherosa Ziehau - * - * 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. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * 3. Neither the name of The DragonFly Project nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific, prior written permission. - * - * 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 MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, 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 DAMAGE. - * - * $DragonFly: src/sys/dev/netif/acx/_acxcmd.h,v 1.2 2008/06/06 10:47:14 sephe Exp $ - */ - -#ifndef _X_ACXCMD_H -#define _X_ACXCMD_H - -#define ACXCMD_GET_CONF 0x01 -#define ACXCMD_SET_CONF 0x02 -#define ACXCMD_ENABLE_RXCHAN 0x03 -#define ACXCMD_ENABLE_TXCHAN 0x04 -#define ACXCMD_TMPLT_TIM 0x0a -#define ACXCMD_JOIN_BSS 0x0b -#define ACXCMD_WEP_MGMT 0x0c /* acx111 */ -#define ACXCMD_SLEEP 0x0f -#define ACXCMD_WAKEUP 0x10 -#define ACXCMD_INIT_MEM 0x12 /* acx100 */ -#define ACXCMD_TMPLT_BEACON 0x13 -#define ACXCMD_TMPLT_PROBE_RESP 0x14 -#define ACXCMD_TMPLT_NULL_DATA 0x15 -#define ACXCMD_TMPLT_PROBE_REQ 0x16 -#define ACXCMD_INIT_RADIO 0x18 -#define ACXCMD_CALIBRATE 0x19 /* acx111 */ - -#if 0 -/* - * acx111 does not agree with acx100 about - * the meaning of following values. So they - * are put into chip specific files. - */ -#define ACX_CONF_FW_RING 0x0003 -#define ACX_CONF_MEMOPT 0x0005 -#endif -#define ACX_CONF_MEMBLK_SIZE 0x0004 /* acx100 */ -#define ACX_CONF_RATE_FALLBACK 0x0006 -#define ACX_CONF_WEPOPT 0x0007 /* acx100 */ -#define ACX_CONF_MMAP 0x0008 -#define ACX_CONF_FWREV 0x000d -#define ACX_CONF_RXOPT 0x0010 -#define ACX_CONF_OPTION 0x0015 /* acx111 */ -#define ACX_CONF_EADDR 0x1001 -#define ACX_CONF_NRETRY_SHORT 0x1005 -#define ACX_CONF_NRETRY_LONG 0x1006 -#define ACX_CONF_WEPKEY 0x1007 /* acx100 */ -#define ACX_CONF_MSDU_LIFETIME 0x1008 -#define ACX_CONF_REGDOM 0x100a -#define ACX_CONF_ANTENNA 0x100b -#define ACX_CONF_TXPOWER 0x100d /* acx111 */ -#define ACX_CONF_CCA_MODE 0x100e -#define ACX_CONF_ED_THRESH 0x100f -#define ACX_CONF_WEP_TXKEY 0x1010 - -#endif /* !_X_ACXCMD_H */ diff --git a/sys/dev/netif/acx/acx100.c b/sys/dev/netif/acx/acx100.c deleted file mode 100644 index 464fbf479b..0000000000 --- a/sys/dev/netif/acx/acx100.c +++ /dev/null @@ -1,859 +0,0 @@ -/* - * Copyright (c) 2006 The DragonFly Project. All rights reserved. - * - * This code is derived from software contributed to The DragonFly Project - * by Sepherosa Ziehau - * - * 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. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * 3. Neither the name of The DragonFly Project nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific, prior written permission. - * - * 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 MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, 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 DAMAGE. - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - -#include - -#define ACX_DEBUG - -#include -#include -#include - -#define ACX100_CONF_FW_RING 0x0003 -#define ACX100_CONF_MEMOPT 0x0005 - -#define ACX100_INTR_ENABLE (ACXRV_INTR_TX_FINI | ACXRV_INTR_RX_FINI) -/* - * XXX do we really care about following interrupts? - * - * ACXRV_INTR_INFO | ACXRV_INTR_SCAN_FINI - */ - -#define ACX100_INTR_DISABLE (uint16_t)~(ACXRV_INTR_UNKN) - -#define ACX100_RATE(rate) ((rate) * 5) - -#define ACX100_RSSI_CORR 8 -#define ACX100_TXPOWER 18 -#define ACX100_GPIO_POWER_LED 0x0800 -#define ACX100_EE_EADDR_OFS 0x1a - -#define ACX100_FW_TXRING_SIZE (ACX_TX_DESC_CNT * sizeof(struct acx_fw_txdesc)) -#define ACX100_FW_RXRING_SIZE (ACX_RX_DESC_CNT * sizeof(struct acx_fw_rxdesc)) - -/* - * NOTE: - * Following structs' fields are little endian - */ - -struct acx100_bss_join { - uint8_t dtim_intvl; - uint8_t basic_rates; - uint8_t op_rates; -} __packed; - -struct acx100_conf_fw_ring { - struct acx_conf confcom; - uint32_t fw_ring_size; /* total size of fw (tx + rx) ring */ - uint32_t fw_rxring_addr; /* start phyaddr of fw rx desc */ - uint8_t opt; /* see ACX100_RINGOPT_ */ - uint8_t fw_txring_num; /* num of TX ring */ - uint8_t fw_rxdesc_num; /* num of fw rx desc */ - uint8_t reserved0; - uint32_t fw_ring_end[2]; /* see ACX100_SET_RING_END() */ - uint32_t fw_txring_addr; /* start phyaddr of fw tx desc */ - uint8_t fw_txring_prio; /* see ACX100_TXRING_PRIO_ */ - uint8_t fw_txdesc_num; /* num of fw tx desc */ - uint16_t reserved1; -} __packed; - -#define ACX100_RINGOPT_AUTO_RESET 0x1 -#define ACX100_TXRING_PRIO_DEFAULT 0 -#define ACX100_SET_RING_END(conf, end) \ -do { \ - (conf)->fw_ring_end[0] = htole32(end); \ - (conf)->fw_ring_end[1] = htole32(end + 8); \ -} while (0) - -struct acx100_conf_memblk_size { - struct acx_conf confcom; - uint16_t memblk_size; /* size of each mem block */ -} __packed; - -struct acx100_conf_mem { - struct acx_conf confcom; - uint32_t opt; /* see ACX100_MEMOPT_ */ - uint32_t h_rxring_paddr; /* host rx desc start phyaddr */ - - /* - * Memory blocks are controled by hardware - * once after they are initialized - */ - uint32_t rx_memblk_addr; /* start addr of rx mem blocks */ - uint32_t tx_memblk_addr; /* start addr of tx mem blocks */ - uint16_t rx_memblk_num; /* num of RX mem block */ - uint16_t tx_memblk_num; /* num of TX mem block */ -} __packed; - -#define ACX100_MEMOPT_MEM_INSTR 0x00000000 /* memory access instruct */ -#define ACX100_MEMOPT_HOSTDESC 0x00010000 /* host indirect desc */ -#define ACX100_MEMOPT_MEMBLOCK 0x00020000 /* local mem block list */ -#define ACX100_MEMOPT_IO_INSTR 0x00040000 /* IO instruct */ -#define ACX100_MEMOPT_PCICONF 0x00080000 /* PCI conf space */ - -#define ACX100_MEMBLK_ALIGN 0x20 - -struct acx100_conf_cca_mode { - struct acx_conf confcom; - uint8_t cca_mode; - uint8_t unknown; -} __packed; - -struct acx100_conf_ed_thresh { - struct acx_conf confcom; - uint8_t ed_thresh; - uint8_t unknown[3]; -} __packed; - -struct acx100_conf_wepkey { - struct acx_conf confcom; - uint8_t action; /* see ACX100_WEPKEY_ACT_ */ - uint8_t key_len; - uint8_t key_idx; -#define ACX100_WEPKEY_LEN 29 - uint8_t key[ACX100_WEPKEY_LEN]; -} __packed; - -#define ACX100_WEPKEY_ACT_ADD 1 - -#define ACX100_CONF_FUNC(sg, name) _ACX_CONF_FUNC(sg, name, 100) -#define ACX_CONF_fw_ring ACX100_CONF_FW_RING -#define ACX_CONF_memblk_size ACX_CONF_MEMBLK_SIZE -#define ACX_CONF_mem ACX100_CONF_MEMOPT -#define ACX_CONF_cca_mode ACX_CONF_CCA_MODE -#define ACX_CONF_ed_thresh ACX_CONF_ED_THRESH -#define ACX_CONF_wepkey ACX_CONF_WEPKEY -ACX100_CONF_FUNC(set, fw_ring); -ACX100_CONF_FUNC(set, memblk_size); -ACX100_CONF_FUNC(set, mem); -ACX100_CONF_FUNC(get, cca_mode); -ACX100_CONF_FUNC(set, cca_mode); -ACX100_CONF_FUNC(get, ed_thresh); -ACX100_CONF_FUNC(set, ed_thresh); -ACX100_CONF_FUNC(set, wepkey); - -#define ACXCMD_init_mem ACXCMD_INIT_MEM -ACX_NOARG_FUNC(init_mem); - -static const uint16_t acx100_reg[ACXREG_MAX] = { - ACXREG(SOFT_RESET, 0x0000), - - ACXREG(FWMEM_ADDR, 0x0014), - ACXREG(FWMEM_DATA, 0x0018), - ACXREG(FWMEM_CTRL, 0x001c), - ACXREG(FWMEM_START, 0x0020), - - ACXREG(EVENT_MASK, 0x0034), - - ACXREG(INTR_TRIG, 0x007c), - ACXREG(INTR_MASK, 0x0098), - ACXREG(INTR_STATUS, 0x00a4), - ACXREG(INTR_STATUS_CLR, 0x00a8), - ACXREG(INTR_ACK, 0x00ac), - - ACXREG(HINTR_TRIG, 0x00b0), - ACXREG(RADIO_ENABLE, 0x0104), - - ACXREG(EEPROM_INIT, 0x02d0), - ACXREG(EEPROM_CTRL, 0x0250), - ACXREG(EEPROM_ADDR, 0x0254), - ACXREG(EEPROM_DATA, 0x0258), - ACXREG(EEPROM_CONF, 0x025c), - ACXREG(EEPROM_INFO, 0x02ac), - - ACXREG(PHY_ADDR, 0x0268), - ACXREG(PHY_DATA, 0x026c), - ACXREG(PHY_CTRL, 0x0270), - - ACXREG(GPIO_OUT_ENABLE, 0x0290), - ACXREG(GPIO_OUT, 0x0298), - - ACXREG(CMD_REG_OFFSET, 0x02a4), - ACXREG(INFO_REG_OFFSET, 0x02a8), - - ACXREG(RESET_SENSE, 0x02d4), - ACXREG(ECPU_CTRL, 0x02d8) -}; - -static const uint8_t acx100_txpower_maxim[21] = { - 63, 63, 63, 62, - 61, 61, 60, 60, - 59, 58, 57, 55, - 53, 50, 47, 43, - 38, 31, 23, 13, - 0 -}; - -static const uint8_t acx100_txpower_rfmd[21] = { - 0, 0, 0, 1, - 2, 2, 3, 3, - 4, 5, 6, 8, - 10, 13, 16, 20, - 25, 32, 41, 50, - 63 -}; - -static const uint8_t acx100_rate_map[45] = { - [2] = 0x01, - [4] = 0x02, - [11] = 0x04, - [22] = 0x08, - [44] = 0x10 -}; - -static int acx100_init(struct acx_softc *); -static int acx100_init_wep(struct acx_softc *); -static int acx100_init_tmplt(struct acx_softc *); -static int acx100_init_fw_ring(struct acx_softc *); -static int acx100_init_memory(struct acx_softc *); - -static void acx100_init_fw_txring(struct acx_softc *, uint32_t); -static void acx100_init_fw_rxring(struct acx_softc *, uint32_t); - -static int acx100_read_config(struct acx_softc *, struct acx_config *); -static int acx100_write_config(struct acx_softc *, struct acx_config *); - -static void *acx100_ratectl_attach(struct ieee80211com *, u_int); - -static int acx100_set_txpower(struct acx_softc *); - -static uint8_t acx100_set_fw_txdesc_rate(struct acx_softc *, - struct acx_txbuf *, - struct ieee80211_node *, int); -static void acx100_tx_complete(struct acx_softc *, struct acx_txbuf *, - int, int); -static void acx100_set_bss_join_param(struct acx_softc *, void *, int); - -static int acx100_set_wepkey(struct acx_softc *, struct ieee80211_key *, - int); - -static void acx100_proc_wep_rxbuf(struct acx_softc *, struct mbuf *, int *); - -#define ACX100_CHK_RATE(ifp, rate, rate_idx) \ - acx100_check_rate(ifp, rate, rate_idx, __func__) - -static __inline int -acx100_check_rate(struct ifnet *ifp, u_int rate, int rate_idx, - const char *fname) -{ - if (rate >= NELEM(acx100_rate_map)) { - if_printf(ifp, "%s rate out of range %u (idx %d)\n", - fname, rate, rate_idx); - return -1; - } - - if (acx100_rate_map[rate] == 0) { - if_printf(ifp, "%s invalid rate %u (idx %d)\n", - fname, rate, rate_idx); - return -1; - } - return 0; -} - -void -acx100_set_param(device_t dev) -{ - struct acx_softc *sc = device_get_softc(dev); - struct ieee80211com *ic = &sc->sc_ic; - struct acx_firmware *fw = &sc->sc_firmware; - - sc->chip_mem1_rid = PCIR_BAR(1); - sc->chip_mem2_rid = PCIR_BAR(2); - sc->chip_ioreg = acx100_reg; - sc->chip_hw_crypt = 1; - sc->chip_intr_enable = ACX100_INTR_ENABLE; - sc->chip_intr_disable = ACX100_INTR_DISABLE; - sc->chip_gpio_pled = ACX100_GPIO_POWER_LED; - sc->chip_ee_eaddr_ofs = ACX100_EE_EADDR_OFS; - sc->chip_txdesc1_len = ACX_FRAME_HDRLEN; - sc->chip_fw_txdesc_ctrl = DESC_CTRL_AUTODMA | - DESC_CTRL_RECLAIM | - DESC_CTRL_FIRST_FRAG; - sc->chip_short_retry_limit = 7; - sc->chip_rssi_corr = ACX100_RSSI_CORR; - - sc->chip_phymode = IEEE80211_MODE_11B; - sc->chip_chan_flags = IEEE80211_CHAN_B; - - ic->ic_phytype = IEEE80211_T_DS; - if (acx_enable_pbcc) - ic->ic_sup_rates[IEEE80211_MODE_11B] = acx_rates_11b_pbcc; - else - ic->ic_sup_rates[IEEE80211_MODE_11B] = acx_rates_11b; - - IEEE80211_ONOE_PARAM_SETUP(&sc->sc_onoe_param); - - ic->ic_ratectl.rc_st_ratectl_cap = IEEE80211_RATECTL_CAP_ONOE; - ic->ic_ratectl.rc_st_ratectl = IEEE80211_RATECTL_ONOE; - ic->ic_ratectl.rc_st_attach = acx100_ratectl_attach; - - sc->chip_init = acx100_init; - sc->chip_set_wepkey = acx100_set_wepkey; - sc->chip_read_config = acx100_read_config; - sc->chip_write_config = acx100_write_config; - sc->chip_set_fw_txdesc_rate = acx100_set_fw_txdesc_rate; - sc->chip_tx_complete = acx100_tx_complete; - sc->chip_set_bss_join_param = acx100_set_bss_join_param; - sc->chip_proc_wep_rxbuf = acx100_proc_wep_rxbuf; - - fw->combined_radio_fw = 0; - fw->fwdir = "100"; -} - -static int -acx100_init(struct acx_softc *sc) -{ - /* - * NOTE: - * Order of initialization: - * 1) WEP - * 2) Templates - * 3) Firmware TX/RX ring - * 4) Hardware memory - * Above order is critical to get a correct memory map - */ - - if (acx100_init_wep(sc) != 0) { - if_printf(&sc->sc_ic.ic_if, "%s can't initialize wep\n", - __func__); - return ENXIO; - } - - if (acx100_init_tmplt(sc) != 0) { - if_printf(&sc->sc_ic.ic_if, "%s can't initialize templates\n", - __func__); - return ENXIO; - } - - if (acx100_init_fw_ring(sc) != 0) { - if_printf(&sc->sc_ic.ic_if, "%s can't initialize fw ring\n", - __func__); - return ENXIO; - } - - if (acx100_init_memory(sc) != 0) { - if_printf(&sc->sc_ic.ic_if, "%s can't initialize hw memory\n", - __func__); - return ENXIO; - } - return 0; -} - -static int -acx100_init_wep(struct acx_softc *sc) -{ - struct acx_conf_wepopt wep_opt; - struct acx_conf_mmap mem_map; - - /* Set WEP cache start/end address */ - if (acx_get_mmap_conf(sc, &mem_map) != 0) { - if_printf(&sc->sc_ic.ic_if, "can't get mmap\n"); - return 1; - } - - mem_map.wep_cache_start = htole32(le32toh(mem_map.code_end) + 4); - mem_map.wep_cache_end = htole32(le32toh(mem_map.code_end) + 4); - if (acx_set_mmap_conf(sc, &mem_map) != 0) { - if_printf(&sc->sc_ic.ic_if, "can't set mmap\n"); - return 1; - } - - /* Set WEP options */ - wep_opt.nkey = htole16(IEEE80211_WEP_NKID + 10); - wep_opt.opt = WEPOPT_HDWEP; - if (acx_set_wepopt_conf(sc, &wep_opt) != 0) { - if_printf(&sc->sc_ic.ic_if, "can't set wep opt\n"); - return 1; - } - return 0; -} - -static int -acx100_init_tmplt(struct acx_softc *sc) -{ - struct acx_conf_mmap mem_map; - - /* Set templates start address */ - if (acx_get_mmap_conf(sc, &mem_map) != 0) { - if_printf(&sc->sc_ic.ic_if, "can't get mmap\n"); - return 1; - } - - mem_map.pkt_tmplt_start = mem_map.wep_cache_end; - if (acx_set_mmap_conf(sc, &mem_map) != 0) { - if_printf(&sc->sc_ic.ic_if, "can't set mmap\n"); - return 1; - } - - /* Initialize various packet templates */ - if (acx_init_tmplt_ordered(sc) != 0) { - if_printf(&sc->sc_ic.ic_if, "can't init tmplt\n"); - return 1; - } - return 0; -} - -static int -acx100_init_fw_ring(struct acx_softc *sc) -{ - struct acx100_conf_fw_ring ring; - struct acx_conf_mmap mem_map; - uint32_t txring_start, rxring_start, ring_end; - - /* Set firmware descriptor ring start address */ - if (acx_get_mmap_conf(sc, &mem_map) != 0) { - if_printf(&sc->sc_ic.ic_if, "can't get mmap\n"); - return 1; - } - - txring_start = le32toh(mem_map.pkt_tmplt_end) + 4; - rxring_start = txring_start + ACX100_FW_TXRING_SIZE; - ring_end = rxring_start + ACX100_FW_RXRING_SIZE; - - mem_map.fw_desc_start = htole32(txring_start); - if (acx_set_mmap_conf(sc, &mem_map) != 0) { - if_printf(&sc->sc_ic.ic_if, "can't set mmap\n"); - return 1; - } - - /* Set firmware descriptor ring configure */ - bzero(&ring, sizeof(ring)); - ring.fw_ring_size = htole32(ACX100_FW_TXRING_SIZE + - ACX100_FW_RXRING_SIZE + 8); - - ring.fw_txring_num = 1; - ring.fw_txring_addr = htole32(txring_start); - ring.fw_txring_prio = ACX100_TXRING_PRIO_DEFAULT; - ring.fw_txdesc_num = 0; /* XXX ignored?? */ - - ring.fw_rxring_addr = htole32(rxring_start); - ring.fw_rxdesc_num = 0; /* XXX ignored?? */ - - ring.opt = ACX100_RINGOPT_AUTO_RESET; - ACX100_SET_RING_END(&ring, ring_end); - if (acx100_set_fw_ring_conf(sc, &ring) != 0) { - if_printf(&sc->sc_ic.ic_if, "can't set fw ring configure\n"); - return 1; - } - - /* Setup firmware TX/RX descriptor ring */ - acx100_init_fw_txring(sc, txring_start); - acx100_init_fw_rxring(sc, rxring_start); - - return 0; -} - -#define MEMBLK_ALIGN(addr) \ - (((addr) + (ACX100_MEMBLK_ALIGN - 1)) & ~(ACX100_MEMBLK_ALIGN - 1)) - -static int -acx100_init_memory(struct acx_softc *sc) -{ - struct acx100_conf_memblk_size memblk_sz; - struct acx100_conf_mem mem; - struct acx_conf_mmap mem_map; - uint32_t memblk_start, memblk_end; - int total_memblk, txblk_num, rxblk_num; - - /* Set memory block start address */ - if (acx_get_mmap_conf(sc, &mem_map) != 0) { - if_printf(&sc->sc_ic.ic_if, "can't get mmap\n"); - return 1; - } - - mem_map.memblk_start = - htole32(MEMBLK_ALIGN(le32toh(mem_map.fw_desc_end) + 4)); - - if (acx_set_mmap_conf(sc, &mem_map) != 0) { - if_printf(&sc->sc_ic.ic_if, "can't set mmap\n"); - return 1; - } - - /* Set memory block size */ - memblk_sz.memblk_size = htole16(ACX_MEMBLOCK_SIZE); - if (acx100_set_memblk_size_conf(sc, &memblk_sz) != 0) { - if_printf(&sc->sc_ic.ic_if, "can't set mem block size\n"); - return 1; - } - - /* Get memory map after setting it */ - if (acx_get_mmap_conf(sc, &mem_map) != 0) { - if_printf(&sc->sc_ic.ic_if, "can't get mmap again\n"); - return 1; - } - memblk_start = le32toh(mem_map.memblk_start); - memblk_end = le32toh(mem_map.memblk_end); - - /* Set memory options */ - mem.opt = htole32(ACX100_MEMOPT_MEMBLOCK | ACX100_MEMOPT_HOSTDESC); - mem.h_rxring_paddr = htole32(sc->sc_ring_data.rx_ring_paddr); - - total_memblk = (memblk_end - memblk_start) / ACX_MEMBLOCK_SIZE; - - rxblk_num = total_memblk / 2; /* 50% */ - txblk_num = total_memblk - rxblk_num; /* 50% */ - - DPRINTF((&sc->sc_ic.ic_if, "\ttotal memory blocks\t%d\n" - "\trx memory blocks\t%d\n" - "\ttx memory blocks\t%d\n", - total_memblk, rxblk_num, txblk_num)); - - mem.rx_memblk_num = htole16(rxblk_num); - mem.tx_memblk_num = htole16(txblk_num); - - mem.rx_memblk_addr = htole32(MEMBLK_ALIGN(memblk_start)); - mem.tx_memblk_addr = - htole32(MEMBLK_ALIGN(memblk_start + - (ACX_MEMBLOCK_SIZE * rxblk_num))); - - if (acx100_set_mem_conf(sc, &mem) != 0) { - if_printf(&sc->sc_ic.ic_if, "can't set mem options\n"); - return 1; - } - - /* Initialize memory */ - if (acx_init_mem(sc) != 0) { - if_printf(&sc->sc_ic.ic_if, "can't init mem\n"); - return 1; - } - return 0; -} - -#undef MEMBLK_ALIGN - -static void -acx100_init_fw_txring(struct acx_softc *sc, uint32_t fw_txdesc_start) -{ - struct acx_fw_txdesc fw_desc; - struct acx_txbuf *tx_buf; - uint32_t desc_paddr, fw_desc_offset; - int i; - - bzero(&fw_desc, sizeof(fw_desc)); - fw_desc.f_tx_ctrl = DESC_CTRL_HOSTOWN | - DESC_CTRL_RECLAIM | - DESC_CTRL_AUTODMA | - DESC_CTRL_FIRST_FRAG; - - tx_buf = sc->sc_buf_data.tx_buf; - fw_desc_offset = fw_txdesc_start; - desc_paddr = sc->sc_ring_data.tx_ring_paddr; - - for (i = 0; i < ACX_TX_DESC_CNT; ++i) { - fw_desc.f_tx_host_desc = htole32(desc_paddr); - - if (i == ACX_TX_DESC_CNT - 1) { - fw_desc.f_tx_next_desc = htole32(fw_txdesc_start); - } else { - fw_desc.f_tx_next_desc = - htole32(fw_desc_offset + - sizeof(struct acx_fw_txdesc)); - } - - tx_buf[i].tb_fwdesc_ofs = fw_desc_offset; - DESC_WRITE_REGION_1(sc, fw_desc_offset, &fw_desc, - sizeof(fw_desc)); - - desc_paddr += (2 * sizeof(struct acx_host_desc)); - fw_desc_offset += sizeof(fw_desc); - } -} - -static void -acx100_init_fw_rxring(struct acx_softc *sc, uint32_t fw_rxdesc_start) -{ - struct acx_fw_rxdesc fw_desc; - uint32_t fw_desc_offset; - int i; - - bzero(&fw_desc, sizeof(fw_desc)); - fw_desc.f_rx_ctrl = DESC_CTRL_RECLAIM | DESC_CTRL_AUTODMA; - - fw_desc_offset = fw_rxdesc_start; - - for (i = 0; i < ACX_RX_DESC_CNT; ++i) { - if (i == ACX_RX_DESC_CNT - 1) { - fw_desc.f_rx_next_desc = htole32(fw_rxdesc_start); - } else { - fw_desc.f_rx_next_desc = - htole32(fw_desc_offset + - sizeof(struct acx_fw_rxdesc)); - } - - DESC_WRITE_REGION_1(sc, fw_desc_offset, &fw_desc, - sizeof(fw_desc)); - - fw_desc_offset += sizeof(fw_desc); - } -} - -static int -acx100_read_config(struct acx_softc *sc, struct acx_config *conf) -{ - struct acx100_conf_cca_mode cca; - struct acx100_conf_ed_thresh ed; - - /* - * NOTE: - * CCA mode and ED threshold MUST be read during initialization - * or the acx100 card won't work as expected - */ - - /* Get CCA mode */ - if (acx100_get_cca_mode_conf(sc, &cca) != 0) { - if_printf(&sc->sc_ic.ic_if, "%s can't get cca mode\n", - __func__); - return ENXIO; - } - conf->cca_mode = cca.cca_mode; - DPRINTF((&sc->sc_ic.ic_if, "cca mode %02x\n", cca.cca_mode)); - - /* Get ED threshold */ - if (acx100_get_ed_thresh_conf(sc, &ed) != 0) { - if_printf(&sc->sc_ic.ic_if, "%s can't get ed threshold\n", - __func__); - return ENXIO; - } - conf->ed_thresh = ed.ed_thresh; - DPRINTF((&sc->sc_ic.ic_if, "ed threshold %02x\n", ed.ed_thresh)); - - return 0; -} - -static int -acx100_write_config(struct acx_softc *sc, struct acx_config *conf) -{ - struct acx100_conf_cca_mode cca; - struct acx100_conf_ed_thresh ed; - - /* Set CCA mode */ - cca.cca_mode = conf->cca_mode; - if (acx100_set_cca_mode_conf(sc, &cca) != 0) { - if_printf(&sc->sc_ic.ic_if, "%s can't set cca mode\n", - __func__); - return ENXIO; - } - - /* Set ED threshold */ - ed.ed_thresh = conf->ed_thresh; - if (acx100_set_ed_thresh_conf(sc, &ed) != 0) { - if_printf(&sc->sc_ic.ic_if, "%s can't set ed threshold\n", - __func__); - return ENXIO; - } - - /* Set TX power */ - acx100_set_txpower(sc); /* ignore return value */ - - return 0; -} - -static int -acx100_set_txpower(struct acx_softc *sc) -{ - const uint8_t *map; - - switch (sc->sc_radio_type) { - case ACX_RADIO_TYPE_MAXIM: - map = acx100_txpower_maxim; - break; - case ACX_RADIO_TYPE_RFMD: - case ACX_RADIO_TYPE_RALINK: - map = acx100_txpower_rfmd; - break; - default: - if_printf(&sc->sc_ic.ic_if, "TX power for radio type 0x%02x " - "can't be set yet\n", sc->sc_radio_type); - return 1; - } - - acx_write_phyreg(sc, ACXRV_PHYREG_TXPOWER, map[ACX100_TXPOWER]); - return 0; -} - -static uint8_t -acx100_set_fw_txdesc_rate(struct acx_softc *sc, struct acx_txbuf *tx_buf, - struct ieee80211_node *ni, int data_len) -{ - int rate; - - tx_buf->tb_rateidx_len = 1; - if (ni == NULL) { - rate = 2; /* 1Mbit/s */ - tx_buf->tb_rateidx[0] = 0; - } else { - ieee80211_ratectl_findrate(ni, data_len, - tx_buf->tb_rateidx, 1); - rate = IEEE80211_RS_RATE(&ni->ni_rates, - tx_buf->tb_rateidx[0]); - if (ACX100_CHK_RATE(&sc->sc_ic.ic_if, rate, - tx_buf->tb_rateidx[0]) < 0) - rate = 2; - } - FW_TXDESC_SETFIELD_1(sc, tx_buf, f_tx_rate100, ACX100_RATE(rate)); - - return rate; -} - -static void -acx100_set_bss_join_param(struct acx_softc *sc, void *param, int dtim_intvl) -{ - struct acx100_bss_join *bj = param; - struct ifnet *ifp = &sc->sc_ic.ic_if; - const struct ieee80211_rateset *rs = &sc->sc_ic.ic_bss->ni_rates; - int i; - - bj->basic_rates = 0; - bj->op_rates = 0; - for (i = 0; i < rs->rs_nrates; ++i) { - u_int map_idx = IEEE80211_RS_RATE(rs, i); - uint8_t rate; - - if (ACX100_CHK_RATE(ifp, map_idx, i) < 0) - continue; - - rate = acx100_rate_map[map_idx]; - if (rs->rs_rates[i] & IEEE80211_RATE_BASIC) - bj->basic_rates |= rate; - bj->op_rates |= rate; - } - DPRINTF((ifp, "basic rates:0x%02x, op rates:0x%02x\n", - bj->basic_rates, bj->op_rates)); - - bj->dtim_intvl = dtim_intvl; -} - -static int -acx100_set_wepkey(struct acx_softc *sc, struct ieee80211_key *wk, int wk_idx) -{ - struct acx100_conf_wepkey conf_wk; - - if (wk->wk_keylen > ACX100_WEPKEY_LEN) { - if_printf(&sc->sc_ic.ic_if, "%dth WEP key size beyond %d\n", - wk_idx, ACX100_WEPKEY_LEN); - return EINVAL; - } - - conf_wk.action = ACX100_WEPKEY_ACT_ADD; - conf_wk.key_len = wk->wk_keylen; - conf_wk.key_idx = wk_idx; - bcopy(wk->wk_key, conf_wk.key, wk->wk_keylen); - if (acx100_set_wepkey_conf(sc, &conf_wk) != 0) { - if_printf(&sc->sc_ic.ic_if, "%s set %dth WEP key failed\n", - __func__, wk_idx); - return ENXIO; - } - return 0; -} - -static void -acx100_proc_wep_rxbuf(struct acx_softc *sc, struct mbuf *m, int *len) -{ - int mac_hdrlen; - struct ieee80211_frame *f; - - /* - * Strip leading IV and KID, and trailing CRC - */ - - f = mtod(m, struct ieee80211_frame *); - - if ((f->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS) - mac_hdrlen = sizeof(struct ieee80211_frame_addr4); - else - mac_hdrlen = sizeof(struct ieee80211_frame); - -#define IEEEWEP_IVLEN (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN) -#define IEEEWEP_EXLEN (IEEEWEP_IVLEN + IEEE80211_WEP_CRCLEN) - - *len = *len - IEEEWEP_EXLEN; - - /* Move MAC header toward frame body */ - ovbcopy(f, (uint8_t *)f + IEEEWEP_IVLEN, mac_hdrlen); - m_adj(m, IEEEWEP_IVLEN); - -#undef IEEEWEP_EXLEN -#undef IEEEWEP_IVLEN -} - -static void -acx100_tx_complete(struct acx_softc *sc, struct acx_txbuf *tx_buf, - int frame_len, int is_fail) -{ - int rts_retries, data_retries; - struct ieee80211_ratectl_res rc_res; - - rts_retries = FW_TXDESC_GETFIELD_1(sc, tx_buf, f_tx_rts_nretry); - data_retries = FW_TXDESC_GETFIELD_1(sc, tx_buf, f_tx_data_nretry); - - rc_res.rc_res_rateidx = tx_buf->tb_rateidx[0]; - rc_res.rc_res_tries = data_retries + 1; - - ieee80211_ratectl_tx_complete(tx_buf->tb_node, frame_len, - &rc_res, 1, data_retries, rts_retries, - is_fail); -} - -static void * -acx100_ratectl_attach(struct ieee80211com *ic, u_int rc) -{ - struct acx_softc *sc = ic->ic_if.if_softc; - - switch (rc) { - case IEEE80211_RATECTL_ONOE: - return &sc->sc_onoe_param; - case IEEE80211_RATECTL_NONE: - /* This could only happen during detaching */ - return NULL; - default: - panic("unknown rate control algo %u", rc); - return NULL; - } -} diff --git a/sys/dev/netif/acx/acx111.c b/sys/dev/netif/acx/acx111.c deleted file mode 100644 index 27eb59404e..0000000000 --- a/sys/dev/netif/acx/acx111.c +++ /dev/null @@ -1,781 +0,0 @@ -/* - * Copyright (c) 2006 The DragonFly Project. All rights reserved. - * - * This code is derived from software contributed to The DragonFly Project - * by Sepherosa Ziehau - * - * 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. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * 3. Neither the name of The DragonFly Project nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific, prior written permission. - * - * 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 MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, 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 DAMAGE. - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - -#include - -#define ACX_DEBUG - -#include -#include -#include - -#define ACX111_CONF_MEM 0x0003 -#define ACX111_CONF_MEMINFO 0x0005 -#define ACX111_CONF_RT0_NRETRY 0x0006 - -#define ACX111_INTR_ENABLE (ACXRV_INTR_TX_FINI | ACXRV_INTR_RX_FINI) -/* - * XXX do we really care about fowlling interrupts? - * - * ACXRV_INTR_IV_ICV_FAILURE | ACXRV_INTR_INFO | - * ACXRV_INTR_SCAN_FINI | ACXRV_INTR_FCS_THRESHOLD - */ - -#define ACX111_INTR_DISABLE (uint16_t)~(ACXRV_INTR_CMD_FINI) - -#define ACX111_RATE_2 0x0001 -#define ACX111_RATE_4 0x0002 -#define ACX111_RATE_11 0x0004 -#define ACX111_RATE_12 0x0008 -#define ACX111_RATE_18 0x0010 -#define ACX111_RATE_22 0x0020 -#define ACX111_RATE_24 0x0040 -#define ACX111_RATE_36 0x0080 -#define ACX111_RATE_44 0x0100 -#define ACX111_RATE_48 0x0200 -#define ACX111_RATE_72 0x0400 -#define ACX111_RATE_96 0x0800 -#define ACX111_RATE_108 0x1000 -#define ACX111_RATE(rate) [rate] = ACX111_RATE_##rate - -#define ACX111_RSSI_CORR 5 -#define ACX111_TXPOWER 15 -#define ACX111_GPIO_POWER_LED 0x0040 -#define ACX111_EE_EADDR_OFS 0x21 - -#define ACX111_FW_TXDESC_SIZE (sizeof(struct acx_fw_txdesc) + 4) - -#if ACX111_TXPOWER <= 12 -#define ACX111_TXPOWER_VAL 1 -#else -#define ACX111_TXPOWER_VAL 2 -#endif - -#define ACX111_ONOE_RATEIDX_MAX 4 -#define ACX111_AMRR_RATEIDX_MAX 4 - -/* - * NOTE: - * Following structs' fields are little endian - */ - -struct acx111_bss_join { - uint16_t basic_rates; - uint8_t dtim_intvl; -} __packed; - -struct acx111_calib { - uint32_t calib; /* ACX111_CALIB_ */ - uint32_t interval; /* TU */ -} __packed; - -#define ACX111_CALIB_AUTO 0x80000000 -#define ACX111_CALIB_DC 0x00000001 -#define ACX111_CALIB_AFE_DC 0x00000002 -#define ACX111_CALIB_TX_MISMATCH 0x00000004 -#define ACX111_CALIB_TX_EQUAL 0x00000008 - -#define ACX111_FW_CALIB_INTVL IEEE80211_MS_TO_TU(60000) /* 60sec */ - -struct acx111_conf_mem { - struct acx_conf confcom; - - uint16_t sta_max; /* max num of sta, ACX111_STA_MAX */ - uint16_t memblk_size; /* mem block size */ - uint8_t rx_memblk_perc; /* percent of RX mem block, unit: 5% */ - uint8_t fw_rxring_num; /* num of RX ring */ - uint8_t fw_txring_num; /* num of TX ring */ - uint8_t opt; /* see ACX111_MEMOPT_ */ - uint8_t xfer_perc; /* frag/xfer proportion, unit: 5% */ - uint16_t reserved0; - uint8_t reserved1; - - uint8_t fw_rxdesc_num; /* num of fw rx desc */ - uint8_t fw_rxring_reserved1; - uint8_t fw_rxring_type; /* see ACX111_RXRING_TYPE_ */ - uint8_t fw_rxring_prio; /* see ACX111_RXRING_PRIO_ */ - - uint32_t h_rxring_paddr; /* host rx desc start phyaddr */ - - uint8_t fw_txdesc_num; /* num of fw tx desc */ - uint8_t fw_txring_reserved1; - uint8_t fw_txring_reserved2; - uint8_t fw_txring_attr; /* see ACX111_TXRING_ATTR_ */ -} __packed; - -/* - * ACX111 does support limited multi-rate retry, following rules apply to - * at least firmware rev1.2.x.x: - * 1) Rate field in firmware descriptor is a bitmask, which indicates - * set of rates to be used to send the packet. - * 2) "acx111_conf_rt0_nretry" configures the number of retries for - * 1st rate. - * 3) Except for the last rate and 1st rate, rest of the rates in the - * rate set are tried only once. - * 4) Last rate will be tried until "short retry limit" + "long retry limit" - * reaches. - * - * e.g. - * a) 54Mbit/s, 48Mbit/s and 1Mbit/s are in the rate set. - * b) Number of retries for the 1st rate (i.e. 54Mbit/s) is set to 3. - * c) Short retry limit is set to 7 - * - * For the above configuration: - * A) 4 tries will be spent at 54Mbit/s. - * B) 1 try will be spent at 48Mbit/s, if A) fails. - * C) 3 tries will be spent at 1Mbit/s, if A) and B) fail. - */ -struct acx111_conf_rt0_nretry { - struct acx_conf confcom; - uint8_t rt0_nretry; /* number of retry for 1st rate */ -} __packed; - -#define ACX111_STA_MAX 32 -#define ACX111_RX_MEMBLK_PERCENT 10 /* 50% */ -#define ACX111_XFER_PERCENT 15 /* 75% */ -#define ACX111_RXRING_TYPE_DEFAULT 7 -#define ACX111_RXRING_PRIO_DEFAULT 0 -#define ACX111_TXRING_ATTR_DEFAULT 0 -#define ACX111_MEMOPT_DEFAULT 0 - -struct acx111_conf_meminfo { - struct acx_conf confcom; - uint32_t tx_memblk_addr; /* start addr of tx mem blocks */ - uint32_t rx_memblk_addr; /* start addr of rx mem blocks */ - uint32_t fw_rxring_start; /* start phyaddr of fw rx ring */ - uint32_t reserved0; - uint32_t fw_txring_start; /* start phyaddr of fw tx ring */ - uint8_t fw_txring_attr; /* XXX see ACX111_TXRING_ATTR_ */ - uint16_t reserved1; - uint8_t reserved2; -} __packed; - -struct acx111_conf_txpower { - struct acx_conf confcom; - uint8_t txpower; -} __packed; - -struct acx111_conf_option { - struct acx_conf confcom; - uint32_t feature; - uint32_t dataflow; /* see ACX111_DF_ */ -} __packed; - -#define ACX111_DF_NO_RXDECRYPT 0x00000080 -#define ACX111_DF_NO_TXENCRYPT 0x00000001 - -struct acx111_wepkey { - uint8_t mac_addr[IEEE80211_ADDR_LEN]; - uint16_t action; /* see ACX111_WEPKEY_ACT_ */ - uint16_t reserved; - uint8_t key_len; - uint8_t key_type; /* see ACX111_WEPKEY_TYPE_ */ - uint8_t index; /* XXX ?? */ - uint8_t key_idx; - uint8_t counter[6]; -#define ACX111_WEPKEY_LEN 32 - uint8_t key[ACX111_WEPKEY_LEN]; -} __packed; - -#define ACX111_WEPKEY_ACT_ADD 1 -#define ACX111_WEPKEY_TYPE_DEFAULT 0 - -#define ACX111_CONF_FUNC(sg, name) _ACX_CONF_FUNC(sg, name, 111) -#define ACX_CONF_mem ACX111_CONF_MEM -#define ACX_CONF_meminfo ACX111_CONF_MEMINFO -#define ACX_CONF_rt0_nretry ACX111_CONF_RT0_NRETRY -#define ACX_CONF_txpower ACX_CONF_TXPOWER -#define ACX_CONF_option ACX_CONF_OPTION -ACX111_CONF_FUNC(set, mem); -ACX111_CONF_FUNC(get, meminfo); -ACX111_CONF_FUNC(set, txpower); -ACX111_CONF_FUNC(get, option); -ACX111_CONF_FUNC(set, option); -ACX111_CONF_FUNC(set, rt0_nretry); - -static const uint16_t acx111_reg[ACXREG_MAX] = { - ACXREG(SOFT_RESET, 0x0000), - - ACXREG(FWMEM_ADDR, 0x0014), - ACXREG(FWMEM_DATA, 0x0018), - ACXREG(FWMEM_CTRL, 0x001c), - ACXREG(FWMEM_START, 0x0020), - - ACXREG(EVENT_MASK, 0x0034), - - ACXREG(INTR_TRIG, 0x00b4), - ACXREG(INTR_MASK, 0x00d4), - ACXREG(INTR_STATUS, 0x00f0), - ACXREG(INTR_STATUS_CLR, 0x00e4), - ACXREG(INTR_ACK, 0x00e8), - - ACXREG(HINTR_TRIG, 0x00ec), - ACXREG(RADIO_ENABLE, 0x01d0), - - ACXREG(EEPROM_INIT, 0x0100), - ACXREG(EEPROM_CTRL, 0x0338), - ACXREG(EEPROM_ADDR, 0x033c), - ACXREG(EEPROM_DATA, 0x0340), - ACXREG(EEPROM_CONF, 0x0344), - ACXREG(EEPROM_INFO, 0x0390), - - ACXREG(PHY_ADDR, 0x0350), - ACXREG(PHY_DATA, 0x0354), - ACXREG(PHY_CTRL, 0x0358), - - ACXREG(GPIO_OUT_ENABLE, 0x0374), - ACXREG(GPIO_OUT, 0x037c), - - ACXREG(CMD_REG_OFFSET, 0x0388), - ACXREG(INFO_REG_OFFSET, 0x038c), - - ACXREG(RESET_SENSE, 0x0104), - ACXREG(ECPU_CTRL, 0x0108) -}; - -static const uint16_t acx111_rate_map[109] = { - ACX111_RATE(2), - ACX111_RATE(4), - ACX111_RATE(11), - ACX111_RATE(22), - ACX111_RATE(12), - ACX111_RATE(18), - ACX111_RATE(24), - ACX111_RATE(36), - ACX111_RATE(44), - ACX111_RATE(48), - ACX111_RATE(72), - ACX111_RATE(96), - ACX111_RATE(108) -}; - -static const int -acx111_onoe_tries[IEEE80211_RATEIDX_MAX] = { 4, 1, 1, 3, 0 }; - -static const int -acx111_amrr_tries[IEEE80211_RATEIDX_MAX] = { 4, 1, 1, 3, 0 }; - -static int acx111_init(struct acx_softc *); -static int acx111_init_memory(struct acx_softc *); -static void acx111_init_fw_txring(struct acx_softc *, uint32_t); - -static int acx111_write_config(struct acx_softc *, struct acx_config *); - -static void acx111_set_bss_join_param(struct acx_softc *, void *, int); -static int acx111_calibrate(struct acx_softc *); - -static void *acx111_ratectl_attach(struct ieee80211com *, u_int); - -static uint8_t _acx111_set_fw_txdesc_rate(struct acx_softc *, - struct acx_txbuf *, - struct ieee80211_node *, int, int); -static uint8_t acx111_set_fw_txdesc_rate_onoe(struct acx_softc *, - struct acx_txbuf *, - struct ieee80211_node *, int); -static uint8_t acx111_set_fw_txdesc_rate_amrr(struct acx_softc *, - struct acx_txbuf *, - struct ieee80211_node *, int); - -static void _acx111_tx_complete(struct acx_softc *, struct acx_txbuf *, - int, int, const int[]); -static void acx111_tx_complete_onoe(struct acx_softc *, struct acx_txbuf *, - int, int); -static void acx111_tx_complete_amrr(struct acx_softc *, struct acx_txbuf *, - int, int); - -#define ACX111_CHK_RATE(ifp, rate, rate_idx) \ - acx111_check_rate(ifp, rate, rate_idx, __func__) - -static __inline int -acx111_check_rate(struct ifnet *ifp, u_int rate, int rate_idx, - const char *fname) -{ - if (rate >= NELEM(acx111_rate_map)) { - if_printf(ifp, "%s rate out of range %u (idx %d)\n", - fname, rate, rate_idx); - return -1; - } - - if (acx111_rate_map[rate] == 0) { - if_printf(ifp, "%s invalid rate %u (idx %d)\n", - fname, rate, rate_idx); - return -1; - } - return 0; -} - -void -acx111_set_param(device_t dev) -{ - struct acx_softc *sc = device_get_softc(dev); - struct ieee80211com *ic = &sc->sc_ic; - struct acx_firmware *fw = &sc->sc_firmware; - - sc->chip_mem1_rid = PCIR_BAR(0); - sc->chip_mem2_rid = PCIR_BAR(1); - sc->chip_ioreg = acx111_reg; - sc->chip_intr_enable = ACX111_INTR_ENABLE; - sc->chip_intr_disable = ACX111_INTR_DISABLE; - sc->chip_gpio_pled = ACX111_GPIO_POWER_LED; - sc->chip_ee_eaddr_ofs = ACX111_EE_EADDR_OFS; - sc->chip_rssi_corr = ACX111_RSSI_CORR; - sc->chip_calibrate = acx111_calibrate; - - sc->chip_phymode = IEEE80211_MODE_11G; - sc->chip_chan_flags = IEEE80211_CHAN_CCK | - IEEE80211_CHAN_OFDM | - IEEE80211_CHAN_DYN | - IEEE80211_CHAN_2GHZ; - - ic->ic_caps = IEEE80211_C_WPA | IEEE80211_C_SHSLOT; - ic->ic_phytype = IEEE80211_T_OFDM; - if (acx_enable_pbcc) { - ic->ic_sup_rates[IEEE80211_MODE_11B] = acx_rates_11b_pbcc; - ic->ic_sup_rates[IEEE80211_MODE_11G] = acx_rates_11g_pbcc; - } else { - ic->ic_sup_rates[IEEE80211_MODE_11B] = acx_rates_11b; - ic->ic_sup_rates[IEEE80211_MODE_11G] = acx_rates_11g; - } - - IEEE80211_ONOE_PARAM_SETUP(&sc->sc_onoe_param); - IEEE80211_AMRR_PARAM_SETUP(&sc->sc_amrr_param); - - ic->ic_ratectl.rc_st_ratectl_cap = IEEE80211_RATECTL_CAP_ONOE | - IEEE80211_RATECTL_CAP_AMRR; - ic->ic_ratectl.rc_st_ratectl = IEEE80211_RATECTL_AMRR; - ic->ic_ratectl.rc_st_attach = acx111_ratectl_attach; - - sc->chip_init = acx111_init; - sc->chip_write_config = acx111_write_config; - sc->chip_set_bss_join_param = acx111_set_bss_join_param; - - fw->combined_radio_fw = 1; - fw->fwdir = "111"; -} - -static int -acx111_init(struct acx_softc *sc) -{ - /* - * NOTE: - * Order of initialization: - * 1) Templates - * 2) Hardware memory - * Above order is critical to get a correct memory map - */ - - if (acx_init_tmplt_ordered(sc) != 0) { - if_printf(&sc->sc_ic.ic_if, "%s can't initialize templates\n", - __func__); - return ENXIO; - } - - if (acx111_init_memory(sc) != 0) { - if_printf(&sc->sc_ic.ic_if, "%s can't initialize hw memory\n", - __func__); - return ENXIO; - } - return 0; -} - -static int -acx111_init_memory(struct acx_softc *sc) -{ - struct acx111_conf_mem mem; - struct acx111_conf_meminfo mem_info; - - /* Set memory configuration */ - bzero(&mem, sizeof(mem)); - - mem.sta_max = htole16(ACX111_STA_MAX); - mem.memblk_size = htole16(ACX_MEMBLOCK_SIZE); - mem.rx_memblk_perc = ACX111_RX_MEMBLK_PERCENT; - mem.opt = ACX111_MEMOPT_DEFAULT; - mem.xfer_perc = ACX111_XFER_PERCENT; - - mem.fw_rxring_num = 1; - mem.fw_rxring_type = ACX111_RXRING_TYPE_DEFAULT; - mem.fw_rxring_prio = ACX111_RXRING_PRIO_DEFAULT; - mem.fw_rxdesc_num = ACX_RX_DESC_CNT; - mem.h_rxring_paddr = htole32(sc->sc_ring_data.rx_ring_paddr); - - mem.fw_txring_num = 1; - mem.fw_txring_attr = ACX111_TXRING_ATTR_DEFAULT; - mem.fw_txdesc_num = ACX_TX_DESC_CNT; - - if (acx111_set_mem_conf(sc, &mem) != 0) { - if_printf(&sc->sc_ic.ic_if, "can't set mem\n"); - return 1; - } - - /* Get memory configuration */ - if (acx111_get_meminfo_conf(sc, &mem_info) != 0) { - if_printf(&sc->sc_ic.ic_if, "can't get meminfo\n"); - return 1; - } - - /* Setup firmware TX descriptor ring */ - acx111_init_fw_txring(sc, le32toh(mem_info.fw_txring_start)); - - /* - * There is no need to setup firmware RX descriptor ring, - * it is automaticly setup by hardware. - */ - - return 0; -} - -static void -acx111_init_fw_txring(struct acx_softc *sc, uint32_t fw_txdesc_start) -{ - struct acx_txbuf *tx_buf; - uint32_t desc_paddr; - int i; - - tx_buf = sc->sc_buf_data.tx_buf; - desc_paddr = sc->sc_ring_data.tx_ring_paddr; - - for (i = 0; i < ACX_TX_DESC_CNT; ++i) { - tx_buf[i].tb_fwdesc_ofs = fw_txdesc_start + - (i * ACX111_FW_TXDESC_SIZE); - - /* - * Except for the following fields, rest of the fields - * are setup by hardware. - */ - FW_TXDESC_SETFIELD_4(sc, &tx_buf[i], f_tx_host_desc, - desc_paddr); - FW_TXDESC_SETFIELD_1(sc, &tx_buf[i], f_tx_ctrl, - DESC_CTRL_HOSTOWN); - - desc_paddr += (2 * sizeof(struct acx_host_desc)); - } -} - -static int -acx111_write_config(struct acx_softc *sc, struct acx_config *conf) -{ - struct acx111_conf_txpower tx_power; - struct acx111_conf_option opt; - struct acx111_conf_rt0_nretry rt0_nretry; - uint32_t dataflow; - - /* Set TX power */ - tx_power.txpower = ACX111_TXPOWER_VAL; - if (acx111_set_txpower_conf(sc, &tx_power) != 0) { - if_printf(&sc->sc_ic.ic_if, "%s can't set TX power\n", - __func__); - return ENXIO; - } - - /* - * Turn off hardware WEP - */ - if (acx111_get_option_conf(sc, &opt) != 0) { - if_printf(&sc->sc_ic.ic_if, "%s can't get option\n", __func__); - return ENXIO; - } - - dataflow = le32toh(opt.dataflow) | - ACX111_DF_NO_TXENCRYPT | - ACX111_DF_NO_RXDECRYPT; - opt.dataflow = htole32(dataflow); - - if (acx111_set_option_conf(sc, &opt) != 0) { - if_printf(&sc->sc_ic.ic_if, "%s can't set option\n", __func__); - return ENXIO; - } - - /* - * Set number of retries for 0th rate - */ - rt0_nretry.rt0_nretry = sc->chip_rate_fallback; - if (acx111_set_rt0_nretry_conf(sc, &rt0_nretry) != 0) { - if_printf(&sc->sc_ic.ic_if, "%s can't set rate0 nretry\n", - __func__); - return ENXIO; - } - return 0; -} - -static uint8_t -_acx111_set_fw_txdesc_rate(struct acx_softc *sc, struct acx_txbuf *tx_buf, - struct ieee80211_node *ni, int data_len, - int rateidx_max) -{ - struct ifnet *ifp = &sc->sc_ic.ic_if; - uint16_t rate; - uint8_t ret = 0; - - KKASSERT(rateidx_max <= IEEE80211_RATEIDX_MAX); - - if (ni == NULL) { - rate = ACX111_RATE_2; /* 1Mbit/s */ - ret = 2; - tx_buf->tb_rateidx_len = 1; - tx_buf->tb_rateidx[0] = 0; - } else { - struct ieee80211_rateset *rs = &ni->ni_rates; - int *rateidx = tx_buf->tb_rateidx; - int i, n; - - n = ieee80211_ratectl_findrate(ni, data_len, rateidx, - rateidx_max); - - rate = 0; - for (i = 0; i < n; ++i) { - u_int map_idx = IEEE80211_RS_RATE(rs, rateidx[i]); - - if (ACX111_CHK_RATE(ifp, map_idx, rateidx[i]) < 0) - continue; - - if (ret == 0) - ret = map_idx; - - rate |= acx111_rate_map[map_idx]; - } - if (rate == 0) { - if_printf(ifp, "WARNING no rate, set to 1Mbit/s\n"); - rate = ACX111_RATE_2; - ret = 2; - tx_buf->tb_rateidx_len = 1; - tx_buf->tb_rateidx[0] = 0; - } else { - tx_buf->tb_rateidx_len = n; - } - } - FW_TXDESC_SETFIELD_2(sc, tx_buf, u.r2.rate111, rate); - - return ret; -} - -static uint8_t -acx111_set_fw_txdesc_rate_onoe(struct acx_softc *sc, struct acx_txbuf *tx_buf, - struct ieee80211_node *ni, int data_len) -{ - return _acx111_set_fw_txdesc_rate(sc, tx_buf, ni, data_len, - ACX111_ONOE_RATEIDX_MAX); -} - -static uint8_t -acx111_set_fw_txdesc_rate_amrr(struct acx_softc *sc, struct acx_txbuf *tx_buf, - struct ieee80211_node *ni, int data_len) -{ - return _acx111_set_fw_txdesc_rate(sc, tx_buf, ni, data_len, - ACX111_AMRR_RATEIDX_MAX); -} - -static void -acx111_set_bss_join_param(struct acx_softc *sc, void *param, int dtim_intvl) -{ - struct acx111_bss_join *bj = param; - const struct ieee80211_rateset *rs = &sc->sc_ic.ic_bss->ni_rates; - struct ifnet *ifp = &sc->sc_ic.ic_if; - uint16_t basic_rates = 0; - int i; - - for (i = 0; i < rs->rs_nrates; ++i) { - if (rs->rs_rates[i] & IEEE80211_RATE_BASIC) { - u_int map_idx = IEEE80211_RS_RATE(rs, i); - - if (ACX111_CHK_RATE(ifp, map_idx, i) < 0) - continue; - - basic_rates |= acx111_rate_map[map_idx]; - } - } - DPRINTF((ifp, "basic rates: 0x%04x\n", basic_rates)); - - bj->basic_rates = htole16(basic_rates); - bj->dtim_intvl = dtim_intvl; -} - -static void * -acx111_ratectl_attach(struct ieee80211com *ic, u_int rc) -{ - struct ifnet *ifp = &ic->ic_if; - struct acx_softc *sc = ifp->if_softc; - const int *tries; - void *ret; - int i; - - switch (rc) { - case IEEE80211_RATECTL_ONOE: - tries = acx111_onoe_tries; - sc->chip_set_fw_txdesc_rate = acx111_set_fw_txdesc_rate_onoe; - sc->chip_tx_complete = acx111_tx_complete_onoe; - ret = &sc->sc_onoe_param; - break; - - case IEEE80211_RATECTL_AMRR: - tries = acx111_amrr_tries; - sc->chip_set_fw_txdesc_rate = acx111_set_fw_txdesc_rate_amrr; - sc->chip_tx_complete = acx111_tx_complete_amrr; - ret = &sc->sc_amrr_param; - break; - - case IEEE80211_RATECTL_NONE: - /* This could only happen during detaching */ - return NULL; - - default: - panic("unknown rate control algo %u", rc); - break; - } - - sc->chip_rate_fallback = tries[0] - 1; - - sc->chip_short_retry_limit = 0; - for (i = 0; i < IEEE80211_RATEIDX_MAX; ++i) - sc->chip_short_retry_limit += tries[i]; - sc->chip_short_retry_limit--; - - if ((ifp->if_flags & (IFF_RUNNING | IFF_UP)) == - (IFF_RUNNING | IFF_UP)) { - struct acx_conf_nretry_short sretry; - struct acx111_conf_rt0_nretry rt0_nretry; - - /* - * Set number of short retries - */ - sretry.nretry = sc->chip_short_retry_limit; - if (acx_set_nretry_short_conf(sc, &sretry) != 0) { - if_printf(ifp, "%s can't set short retry limit\n", - __func__); - } - DPRINTF((ifp, "%s set sretry %d\n", __func__, - sc->chip_short_retry_limit)); - - /* - * Set number of retries for 0th rate - */ - rt0_nretry.rt0_nretry = sc->chip_rate_fallback; - if (acx111_set_rt0_nretry_conf(sc, &rt0_nretry) != 0) { - if_printf(ifp, "%s can't set rate0 nretry\n", - __func__); - } - DPRINTF((ifp, "%s set rate 0 nretry %d\n", __func__, - sc->chip_rate_fallback)); - } - return ret; -} - -static void -_acx111_tx_complete(struct acx_softc *sc, struct acx_txbuf *tx_buf, - int frame_len, int is_fail, const int tries_arr[]) -{ - struct ieee80211_ratectl_res rc_res[IEEE80211_RATEIDX_MAX]; - int rts_retries, data_retries, n, tries, prev_tries; - - KKASSERT(tx_buf->tb_rateidx_len <= IEEE80211_RATEIDX_MAX); - - rts_retries = FW_TXDESC_GETFIELD_1(sc, tx_buf, f_tx_rts_nretry); - data_retries = FW_TXDESC_GETFIELD_1(sc, tx_buf, f_tx_data_nretry); - -#if 0 - DPRINTF((&sc->sc_ic.ic_if, "d%d r%d rateidx_len %d\n", - data_retries, rts_retries, tx_buf->tb_rateidx_len)); -#endif - - prev_tries = tries = 0; - for (n = 0; n < tx_buf->tb_rateidx_len; ++n) { - rc_res[n].rc_res_tries = tries_arr[n]; - rc_res[n].rc_res_rateidx = tx_buf->tb_rateidx[n]; - if (!is_fail) { - if (data_retries + 1 <= tries) - break; - prev_tries = tries; - tries += tries_arr[n]; - } - } - KKASSERT(n != 0); - - if (!is_fail && data_retries + 1 <= tries) { - rc_res[n - 1].rc_res_tries = data_retries + 1 - prev_tries; -#if 0 - DPRINTF((&sc->sc_ic.ic_if, "n %d, last tries%d\n", - n, rc_res[n - 1].rc_res_tries)); -#endif - } - ieee80211_ratectl_tx_complete(tx_buf->tb_node, frame_len, rc_res, n, - data_retries, rts_retries, is_fail); -} - -static void -acx111_tx_complete_onoe(struct acx_softc *sc, struct acx_txbuf *tx_buf, - int frame_len, int is_fail) -{ - _acx111_tx_complete(sc, tx_buf, frame_len, is_fail, - acx111_onoe_tries); -} - -static void -acx111_tx_complete_amrr(struct acx_softc *sc, struct acx_txbuf *tx_buf, - int frame_len, int is_fail) -{ - _acx111_tx_complete(sc, tx_buf, frame_len, is_fail, - acx111_amrr_tries); -} - -static int -acx111_calibrate(struct acx_softc *sc) -{ - struct acx111_calib calib; - - calib.calib = htole32(ACX111_CALIB_AUTO | - ACX111_CALIB_DC | - ACX111_CALIB_AFE_DC | - ACX111_CALIB_TX_MISMATCH | - ACX111_CALIB_TX_EQUAL); - calib.interval = htole32(ACX111_FW_CALIB_INTVL); - - return acx_exec_command(sc, ACXCMD_CALIBRATE, &calib, sizeof(calib), - NULL, 0); -} diff --git a/sys/dev/netif/acx/acxcmd.c b/sys/dev/netif/acx/acxcmd.c deleted file mode 100644 index dc94801450..0000000000 --- a/sys/dev/netif/acx/acxcmd.c +++ /dev/null @@ -1,314 +0,0 @@ -/* - * Copyright (c) 2006 The DragonFly Project. All rights reserved. - * - * This code is derived from software contributed to The DragonFly Project - * by Sepherosa Ziehau - * - * 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. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * 3. Neither the name of The DragonFly Project nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific, prior written permission. - * - * 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 MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, 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 DAMAGE. - * - * $DragonFly: src/sys/dev/netif/acx/acxcmd.c,v 1.11 2008/06/01 03:58:38 sephe Exp $ - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - -#define ACX_DEBUG - -#include -#include -#include - -#define CMDPRM_WRITE_REGION_1(sc, r, rlen) \ - bus_space_write_region_1((sc)->sc_mem2_bt, \ - (sc)->sc_mem2_bh, \ - (sc)->sc_cmd_param, \ - (const uint8_t *)(r), (rlen)) - -#define CMDPRM_READ_REGION_1(sc, r, rlen) \ - bus_space_read_region_1((sc)->sc_mem2_bt, (sc)->sc_mem2_bh, \ - (sc)->sc_cmd_param, (uint8_t *)(r), (rlen)) - -/* - * This will clear previous command's - * execution status too - */ -#define CMD_WRITE_4(sc, val) \ - bus_space_write_4((sc)->sc_mem2_bt, (sc)->sc_mem2_bh, \ - (sc)->sc_cmd, (val)) -#define CMD_READ_4(sc) \ - bus_space_read_4((sc)->sc_mem2_bt, (sc)->sc_mem2_bh, (sc)->sc_cmd) - -/* - * acx command register layerout: - * upper 16bits are command execution status - * lower 16bits are command to be executed - */ -#define ACX_CMD_STATUS_SHIFT 16 -#define ACX_CMD_STATUS_OK 1 - -struct radio_init { - uint32_t radio_ofs; /* radio firmware offset */ - uint32_t radio_len; /* radio firmware length */ -} __packed; - -struct bss_join_hdr { - uint8_t bssid[IEEE80211_ADDR_LEN]; - uint16_t beacon_intvl; - uint8_t chip_spec[3]; - uint8_t ndata_txrate; /* see ACX_NDATA_TXRATE_ */ - uint8_t ndata_txopt; /* see ACX_NDATA_TXOPT_ */ - uint8_t mode; /* see ACX_MODE_ */ - uint8_t channel; - uint8_t esslen; - char essid[1]; -} __packed; - -/* - * non-data frame tx rate - */ -#define ACX_NDATA_TXRATE_1 10 /* 1Mbits/s */ -#define ACX_NDATA_TXRATE_2 20 /* 2Mbits/s */ - -/* - * non-data frame tx options - */ -#define ACX_NDATA_TXOPT_PBCC 0x40 -#define ACX_NDATA_TXOPT_OFDM 0x20 -#define ACX_NDATA_TXOPT_SHORT_PREAMBLE 0x10 - -#define BSS_JOIN_BUFLEN \ - (sizeof(struct bss_join_hdr) + IEEE80211_NWID_LEN) -#define BSS_JOIN_PARAM_SIZE(bj) \ - (sizeof(struct bss_join_hdr) + (bj)->esslen) - -void -acx_init_cmd_reg(struct acx_softc *sc) -{ - sc->sc_cmd = CSR_READ_4(sc, ACXREG_CMD_REG_OFFSET); - sc->sc_cmd_param = sc->sc_cmd + ACX_CMD_REG_SIZE; - - /* Clear command & status */ - CMD_WRITE_4(sc, 0); -} - -int -acx_join_bss(struct acx_softc *sc, uint8_t mode, struct ieee80211_node *ni, - struct ieee80211_channel *c) -{ - uint8_t bj_buf[BSS_JOIN_BUFLEN]; - struct ieee80211com *ic = &sc->sc_ic; - struct bss_join_hdr *bj; - int i; - - bzero(bj_buf, sizeof(bj_buf)); - bj = (struct bss_join_hdr *)bj_buf; - - for (i = 0; i < IEEE80211_ADDR_LEN; ++i) - bj->bssid[i] = ni->ni_bssid[IEEE80211_ADDR_LEN - i - 1]; - - bj->beacon_intvl = htole16(ni->ni_intval); - - sc->chip_set_bss_join_param(sc, bj->chip_spec, ic->ic_dtim_period); - - bj->ndata_txrate = ACX_NDATA_TXRATE_1; - bj->ndata_txopt = 0; - bj->mode = mode; - bj->channel = ieee80211_chan2ieee(ic, c); - bj->esslen = ni->ni_esslen; - bcopy(ni->ni_essid, bj->essid, ni->ni_esslen); - - DPRINTF((&ic->ic_if, "join BSS/IBSS on channel %d\n", bj->channel)); - return acx_exec_command(sc, ACXCMD_JOIN_BSS, - bj, BSS_JOIN_PARAM_SIZE(bj), NULL, 0); -} - -int -acx_enable_txchan(struct acx_softc *sc, uint8_t chan) -{ - return acx_exec_command(sc, ACXCMD_ENABLE_TXCHAN, &chan, sizeof(chan), - NULL, 0); -} - -int -acx_enable_rxchan(struct acx_softc *sc, uint8_t chan) -{ - return acx_exec_command(sc, ACXCMD_ENABLE_RXCHAN, &chan, sizeof(chan), - NULL, 0); -} - -int -acx_get_conf(struct acx_softc *sc, uint16_t conf_id, void *conf, - uint16_t conf_len) -{ - struct acx_conf *confcom; - - if (conf_len < sizeof(*confcom)) { - if_printf(&sc->sc_ic.ic_if, "%s configure data is too short\n", - __func__); - return 1; - } - - confcom = conf; - confcom->conf_id = htole16(conf_id); - confcom->conf_data_len = htole16(conf_len - sizeof(*confcom)); - - return acx_exec_command(sc, ACXCMD_GET_CONF, confcom, sizeof(*confcom), - conf, conf_len); -} - -int -acx_set_conf(struct acx_softc *sc, uint16_t conf_id, void *conf, - uint16_t conf_len) -{ - struct acx_conf *confcom; - - if (conf_len < sizeof(*confcom)) { - if_printf(&sc->sc_ic.ic_if, "%s configure data is too short\n", - __func__); - return 1; - } - - confcom = conf; - confcom->conf_id = htole16(conf_id); - confcom->conf_data_len = htole16(conf_len - sizeof(*confcom)); - - return acx_exec_command(sc, ACXCMD_SET_CONF, conf, conf_len, NULL, 0); -} - -int -acx_set_tmplt(struct acx_softc *sc, uint16_t cmd, void *tmplt, - uint16_t tmplt_len) -{ - uint16_t *size; - - if (tmplt_len < sizeof(*size)) { - if_printf(&sc->sc_ic.ic_if, "%s template is too short\n", - __func__); - return 1; - } - - size = tmplt; - *size = htole16(tmplt_len - sizeof(*size)); - - return acx_exec_command(sc, cmd, tmplt, tmplt_len, NULL, 0); -} - -int -acx_init_radio(struct acx_softc *sc, uint32_t radio_ofs, uint32_t radio_len) -{ - struct radio_init r; - - r.radio_ofs = htole32(radio_ofs); - r.radio_len = htole32(radio_len); - return acx_exec_command(sc, ACXCMD_INIT_RADIO, &r, sizeof(r), NULL, 0); -} - -int -acx_exec_command(struct acx_softc *sc, uint16_t cmd, void *param, - uint16_t param_len, void *result, uint16_t result_len) -{ - uint16_t status; - int i, ret; - - ASSERT_SERIALIZED(sc->sc_ic.ic_if.if_serializer); - - if ((sc->sc_flags & ACX_FLAG_FW_LOADED) == 0) { - if_printf(&sc->sc_ic.ic_if, "cmd 0x%04x failed (base firmware " - "not loaded)", cmd); - return 1; - } - - ret = 0; - - if (param != NULL && param_len != 0) { - /* Set command param */ - CMDPRM_WRITE_REGION_1(sc, param, param_len); - } - - /* Set command */ - CMD_WRITE_4(sc, cmd); - - /* Exec command */ - CSR_WRITE_2(sc, ACXREG_INTR_TRIG, ACXRV_TRIG_CMD_FINI); - DELAY(50); /* XXX maybe 100 */ - - /* Wait for command to complete */ - if (cmd == ACXCMD_INIT_RADIO) { - /* XXX radio initialization is extremely long */ - tsleep(&cmd, 0, "rdinit", (150 * hz) / 1000); /* 150ms */ - } - -#define CMDWAIT_RETRY_MAX 1000 - for (i = 0; i < CMDWAIT_RETRY_MAX; ++i) { - uint16_t reg; - - reg = CSR_READ_2(sc, ACXREG_INTR_STATUS); - if (reg & ACXRV_INTR_CMD_FINI) { - CSR_WRITE_2(sc, ACXREG_INTR_ACK, ACXRV_INTR_CMD_FINI); - break; - } - DELAY(50); - } - if (i == CMDWAIT_RETRY_MAX) { - if_printf(&sc->sc_ic.ic_if, "cmd %04x failed (timeout)\n", cmd); - ret = 1; - goto back; - } -#undef CMDWAIT_RETRY_MAX - - /* Get command exec status */ - status = (CMD_READ_4(sc) >> ACX_CMD_STATUS_SHIFT); - if (status != ACX_CMD_STATUS_OK) { - if_printf(&sc->sc_ic.ic_if, "cmd %04x failed\n", cmd); - ret = 1; - goto back; - } - - if (result != NULL && result_len != 0) { - /* Get command result */ - CMDPRM_READ_REGION_1(sc, result, result_len); - } - -back: - CMD_WRITE_4(sc, 0); - return ret; -} diff --git a/sys/dev/netif/acx/acxcmd.h b/sys/dev/netif/acx/acxcmd.h deleted file mode 100644 index bfe51004e5..0000000000 --- a/sys/dev/netif/acx/acxcmd.h +++ /dev/null @@ -1,333 +0,0 @@ -/* - * Copyright (c) 2006 The DragonFly Project. All rights reserved. - * - * This code is derived from software contributed to The DragonFly Project - * by Sepherosa Ziehau - * - * 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. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * 3. Neither the name of The DragonFly Project nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific, prior written permission. - * - * 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 MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, 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 DAMAGE. - * - * $DragonFly: src/sys/dev/netif/acx/acxcmd.h,v 1.6 2007/02/17 07:05:53 sephe Exp $ - */ - -#ifndef _ACXCMD_H -#define _ACXCMD_H - -#include "_acxcmd.h" - -void acx_init_cmd_reg(struct acx_softc *); - -int acx_enable_txchan(struct acx_softc *, uint8_t); -int acx_enable_rxchan(struct acx_softc *, uint8_t); -int acx_init_radio(struct acx_softc *, uint32_t, uint32_t); -int acx_join_bss(struct acx_softc *, uint8_t, - struct ieee80211_node *, struct ieee80211_channel *); - -/* - * Possible values for the second parameter of acx_join_bss() - */ -#define ACX_MODE_ADHOC 0 -#define ACX_MODE_UNUSED 1 -#define ACX_MODE_STA 2 -#define ACX_MODE_AP 3 - -/* - * Do not use following functions directly - */ -int acx_get_conf(struct acx_softc *, uint16_t, void *, uint16_t); -int acx_set_conf(struct acx_softc *, uint16_t, void *, uint16_t); -int acx_set_tmplt(struct acx_softc *, uint16_t, void *, uint16_t); -int acx_exec_command(struct acx_softc *, uint16_t, void *, uint16_t, - void *, uint16_t); - - -/* - * NOTE: - * Following structs' fields are little endian - */ - -struct acx_conf { - uint16_t conf_id; /* see ACXCONF_ (_acxcmd.h) */ - uint16_t conf_data_len; -} __packed; - -struct acx_conf_mmap { - struct acx_conf confcom; - uint32_t code_start; - uint32_t code_end; - uint32_t wep_cache_start; - uint32_t wep_cache_end; - uint32_t pkt_tmplt_start; - uint32_t pkt_tmplt_end; - uint32_t fw_desc_start; - uint32_t fw_desc_end; - uint32_t memblk_start; - uint32_t memblk_end; -} __packed; - -struct acx_conf_wepopt { - struct acx_conf confcom; - uint16_t nkey; - uint8_t opt; /* see WEPOPT_ */ -} __packed; - -#define WEPOPT_HDWEP 0 /* hardware WEP */ - -struct acx_conf_eaddr { - struct acx_conf confcom; - uint8_t eaddr[IEEE80211_ADDR_LEN]; -} __packed; - -struct acx_conf_regdom { - struct acx_conf confcom; - uint8_t regdom; - uint8_t unknown; -} __packed; - -struct acx_conf_antenna { - struct acx_conf confcom; - uint8_t antenna; -} __packed; - -struct acx_conf_fwrev { - struct acx_conf confcom; -#define ACX_FWREV_LEN 20 - /* - * "Rev xx.xx.xx.xx" - * '\0' terminated - */ - char fw_rev[ACX_FWREV_LEN]; - uint32_t hw_id; -} __packed; - -struct acx_conf_nretry_long { - struct acx_conf confcom; - uint8_t nretry; -} __packed; - -struct acx_conf_nretry_short { - struct acx_conf confcom; - uint8_t nretry; -} __packed; - -struct acx_conf_msdu_lifetime { - struct acx_conf confcom; - uint32_t lifetime; -} __packed; - -struct acx_conf_rate_fallback { - struct acx_conf confcom; - uint8_t ratefb_enable; /* 0/1 */ -} __packed; - -struct acx_conf_rxopt { - struct acx_conf confcom; - uint16_t opt1; /* see RXOPT1_ */ - uint16_t opt2; /* see RXOPT2_ */ -} __packed; - -#define RXOPT1_INCL_RXBUF_HDR 0x2000 /* rxbuf with acx_rxbuf_hdr */ -#define RXOPT1_RECV_SSID 0x0400 /* recv frame for joined SSID */ -#define RXOPT1_FILT_BCAST 0x0200 /* filt broadcast pkt */ -#define RXOPT1_RECV_MCAST1 0x0100 /* recv pkt for multicast addr1 */ -#define RXOPT1_RECV_MCAST0 0x0080 /* recv pkt for multicast addr0 */ -#define RXOPT1_FILT_ALLMULTI 0x0040 /* filt allmulti pkt */ -#define RXOPT1_FILT_FSSID 0x0020 /* filt frame for foreign SSID */ -#define RXOPT1_FILT_FDEST 0x0010 /* filt frame for foreign dest addr */ -#define RXOPT1_PROMISC 0x0008 /* promisc mode */ -#define RXOPT1_INCL_FCS 0x0004 -#define RXOPT1_INCL_PHYHDR 0x0000 /* XXX 0x0002 */ - -#define RXOPT2_RECV_ASSOC_REQ 0x0800 -#define RXOPT2_RECV_AUTH 0x0400 -#define RXOPT2_RECV_BEACON 0x0200 -#define RXOPT2_RECV_CF 0x0100 -#define RXOPT2_RECV_CTRL 0x0080 -#define RXOPT2_RECV_DATA 0x0040 -#define RXOPT2_RECV_BROKEN 0x0020 /* broken frame */ -#define RXOPT2_RECV_MGMT 0x0010 -#define RXOPT2_RECV_PROBE_REQ 0x0008 -#define RXOPT2_RECV_PROBE_RESP 0x0004 -#define RXOPT2_RECV_ACK 0x0002 /* RTS/CTS/ACK */ -#define RXOPT2_RECV_OTHER 0x0001 - -struct acx_conf_wep_txkey { - struct acx_conf confcom; - uint8_t wep_txkey; -} __packed; - - -struct acx_tmplt_null_data { - uint16_t size; - struct ieee80211_frame data; -} __packed; - -struct acx_tmplt_probe_req { - uint16_t size; - union { - struct { - struct ieee80211_frame f; - uint8_t var[1]; - } __packed u_data; - uint8_t u_mem[0x44]; - } data; -} __packed; - -#define ACX_TMPLT_PROBE_REQ_SIZ(var_len) \ - (sizeof(uint16_t) + sizeof(struct ieee80211_frame) + (var_len)) - -struct acx_tmplt_probe_resp { - uint16_t size; - union { - struct { - struct ieee80211_frame f; - uint8_t time_stamp[8]; - uint16_t beacon_intvl; - uint16_t cap; - uint8_t var[1]; - } __packed u_data; - uint8_t u_mem[0x100]; - } data; -} __packed; - -/* XXX same as acx_tmplt_probe_resp */ -struct acx_tmplt_beacon { - uint16_t size; - union { - struct { - struct ieee80211_frame f; - uint8_t time_stamp[8]; - uint16_t beacon_intvl; - uint16_t cap; - uint8_t var[1]; - } __packed u_data; - uint8_t u_mem[0x100]; - } data; -} __packed; - -struct acx_tmplt_tim { - uint16_t size; - union { - struct ieee80211_tim_ie u_tim; - uint8_t u_mem[0x100]; - } data; -} __packed; - -#define ACX_INIT_TMPLT_FUNC(name) \ -static __inline int \ -acx_init_##name##_tmplt(struct acx_softc *_sc) \ -{ \ - struct acx_tmplt_##name _tmplt; \ - \ - bzero(&_tmplt, sizeof(_tmplt)); \ - return acx_set_tmplt(_sc, ACXCMD_TMPLT_##name, \ - &_tmplt, sizeof(_tmplt)); \ -} \ -struct __hack - -#define ACX_SET_TMPLT_FUNC(name) \ -static __inline int \ -_acx_set_##name##_tmplt(struct acx_softc *_sc, \ - struct acx_tmplt_##name *_tmplt, \ - uint16_t _tmplt_len) \ -{ \ - return acx_set_tmplt(_sc, ACXCMD_TMPLT_##name, \ - _tmplt, _tmplt_len); \ -} \ -struct __hack - -#define _ACX_CONF_FUNC(sg, name, chip) \ -static __inline int \ -acx##chip##_##sg##_##name##_conf(struct acx_softc *_sc, \ - struct acx##chip##_conf_##name *_conf) \ -{ \ - return acx_##sg##_conf(_sc, ACX_CONF_##name, \ - _conf, sizeof(*_conf)); \ -} \ -struct __hack - -#define ACX_NOARG_FUNC(name) \ -static __inline int \ -acx_##name(struct acx_softc *_sc) \ -{ \ - return acx_exec_command(_sc, ACXCMD_##name, \ - NULL, 0, NULL, 0); \ -} \ -struct __hack - - -#define ACXCMD_TMPLT_tim ACXCMD_TMPLT_TIM -#define ACXCMD_TMPLT_beacon ACXCMD_TMPLT_BEACON -#define ACXCMD_TMPLT_probe_resp ACXCMD_TMPLT_PROBE_RESP -#define ACXCMD_TMPLT_null_data ACXCMD_TMPLT_NULL_DATA -#define ACXCMD_TMPLT_probe_req ACXCMD_TMPLT_PROBE_REQ -ACX_INIT_TMPLT_FUNC(tim); -ACX_INIT_TMPLT_FUNC(null_data); -ACX_INIT_TMPLT_FUNC(beacon); -ACX_INIT_TMPLT_FUNC(probe_req); -ACX_INIT_TMPLT_FUNC(probe_resp); -ACX_SET_TMPLT_FUNC(tim); -ACX_SET_TMPLT_FUNC(null_data); -ACX_SET_TMPLT_FUNC(beacon); -ACX_SET_TMPLT_FUNC(probe_req); -ACX_SET_TMPLT_FUNC(probe_resp); - -#define ACX_CONF_FUNC(sg, name) _ACX_CONF_FUNC(sg, name,) -#define ACX_CONF_wepopt ACX_CONF_WEPOPT -#define ACX_CONF_mmap ACX_CONF_MMAP -#define ACX_CONF_eaddr ACX_CONF_EADDR -#define ACX_CONF_regdom ACX_CONF_REGDOM -#define ACX_CONF_antenna ACX_CONF_ANTENNA -#define ACX_CONF_fwrev ACX_CONF_FWREV -#define ACX_CONF_nretry_long ACX_CONF_NRETRY_LONG -#define ACX_CONF_nretry_short ACX_CONF_NRETRY_SHORT -#define ACX_CONF_msdu_lifetime ACX_CONF_MSDU_LIFETIME -#define ACX_CONF_rate_fallback ACX_CONF_RATE_FALLBACK -#define ACX_CONF_rxopt ACX_CONF_RXOPT -#define ACX_CONF_wep_txkey ACX_CONF_WEP_TXKEY -ACX_CONF_FUNC(get, mmap); -ACX_CONF_FUNC(set, mmap); -ACX_CONF_FUNC(set, wepopt); -ACX_CONF_FUNC(get, eaddr); -ACX_CONF_FUNC(get, regdom); -ACX_CONF_FUNC(set, regdom); -ACX_CONF_FUNC(get, antenna); -ACX_CONF_FUNC(set, antenna); -ACX_CONF_FUNC(get, fwrev); -ACX_CONF_FUNC(set, nretry_long); -ACX_CONF_FUNC(set, nretry_short); -ACX_CONF_FUNC(set, msdu_lifetime); -ACX_CONF_FUNC(set, rate_fallback); -ACX_CONF_FUNC(set, rxopt); -ACX_CONF_FUNC(set, wep_txkey); - -#define ACXCMD_sleep ACXCMD_SLEEP -#define ACXCMD_wakeup ACXCMD_WAKEUP -ACX_NOARG_FUNC(sleep); -ACX_NOARG_FUNC(wakeup); - -#endif /* !_ACXCMD_H */ diff --git a/sys/dev/netif/acx/if_acx.c b/sys/dev/netif/acx/if_acx.c deleted file mode 100644 index dc4530ec77..0000000000 --- a/sys/dev/netif/acx/if_acx.c +++ /dev/null @@ -1,2773 +0,0 @@ -/* - * Copyright (c) 2006 The DragonFly Project. All rights reserved. - * - * This code is derived from software contributed to The DragonFly Project - * by Sepherosa Ziehau - * - * 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. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * 3. Neither the name of The DragonFly Project nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific, prior written permission. - * - * 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 MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, 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 DAMAGE. - * - */ - -/* - * Copyright (c) 2003-2004 wlan.kewl.org Project - * All rights reserved. - * - * $Id: LICENSE,v 1.1.1.1 2004/07/01 12:20:39 darron Exp $ - * - * 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. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * - * This product includes software developed by the wlan.kewl.org Project. - * - * 4. Neither the name of the wlan.kewl.org Project nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE wlan.kewl.org Project BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * 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 DAMAGE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include "pcidevs.h" - -#define ACX_DEBUG - -#include -#include -#include - -static int acx_probe(device_t); -static int acx_attach(device_t); -static int acx_detach(device_t); -static int acx_shutdown(device_t); - -static void acx_init(void *); -static void acx_start(struct ifnet *, struct ifaltq_subque *); -static int acx_ioctl(struct ifnet *, u_long, caddr_t, struct ucred *); -static void acx_watchdog(struct ifnet *); - -static void acx_intr(void *); -static void acx_txeof(struct acx_softc *); -static void acx_txerr(struct acx_softc *, uint8_t); -static void acx_rxeof(struct acx_softc *); -static void acx_disable_intr(struct acx_softc *); -static void acx_enable_intr(struct acx_softc *); - -static int acx_reset(struct acx_softc *); -static int acx_stop(struct acx_softc *); -static void acx_init_info_reg(struct acx_softc *); -static int acx_config(struct acx_softc *); -static int acx_read_config(struct acx_softc *, struct acx_config *); -static int acx_write_config(struct acx_softc *, struct acx_config *); -static int acx_rx_config(struct acx_softc *, int); -static int acx_set_crypt_keys(struct acx_softc *); -static void acx_calibrate(void *); - -static int acx_dma_alloc(struct acx_softc *); -static void acx_dma_free(struct acx_softc *); -static int acx_init_tx_ring(struct acx_softc *); -static int acx_init_rx_ring(struct acx_softc *); -static int acx_newbuf(struct acx_softc *, struct acx_rxbuf *, int); -static int acx_encap(struct acx_softc *, struct acx_txbuf *, - struct mbuf *, struct ieee80211_node *); - -static int acx_set_null_tmplt(struct acx_softc *); -static int acx_set_probe_req_tmplt(struct acx_softc *, const char *, int); -static int acx_set_probe_resp_tmplt(struct acx_softc *, - struct ieee80211_node *); -static int acx_set_beacon_tmplt(struct acx_softc *, - struct ieee80211_node *); - -static int acx_read_eeprom(struct acx_softc *, uint32_t, uint8_t *); -static int acx_read_phyreg(struct acx_softc *, uint32_t, uint8_t *); - -static int acx_alloc_firmware(struct acx_softc *); -static void acx_free_firmware(struct acx_softc *); -static int acx_setup_firmware(struct acx_softc *, struct fw_image *, - const uint8_t **, int *); -static int acx_load_firmware(struct acx_softc *, uint32_t, - const uint8_t *, int); -static int acx_load_radio_firmware(struct acx_softc *, const uint8_t *, - uint32_t); -static int acx_load_base_firmware(struct acx_softc *, const uint8_t *, - uint32_t); - -static void acx_next_scan(void *); -static int acx_set_chan(struct acx_softc *, struct ieee80211_channel *); - -static int acx_media_change(struct ifnet *); -static int acx_newstate(struct ieee80211com *, enum ieee80211_state, int); - -static int acx_sysctl_msdu_lifetime(SYSCTL_HANDLER_ARGS); -static int acx_sysctl_free_firmware(SYSCTL_HANDLER_ARGS); - -const struct ieee80211_rateset acx_rates_11b = - { 4, { 2, 4, 11, 22 } }; -const struct ieee80211_rateset acx_rates_11g = - { 12, { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 } }; -const struct ieee80211_rateset acx_rates_11b_pbcc = - { 5, { 2, 4, 11, 22, 44 } }; -const struct ieee80211_rateset acx_rates_11g_pbcc = - { 13, { 2, 4, 11, 22, 44, 12, 18, 24, 36, 48, 72, 96, 108 } }; - -int acx_enable_pbcc = 1; -TUNABLE_INT("hw.acx.enable_pbcc", &acx_enable_pbcc); - -static const struct acx_device { - uint16_t vid; - uint16_t did; - void (*set_param)(device_t); - const char *desc; -} acx_devices[] = { - { PCI_VENDOR_TI, PCI_PRODUCT_TI_ACX100A, acx100_set_param, - "Texas Instruments TNETW1100A Wireless Adapter" }, - { PCI_VENDOR_TI, PCI_PRODUCT_TI_ACX100B, acx100_set_param, - "Texas Instruments TNETW1100B Wireless Adapter" }, - { PCI_VENDOR_TI, PCI_PRODUCT_TI_ACX111, acx111_set_param, - "Texas Instruments TNETW1130 Wireless Adapter" }, - { 0, 0, NULL, NULL } -}; - -static device_method_t acx_methods[] = { - DEVMETHOD(device_probe, acx_probe), - DEVMETHOD(device_attach, acx_attach), - DEVMETHOD(device_detach, acx_detach), - DEVMETHOD(device_shutdown, acx_shutdown), -#if 0 - DEVMETHOD(device_suspend, acx_suspend), - DEVMETHOD(device_resume, acx_resume), -#endif - DEVMETHOD_END -}; - -static driver_t acx_driver = { - "acx", - acx_methods, - sizeof(struct acx_softc) -}; - -static devclass_t acx_devclass; - -DRIVER_MODULE(acx, pci, acx_driver, acx_devclass, NULL, NULL); -DRIVER_MODULE(acx, cardbus, acx_driver, acx_devclass, NULL, NULL); - -MODULE_DEPEND(acx, wlan, 1, 1, 1); -MODULE_DEPEND(acx, wlan_ratectl_onoe, 1, 1, 1); -MODULE_DEPEND(acx, wlan_ratectl_amrr, 1, 1, 1); -MODULE_DEPEND(acx, pci, 1, 1, 1); -MODULE_DEPEND(acx, cardbus, 1, 1, 1); - -static __inline int -acx_get_rssi(struct acx_softc *sc, uint8_t raw) -{ - int rssi; - - rssi = ((sc->chip_rssi_corr / 2) + (raw * 5)) / sc->chip_rssi_corr; - return rssi > 100 ? 100 : rssi; -} - -static int -acx_probe(device_t dev) -{ - const struct acx_device *a; - uint16_t did, vid; - - vid = pci_get_vendor(dev); - did = pci_get_device(dev); - for (a = acx_devices; a->desc != NULL; ++a) { - if (vid == a->vid && did == a->did) { - a->set_param(dev); - device_set_desc(dev, a->desc); - return 0; - } - } - return ENXIO; -} - -static int -acx_attach(device_t dev) -{ - struct acx_softc *sc; - struct ifnet *ifp; - struct ieee80211com *ic; - struct sysctl_ctx_list *sctx; - struct sysctl_oid *soid; - int i, error; - - sc = device_get_softc(dev); - ic = &sc->sc_ic; - ifp = &ic->ic_if; - - if_initname(ifp, device_get_name(dev), device_get_unit(dev)); - -#ifndef BURN_BRIDGES - if (pci_get_powerstate(dev) != PCI_POWERSTATE_D0) { - uint32_t mem1, mem2, irq; - - mem1 = pci_read_config(dev, sc->chip_mem1_rid, 4); - mem2 = pci_read_config(dev, sc->chip_mem2_rid, 4); - irq = pci_read_config(dev, PCIR_INTLINE, 4); - - device_printf(dev, "chip is in D%d power mode " - "-- setting to D0\n", pci_get_powerstate(dev)); - - pci_set_powerstate(dev, PCI_POWERSTATE_D0); - - pci_write_config(dev, sc->chip_mem1_rid, mem1, 4); - pci_write_config(dev, sc->chip_mem2_rid, mem2, 4); - pci_write_config(dev, PCIR_INTLINE, irq, 4); - } -#endif /* !BURN_BRIDGE */ - - /* Enable bus mastering */ - pci_enable_busmaster(dev); - - /* Allocate IO memory 1 */ - sc->sc_mem1_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, - &sc->chip_mem1_rid, - RF_ACTIVE); - if (sc->sc_mem1_res == NULL) { - error = ENXIO; - device_printf(dev, "can't allocate IO mem1\n"); - goto fail; - } - sc->sc_mem1_bt = rman_get_bustag(sc->sc_mem1_res); - sc->sc_mem1_bh = rman_get_bushandle(sc->sc_mem1_res); - - /* Allocate IO memory 2 */ - sc->sc_mem2_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, - &sc->chip_mem2_rid, - RF_ACTIVE); - if (sc->sc_mem2_res == NULL) { - error = ENXIO; - device_printf(dev, "can't allocate IO mem2\n"); - goto fail; - } - sc->sc_mem2_bt = rman_get_bustag(sc->sc_mem2_res); - sc->sc_mem2_bh = rman_get_bushandle(sc->sc_mem2_res); - - /* Allocate irq */ - sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, - &sc->sc_irq_rid, - RF_SHAREABLE | RF_ACTIVE); - if (sc->sc_irq_res == NULL) { - error = ENXIO; - device_printf(dev, "can't allocate intr\n"); - goto fail; - } - - /* Initialize channel scanning timer */ - callout_init(&sc->sc_scan_timer); - - /* Initialize calibration timer */ - callout_init(&sc->sc_calibrate_timer); - - /* Allocate busdma stuffs */ - error = acx_dma_alloc(sc); - if (error) - goto fail; - - /* Reset Hardware */ - error = acx_reset(sc); - if (error) - goto fail; - - /* Disable interrupts before firmware is loaded */ - acx_disable_intr(sc); - - /* Get radio type and form factor */ -#define EEINFO_RETRY_MAX 50 - for (i = 0; i < EEINFO_RETRY_MAX; ++i) { - uint16_t ee_info; - - ee_info = CSR_READ_2(sc, ACXREG_EEPROM_INFO); - if (ACX_EEINFO_HAS_RADIO_TYPE(ee_info)) { - sc->sc_form_factor = ACX_EEINFO_FORM_FACTOR(ee_info); - sc->sc_radio_type = ACX_EEINFO_RADIO_TYPE(ee_info); - break; - } - DELAY(10000); - } - if (i == EEINFO_RETRY_MAX) { - error = ENXIO; - goto fail; - } -#undef EEINFO_RETRY_MAX - - DPRINTF((&sc->sc_ic.ic_if, "radio type %02x\n", sc->sc_radio_type)); - -#ifdef DUMP_EEPROM - for (i = 0; i < 0x40; ++i) { - uint8_t val; - - error = acx_read_eeprom(sc, i, &val); - if (i % 10 == 0) - kprintf("\n"); - kprintf("%02x ", val); - } - kprintf("\n"); -#endif /* DUMP_EEPROM */ - - /* Get EEPROM version */ - error = acx_read_eeprom(sc, ACX_EE_VERSION_OFS, &sc->sc_eeprom_ver); - if (error) - goto fail; - DPRINTF((&sc->sc_ic.ic_if, "EEPROM version %u\n", sc->sc_eeprom_ver)); - - /* - * Initialize device sysctl before ieee80211_ifattach() - */ - sc->sc_long_retry_limit = 4; - sc->sc_msdu_lifetime = 4096; - sc->sc_scan_dwell = 200; /* 200 milliseconds */ - sc->sc_calib_intvl = 3 * 60; /* 3 minutes */ - - sctx = device_get_sysctl_ctx(dev); - soid = device_get_sysctl_tree(dev); - SYSCTL_ADD_PROC(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, - "msdu_lifetime", CTLTYPE_INT | CTLFLAG_RW, - sc, 0, acx_sysctl_msdu_lifetime, "I", - "MSDU life time"); - SYSCTL_ADD_INT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, - "long_retry_limit", CTLFLAG_RW, - &sc->sc_long_retry_limit, 0, "Long retry limit"); - SYSCTL_ADD_INT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, - "scan_dwell", CTLFLAG_RW, - &sc->sc_scan_dwell, 0, "Scan channel dwell time (ms)"); - SYSCTL_ADD_INT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, - "calib_intvl", CTLFLAG_RW, - &sc->sc_calib_intvl, 0, "Calibration interval (second)"); - - /* - * Nodes for firmware operation - */ - SYSCTL_ADD_INT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, - "combined_radio_fw", CTLFLAG_RW, - &sc->sc_firmware.combined_radio_fw, 0, - "Radio and base firmwares are combined"); - SYSCTL_ADD_PROC(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "free_fw", - CTLTYPE_INT | CTLFLAG_RW, - sc, 0, acx_sysctl_free_firmware, "I", - "Free firmware"); - - /* - * Nodes for statistics - */ - SYSCTL_ADD_UQUAD(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, - "frag_error", CTLFLAG_RW, &sc->sc_stats.err_oth_frag, - 0, "Fragment errors"); - SYSCTL_ADD_UQUAD(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, - "tx_abort", CTLFLAG_RW, &sc->sc_stats.err_abort, - 0, "TX abortions"); - SYSCTL_ADD_UQUAD(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, - "tx_invalid", CTLFLAG_RW, &sc->sc_stats.err_param, - 0, "Invalid TX param in TX descriptor"); - SYSCTL_ADD_UQUAD(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, - "no_wepkey", CTLFLAG_RW, &sc->sc_stats.err_no_wepkey, - 0, "No WEP key exists"); - SYSCTL_ADD_UQUAD(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, - "msdu_timeout", CTLFLAG_RW, - &sc->sc_stats.err_msdu_timeout, - 0, "MSDU timeouts"); - SYSCTL_ADD_UQUAD(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, - "ex_txretry", CTLFLAG_RW, &sc->sc_stats.err_ex_retry, - 0, "Excessive TX retries"); - SYSCTL_ADD_UQUAD(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, - "buf_oflow", CTLFLAG_RW, &sc->sc_stats.err_buf_oflow, - 0, "Buffer overflows"); - SYSCTL_ADD_UQUAD(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, - "dma_error", CTLFLAG_RW, &sc->sc_stats.err_dma, - 0, "DMA errors"); - SYSCTL_ADD_UQUAD(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, - "unkn_error", CTLFLAG_RW, &sc->sc_stats.err_unkn, - 0, "Unknown errors"); - - ifp->if_softc = sc; - ifp->if_init = acx_init; - ifp->if_ioctl = acx_ioctl; - ifp->if_start = acx_start; - ifp->if_watchdog = acx_watchdog; - ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST; - ifq_set_maxlen(&ifp->if_snd, IFQ_MAXLEN); -#ifdef notyet - ifq_set_ready(&ifp->if_snd); -#endif - - /* Set channels */ - for (i = 1; i <= 14; ++i) { - ic->ic_channels[i].ic_freq = - ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ); - ic->ic_channels[i].ic_flags = sc->chip_chan_flags; - } - - ic->ic_opmode = IEEE80211_M_STA; - ic->ic_state = IEEE80211_S_INIT; - - /* - * NOTE: Don't overwrite ic_caps set by chip specific code - */ - ic->ic_caps |= IEEE80211_C_WEP | /* WEP */ - IEEE80211_C_HOSTAP | /* HostAP mode */ - IEEE80211_C_MONITOR | /* Monitor mode */ - IEEE80211_C_IBSS | /* IBSS modes */ - IEEE80211_C_SHPREAMBLE; /* Short preamble */ - if (acx_enable_pbcc) - ic->ic_caps_ext = IEEE80211_CEXT_PBCC; /* PBCC modulation */ - - /* Get station id */ - for (i = 0; i < IEEE80211_ADDR_LEN; ++i) { - error = acx_read_eeprom(sc, sc->chip_ee_eaddr_ofs - i, - &ic->ic_myaddr[i]); - } - - ieee80211_ifattach(ic); - - /* Enable software beacon missing */ - ic->ic_flags_ext |= IEEE80211_FEXT_SWBMISS; - - /* Override newstate */ - sc->sc_newstate = ic->ic_newstate; - ic->ic_newstate = acx_newstate; - - ieee80211_media_init(ic, acx_media_change, ieee80211_media_status); - - /* - * Radio tap attaching - */ - bpfattach_dlt(ifp, DLT_IEEE802_11_RADIO, - sizeof(struct ieee80211_frame) + sizeof(sc->sc_tx_th), - &sc->sc_drvbpf); - - sc->sc_tx_th_len = roundup(sizeof(sc->sc_tx_th), sizeof(uint32_t)); - sc->sc_tx_th.wt_ihdr.it_len = htole16(sc->sc_tx_th_len); - sc->sc_tx_th.wt_ihdr.it_present = htole32(ACX_TX_RADIOTAP_PRESENT); - - sc->sc_rx_th_len = roundup(sizeof(sc->sc_rx_th), sizeof(uint32_t)); - sc->sc_rx_th.wr_ihdr.it_len = htole16(sc->sc_rx_th_len); - sc->sc_rx_th.wr_ihdr.it_present = htole32(ACX_RX_RADIOTAP_PRESENT); - - ifq_set_cpuid(&ifp->if_snd, rman_get_cpuid(sc->sc_irq_res)); - - error = bus_setup_intr(dev, sc->sc_irq_res, INTR_MPSAFE, acx_intr, sc, - &sc->sc_irq_handle, ifp->if_serializer); - if (error) { - device_printf(dev, "can't set up interrupt\n"); - bpfdetach(ifp); - ieee80211_ifdetach(ic); - goto fail; - } - - if (bootverbose) - ieee80211_announce(ic); - - return 0; -fail: - acx_detach(dev); - return error; -} - -static int -acx_detach(device_t dev) -{ - struct acx_softc *sc = device_get_softc(dev); - - if (device_is_attached(dev)) { - struct ieee80211com *ic = &sc->sc_ic; - struct ifnet *ifp = &ic->ic_if; - - lwkt_serialize_enter(ifp->if_serializer); - - acx_stop(sc); - acx_free_firmware(sc); - bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_irq_handle); - - lwkt_serialize_exit(ifp->if_serializer); - - bpfdetach(ifp); - ieee80211_ifdetach(ic); - } - - if (sc->sc_irq_res != NULL) { - bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irq_rid, - sc->sc_irq_res); - } - if (sc->sc_mem1_res != NULL) { - bus_release_resource(dev, SYS_RES_MEMORY, sc->chip_mem1_rid, - sc->sc_mem1_res); - } - if (sc->sc_mem2_res != NULL) { - bus_release_resource(dev, SYS_RES_MEMORY, sc->chip_mem2_rid, - sc->sc_mem2_res); - } - - acx_dma_free(sc); - return 0; -} - -static int -acx_shutdown(device_t dev) -{ - struct acx_softc *sc = device_get_softc(dev); - - lwkt_serialize_enter(sc->sc_ic.ic_if.if_serializer); - acx_stop(sc); - lwkt_serialize_exit(sc->sc_ic.ic_if.if_serializer); - return 0; -} - -static void -acx_init(void *arg) -{ - struct acx_softc *sc = arg; - struct ieee80211com *ic = &sc->sc_ic; - struct ifnet *ifp = &ic->ic_if; - struct acx_firmware *fw = &sc->sc_firmware; - int error; - - error = acx_stop(sc); - if (error) - return; - - error = acx_alloc_firmware(sc); - if (error) - return; - - error = acx_init_tx_ring(sc); - if (error) { - if_printf(ifp, "can't initialize TX ring\n"); - goto back; - } - - error = acx_init_rx_ring(sc); - if (error) { - if_printf(ifp, "can't initialize RX ring\n"); - goto back; - } - - error = acx_load_base_firmware(sc, fw->base_fw, fw->base_fw_len); - if (error) - goto back; - - /* - * Initialize command and information registers - * NOTE: This should be done after base firmware is loaded - */ - acx_init_cmd_reg(sc); - acx_init_info_reg(sc); - - sc->sc_flags |= ACX_FLAG_FW_LOADED; - -#if 0 - if (sc->chip_post_basefw != NULL) { - error = sc->chip_post_basefw(sc); - if (error) - goto back; - } -#endif - - if (fw->radio_fw != NULL) { - error = acx_load_radio_firmware(sc, fw->radio_fw, - fw->radio_fw_len); - if (error) - goto back; - } - - error = sc->chip_init(sc); - if (error) - goto back; - - /* Get and set device various configuration */ - error = acx_config(sc); - if (error) - goto back; - - /* Setup crypto stuffs */ - if (sc->sc_ic.ic_flags & IEEE80211_F_PRIVACY) { - error = acx_set_crypt_keys(sc); - if (error) - goto back; - sc->sc_ic.ic_flags &= ~IEEE80211_F_DROPUNENC; - } - - /* Turn on power led */ - CSR_CLRB_2(sc, ACXREG_GPIO_OUT, sc->chip_gpio_pled); - - acx_enable_intr(sc); - - ifp->if_flags |= IFF_RUNNING; - ifq_clr_oactive(&ifp->if_snd); - - if (ic->ic_opmode != IEEE80211_M_MONITOR) { - if (ic->ic_roaming != IEEE80211_ROAMING_MANUAL) - ieee80211_new_state(&sc->sc_ic, IEEE80211_S_SCAN, -1); - } else { - ieee80211_new_state(ic, IEEE80211_S_RUN, -1); - } -back: - if (error) - acx_stop(sc); -} - -static void -acx_init_info_reg(struct acx_softc *sc) -{ - sc->sc_info = CSR_READ_4(sc, ACXREG_INFO_REG_OFFSET); - sc->sc_info_param = sc->sc_info + ACX_INFO_REG_SIZE; -} - -static int -acx_set_crypt_keys(struct acx_softc *sc) -{ - struct ieee80211com *ic = &sc->sc_ic; - struct acx_conf_wep_txkey wep_txkey; - int i, error, got_wk = 0; - - for (i = 0; i < IEEE80211_WEP_NKID; ++i) { - struct ieee80211_key *wk = &ic->ic_nw_keys[i]; - - if (wk->wk_keylen == 0) - continue; - - if (sc->chip_hw_crypt) { - error = sc->chip_set_wepkey(sc, wk, i); - if (error) - return error; - got_wk = 1; - } else if (wk->wk_flags & IEEE80211_KEY_XMIT) { - wk->wk_flags |= IEEE80211_KEY_SWCRYPT; - } - } - - if (!got_wk || sc->chip_hw_crypt || - ic->ic_def_txkey == IEEE80211_KEYIX_NONE) - return 0; - - /* Set current WEP key index */ - wep_txkey.wep_txkey = ic->ic_def_txkey; - if (acx_set_wep_txkey_conf(sc, &wep_txkey) != 0) { - if_printf(&ic->ic_if, "set WEP txkey failed\n"); - return ENXIO; - } - return 0; -} - -static void -acx_next_scan(void *arg) -{ - struct acx_softc *sc = arg; - struct ieee80211com *ic = &sc->sc_ic; - struct ifnet *ifp = &ic->ic_if; - - lwkt_serialize_enter(ifp->if_serializer); - - if (ic->ic_state == IEEE80211_S_SCAN) - ieee80211_next_scan(ic); - - lwkt_serialize_exit(ifp->if_serializer); -} - -static int -acx_stop(struct acx_softc *sc) -{ - struct ieee80211com *ic = &sc->sc_ic; - struct ifnet *ifp = &ic->ic_if; - struct acx_buf_data *bd = &sc->sc_buf_data; - struct acx_ring_data *rd = &sc->sc_ring_data; - int i, error; - - ASSERT_SERIALIZED(ifp->if_serializer); - - ieee80211_new_state(&sc->sc_ic, IEEE80211_S_INIT, -1); - - sc->sc_firmware_ver = 0; - sc->sc_hardware_id = 0; - - /* Reset hardware */ - error = acx_reset(sc); - if (error) - return error; - - /* Firmware no longer functions after hardware reset */ - sc->sc_flags &= ~ACX_FLAG_FW_LOADED; - - acx_disable_intr(sc); - - /* Stop backgroud scanning */ - callout_stop(&sc->sc_scan_timer); - - /* Turn off power led */ - CSR_SETB_2(sc, ACXREG_GPIO_OUT, sc->chip_gpio_pled); - - /* Free TX mbuf */ - for (i = 0; i < ACX_TX_DESC_CNT; ++i) { - struct acx_txbuf *buf; - - buf = &bd->tx_buf[i]; - - if (buf->tb_mbuf != NULL) { - bus_dmamap_unload(bd->mbuf_dma_tag, - buf->tb_mbuf_dmamap); - m_freem(buf->tb_mbuf); - buf->tb_mbuf = NULL; - } - - if (buf->tb_node != NULL) - ieee80211_free_node(buf->tb_node); - buf->tb_node = NULL; - } - - /* Clear TX host descriptors */ - bzero(rd->tx_ring, ACX_TX_RING_SIZE); - - /* Free RX mbuf */ - for (i = 0; i < ACX_RX_DESC_CNT; ++i) { - if (bd->rx_buf[i].rb_mbuf != NULL) { - bus_dmamap_unload(bd->mbuf_dma_tag, - bd->rx_buf[i].rb_mbuf_dmamap); - m_freem(bd->rx_buf[i].rb_mbuf); - bd->rx_buf[i].rb_mbuf = NULL; - } - } - - /* Clear RX host descriptors */ - bzero(rd->rx_ring, ACX_RX_RING_SIZE); - - sc->sc_tx_timer = 0; - ifp->if_timer = 0; - ifp->if_flags &= ~IFF_RUNNING; - ifq_clr_oactive(&ifp->if_snd); - - return 0; -} - -static int -acx_config(struct acx_softc *sc) -{ - struct acx_config conf; - int error; - - error = acx_read_config(sc, &conf); - if (error) - return error; - - error = acx_write_config(sc, &conf); - if (error) - return error; - - error = acx_rx_config(sc, sc->sc_flags & ACX_FLAG_PROMISC); - if (error) - return error; - - if (acx_set_probe_req_tmplt(sc, "", 0) != 0) { - if_printf(&sc->sc_ic.ic_if, "can't set probe req template " - "(empty ssid)\n"); - return ENXIO; - } - - /* XXX for PM?? */ - if (acx_set_null_tmplt(sc) != 0) { - if_printf(&sc->sc_ic.ic_if, "can't set null data template\n"); - return ENXIO; - } - return 0; -} - -static int -acx_read_config(struct acx_softc *sc, struct acx_config *conf) -{ - struct acx_conf_eaddr addr; - struct acx_conf_regdom reg_dom; - struct acx_conf_antenna ant; - struct acx_conf_fwrev fw_rev; - char ethstr[ETHER_ADDRSTRLEN + 1]; - uint32_t fw_rev_no; - uint8_t sen; - int i, error; - - /* Get station id */ - if (acx_get_eaddr_conf(sc, &addr) != 0) { - if_printf(&sc->sc_ic.ic_if, "can't get station id\n"); - return ENXIO; - } - - /* - * Get and print station id in case that EEPROM station id's - * offset is not correct - */ - for (i = 0; i < IEEE80211_ADDR_LEN; ++i) - conf->eaddr[IEEE80211_ADDR_LEN - 1 - i] = addr.eaddr[i]; - if_printf(&sc->sc_ic.ic_if, "MAC address (from firmware): %s\n", - kether_ntoa(conf->eaddr, ethstr)); - - /* Get region domain */ - if (acx_get_regdom_conf(sc, ®_dom) != 0) { - if_printf(&sc->sc_ic.ic_if, "can't get region domain\n"); - return ENXIO; - } - conf->regdom = reg_dom.regdom; - DPRINTF((&sc->sc_ic.ic_if, "regdom %02x\n", reg_dom.regdom)); - - /* Get antenna */ - if (acx_get_antenna_conf(sc, &ant) != 0) { - if_printf(&sc->sc_ic.ic_if, "can't get antenna\n"); - return ENXIO; - } - conf->antenna = ant.antenna; - DPRINTF((&sc->sc_ic.ic_if, "antenna %02x\n", ant.antenna)); - - /* Get sensitivity XXX not used */ - if (sc->sc_radio_type == ACX_RADIO_TYPE_MAXIM || - sc->sc_radio_type == ACX_RADIO_TYPE_RFMD || - sc->sc_radio_type == ACX_RADIO_TYPE_RALINK) { - error = acx_read_phyreg(sc, ACXRV_PHYREG_SENSITIVITY, &sen); - if (error) { - if_printf(&sc->sc_ic.ic_if, "can't get sensitivity\n"); - return error; - } - } else { - sen = 0; - } - DPRINTF((&sc->sc_ic.ic_if, "sensitivity %02x\n", sen)); - - /* Get firmware revision */ - if (acx_get_fwrev_conf(sc, &fw_rev) != 0) { - if_printf(&sc->sc_ic.ic_if, "can't get firmware revision\n"); - return ENXIO; - } - - if (strncmp(fw_rev.fw_rev, "Rev ", 4) != 0) { - if_printf(&sc->sc_ic.ic_if, "strange revision string -- %s\n", - fw_rev.fw_rev); - fw_rev_no = 0x01090407; - } else { - char *s, *endp; - - /* - * 01234 - * "Rev xx.xx.xx.xx" - * ^ Start from here - */ - s = &fw_rev.fw_rev[4]; - fw_rev_no = 0; - for (i = 0; i < 4; ++i) { - uint8_t val; - - val = strtoul(s, &endp, 16); - fw_rev_no |= val << ((3 - i) * 8); - - if (*endp == '\0') - break; - else - s = ++endp; - } - } - sc->sc_firmware_ver = fw_rev_no; - sc->sc_hardware_id = le32toh(fw_rev.hw_id); - DPRINTF((&sc->sc_ic.ic_if, "fw rev %08x, hw id %08x\n", - sc->sc_firmware_ver, sc->sc_hardware_id)); - - if (sc->chip_read_config != NULL) { - error = sc->chip_read_config(sc, conf); - if (error) - return error; - } - return 0; -} - -static int -acx_write_config(struct acx_softc *sc, struct acx_config *conf) -{ - struct acx_conf_nretry_short sretry; - struct acx_conf_nretry_long lretry; - struct acx_conf_msdu_lifetime msdu_lifetime; - struct acx_conf_rate_fallback rate_fb; - struct acx_conf_antenna ant; - struct acx_conf_regdom reg_dom; - int error; - - /* Set number of long/short retry */ - KKASSERT(sc->chip_short_retry_limit > 0); - sretry.nretry = sc->chip_short_retry_limit; - if (acx_set_nretry_short_conf(sc, &sretry) != 0) { - if_printf(&sc->sc_ic.ic_if, "can't set short retry limit\n"); - return ENXIO; - } - - lretry.nretry = sc->sc_long_retry_limit; - if (acx_set_nretry_long_conf(sc, &lretry) != 0) { - if_printf(&sc->sc_ic.ic_if, "can't set long retry limit\n"); - return ENXIO; - } - - /* Set MSDU lifetime */ - msdu_lifetime.lifetime = htole32(sc->sc_msdu_lifetime); - if (acx_set_msdu_lifetime_conf(sc, &msdu_lifetime) != 0) { - if_printf(&sc->sc_ic.ic_if, "can't set MSDU lifetime\n"); - return ENXIO; - } - - /* Enable rate fallback */ - rate_fb.ratefb_enable = 1; - if (acx_set_rate_fallback_conf(sc, &rate_fb) != 0) { - if_printf(&sc->sc_ic.ic_if, "can't enable rate fallback\n"); - return ENXIO; - } - - /* Set antenna */ - ant.antenna = conf->antenna; - if (acx_set_antenna_conf(sc, &ant) != 0) { - if_printf(&sc->sc_ic.ic_if, "can't set antenna\n"); - return ENXIO; - } - - /* Set region domain */ - reg_dom.regdom = conf->regdom; - if (acx_set_regdom_conf(sc, ®_dom) != 0) { - if_printf(&sc->sc_ic.ic_if, "can't set region domain\n"); - return ENXIO; - } - - if (sc->chip_write_config != NULL) { - error = sc->chip_write_config(sc, conf); - if (error) - return error; - } - - return 0; -} - -static int -acx_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *cr) -{ - struct acx_softc *sc = ifp->if_softc; - struct ieee80211com *ic = &sc->sc_ic; - int error; - - error = 0; - - switch (cmd) { - case SIOCSIFFLAGS: - if (ifp->if_flags & IFF_UP) { - if ((ifp->if_flags & IFF_RUNNING)) { - int promisc = -1; - - if ((ifp->if_flags & IFF_PROMISC) && - (sc->sc_flags & ACX_FLAG_PROMISC) == 0) - promisc = 1; - else if ((ifp->if_flags & IFF_PROMISC) == 0 && - (sc->sc_flags & ACX_FLAG_PROMISC)) - promisc = 0; - - /* - * Promisc mode is always enabled when - * operation mode is Monitor. - */ - if (ic->ic_opmode != IEEE80211_M_MONITOR && - promisc >= 0) - error = acx_rx_config(sc, promisc); - } else { - acx_init(sc); - } - } else { - if (ifp->if_flags & IFF_RUNNING) - acx_stop(sc); - } - - if (ifp->if_flags & IFF_PROMISC) - sc->sc_flags |= ACX_FLAG_PROMISC; - else - sc->sc_flags &= ~ACX_FLAG_PROMISC; - break; - case SIOCADDMULTI: - case SIOCDELMULTI: - /* TODO */ - break; - default: - error = ieee80211_ioctl(ic, cmd, data, cr); - break; - } - - if (error == ENETRESET) { - if ((ifp->if_flags & (IFF_RUNNING | IFF_UP)) == - (IFF_RUNNING | IFF_UP)) - acx_init(sc); - error = 0; - } - return error; -} - -static void -acx_start(struct ifnet *ifp, struct ifaltq_subque *ifsq) -{ - struct acx_softc *sc = ifp->if_softc; - struct ieee80211com *ic = &sc->sc_ic; - struct acx_buf_data *bd = &sc->sc_buf_data; - struct acx_txbuf *buf; - int trans, idx; - - ASSERT_ALTQ_SQ_DEFAULT(ifp, ifsq); - ASSERT_SERIALIZED(ifp->if_serializer); - - if ((sc->sc_flags & ACX_FLAG_FW_LOADED) == 0) { - ifq_purge(&ifp->if_snd); - ieee80211_drain_mgtq(&ic->ic_mgtq); - return; - } - - if ((ifp->if_flags & IFF_RUNNING) == 0 || ifq_is_oactive(ifp->if_snd)) - return; - - /* - * NOTE: - * We can't start from a random position that TX descriptor - * is free, since hardware will be confused by that. - * We have to follow the order of the TX ring. - */ - idx = bd->tx_free_start; - trans = 0; - for (buf = &bd->tx_buf[idx]; buf->tb_mbuf == NULL; - buf = &bd->tx_buf[idx]) { - struct ieee80211_frame *f; - struct ieee80211_node *ni = NULL; - struct mbuf *m; - int mgmt_pkt = 0; - - if (!IF_QEMPTY(&ic->ic_mgtq)) { - IF_DEQUEUE(&ic->ic_mgtq, m); - - ni = (struct ieee80211_node *)m->m_pkthdr.rcvif; - m->m_pkthdr.rcvif = NULL; - - mgmt_pkt = 1; - - /* - * Don't transmit probe response firmware will - * do it for us. - */ - f = mtod(m, struct ieee80211_frame *); - if ((f->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == - IEEE80211_FC0_TYPE_MGT && - (f->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == - IEEE80211_FC0_SUBTYPE_PROBE_RESP) { - if (ni != NULL) - ieee80211_free_node(ni); - m_freem(m); - continue; - } - } else if (!ifq_is_empty(&ifp->if_snd)) { - struct ether_header *eh; - - if (ic->ic_state != IEEE80211_S_RUN) { - ifq_purge(&ifp->if_snd); - break; - } - - m = ifq_dequeue(&ifp->if_snd); - if (m == NULL) - break; - - if (m->m_len < sizeof(struct ether_header)) { - m = m_pullup(m, sizeof(struct ether_header)); - if (m == NULL) { - IFNET_STAT_INC(ifp, oerrors, 1); - continue; - } - } - eh = mtod(m, struct ether_header *); - - ni = ieee80211_find_txnode(ic, eh->ether_dhost); - if (ni == NULL) { - m_freem(m); - IFNET_STAT_INC(ifp, oerrors, 1); - continue; - } - - /* TODO power save */ - - BPF_MTAP(ifp, m); - - m = ieee80211_encap(ic, m, ni); - if (m == NULL) { - ieee80211_free_node(ni); - IFNET_STAT_INC(ifp, oerrors, 1); - continue; - } - } else { - break; - } - - if (ic->ic_rawbpf != NULL) - bpf_mtap(ic->ic_rawbpf, m); - - f = mtod(m, struct ieee80211_frame *); - if ((f->i_fc[1] & IEEE80211_FC1_PROTECTED) && !sc->chip_hw_crypt) { - KASSERT(ni != NULL, ("TX node is NULL (WEP)")); - if (ieee80211_crypto_encap(ic, ni, m) == NULL) { - ieee80211_free_node(ni); - m_freem(m); - IFNET_STAT_INC(ifp, oerrors, 1); - continue; - } - } - - /* - * Since mgmt data are transmitted at fixed rate - * they will not be used to do rate control. - */ - if (mgmt_pkt && ni != NULL) { - ieee80211_free_node(ni); - ni = NULL; - } - - if (acx_encap(sc, buf, m, ni) != 0) { - /* - * NOTE: `m' will be freed in acx_encap() - * if we reach here. - */ - if (ni != NULL) - ieee80211_free_node(ni); - IFNET_STAT_INC(ifp, oerrors, 1); - continue; - } - - /* - * NOTE: - * 1) `m' should not be touched after acx_encap() - * 2) `node' will be used to do TX rate control during - * acx_txeof(), so it is not freed here. acx_txeof() - * will free it for us - */ - - trans = 1; - bd->tx_used_count++; - idx = (idx + 1) % ACX_TX_DESC_CNT; - } - bd->tx_free_start = idx; - - if (bd->tx_used_count == ACX_TX_DESC_CNT) - ifq_set_oactive(&ifp->if_snd); - - if (trans && sc->sc_tx_timer == 0) - sc->sc_tx_timer = 5; - ifp->if_timer = 1; -} - -static void -acx_watchdog(struct ifnet *ifp) -{ - struct acx_softc *sc = ifp->if_softc; - - ifp->if_timer = 0; - - if ((ifp->if_flags & IFF_RUNNING) == 0) - return; - - if (sc->sc_tx_timer) { - if (--sc->sc_tx_timer == 0) { - if_printf(ifp, "watchdog timeout\n"); - IFNET_STAT_INC(ifp, oerrors, 1); - acx_txeof(ifp->if_softc); - } else { - ifp->if_timer = 1; - } - } - ieee80211_watchdog(&sc->sc_ic); -} - -static void -acx_intr(void *arg) -{ - struct acx_softc *sc = arg; - uint16_t intr_status; - - if ((sc->sc_flags & ACX_FLAG_FW_LOADED) == 0) - return; - - intr_status = CSR_READ_2(sc, ACXREG_INTR_STATUS_CLR); - if (intr_status == ACXRV_INTR_ALL) { - /* not our interrupt */ - return; - } - - intr_status &= sc->chip_intr_enable; - if (intr_status == 0) { - /* not interrupts we care about */ - return; - } - - /* Acknowledge all interrupts */ - CSR_WRITE_2(sc, ACXREG_INTR_ACK, ACXRV_INTR_ALL); - - if (intr_status & ACXRV_INTR_TX_FINI) - acx_txeof(sc); - - if (intr_status & ACXRV_INTR_RX_FINI) - acx_rxeof(sc); -} - -static void -acx_disable_intr(struct acx_softc *sc) -{ - CSR_WRITE_2(sc, ACXREG_INTR_MASK, sc->chip_intr_disable); - CSR_WRITE_2(sc, ACXREG_EVENT_MASK, 0); -} - -static void -acx_enable_intr(struct acx_softc *sc) -{ - /* Mask out interrupts that are not in the enable set */ - CSR_WRITE_2(sc, ACXREG_INTR_MASK, ~sc->chip_intr_enable); - CSR_WRITE_2(sc, ACXREG_EVENT_MASK, ACXRV_EVENT_DISABLE); -} - -static void -acx_txeof(struct acx_softc *sc) -{ - struct acx_buf_data *bd; - struct acx_txbuf *buf; - struct ifnet *ifp; - int idx; - - ifp = &sc->sc_ic.ic_if; - ASSERT_SERIALIZED(ifp->if_serializer); - - bd = &sc->sc_buf_data; - idx = bd->tx_used_start; - for (buf = &bd->tx_buf[idx]; buf->tb_mbuf != NULL; - buf = &bd->tx_buf[idx]) { - uint8_t ctrl, error; - int frame_len; - - ctrl = FW_TXDESC_GETFIELD_1(sc, buf, f_tx_ctrl); - if ((ctrl & (DESC_CTRL_HOSTOWN | DESC_CTRL_ACXDONE)) != - (DESC_CTRL_HOSTOWN | DESC_CTRL_ACXDONE)) - break; - - bus_dmamap_unload(bd->mbuf_dma_tag, buf->tb_mbuf_dmamap); - frame_len = buf->tb_mbuf->m_pkthdr.len; - m_freem(buf->tb_mbuf); - buf->tb_mbuf = NULL; - - error = FW_TXDESC_GETFIELD_1(sc, buf, f_tx_error); - if (error) { - acx_txerr(sc, error); - IFNET_STAT_INC(ifp, oerrors, 1); - } else { - IFNET_STAT_INC(ifp, opackets, 1); - } - - if (buf->tb_node != NULL) { - sc->chip_tx_complete(sc, buf, frame_len, error); - ieee80211_free_node(buf->tb_node); - buf->tb_node = NULL; - } - - FW_TXDESC_SETFIELD_1(sc, buf, f_tx_ctrl, DESC_CTRL_HOSTOWN); - - bd->tx_used_count--; - - idx = (idx + 1) % ACX_TX_DESC_CNT; - } - bd->tx_used_start = idx; - - sc->sc_tx_timer = bd->tx_used_count == 0 ? 0 : 5; - - if (bd->tx_used_count != ACX_TX_DESC_CNT) { - ifq_clr_oactive(&ifp->if_snd); - ifp->if_start(ifp); - } -} - -static void -acx_txerr(struct acx_softc *sc, uint8_t err) -{ - struct ifnet *ifp = &sc->sc_ic.ic_if; - struct acx_stats *stats = &sc->sc_stats; - - if (err == DESC_ERR_EXCESSIVE_RETRY) { - /* - * This a common error (see comment below), - * so print it using DPRINTF() - */ - DPRINTF((ifp, "TX failed -- excessive retry\n")); - } else { - if_printf(ifp, "TX failed -- "); - } - - /* - * Although `err' looks like bitmask, it never - * has multiple bits set. - */ - switch (err) { -#if 0 - case DESC_ERR_OTHER_FRAG: - /* XXX what's this */ - kprintf("error in other fragment\n"); - stats->err_oth_frag++; - break; -#endif - case DESC_ERR_ABORT: - kprintf("aborted\n"); - stats->err_abort++; - break; - case DESC_ERR_PARAM: - kprintf("wrong parameters in descriptor\n"); - stats->err_param++; - break; - case DESC_ERR_NO_WEPKEY: - kprintf("WEP key missing\n"); - stats->err_no_wepkey++; - break; - case DESC_ERR_MSDU_TIMEOUT: - kprintf("MSDU life timeout\n"); - stats->err_msdu_timeout++; - break; - case DESC_ERR_EXCESSIVE_RETRY: - /* - * Possible causes: - * 1) Distance is too long - * 2) Transmit failed (e.g. no MAC level ACK) - * 3) Chip overheated (this should be rare) - */ - stats->err_ex_retry++; - break; - case DESC_ERR_BUF_OVERFLOW: - kprintf("buffer overflow\n"); - stats->err_buf_oflow++; - break; - case DESC_ERR_DMA: - kprintf("DMA error\n"); - stats->err_dma++; - break; - default: - kprintf("unknown error %d\n", err); - stats->err_unkn++; - break; - } -} - -static void -acx_rxeof(struct acx_softc *sc) -{ - struct ieee80211com *ic = &sc->sc_ic; - struct acx_ring_data *rd = &sc->sc_ring_data; - struct acx_buf_data *bd = &sc->sc_buf_data; - struct ifnet *ifp = &ic->ic_if; - int idx, ready; - - ASSERT_SERIALIZED(ic->ic_if.if_serializer); - - bus_dmamap_sync(rd->rx_ring_dma_tag, rd->rx_ring_dmamap, - BUS_DMASYNC_POSTREAD); - - /* - * Locate first "ready" rx buffer, - * start from last stopped position - */ - idx = bd->rx_scan_start; - ready = 0; - do { - struct acx_rxbuf *buf; - - buf = &bd->rx_buf[idx]; - if ((buf->rb_desc->h_ctrl & htole16(DESC_CTRL_HOSTOWN)) && - (buf->rb_desc->h_status & htole32(DESC_STATUS_FULL))) { - ready = 1; - break; - } - idx = (idx + 1) % ACX_RX_DESC_CNT; - } while (idx != bd->rx_scan_start); - - if (!ready) - return; - - /* - * NOTE: don't mess up `idx' here, it will - * be used in the following code - */ - - do { - struct acx_rxbuf_hdr *head; - struct acx_rxbuf *buf; - struct ieee80211_frame_min *wh; - struct mbuf *m; - uint32_t desc_status; - uint16_t desc_ctrl; - int len, error, rssi, is_priv; - - buf = &bd->rx_buf[idx]; - - desc_ctrl = le16toh(buf->rb_desc->h_ctrl); - desc_status = le32toh(buf->rb_desc->h_status); - if (!(desc_ctrl & DESC_CTRL_HOSTOWN) || - !(desc_status & DESC_STATUS_FULL)) - break; - - bus_dmamap_sync(bd->mbuf_dma_tag, buf->rb_mbuf_dmamap, - BUS_DMASYNC_POSTREAD); - - m = buf->rb_mbuf; - - error = acx_newbuf(sc, buf, 0); - if (error) { - IFNET_STAT_INC(ifp, ierrors, 1); - goto next; - } - - head = mtod(m, struct acx_rxbuf_hdr *); - len = le16toh(head->rbh_len) & ACX_RXBUF_LEN_MASK; - rssi = acx_get_rssi(sc, head->rbh_level); - - m_adj(m, sizeof(struct acx_rxbuf_hdr) + sc->chip_rxbuf_exhdr); - m->m_len = m->m_pkthdr.len = len; - m->m_pkthdr.rcvif = &ic->ic_if; - - wh = mtod(m, struct ieee80211_frame_min *); - is_priv = (wh->i_fc[1] & IEEE80211_FC1_PROTECTED); - - if (sc->sc_drvbpf != NULL) { - sc->sc_rx_th.wr_tsf = htole32(head->rbh_time); - - sc->sc_rx_th.wr_flags = 0; - if (is_priv) { - sc->sc_rx_th.wr_flags |= - IEEE80211_RADIOTAP_F_WEP; - } - if (head->rbh_bbp_stat & ACX_RXBUF_STAT_SHPRE) { - sc->sc_rx_th.wr_flags |= - IEEE80211_RADIOTAP_F_SHORTPRE; - } - - if (sc->chip_phymode == IEEE80211_MODE_11G) { - sc->sc_rx_th.wr_rate = - ieee80211_plcp2rate(head->rbh_plcp, - head->rbh_bbp_stat & ACX_RXBUF_STAT_OFDM); - } else { - sc->sc_rx_th.wr_rate = - ieee80211_plcp2rate(head->rbh_plcp, 0); - } - - sc->sc_rx_th.wr_antsignal = rssi; - - if (head->rbh_bbp_stat & ACX_RXBUF_STAT_ANT1) - sc->sc_rx_th.wr_antenna = 1; - else - sc->sc_rx_th.wr_antenna = 0; - - bpf_ptap(sc->sc_drvbpf, m, &sc->sc_rx_th, - sc->sc_rx_th_len); - } - - if (len >= sizeof(struct ieee80211_frame_min) && - len < MCLBYTES) { - struct ieee80211_node *ni; - - if (is_priv && sc->chip_hw_crypt) { - /* Short circuit software WEP */ - wh->i_fc[1] &= ~IEEE80211_FC1_PROTECTED; - - /* Do chip specific RX buffer processing */ - if (sc->chip_proc_wep_rxbuf != NULL) { - sc->chip_proc_wep_rxbuf(sc, m, &len); - wh = mtod(m, - struct ieee80211_frame_min *); - } - } - m->m_len = m->m_pkthdr.len = len; - - ni = ieee80211_find_rxnode(ic, wh); - ieee80211_input(ic, m, ni, rssi, - le32toh(head->rbh_time)); - ieee80211_free_node(ni); - - IFNET_STAT_INC(ifp, ipackets, 1); - } else { - if (len < sizeof(struct ieee80211_frame_min)) { - if (ic->ic_rawbpf != NULL && - len >= sizeof(struct ieee80211_frame_ack)) - bpf_mtap(ic->ic_rawbpf, m); - - if (ic->ic_opmode != IEEE80211_M_MONITOR) - ic->ic_stats.is_rx_tooshort++; - } - m_freem(m); - } -next: - buf->rb_desc->h_ctrl = htole16(desc_ctrl & ~DESC_CTRL_HOSTOWN); - buf->rb_desc->h_status = 0; - bus_dmamap_sync(rd->rx_ring_dma_tag, rd->rx_ring_dmamap, - BUS_DMASYNC_PREWRITE); - - idx = (idx + 1) % ACX_RX_DESC_CNT; - } while (idx != bd->rx_scan_start); - - /* - * Record the position so that next - * time we can start from it - */ - bd->rx_scan_start = idx; -} - -static int -acx_reset(struct acx_softc *sc) -{ - uint16_t reg; - - /* Halt ECPU */ - CSR_SETB_2(sc, ACXREG_ECPU_CTRL, ACXRV_ECPU_HALT); - - /* Software reset */ - reg = CSR_READ_2(sc, ACXREG_SOFT_RESET); - CSR_WRITE_2(sc, ACXREG_SOFT_RESET, reg | ACXRV_SOFT_RESET); - DELAY(100); - CSR_WRITE_2(sc, ACXREG_SOFT_RESET, reg); - - /* Initialize EEPROM */ - CSR_SETB_2(sc, ACXREG_EEPROM_INIT, ACXRV_EEPROM_INIT); - DELAY(50000); - - /* Test whether ECPU is stopped */ - reg = CSR_READ_2(sc, ACXREG_ECPU_CTRL); - if (!(reg & ACXRV_ECPU_HALT)) { - if_printf(&sc->sc_ic.ic_if, "can't halt ECPU\n"); - return ENXIO; - } - return 0; -} - -static int -acx_read_eeprom(struct acx_softc *sc, uint32_t offset, uint8_t *val) -{ - int i; - - CSR_WRITE_4(sc, ACXREG_EEPROM_CONF, 0); - CSR_WRITE_4(sc, ACXREG_EEPROM_ADDR, offset); - CSR_WRITE_4(sc, ACXREG_EEPROM_CTRL, ACXRV_EEPROM_READ); - -#define EE_READ_RETRY_MAX 100 - for (i = 0; i < EE_READ_RETRY_MAX; ++i) { - if (CSR_READ_2(sc, ACXREG_EEPROM_CTRL) == 0) - break; - DELAY(10000); - } - if (i == EE_READ_RETRY_MAX) { - if_printf(&sc->sc_ic.ic_if, "can't read EEPROM offset %x " - "(timeout)\n", offset); - return ETIMEDOUT; - } -#undef EE_READ_RETRY_MAX - - *val = CSR_READ_1(sc, ACXREG_EEPROM_DATA); - return 0; -} - -static int -acx_read_phyreg(struct acx_softc *sc, uint32_t reg, uint8_t *val) -{ - int i; - - CSR_WRITE_4(sc, ACXREG_PHY_ADDR, reg); - CSR_WRITE_4(sc, ACXREG_PHY_CTRL, ACXRV_PHY_READ); - -#define PHY_READ_RETRY_MAX 100 - for (i = 0; i < PHY_READ_RETRY_MAX; ++i) { - if (CSR_READ_4(sc, ACXREG_PHY_CTRL) == 0) - break; - DELAY(10000); - } - if (i == PHY_READ_RETRY_MAX) { - if_printf(&sc->sc_ic.ic_if, "can't read phy reg %x (timeout)\n", - reg); - return ETIMEDOUT; - } -#undef PHY_READ_RETRY_MAX - - *val = CSR_READ_1(sc, ACXREG_PHY_DATA); - return 0; -} - -void -acx_write_phyreg(struct acx_softc *sc, uint32_t reg, uint8_t val) -{ - CSR_WRITE_4(sc, ACXREG_PHY_DATA, val); - CSR_WRITE_4(sc, ACXREG_PHY_ADDR, reg); - CSR_WRITE_4(sc, ACXREG_PHY_CTRL, ACXRV_PHY_WRITE); -} - -static int -acx_alloc_firmware(struct acx_softc *sc) -{ - struct acx_firmware *fw = &sc->sc_firmware; - struct ifnet *ifp = &sc->sc_ic.ic_if; - struct fw_image *img; - char filename[64]; - int error = 0; - - /* - * NB: serializer need to be released before loading firmware - * image to avoid possible dead lock - */ - ASSERT_SERIALIZED(ifp->if_serializer); - - if (fw->base_fw_image == NULL) { - if (fw->combined_radio_fw) { - ksnprintf(filename, sizeof(filename), - ACX_BASE_RADIO_FW_PATH, - fw->fwdir, sc->sc_radio_type); - } else { - ksnprintf(filename, sizeof(filename), - ACX_BASE_FW_PATH, fw->fwdir); - } - - lwkt_serialize_exit(ifp->if_serializer); - img = firmware_image_load(filename, NULL); - lwkt_serialize_enter(ifp->if_serializer); - - fw->base_fw_image = img; - if (fw->base_fw_image == NULL) { - if_printf(ifp, "load %s base fw failed\n", filename); - error = EIO; - goto back; - } - - error = acx_setup_firmware(sc, fw->base_fw_image, - &fw->base_fw, &fw->base_fw_len); - if (error) - goto back; - } - - if (!fw->combined_radio_fw && fw->radio_fw_image == NULL) { - ksnprintf(filename, sizeof(filename), ACX_RADIO_FW_PATH, - fw->fwdir, sc->sc_radio_type); - - lwkt_serialize_exit(ifp->if_serializer); - img = firmware_image_load(filename, NULL); - lwkt_serialize_enter(ifp->if_serializer); - - fw->radio_fw_image = img; - if (fw->radio_fw_image == NULL) { - if_printf(ifp, "load %s radio fw failed\n", filename); - error = EIO; - goto back; - } - - error = acx_setup_firmware(sc, fw->radio_fw_image, - &fw->radio_fw, &fw->radio_fw_len); - } -back: - if (error) - acx_free_firmware(sc); - return error; -} - -static int -acx_setup_firmware(struct acx_softc *sc, struct fw_image *img, - const uint8_t **ptr, int *len) -{ - const struct acx_firmware_hdr *hdr; - const uint8_t *p; - uint32_t cksum; - int i; - - *ptr = NULL; - *len = 0; - - /* - * Make sure that the firmware image contains more than just a header - */ - if (img->fw_imglen <= sizeof(*hdr)) { - if_printf(&sc->sc_ic.ic_if, "%s is invalid image, " - "size %zu (too small)\n", - img->fw_name, img->fw_imglen); - return EINVAL; - } - hdr = (const struct acx_firmware_hdr *)img->fw_image; - - /* - * Verify length - */ - if (hdr->fwh_len != img->fw_imglen - sizeof(*hdr)) { - if_printf(&sc->sc_ic.ic_if, "%s is invalid image, " - "size in hdr %u and image size %zu mismatches\n", - img->fw_name, hdr->fwh_len, img->fw_imglen); - return EINVAL; - } - - /* - * Verify cksum - */ - cksum = 0; - for (i = 0, p = (const uint8_t *)&hdr->fwh_len; - i < img->fw_imglen - sizeof(hdr->fwh_cksum); ++i, ++p) - cksum += *p; - if (cksum != hdr->fwh_cksum) { - if_printf(&sc->sc_ic.ic_if, "%s is invalid image, " - "checksum mismatch\n", img->fw_name); - return EINVAL; - } - - *ptr = ((const uint8_t *)img->fw_image + sizeof(*hdr)); - *len = img->fw_imglen - sizeof(*hdr); - return 0; -} - -static void -acx_free_firmware(struct acx_softc *sc) -{ - struct acx_firmware *fw = &sc->sc_firmware; - - if (fw->base_fw_image != NULL) { - firmware_image_unload(fw->base_fw_image); - fw->base_fw_image = NULL; - fw->base_fw = NULL; - fw->base_fw_len = 0; - } - if (fw->radio_fw_image != NULL) { - firmware_image_unload(fw->radio_fw_image); - fw->radio_fw_image = NULL; - fw->radio_fw = NULL; - fw->radio_fw_len = 0; - } -} - -static int -acx_load_base_firmware(struct acx_softc *sc, const uint8_t *base_fw, - uint32_t base_fw_len) -{ - int i, error; - - /* Load base firmware */ - error = acx_load_firmware(sc, 0, base_fw, base_fw_len); - if (error) { - if_printf(&sc->sc_ic.ic_if, "can't load base firmware\n"); - return error; - } - DPRINTF((&sc->sc_ic.ic_if, "base firmware loaded\n")); - - /* Start ECPU */ - CSR_WRITE_2(sc, ACXREG_ECPU_CTRL, ACXRV_ECPU_START); - - /* Wait for ECPU to be up */ - for (i = 0; i < 500; ++i) { - uint16_t reg; - - reg = CSR_READ_2(sc, ACXREG_INTR_STATUS); - if (reg & ACXRV_INTR_FCS_THRESH) { - CSR_WRITE_2(sc, ACXREG_INTR_ACK, ACXRV_INTR_FCS_THRESH); - return 0; - } - DELAY(10000); - } - - if_printf(&sc->sc_ic.ic_if, "can't initialize ECPU (timeout)\n"); - return ENXIO; -} - -static int -acx_load_radio_firmware(struct acx_softc *sc, const uint8_t *radio_fw, - uint32_t radio_fw_len) -{ - struct acx_conf_mmap mem_map; - uint32_t radio_fw_ofs; - int error; - - /* - * Get the position, where base firmware is loaded, so that - * radio firmware can be loaded after it. - */ - if (acx_get_mmap_conf(sc, &mem_map) != 0) - return ENXIO; - radio_fw_ofs = le32toh(mem_map.code_end); - - /* Put ECPU into sleeping state, before loading radio firmware */ - if (acx_sleep(sc) != 0) - return ENXIO; - - /* Load radio firmware */ - error = acx_load_firmware(sc, radio_fw_ofs, radio_fw, radio_fw_len); - if (error) { - if_printf(&sc->sc_ic.ic_if, "can't load radio firmware\n"); - return ENXIO; - } - DPRINTF((&sc->sc_ic.ic_if, "radio firmware loaded\n")); - - /* Wake up sleeping ECPU, after radio firmware is loaded */ - if (acx_wakeup(sc) != 0) - return ENXIO; - - /* Initialize radio */ - if (acx_init_radio(sc, radio_fw_ofs, radio_fw_len) != 0) - return ENXIO; - - /* Verify radio firmware's loading position */ - if (acx_get_mmap_conf(sc, &mem_map) != 0) - return ENXIO; - if (le32toh(mem_map.code_end) != radio_fw_ofs + radio_fw_len) { - if_printf(&sc->sc_ic.ic_if, "loaded radio firmware position " - "mismatch\n"); - return ENXIO; - } - - DPRINTF((&sc->sc_ic.ic_if, "radio firmware initialized\n")); - return 0; -} - -static int -acx_load_firmware(struct acx_softc *sc, uint32_t offset, const uint8_t *data, - int data_len) -{ - const uint32_t *fw; - int i, fw_len; - - fw = (const uint32_t *)data; - fw_len = data_len / sizeof(uint32_t); - - /* - * LOADFW_AUTO_INC only works with some older firmware: - * 1) acx100's firmware - * 2) acx111's firmware whose rev is 0x00010011 - */ - - /* Load firmware */ - CSR_WRITE_4(sc, ACXREG_FWMEM_START, ACXRV_FWMEM_START_OP); -#ifndef LOADFW_AUTO_INC - CSR_WRITE_4(sc, ACXREG_FWMEM_CTRL, 0); -#else - CSR_WRITE_4(sc, ACXREG_FWMEM_CTRL, ACXRV_FWMEM_ADDR_AUTOINC); - CSR_WRITE_4(sc, ACXREG_FWMEM_ADDR, offset); -#endif - - for (i = 0; i < fw_len; ++i) { -#ifndef LOADFW_AUTO_INC - CSR_WRITE_4(sc, ACXREG_FWMEM_ADDR, offset + (i * 4)); -#endif - CSR_WRITE_4(sc, ACXREG_FWMEM_DATA, be32toh(fw[i])); - } - - /* Verify firmware */ - CSR_WRITE_4(sc, ACXREG_FWMEM_START, ACXRV_FWMEM_START_OP); -#ifndef LOADFW_AUTO_INC - CSR_WRITE_4(sc, ACXREG_FWMEM_CTRL, 0); -#else - CSR_WRITE_4(sc, ACXREG_FWMEM_CTRL, ACXRV_FWMEM_ADDR_AUTOINC); - CSR_WRITE_4(sc, ACXREG_FWMEM_ADDR, offset); -#endif - - for (i = 0; i < fw_len; ++i) { - uint32_t val; - -#ifndef LOADFW_AUTO_INC - CSR_WRITE_4(sc, ACXREG_FWMEM_ADDR, offset + (i * 4)); -#endif - val = CSR_READ_4(sc, ACXREG_FWMEM_DATA); - if (be32toh(fw[i]) != val) { - if_printf(&sc->sc_ic.ic_if, "fireware mismatch " - "fw %08x loaded %08x\n", fw[i], val); - return ENXIO; - } - } - return 0; -} - -static int -acx_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg) -{ - struct ifnet *ifp = &ic->ic_if; - struct acx_softc *sc = ifp->if_softc; - struct ieee80211_node *ni = NULL; - struct ieee80211_channel *c = NULL; - int error = 1, mode = 0; - - ASSERT_SERIALIZED(ifp->if_serializer); - - ieee80211_ratectl_newstate(ic, nstate); - callout_stop(&sc->sc_scan_timer); - callout_stop(&sc->sc_calibrate_timer); - - switch (nstate) { - case IEEE80211_S_SCAN: - acx_set_chan(sc, ic->ic_curchan); - callout_reset(&sc->sc_scan_timer, - (hz * sc->sc_scan_dwell) / 1000, - acx_next_scan, sc); - break; - case IEEE80211_S_AUTH: - if (ic->ic_opmode == IEEE80211_M_STA) { - ni = ic->ic_bss; - c = ni->ni_chan; - mode = ACX_MODE_STA; - } - break; - case IEEE80211_S_RUN: - if (ic->ic_opmode == IEEE80211_M_IBSS || - ic->ic_opmode == IEEE80211_M_HOSTAP) { - ni = ic->ic_bss; - c = ni->ni_chan; - if (ic->ic_opmode == IEEE80211_M_IBSS) - mode = ACX_MODE_ADHOC; - else - mode = ACX_MODE_AP; - - if (acx_set_beacon_tmplt(sc, ni) != 0) { - if_printf(ifp, "set bescon template failed\n"); - goto back; - } - if (acx_set_probe_resp_tmplt(sc, ni) != 0) { - if_printf(ifp, "set probe response template" - " failed\n"); - goto back; - } - } else if (ic->ic_opmode == IEEE80211_M_MONITOR) { - ni = ic->ic_bss; - c = ic->ic_curchan; - mode = ACX_MODE_STA; - } - break; - default: - break; - } - - if (ni != NULL) { - KKASSERT(c != NULL); - - if (acx_set_chan(sc, c) != 0) - goto back; - - if (acx_join_bss(sc, mode, ni, c) != 0) { - if_printf(ifp, "join BSS failed\n"); - goto back; - } - } - - if (nstate == IEEE80211_S_RUN) { - int interval = sc->sc_calib_intvl; - - if (sc->chip_calibrate != NULL) { - error = sc->chip_calibrate(sc); - if (error) { - /* - * Restart calibration some time later - */ - interval = 10; - } - callout_reset(&sc->sc_calibrate_timer, - hz * interval, acx_calibrate, sc); - } - } - error = 0; -back: - if (error) { - /* XXX */ - nstate = IEEE80211_S_INIT; - arg = -1; - } - return sc->sc_newstate(ic, nstate, arg); -} - -int -acx_init_tmplt_ordered(struct acx_softc *sc) -{ -#define INIT_TMPLT(name) \ -do { \ - if (acx_init_##name##_tmplt(sc) != 0) \ - return 1; \ -} while (0) - - /* - * NOTE: - * Order of templates initialization: - * 1) Probe request - * 2) NULL data - * 3) Beacon - * 4) TIM - * 5) Probe response - * Above order is critical to get a correct memory map. - */ - INIT_TMPLT(probe_req); - INIT_TMPLT(null_data); - INIT_TMPLT(beacon); - INIT_TMPLT(tim); - INIT_TMPLT(probe_resp); - -#undef INIT_TMPLT - return 0; -} - -static void -acx_ring_dma_addr(void *arg, bus_dma_segment_t *seg, int nseg, int error) -{ - *((uint32_t *)arg) = seg->ds_addr; -} - -static int -acx_dma_alloc(struct acx_softc *sc) -{ - struct acx_ring_data *rd = &sc->sc_ring_data; - struct acx_buf_data *bd = &sc->sc_buf_data; - int i, error; - - /* Allocate DMA stuffs for RX descriptors */ - error = bus_dma_tag_create(NULL, PAGE_SIZE, 0, - BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, - NULL, NULL, - ACX_RX_RING_SIZE, 1, ACX_RX_RING_SIZE, - 0, &rd->rx_ring_dma_tag); - if (error) { - if_printf(&sc->sc_ic.ic_if, "can't create rx ring dma tag\n"); - return error; - } - - error = bus_dmamem_alloc(rd->rx_ring_dma_tag, (void **)&rd->rx_ring, - BUS_DMA_WAITOK | BUS_DMA_ZERO, - &rd->rx_ring_dmamap); - if (error) { - if_printf(&sc->sc_ic.ic_if, - "can't allocate rx ring dma memory\n"); - bus_dma_tag_destroy(rd->rx_ring_dma_tag); - rd->rx_ring_dma_tag = NULL; - return error; - } - - error = bus_dmamap_load(rd->rx_ring_dma_tag, rd->rx_ring_dmamap, - rd->rx_ring, ACX_RX_RING_SIZE, - acx_ring_dma_addr, &rd->rx_ring_paddr, - BUS_DMA_WAITOK); - if (error) { - if_printf(&sc->sc_ic.ic_if, "can't get rx ring dma address\n"); - bus_dmamem_free(rd->rx_ring_dma_tag, rd->rx_ring, - rd->rx_ring_dmamap); - bus_dma_tag_destroy(rd->rx_ring_dma_tag); - rd->rx_ring_dma_tag = NULL; - return error; - } - - /* Allocate DMA stuffs for TX descriptors */ - error = bus_dma_tag_create(NULL, PAGE_SIZE, 0, - BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, - NULL, NULL, - ACX_TX_RING_SIZE, 1, ACX_TX_RING_SIZE, - 0, &rd->tx_ring_dma_tag); - if (error) { - if_printf(&sc->sc_ic.ic_if, "can't create tx ring dma tag\n"); - return error; - } - - error = bus_dmamem_alloc(rd->tx_ring_dma_tag, (void **)&rd->tx_ring, - BUS_DMA_WAITOK | BUS_DMA_ZERO, - &rd->tx_ring_dmamap); - if (error) { - if_printf(&sc->sc_ic.ic_if, - "can't allocate tx ring dma memory\n"); - bus_dma_tag_destroy(rd->tx_ring_dma_tag); - rd->tx_ring_dma_tag = NULL; - return error; - } - - error = bus_dmamap_load(rd->tx_ring_dma_tag, rd->tx_ring_dmamap, - rd->tx_ring, ACX_TX_RING_SIZE, - acx_ring_dma_addr, &rd->tx_ring_paddr, - BUS_DMA_WAITOK); - if (error) { - if_printf(&sc->sc_ic.ic_if, "can't get tx ring dma address\n"); - bus_dmamem_free(rd->tx_ring_dma_tag, rd->tx_ring, - rd->tx_ring_dmamap); - bus_dma_tag_destroy(rd->tx_ring_dma_tag); - rd->tx_ring_dma_tag = NULL; - return error; - } - - /* Create DMA tag for RX/TX mbuf map */ - error = bus_dma_tag_create(NULL, 1, 0, - BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, - NULL, NULL, - MCLBYTES, 1, MCLBYTES, - 0, &bd->mbuf_dma_tag); - if (error) { - if_printf(&sc->sc_ic.ic_if, "can't create mbuf dma tag\n"); - return error; - } - - /* Create a spare RX DMA map */ - error = bus_dmamap_create(bd->mbuf_dma_tag, 0, &bd->mbuf_tmp_dmamap); - if (error) { - if_printf(&sc->sc_ic.ic_if, "can't create tmp mbuf dma map\n"); - bus_dma_tag_destroy(bd->mbuf_dma_tag); - bd->mbuf_dma_tag = NULL; - return error; - } - - /* Create DMA map for RX mbufs */ - for (i = 0; i < ACX_RX_DESC_CNT; ++i) { - error = bus_dmamap_create(bd->mbuf_dma_tag, 0, - &bd->rx_buf[i].rb_mbuf_dmamap); - if (error) { - if_printf(&sc->sc_ic.ic_if, "can't create rx mbuf " - "dma map (%d)\n", i); - return error; - } - bd->rx_buf[i].rb_desc = &rd->rx_ring[i]; - } - - /* Create DMA map for TX mbufs */ - for (i = 0; i < ACX_TX_DESC_CNT; ++i) { - error = bus_dmamap_create(bd->mbuf_dma_tag, 0, - &bd->tx_buf[i].tb_mbuf_dmamap); - if (error) { - if_printf(&sc->sc_ic.ic_if, "can't create tx mbuf " - "dma map (%d)\n", i); - return error; - } - bd->tx_buf[i].tb_desc1 = &rd->tx_ring[i * 2]; - bd->tx_buf[i].tb_desc2 = &rd->tx_ring[(i * 2) + 1]; - } - - return 0; -} - -static void -acx_dma_free(struct acx_softc *sc) -{ - struct acx_ring_data *rd = &sc->sc_ring_data; - struct acx_buf_data *bd = &sc->sc_buf_data; - int i; - - if (rd->rx_ring_dma_tag != NULL) { - bus_dmamap_unload(rd->rx_ring_dma_tag, rd->rx_ring_dmamap); - bus_dmamem_free(rd->rx_ring_dma_tag, rd->rx_ring, - rd->rx_ring_dmamap); - bus_dma_tag_destroy(rd->rx_ring_dma_tag); - } - - if (rd->tx_ring_dma_tag != NULL) { - bus_dmamap_unload(rd->tx_ring_dma_tag, rd->tx_ring_dmamap); - bus_dmamem_free(rd->tx_ring_dma_tag, rd->tx_ring, - rd->tx_ring_dmamap); - bus_dma_tag_destroy(rd->tx_ring_dma_tag); - } - - for (i = 0; i < ACX_RX_DESC_CNT; ++i) { - if (bd->rx_buf[i].rb_desc != NULL) { - if (bd->rx_buf[i].rb_mbuf != NULL) { - bus_dmamap_unload(bd->mbuf_dma_tag, - bd->rx_buf[i].rb_mbuf_dmamap); - m_freem(bd->rx_buf[i].rb_mbuf); - } - bus_dmamap_destroy(bd->mbuf_dma_tag, - bd->rx_buf[i].rb_mbuf_dmamap); - } - } - - for (i = 0; i < ACX_TX_DESC_CNT; ++i) { - if (bd->tx_buf[i].tb_desc1 != NULL) { - if (bd->tx_buf[i].tb_mbuf != NULL) { - bus_dmamap_unload(bd->mbuf_dma_tag, - bd->tx_buf[i].tb_mbuf_dmamap); - m_freem(bd->tx_buf[i].tb_mbuf); - } - bus_dmamap_destroy(bd->mbuf_dma_tag, - bd->tx_buf[i].tb_mbuf_dmamap); - } - } - - if (bd->mbuf_dma_tag != NULL) { - bus_dmamap_destroy(bd->mbuf_dma_tag, bd->mbuf_tmp_dmamap); - bus_dma_tag_destroy(bd->mbuf_dma_tag); - } -} - -static int -acx_init_tx_ring(struct acx_softc *sc) -{ - struct acx_ring_data *rd; - struct acx_buf_data *bd; - uint32_t paddr; - int i; - - rd = &sc->sc_ring_data; - paddr = rd->tx_ring_paddr; - for (i = 0; i < (ACX_TX_DESC_CNT * 2) - 1; ++i) { - paddr += sizeof(struct acx_host_desc); - - rd->tx_ring[i].h_ctrl = htole16(DESC_CTRL_HOSTOWN); - - if (i == (ACX_TX_DESC_CNT * 2) - 1) - rd->tx_ring[i].h_next_desc = htole32(rd->tx_ring_paddr); - else - rd->tx_ring[i].h_next_desc = htole32(paddr); - } - - bus_dmamap_sync(rd->tx_ring_dma_tag, rd->tx_ring_dmamap, - BUS_DMASYNC_PREWRITE); - - bd = &sc->sc_buf_data; - bd->tx_free_start = 0; - bd->tx_used_start = 0; - bd->tx_used_count = 0; - - return 0; -} - -static int -acx_init_rx_ring(struct acx_softc *sc) -{ - struct acx_ring_data *rd; - struct acx_buf_data *bd; - uint32_t paddr; - int i; - - bd = &sc->sc_buf_data; - rd = &sc->sc_ring_data; - paddr = rd->rx_ring_paddr; - - for (i = 0; i < ACX_RX_DESC_CNT; ++i) { - int error; - - paddr += sizeof(struct acx_host_desc); - - error = acx_newbuf(sc, &bd->rx_buf[i], 1); - if (error) - return error; - - if (i == ACX_RX_DESC_CNT - 1) - rd->rx_ring[i].h_next_desc = htole32(rd->rx_ring_paddr); - else - rd->rx_ring[i].h_next_desc = htole32(paddr); - } - - bus_dmamap_sync(rd->rx_ring_dma_tag, rd->rx_ring_dmamap, - BUS_DMASYNC_PREWRITE); - - bd->rx_scan_start = 0; - return 0; -} - -static void -acx_buf_dma_addr(void *arg, bus_dma_segment_t *seg, int nseg, - bus_size_t mapsz, int error) -{ - if (error) - return; - - /* XXX */ - KASSERT(nseg == 1, ("too many RX dma segments")); - *((uint32_t *)arg) = seg->ds_addr; -} - -static int -acx_newbuf(struct acx_softc *sc, struct acx_rxbuf *rb, int wait) -{ - struct acx_buf_data *bd; - struct mbuf *m; - bus_dmamap_t map; - uint32_t paddr; - int error; - - bd = &sc->sc_buf_data; - - m = m_getcl(wait ? M_WAITOK : M_NOWAIT, MT_DATA, M_PKTHDR); - if (m == NULL) - return ENOBUFS; - - m->m_len = m->m_pkthdr.len = MCLBYTES; - - error = bus_dmamap_load_mbuf(bd->mbuf_dma_tag, bd->mbuf_tmp_dmamap, - m, acx_buf_dma_addr, &paddr, - wait ? BUS_DMA_WAITOK : BUS_DMA_NOWAIT); - if (error) { - m_freem(m); - if_printf(&sc->sc_ic.ic_if, "can't map rx mbuf %d\n", error); - return error; - } - - /* Unload originally mapped mbuf */ - bus_dmamap_unload(bd->mbuf_dma_tag, rb->rb_mbuf_dmamap); - - /* Swap this dmamap with tmp dmamap */ - map = rb->rb_mbuf_dmamap; - rb->rb_mbuf_dmamap = bd->mbuf_tmp_dmamap; - bd->mbuf_tmp_dmamap = map; - - rb->rb_mbuf = m; - rb->rb_desc->h_data_paddr = htole32(paddr); - rb->rb_desc->h_data_len = htole16(m->m_len); - - bus_dmamap_sync(bd->mbuf_dma_tag, rb->rb_mbuf_dmamap, - BUS_DMASYNC_PREREAD); - return 0; -} - -static int -acx_encap(struct acx_softc *sc, struct acx_txbuf *txbuf, struct mbuf *m, - struct ieee80211_node *ni) -{ - struct acx_buf_data *bd = &sc->sc_buf_data; - struct acx_ring_data *rd = &sc->sc_ring_data; - uint32_t paddr; - uint8_t ctrl, rate; - int error; - - KASSERT(txbuf->tb_mbuf == NULL, ("free TX buf has mbuf installed")); - - if (m->m_pkthdr.len > MCLBYTES) { - if_printf(&sc->sc_ic.ic_if, "mbuf too big\n"); - error = E2BIG; - goto back; - } else if (m->m_pkthdr.len < ACX_FRAME_HDRLEN) { - if_printf(&sc->sc_ic.ic_if, "mbuf too small\n"); - error = EINVAL; - goto back; - } - - error = bus_dmamap_load_mbuf(bd->mbuf_dma_tag, txbuf->tb_mbuf_dmamap, - m, acx_buf_dma_addr, &paddr, - BUS_DMA_NOWAIT); - if (error && error != EFBIG) { - if_printf(&sc->sc_ic.ic_if, "can't map tx mbuf1 %d\n", error); - goto back; - } - - if (error) { /* error == EFBIG */ - struct mbuf *m_new; - - m_new = m_defrag(m, M_NOWAIT); - if (m_new == NULL) { - if_printf(&sc->sc_ic.ic_if, "can't defrag tx mbuf\n"); - error = ENOBUFS; - goto back; - } else { - m = m_new; - } - - error = bus_dmamap_load_mbuf(bd->mbuf_dma_tag, - txbuf->tb_mbuf_dmamap, m, - acx_buf_dma_addr, &paddr, - BUS_DMA_NOWAIT); - if (error) { - if_printf(&sc->sc_ic.ic_if, "can't map tx mbuf2 %d\n", - error); - goto back; - } - } - - error = 0; - - bus_dmamap_sync(bd->mbuf_dma_tag, txbuf->tb_mbuf_dmamap, - BUS_DMASYNC_PREWRITE); - - txbuf->tb_mbuf = m; - txbuf->tb_node = ni; - - /* - * TX buffers are accessed in following way: - * acx_fw_txdesc -> acx_host_desc -> buffer - * - * It is quite strange that acx also querys acx_host_desc next to - * the one we have assigned to acx_fw_txdesc even if first one's - * acx_host_desc.h_data_len == acx_fw_txdesc.f_tx_len - * - * So we allocate two acx_host_desc for one acx_fw_txdesc and - * assign the first acx_host_desc to acx_fw_txdesc - * - * For acx111 - * host_desc1.h_data_len = buffer_len - * host_desc2.h_data_len = buffer_len - mac_header_len - * - * For acx100 - * host_desc1.h_data_len = mac_header_len - * host_desc2.h_data_len = buffer_len - mac_header_len - */ - - txbuf->tb_desc1->h_data_paddr = htole32(paddr); - txbuf->tb_desc2->h_data_paddr = htole32(paddr + ACX_FRAME_HDRLEN); - - txbuf->tb_desc1->h_data_len = - htole16(sc->chip_txdesc1_len ? sc->chip_txdesc1_len - : m->m_pkthdr.len); - txbuf->tb_desc2->h_data_len = - htole16(m->m_pkthdr.len - ACX_FRAME_HDRLEN); - - /* - * NOTE: - * We can't simply assign f_tx_ctrl, we will first read it back - * and change it bit by bit - */ - ctrl = FW_TXDESC_GETFIELD_1(sc, txbuf, f_tx_ctrl); - ctrl |= sc->chip_fw_txdesc_ctrl; /* extra chip specific flags */ - ctrl &= ~(DESC_CTRL_HOSTOWN | DESC_CTRL_ACXDONE); - - FW_TXDESC_SETFIELD_2(sc, txbuf, f_tx_len, m->m_pkthdr.len); - FW_TXDESC_SETFIELD_1(sc, txbuf, f_tx_error, 0); - FW_TXDESC_SETFIELD_1(sc, txbuf, f_tx_data_nretry, 0); - FW_TXDESC_SETFIELD_1(sc, txbuf, f_tx_rts_nretry, 0); - FW_TXDESC_SETFIELD_1(sc, txbuf, f_tx_rts_ok, 0); - rate = sc->chip_set_fw_txdesc_rate(sc, txbuf, ni, m->m_pkthdr.len); - - if (sc->sc_drvbpf != NULL) { - struct ieee80211_frame_min *wh; - - wh = mtod(m, struct ieee80211_frame_min *); - sc->sc_tx_th.wt_flags = 0; - if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) - sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP; - sc->sc_tx_th.wt_rate = rate; - - bpf_ptap(sc->sc_drvbpf, m, &sc->sc_tx_th, sc->sc_tx_th_len); - } - - txbuf->tb_desc1->h_ctrl = 0; - txbuf->tb_desc2->h_ctrl = 0; - bus_dmamap_sync(rd->tx_ring_dma_tag, rd->tx_ring_dmamap, - BUS_DMASYNC_PREWRITE); - - FW_TXDESC_SETFIELD_1(sc, txbuf, f_tx_ctrl2, 0); - FW_TXDESC_SETFIELD_1(sc, txbuf, f_tx_ctrl, ctrl); - - /* Tell chip to inform us about TX completion */ - CSR_WRITE_2(sc, ACXREG_INTR_TRIG, ACXRV_TRIG_TX_FINI); -back: - if (error) - m_freem(m); - return error; -} - -static int -acx_set_null_tmplt(struct acx_softc *sc) -{ - struct acx_tmplt_null_data n; - struct ieee80211_frame *f; - - bzero(&n, sizeof(n)); - - f = &n.data; - f->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_DATA | - IEEE80211_FC0_SUBTYPE_NODATA; - IEEE80211_ADDR_COPY(f->i_addr1, etherbroadcastaddr); - IEEE80211_ADDR_COPY(f->i_addr2, IF_LLADDR(&sc->sc_ic.ic_if)); - IEEE80211_ADDR_COPY(f->i_addr3, etherbroadcastaddr); - - return _acx_set_null_data_tmplt(sc, &n, sizeof(n)); -} - -static int -acx_set_probe_req_tmplt(struct acx_softc *sc, const char *ssid, int ssid_len) -{ - struct acx_tmplt_probe_req req; - struct ieee80211_frame *f; - uint8_t *v; - int vlen; - - bzero(&req, sizeof(req)); - - f = &req.data.u_data.f; - f->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT | - IEEE80211_FC0_SUBTYPE_PROBE_REQ; - IEEE80211_ADDR_COPY(f->i_addr1, etherbroadcastaddr); - IEEE80211_ADDR_COPY(f->i_addr2, IF_LLADDR(&sc->sc_ic.ic_if)); - IEEE80211_ADDR_COPY(f->i_addr3, etherbroadcastaddr); - - v = req.data.u_data.var; - v = ieee80211_add_ssid(v, ssid, ssid_len); - v = ieee80211_add_rates(v, &sc->sc_ic.ic_sup_rates[sc->chip_phymode]); - v = ieee80211_add_xrates(v, &sc->sc_ic.ic_sup_rates[sc->chip_phymode]); - vlen = v - req.data.u_data.var; - - return _acx_set_probe_req_tmplt(sc, &req, - ACX_TMPLT_PROBE_REQ_SIZ(vlen)); -} - -static int -acx_set_probe_resp_tmplt(struct acx_softc *sc, struct ieee80211_node *ni) -{ - struct ieee80211com *ic = &sc->sc_ic; - struct acx_tmplt_probe_resp resp; - struct ieee80211_frame *f; - struct mbuf *m; - int len; - - m = ieee80211_probe_resp_alloc(ic, ni); - if (m == NULL) - return 1; - DPRINTF((&ic->ic_if, "%s alloc probe resp size %d\n", __func__, - m->m_pkthdr.len)); - - f = mtod(m, struct ieee80211_frame *); - IEEE80211_ADDR_COPY(f->i_addr1, etherbroadcastaddr); - - bzero(&resp, sizeof(resp)); - m_copydata(m, 0, m->m_pkthdr.len, (caddr_t)&resp.data); - len = m->m_pkthdr.len + sizeof(resp.size); - m_freem(m); - - return _acx_set_probe_resp_tmplt(sc, &resp, len); -} - -static int -acx_set_beacon_tmplt(struct acx_softc *sc, struct ieee80211_node *ni) -{ - struct ieee80211com *ic = &sc->sc_ic; - struct acx_tmplt_beacon beacon; - struct acx_tmplt_tim tim; - struct ieee80211_beacon_offsets bo; - struct mbuf *m; - int beacon_tmplt_len = 0, tim_tmplt_len = 0; - - bzero(&bo, sizeof(bo)); - m = ieee80211_beacon_alloc(ic, ni, &bo); - if (m == NULL) - return 1; - DPRINTF((&ic->ic_if, "%s alloc beacon size %d\n", __func__, - m->m_pkthdr.len)); - - if (bo.bo_tim_len == 0) { - beacon_tmplt_len = m->m_pkthdr.len; - } else { - beacon_tmplt_len = bo.bo_tim - mtod(m, uint8_t *); - tim_tmplt_len = m->m_pkthdr.len - beacon_tmplt_len; - } - - bzero(&beacon, sizeof(beacon)); - bzero(&tim, sizeof(tim)); - - m_copydata(m, 0, beacon_tmplt_len, (caddr_t)&beacon.data); - if (tim_tmplt_len != 0) { - m_copydata(m, beacon_tmplt_len, tim_tmplt_len, - (caddr_t)&tim.data); - } - m_freem(m); - - beacon_tmplt_len += sizeof(beacon.size); - if (_acx_set_beacon_tmplt(sc, &beacon, beacon_tmplt_len) != 0) - return 1; - - if (tim_tmplt_len != 0) { - tim_tmplt_len += sizeof(tim.size); - if (_acx_set_tim_tmplt(sc, &tim, tim_tmplt_len) != 0) - return 1; - } - return 0; -} - -static int -acx_sysctl_msdu_lifetime(SYSCTL_HANDLER_ARGS) -{ - struct acx_softc *sc = arg1; - struct ifnet *ifp = &sc->sc_ic.ic_if; - int error = 0, v; - - lwkt_serialize_enter(ifp->if_serializer); - - v = sc->sc_msdu_lifetime; - error = sysctl_handle_int(oidp, &v, 0, req); - if (error || req->newptr == NULL) - goto back; - if (v <= 0) { - error = EINVAL; - goto back; - } - - if (sc->sc_flags & ACX_FLAG_FW_LOADED) { - struct acx_conf_msdu_lifetime msdu_lifetime; - - msdu_lifetime.lifetime = htole32(v); - if (acx_set_msdu_lifetime_conf(sc, &msdu_lifetime) != 0) { - if_printf(&sc->sc_ic.ic_if, - "can't set MSDU lifetime\n"); - error = ENXIO; - goto back; - } - } - sc->sc_msdu_lifetime = v; -back: - lwkt_serialize_exit(ifp->if_serializer); - return error; -} - -static int -acx_sysctl_free_firmware(SYSCTL_HANDLER_ARGS) -{ - struct acx_softc *sc = arg1; - struct ifnet *ifp = &sc->sc_ic.ic_if; - int error = 0, v; - - lwkt_serialize_enter(ifp->if_serializer); - - v = 0; - error = sysctl_handle_int(oidp, &v, 0, req); - if (error || req->newptr == NULL) - goto back; - if (v == 0) /* Do nothing */ - goto back; - - acx_free_firmware(sc); -back: - lwkt_serialize_exit(ifp->if_serializer); - return error; -} - -static int -acx_media_change(struct ifnet *ifp) -{ - int error; - - error = ieee80211_media_change(ifp); - if (error != ENETRESET) - return error; - - if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING)) - acx_init(ifp->if_softc); - return 0; -} - -static int -acx_rx_config(struct acx_softc *sc, int promisc) -{ - struct acx_conf_rxopt rx_opt; - struct ieee80211com *ic = &sc->sc_ic; - - /* - * What we want to receive and how to receive - */ - - /* Common for all operational modes */ - rx_opt.opt1 = RXOPT1_INCL_RXBUF_HDR; - rx_opt.opt2 = RXOPT2_RECV_ASSOC_REQ | - RXOPT2_RECV_AUTH | - RXOPT2_RECV_BEACON | - RXOPT2_RECV_CF | - RXOPT2_RECV_CTRL | - RXOPT2_RECV_DATA | - RXOPT2_RECV_MGMT | - RXOPT2_RECV_PROBE_REQ | - RXOPT2_RECV_PROBE_RESP | - RXOPT2_RECV_OTHER; - - if (ic->ic_opmode == IEEE80211_M_MONITOR) { - rx_opt.opt1 |= RXOPT1_PROMISC; - rx_opt.opt2 |= RXOPT2_RECV_BROKEN | RXOPT2_RECV_ACK; - } else { - rx_opt.opt1 |= promisc ? RXOPT1_PROMISC : RXOPT1_FILT_FDEST; - } - - if (acx_set_rxopt_conf(sc, &rx_opt) != 0) { - if_printf(&sc->sc_ic.ic_if, "can't config RX\n"); - return ENXIO; - } - return 0; -} - -static int -acx_set_chan(struct acx_softc *sc, struct ieee80211_channel *c) -{ - struct ieee80211com *ic = &sc->sc_ic; - uint16_t flags; - uint8_t chan; - - chan = ieee80211_chan2ieee(ic, c); - if (acx_enable_txchan(sc, chan) != 0) { - if_printf(&ic->ic_if, "enable TX on channel %d failed\n", chan); - return EIO; - } - if (acx_enable_rxchan(sc, chan) != 0) { - if_printf(&ic->ic_if, "enable RX on channel %d failed\n", chan); - return EIO; - } - - if (IEEE80211_IS_CHAN_G(c)) - flags = IEEE80211_CHAN_G; - else - flags = IEEE80211_CHAN_B; - - sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq = - htole16(c->ic_freq); - sc->sc_tx_th.wt_chan_flags = sc->sc_rx_th.wr_chan_flags = - htole16(flags); - return 0; -} - -static void -acx_calibrate(void *xsc) -{ - struct acx_softc *sc = xsc; - struct ifnet *ifp = &sc->sc_ic.ic_if; - - lwkt_serialize_enter(ifp->if_serializer); - if (sc->chip_calibrate != NULL && - sc->sc_ic.ic_state == IEEE80211_S_RUN) { - sc->chip_calibrate(sc); - callout_reset(&sc->sc_calibrate_timer, hz * sc->sc_calib_intvl, - acx_calibrate, sc); - } - lwkt_serialize_exit(ifp->if_serializer); -} diff --git a/sys/dev/netif/acx/if_acxreg.h b/sys/dev/netif/acx/if_acxreg.h deleted file mode 100644 index 425b8abd39..0000000000 --- a/sys/dev/netif/acx/if_acxreg.h +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (c) 2006 The DragonFly Project. All rights reserved. - * - * This code is derived from software contributed to The DragonFly Project - * by Sepherosa Ziehau - * - * 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. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * 3. Neither the name of The DragonFly Project nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific, prior written permission. - * - * 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 MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, 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 DAMAGE. - * - * $DragonFly: src/sys/dev/netif/acx/if_acxreg.h,v 1.1 2006/04/01 02:55:36 sephe Exp $ - */ - -#ifndef _IF_ACXREG_H -#define _IF_ACXREG_H - -/* - * IO register index - */ -#define ACXREG_SOFT_RESET 0 -#define ACXREG_FWMEM_ADDR 1 -#define ACXREG_FWMEM_DATA 2 -#define ACXREG_FWMEM_CTRL 3 -#define ACXREG_FWMEM_START 4 -#define ACXREG_EVENT_MASK 5 -#define ACXREG_INTR_TRIG 6 -#define ACXREG_INTR_MASK 7 -#define ACXREG_INTR_STATUS 8 -#define ACXREG_INTR_STATUS_CLR 9 /* cleared after being read */ -#define ACXREG_INTR_ACK 10 -#define ACXREG_HINTR_TRIG 11 /* XXX what's this? */ -#define ACXREG_RADIO_ENABLE 12 -#define ACXREG_EEPROM_INIT 13 -#define ACXREG_EEPROM_CTRL 14 -#define ACXREG_EEPROM_ADDR 15 -#define ACXREG_EEPROM_DATA 16 -#define ACXREG_EEPROM_CONF 17 -#define ACXREG_EEPROM_INFO 18 -#define ACXREG_PHY_ADDR 19 -#define ACXREG_PHY_DATA 20 -#define ACXREG_PHY_CTRL 21 -#define ACXREG_GPIO_OUT_ENABLE 22 -#define ACXREG_GPIO_OUT 23 -#define ACXREG_CMD_REG_OFFSET 24 -#define ACXREG_INFO_REG_OFFSET 25 -#define ACXREG_RESET_SENSE 26 -#define ACXREG_ECPU_CTRL 27 -#define ACXREG_MAX 28 -#define ACXREG(reg, val) [ACXREG_##reg] = val - -/* - * Value read from ACXREG_EEPROM_INFO - * upper 8bits are radio type - * lower 8bits are form factor - */ -#define ACX_EEINFO_RADIO_TYPE_SHIFT 8 -#define ACX_EEINFO_RADIO_TYPE_MASK (0xff << ACX_EEINFO_RADIO_TYPE_SHIFT) -#define ACX_EEINFO_FORM_FACTOR_MASK 0xff - -#define ACX_EEINFO_HAS_RADIO_TYPE(info) ((info) & ACX_EEINFO_RADIO_TYPE_MASK) -#define ACX_EEINFO_RADIO_TYPE(info) ((info) >> ACX_EEINFO_RADIO_TYPE_SHIFT) -#define ACX_EEINFO_FORM_FACTOR(info) ((info) & ACX_EEINFO_FORM_FACTOR_MASK) - -/* - * Size of command register whose location is obtained - * from ACXREG_CMD_REG_OFFSET IO register - */ -#define ACX_CMD_REG_SIZE 4 /* 4 bytes */ - -/* - * Size of infomation register whose location is obtained - * from ACXREG_INFO_REG_OFFSET IO register - */ -#define ACX_INFO_REG_SIZE 4 /* 4 bytes */ - -/* - * Offset of EEPROM variables - */ -#define ACX_EE_VERSION_OFS 0x05 - -/* - * Possible values for various IO registers - */ - -/* ACXREG_SOFT_RESET */ -#define ACXRV_SOFT_RESET 0x1 - -/* ACXREG_FWMEM_START */ -#define ACXRV_FWMEM_START_OP 0x0 - -/* ACXREG_FWMEM_CTRL */ -#define ACXRV_FWMEM_ADDR_AUTOINC 0x10000 - -/* ACXREG_EVENT_MASK */ -#define ACXRV_EVENT_DISABLE 0x8000 /* XXX What's this?? */ - -/* ACXREG_INTR_TRIG */ -#define ACXRV_TRIG_CMD_FINI 0x0001 -#define ACXRV_TRIG_TX_FINI 0x0004 - -/* ACXREG_INTR_MASK */ -#define ACXRV_INTR_RX_DATA 0x0001 -#define ACXRV_INTR_TX_FINI 0x0002 -#define ACXRV_INTR_TX_XFER 0x0004 -#define ACXRV_INTR_RX_FINI 0x0008 -#define ACXRV_INTR_DTIM 0x0010 -#define ACXRV_INTR_BEACON 0x0020 -#define ACXRV_INTR_TIMER 0x0040 -#define ACXRV_INTR_KEY_MISS 0x0080 -#define ACXRV_INTR_WEP_FAIL 0x0100 -#define ACXRV_INTR_CMD_FINI 0x0200 -#define ACXRV_INTR_INFO 0x0400 -#define ACXRV_INTR_OVERFLOW 0x0800 /* XXX */ -#define ACXRV_INTR_PROC_ERR 0x1000 /* XXX */ -#define ACXRV_INTR_SCAN_FINI 0x2000 -#define ACXRV_INTR_FCS_THRESH 0x4000 /* XXX */ -#define ACXRV_INTR_UNKN 0x8000 -#define ACXRV_INTR_ALL 0xffff - -/* ACXREG_EEPROM_INIT */ -#define ACXRV_EEPROM_INIT 0x1 - -/* ACXREG_EEPROM_CTRL */ -#define ACXRV_EEPROM_READ 0x2 - -/* ACXREG_PHY_CTRL */ -#define ACXRV_PHY_WRITE 0x1 -#define ACXRV_PHY_READ 0x2 - -/* ACXREG_PHY_ADDR */ -#define ACXRV_PHYREG_TXPOWER 0x11 /* axc100 */ -#define ACXRV_PHYREG_SENSITIVITY 0x30 - -/* ACXREG_ECPU_CTRL */ -#define ACXRV_ECPU_HALT 0x1 -#define ACXRV_ECPU_START 0x0 - -#endif /* !_IF_ACXREG_H */ diff --git a/sys/dev/netif/acx/if_acxvar.h b/sys/dev/netif/acx/if_acxvar.h deleted file mode 100644 index 31935a33a4..0000000000 --- a/sys/dev/netif/acx/if_acxvar.h +++ /dev/null @@ -1,521 +0,0 @@ -/* - * Copyright (c) 2006 The DragonFly Project. All rights reserved. - * - * This code is derived from software contributed to The DragonFly Project - * by Sepherosa Ziehau - * - * 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. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * 3. Neither the name of The DragonFly Project nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific, prior written permission. - * - * 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 MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, 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 DAMAGE. - */ - -#ifndef _IF_ACXVAR_H -#define _IF_ACXVAR_H - -#ifdef ACX_DEBUG -#define DPRINTF(x) if_printf x -#else -#define DPRINTF(x) ((void)0) -#endif - -#define ACX_FRAME_HDRLEN sizeof(struct ieee80211_frame) -#define ACX_MEMBLOCK_SIZE 256 - -#define ACX_TX_DESC_CNT 16 -#define ACX_RX_DESC_CNT 16 - -#define ACX_TX_RING_SIZE \ - (2 * ACX_TX_DESC_CNT * sizeof(struct acx_host_desc)) -#define ACX_RX_RING_SIZE \ - (ACX_RX_DESC_CNT * sizeof(struct acx_host_desc)) - -#define CSR_READ_1(sc, reg) \ - bus_space_read_1((sc)->sc_mem1_bt, (sc)->sc_mem1_bh, \ - (sc)->chip_ioreg[(reg)]) -#define CSR_READ_2(sc, reg) \ - bus_space_read_2((sc)->sc_mem1_bt, (sc)->sc_mem1_bh, \ - (sc)->chip_ioreg[(reg)]) -#define CSR_READ_4(sc, reg) \ - bus_space_read_4((sc)->sc_mem1_bt, (sc)->sc_mem1_bh, \ - (sc)->chip_ioreg[(reg)]) - -#define CSR_WRITE_2(sc, reg, val) \ - bus_space_write_2((sc)->sc_mem1_bt, (sc)->sc_mem1_bh, \ - (sc)->chip_ioreg[(reg)], val) -#define CSR_WRITE_4(sc, reg, val) \ - bus_space_write_4((sc)->sc_mem1_bt, (sc)->sc_mem1_bh, \ - (sc)->chip_ioreg[(reg)], val) - -#define CSR_SETB_2(sc, reg, b) \ - CSR_WRITE_2((sc), (reg), CSR_READ_2((sc), (reg)) | (b)) -#define CSR_CLRB_2(sc, reg, b) \ - CSR_WRITE_2((sc), (reg), CSR_READ_2((sc), (reg)) & (~(b))) - -#define DESC_READ_1(sc, off) \ - bus_space_read_1((sc)->sc_mem2_bt, (sc)->sc_mem2_bh, (off)) -#define DESC_READ_2(sc, off) \ - bus_space_read_2((sc)->sc_mem2_bt, (sc)->sc_mem2_bh, (off)) -#define DESC_READ_4(sc, off) \ - bus_space_read_4((sc)->sc_mem2_bt, (sc)->sc_mem2_bh, (off)) - -#define DESC_WRITE_1(sc, off, val) \ - bus_space_write_1((sc)->sc_mem2_bt, (sc)->sc_mem2_bh, (off), (val)) -#define DESC_WRITE_2(sc, off, val) \ - bus_space_write_2((sc)->sc_mem2_bt, (sc)->sc_mem2_bh, (off), (val)) -#define DESC_WRITE_4(sc, off, val) \ - bus_space_write_4((sc)->sc_mem2_bt, (sc)->sc_mem2_bh, (off), (val)) -#define DESC_WRITE_REGION_1(sc, off, d, dlen) \ - bus_space_write_region_1((sc)->sc_mem2_bt, (sc)->sc_mem2_bh, \ - (off), (const uint8_t *)(d), (dlen)) - -#define FW_TXDESC_SETFIELD(sc, mb, field, val, sz) \ - DESC_WRITE_##sz((sc), (mb)->tb_fwdesc_ofs + \ - __offsetof(struct acx_fw_txdesc, field), (val)) - -#define FW_TXDESC_GETFIELD(sc, mb, field, sz) \ - DESC_READ_##sz((sc), (mb)->tb_fwdesc_ofs + \ - __offsetof(struct acx_fw_txdesc, field)) - -#define FW_TXDESC_SETFIELD_1(sc, mb, field, val) \ - FW_TXDESC_SETFIELD(sc, mb, field, val, 1) -#define FW_TXDESC_SETFIELD_2(sc, mb, field, val) \ - FW_TXDESC_SETFIELD(sc, mb, field, htole16(val), 2) -#define FW_TXDESC_SETFIELD_4(sc, mb, field, val) \ - FW_TXDESC_SETFIELD(sc, mb, field, htole32(val), 4) - -#define FW_TXDESC_GETFIELD_1(sc, mb, field) \ - FW_TXDESC_GETFIELD(sc, mb, field, 1) -#define FW_TXDESC_GETFIELD_2(sc, mb, field) \ - le16toh(FW_TXDESC_GETFIELD(sc, mb, field, 2)) -#define FW_TXDESC_GETFIELD_4(sc, mb, field) \ - le32toh(FW_TXDESC_GETFIELD(sc, mb, field, 4)) - -/* - * Firmware TX descriptor - * Fields are little endian - */ -struct acx_fw_txdesc { - uint32_t f_tx_next_desc; /* next acx_fw_txdesc phyaddr */ - uint32_t f_tx_host_desc; /* acx_host_desc phyaddr */ - uint32_t f_tx_acx_ptr; - uint32_t f_tx_time; - uint16_t f_tx_len; - uint16_t f_tx_reserved; - - uint32_t f_tx_dev_spec[4]; - - uint8_t f_tx_ctrl; /* see DESC_CTRL_ */ - uint8_t f_tx_ctrl2; - uint8_t f_tx_error; /* see DESC_ERR_ */ - uint8_t f_tx_data_nretry; /* non-RTS retries */ - uint8_t f_tx_rts_nretry; /* RTS retries */ - uint8_t f_tx_rts_ok; - - /* XXX should be moved to chip specific file */ - union { - struct { - uint8_t rate100; /* acx100 tx rate */ - uint8_t queue_ctrl; - } __packed r1; - struct { - uint16_t rate111; /* acx111 tx rate */ - } __packed r2; - } u; -#define f_tx_rate100 u.r1.rate100 -#define f_tx_queue_ctrl u.r1.queue_ctrl -#define f_tx_rate111 u.r2.rate111 - uint32_t f_tx_queue_info; -} __packed; - -/* - * Firmware RX descriptor - * Fields are little endian - */ -struct acx_fw_rxdesc { - uint32_t f_rx_next_desc; /* next acx_fw_rxdesc phyaddr */ - uint32_t f_rx_host_desc; /* acx_host_desc phyaddr */ - uint32_t f_rx_acx_ptr; - uint32_t f_rx_time; - uint16_t f_rx_len; - uint16_t f_rx_wep_len; - uint32_t f_rx_wep_ofs; - - uint8_t f_rx_dev_spec[16]; - - uint8_t f_rx_ctrl; /* see DESC_CTRL_ */ - uint8_t f_rx_rate; - uint8_t f_rx_error; - uint8_t f_rx_snr; /* signal noise ratio */ - uint8_t f_rx_level; - uint8_t f_rx_queue_ctrl; - uint16_t f_rx_unknown0; - uint32_t f_rx_unknown1; -} __packed; - -/* - * Host TX/RX descriptor - * Fields are little endian - */ -struct acx_host_desc { - uint32_t h_data_paddr; /* data phyaddr */ - uint16_t h_data_ofs; - uint16_t h_reserved; - uint16_t h_ctrl; /* see DESC_CTRL_ */ - uint16_t h_data_len; /* data length */ - uint32_t h_next_desc; /* next acx_host_desc phyaddr */ - uint32_t h_pnext; - uint32_t h_status; /* see DESC_STATUS_ */ -} __packed; - -#define DESC_STATUS_FULL 0x80000000 - -#define DESC_CTRL_SHORT_PREAMBLE 0x01 -#define DESC_CTRL_FIRST_FRAG 0x02 -#define DESC_CTRL_AUTODMA 0x04 -#define DESC_CTRL_RECLAIM 0x08 -#define DESC_CTRL_HOSTDONE 0x20 /* host finished buf proc */ -#define DESC_CTRL_ACXDONE 0x40 /* chip finished buf proc */ -#define DESC_CTRL_HOSTOWN 0x80 /* host controls desc */ - -#define DESC_ERR_OTHER_FRAG 0x01 -#define DESC_ERR_ABORT 0x02 -#define DESC_ERR_PARAM 0x04 -#define DESC_ERR_NO_WEPKEY 0x08 -#define DESC_ERR_MSDU_TIMEOUT 0x10 -#define DESC_ERR_EXCESSIVE_RETRY 0x20 -#define DESC_ERR_BUF_OVERFLOW 0x40 -#define DESC_ERR_DMA 0x80 - -/* - * Extra header in receiving buffer - * Fields are little endian - */ -struct acx_rxbuf_hdr { - uint16_t rbh_len; /* ACX_RXBUG_LEN_MASK part is len */ - uint8_t rbh_memblk_cnt; - uint8_t rbh_status; - uint8_t rbh_bbp_stat; /* see ACX_RXBUF_STAT_ */ - uint8_t rbh_plcp; - uint8_t rbh_level; /* signal level */ - uint8_t rbh_snr; /* signal noise ratio */ - uint32_t rbh_time; /* recv timestamp */ - - /* - * XXX may have 4~8 byte here which - * depends on firmware version - */ -} __packed; - -#define ACX_RXBUF_LEN_MASK 0xfff - -#define ACX_RXBUF_STAT_OFDM 0x04 -#define ACX_RXBUF_STAT_ANT1 0x10 -#define ACX_RXBUF_STAT_SHPRE 0x80 - -struct acx_ring_data { - struct acx_host_desc *rx_ring; - bus_dma_tag_t rx_ring_dma_tag; - bus_dmamap_t rx_ring_dmamap; - uint32_t rx_ring_paddr; - - struct acx_host_desc *tx_ring; - bus_dma_tag_t tx_ring_dma_tag; - bus_dmamap_t tx_ring_dmamap; - uint32_t tx_ring_paddr; -}; - -struct acx_txbuf { - struct mbuf *tb_mbuf; - bus_dmamap_t tb_mbuf_dmamap; - - struct acx_host_desc *tb_desc1; - struct acx_host_desc *tb_desc2; - - uint32_t tb_fwdesc_ofs; - - /* - * TX rate control - */ - struct ieee80211_node *tb_node; - int tb_rateidx_len; - int tb_rateidx[IEEE80211_RATEIDX_MAX]; -}; - -struct acx_rxbuf { - struct mbuf *rb_mbuf; - bus_dmamap_t rb_mbuf_dmamap; - - struct acx_host_desc *rb_desc; -}; - -struct acx_buf_data { - struct acx_rxbuf rx_buf[ACX_RX_DESC_CNT]; - struct acx_txbuf tx_buf[ACX_TX_DESC_CNT]; - bus_dma_tag_t mbuf_dma_tag; - bus_dmamap_t mbuf_tmp_dmamap; - - int rx_scan_start; - - int tx_free_start; - int tx_used_start; - int tx_used_count; -}; - -struct acx_firmware_hdr { - uint32_t fwh_cksum; - uint32_t fwh_len; -} __packed; - -struct acx_firmware { - struct fw_image *base_fw_image; - const uint8_t *base_fw; - int base_fw_len; - - struct fw_image *radio_fw_image; - const uint8_t *radio_fw; - int radio_fw_len; - - int combined_radio_fw; - const char *fwdir; -}; - -struct acx_config { - uint8_t eaddr[IEEE80211_ADDR_LEN]; - uint8_t antenna; - uint8_t regdom; - uint8_t cca_mode; /* acx100 */ - uint8_t ed_thresh; /* acx100 */ -}; - -struct acx_stats { - uint64_t err_oth_frag; /* XXX error in other frag?? */ - uint64_t err_abort; /* tx abortion */ - uint64_t err_param; /* tx desc contains invalid param */ - uint64_t err_no_wepkey; /* no WEP key exists */ - uint64_t err_msdu_timeout; /* MSDU timed out */ - uint64_t err_ex_retry; /* excessive tx retry */ - uint64_t err_buf_oflow; /* buffer overflow */ - uint64_t err_dma; /* DMA error */ - uint64_t err_unkn; /* XXX unknown error */ -}; - -#define ACX_RX_RADIOTAP_PRESENT \ - ((1 << IEEE80211_RADIOTAP_TSFT) | \ - (1 << IEEE80211_RADIOTAP_FLAGS) | \ - (1 << IEEE80211_RADIOTAP_RATE) | \ - (1 << IEEE80211_RADIOTAP_CHANNEL) | \ - (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL)| \ - (1 << IEEE80211_RADIOTAP_ANTENNA)) - -struct acx_rx_radiotap_header { - struct ieee80211_radiotap_header wr_ihdr; - uint64_t wr_tsf; - uint8_t wr_flags; - uint8_t wr_rate; - uint16_t wr_chan_freq; - uint16_t wr_chan_flags; - uint8_t wr_antsignal; - uint8_t wr_antenna; -}; - -#define ACX_TX_RADIOTAP_PRESENT \ - ((1 << IEEE80211_RADIOTAP_FLAGS) | \ - (1 << IEEE80211_RADIOTAP_RATE) | \ - (1 << IEEE80211_RADIOTAP_CHANNEL)) - -struct acx_tx_radiotap_header { - struct ieee80211_radiotap_header wt_ihdr; - uint8_t wt_flags; - uint8_t wt_rate; - uint16_t wt_chan_freq; - uint16_t wt_chan_flags; -}; - -struct acx_softc { - /* - * sc_xxx are filled in by common code - * chip_xxx are filled in by chip specific code - */ - struct ieee80211com sc_ic; - - /* - * Radio tap - */ - struct bpf_if *sc_drvbpf; - union { - struct acx_tx_radiotap_header u_tx_th; - uint8_t u_pad[IEEE80211_RADIOTAP_HDRLEN]; - } sc_u_tx_th; - int sc_tx_th_len; - union { - struct acx_rx_radiotap_header u_rx_th; - uint8_t u_pad[IEEE80211_RADIOTAP_HDRLEN]; - } sc_u_rx_th; - int sc_rx_th_len; -#define sc_tx_th sc_u_tx_th.u_tx_th -#define sc_rx_th sc_u_rx_th.u_rx_th - - struct callout sc_scan_timer; - uint32_t sc_flags; /* see ACX_FLAG_ */ - int sc_tx_timer; - - struct acx_firmware sc_firmware; - uint32_t sc_firmware_ver; - uint32_t sc_hardware_id; - - /* - * MMIO 1 - */ - struct resource *sc_mem1_res; - bus_space_tag_t sc_mem1_bt; - bus_space_handle_t sc_mem1_bh; - int chip_mem1_rid; - - /* - * MMIO 2 - */ - struct resource *sc_mem2_res; - bus_space_tag_t sc_mem2_bt; - bus_space_handle_t sc_mem2_bh; - int chip_mem2_rid; - - struct resource *sc_irq_res; - void *sc_irq_handle; - int sc_irq_rid; - - uint32_t sc_cmd; /* cmd reg (MMIO 2) */ - uint32_t sc_cmd_param; /* cmd param reg (MMIO 2) */ - uint32_t sc_info; /* unused */ - uint32_t sc_info_param; /* unused */ - - const uint16_t *chip_ioreg; /* reg map (MMIO 1) */ - - /* - * NOTE: - * chip_intr_enable is not necessarily same as - * ~chip_intr_disable - */ - uint16_t chip_intr_enable; - uint16_t chip_intr_disable; - - int chip_hw_crypt; - uint16_t chip_gpio_pled; /* power led */ - uint16_t chip_chan_flags; /* see IEEE80211_CHAN_ */ - uint16_t chip_txdesc1_len; - int chip_rxbuf_exhdr; /* based on fw ver */ - uint32_t chip_ee_eaddr_ofs; - enum ieee80211_phymode chip_phymode; /* see IEEE80211_MODE_ */ - uint8_t chip_fw_txdesc_ctrl; - int chip_rssi_corr; - - uint8_t sc_eeprom_ver; /* unused */ - uint8_t sc_form_factor; /* unused */ - uint8_t sc_radio_type; /* see ACX_RADIO_TYPE_ */ - - struct acx_ring_data sc_ring_data; - struct acx_buf_data sc_buf_data; - - struct acx_stats sc_stats; /* statistics */ - - /* - * TX rate control - */ - struct ieee80211_onoe_param sc_onoe_param; - struct ieee80211_amrr_param sc_amrr_param; - int sc_long_retry_limit; - int chip_short_retry_limit; - int chip_rate_fallback; - - /* - * Per interface sysctl variables - */ - int sc_msdu_lifetime; - int sc_scan_dwell; /* unit: millisecond */ - int sc_calib_intvl; /* unit: minute */ - - int (*sc_newstate) - (struct ieee80211com *, - enum ieee80211_state, int); - - int (*chip_init) /* non-NULL */ - (struct acx_softc *); - - int (*chip_set_wepkey) - (struct acx_softc *, - struct ieee80211_key *, int); - - int (*chip_read_config) - (struct acx_softc *, struct acx_config *); - - int (*chip_write_config) - (struct acx_softc *, struct acx_config *); - - uint8_t (*chip_set_fw_txdesc_rate) /* non-NULL */ - (struct acx_softc *, struct acx_txbuf *, - struct ieee80211_node *, int); - - void (*chip_tx_complete) /* non-NULL */ - (struct acx_softc *, struct acx_txbuf *, - int, int); - - void (*chip_set_bss_join_param) /* non-NULL */ - (struct acx_softc *, void *, int); - - void (*chip_proc_wep_rxbuf) - (struct acx_softc *, struct mbuf *, int *); - - struct callout sc_calibrate_timer; - int (*chip_calibrate) - (struct acx_softc *); -}; - -#define ACX_FLAG_FW_LOADED 0x1 -#define ACX_FLAG_PROMISC 0x2 - -#define ACX_RADIO_TYPE_MAXIM 0x0d -#define ACX_RADIO_TYPE_RFMD 0x11 -#define ACX_RADIO_TYPE_RALINK 0x15 -#define ACX_RADIO_TYPE_RADIA 0x16 -#define ACX_RADIO_TYPE_UNKN17 0x17 -#define ACX_RADIO_TYPE_UNKN19 0x19 - -#define ACX_BASE_FW_PATH "acx/%s/wlangen.bin" -#define ACX_RADIO_FW_PATH "acx/%s/radio%02x.bin" -#define ACX_BASE_RADIO_FW_PATH "acx/%s/FwRad%02x.bin" - -extern const struct ieee80211_rateset acx_rates_11b; -extern const struct ieee80211_rateset acx_rates_11b_pbcc; -extern const struct ieee80211_rateset acx_rates_11g; -extern const struct ieee80211_rateset acx_rates_11g_pbcc; -extern int acx_enable_pbcc; - -void acx100_set_param(device_t); -void acx111_set_param(device_t); - -int acx_init_tmplt_ordered(struct acx_softc *); -void acx_write_phyreg(struct acx_softc *, uint32_t, uint8_t); - -#endif /* !_IF_ACXVAR_H */ diff --git a/sys/dev/netif/bwi/Makefile b/sys/dev/netif/bwi/Makefile deleted file mode 100644 index d691f2c75f..0000000000 --- a/sys/dev/netif/bwi/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -KMOD = if_bwi - -SRCS = if_bwi.c bwimac.c bwiphy.c bwirf.c -SRCS += device_if.h bus_if.h pci_if.h pcidevs.h - -.include diff --git a/sys/dev/netif/bwi/bwimac.c b/sys/dev/netif/bwi/bwimac.c deleted file mode 100644 index a31fb67741..0000000000 --- a/sys/dev/netif/bwi/bwimac.c +++ /dev/null @@ -1,1953 +0,0 @@ -/* - * Copyright (c) 2007 The DragonFly Project. All rights reserved. - * - * This code is derived from software contributed to The DragonFly Project - * by Sepherosa Ziehau - * - * 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. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * 3. Neither the name of The DragonFly Project nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific, prior written permission. - * - * 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 MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, 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 DAMAGE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include "pcidevs.h" - -#include -#include -#include -#include -#include - -struct bwi_retry_lim { - uint16_t shretry; - uint16_t shretry_fb; - uint16_t lgretry; - uint16_t lgretry_fb; -}; - -static int bwi_mac_test(struct bwi_mac *); -static int bwi_mac_get_property(struct bwi_mac *); - -static void bwi_mac_set_retry_lim(struct bwi_mac *, - const struct bwi_retry_lim *); -static void bwi_mac_set_ackrates(struct bwi_mac *, - const struct ieee80211_rateset *); - -static int bwi_mac_gpio_init(struct bwi_mac *); -static int bwi_mac_gpio_fini(struct bwi_mac *); -static void bwi_mac_opmode_init(struct bwi_mac *); -static void bwi_mac_hostflags_init(struct bwi_mac *); -static void bwi_mac_bss_param_init(struct bwi_mac *); - -static int bwi_mac_fw_alloc(struct bwi_mac *); -static void bwi_mac_fw_free(struct bwi_mac *); -static int bwi_mac_fw_load(struct bwi_mac *); -static int bwi_mac_fw_init(struct bwi_mac *); -static int bwi_mac_fw_load_iv(struct bwi_mac *, const struct fw_image *); - -static void bwi_mac_setup_tpctl(struct bwi_mac *); -static void bwi_mac_adjust_tpctl(struct bwi_mac *, int, int); - -static void bwi_mac_lock(struct bwi_mac *); -static void bwi_mac_unlock(struct bwi_mac *); - -static const uint8_t bwi_sup_macrev[] = { 2, 4, 5, 6, 7, 9, 10 }; - -void -bwi_tmplt_write_4(struct bwi_mac *mac, uint32_t ofs, uint32_t val) -{ - struct bwi_softc *sc = mac->mac_sc; - - if (mac->mac_flags & BWI_MAC_F_BSWAP) - val = bswap32(val); - - CSR_WRITE_4(sc, BWI_MAC_TMPLT_CTRL, ofs); - CSR_WRITE_4(sc, BWI_MAC_TMPLT_DATA, val); -} - -void -bwi_hostflags_write(struct bwi_mac *mac, uint64_t flags) -{ - uint64_t val; - - val = flags & 0xffff; - MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_HFLAGS_LO, val); - - val = (flags >> 16) & 0xffff; - MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_HFLAGS_MI, val); - - /* HI has unclear meaning, so leave it as it is */ -} - -uint64_t -bwi_hostflags_read(struct bwi_mac *mac) -{ - uint64_t flags, val; - - /* HI has unclear meaning, so don't touch it */ - flags = 0; - - val = MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_HFLAGS_MI); - flags |= val << 16; - - val = MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_HFLAGS_LO); - flags |= val; - - return flags; -} - -uint16_t -bwi_memobj_read_2(struct bwi_mac *mac, uint16_t obj_id, uint16_t ofs0) -{ - struct bwi_softc *sc = mac->mac_sc; - uint32_t data_reg; - int ofs; - - data_reg = BWI_MOBJ_DATA; - ofs = ofs0 / 4; - - if (ofs0 % 4 != 0) - data_reg = BWI_MOBJ_DATA_UNALIGN; - - CSR_WRITE_4(sc, BWI_MOBJ_CTRL, BWI_MOBJ_CTRL_VAL(obj_id, ofs)); - return CSR_READ_2(sc, data_reg); -} - -uint32_t -bwi_memobj_read_4(struct bwi_mac *mac, uint16_t obj_id, uint16_t ofs0) -{ - struct bwi_softc *sc = mac->mac_sc; - int ofs; - - ofs = ofs0 / 4; - if (ofs0 % 4 != 0) { - uint32_t ret; - - CSR_WRITE_4(sc, BWI_MOBJ_CTRL, BWI_MOBJ_CTRL_VAL(obj_id, ofs)); - ret = CSR_READ_2(sc, BWI_MOBJ_DATA_UNALIGN); - ret <<= 16; - - CSR_WRITE_4(sc, BWI_MOBJ_CTRL, - BWI_MOBJ_CTRL_VAL(obj_id, ofs + 1)); - ret |= CSR_READ_2(sc, BWI_MOBJ_DATA); - - return ret; - } else { - CSR_WRITE_4(sc, BWI_MOBJ_CTRL, BWI_MOBJ_CTRL_VAL(obj_id, ofs)); - return CSR_READ_4(sc, BWI_MOBJ_DATA); - } -} - -void -bwi_memobj_write_2(struct bwi_mac *mac, uint16_t obj_id, uint16_t ofs0, - uint16_t v) -{ - struct bwi_softc *sc = mac->mac_sc; - uint32_t data_reg; - int ofs; - - data_reg = BWI_MOBJ_DATA; - ofs = ofs0 / 4; - - if (ofs0 % 4 != 0) - data_reg = BWI_MOBJ_DATA_UNALIGN; - - CSR_WRITE_4(sc, BWI_MOBJ_CTRL, BWI_MOBJ_CTRL_VAL(obj_id, ofs)); - CSR_WRITE_2(sc, data_reg, v); -} - -void -bwi_memobj_write_4(struct bwi_mac *mac, uint16_t obj_id, uint16_t ofs0, - uint32_t v) -{ - struct bwi_softc *sc = mac->mac_sc; - int ofs; - - ofs = ofs0 / 4; - if (ofs0 % 4 != 0) { - CSR_WRITE_4(sc, BWI_MOBJ_CTRL, BWI_MOBJ_CTRL_VAL(obj_id, ofs)); - CSR_WRITE_2(sc, BWI_MOBJ_DATA_UNALIGN, v >> 16); - - CSR_WRITE_4(sc, BWI_MOBJ_CTRL, - BWI_MOBJ_CTRL_VAL(obj_id, ofs + 1)); - CSR_WRITE_2(sc, BWI_MOBJ_DATA, v & 0xffff); - } else { - CSR_WRITE_4(sc, BWI_MOBJ_CTRL, BWI_MOBJ_CTRL_VAL(obj_id, ofs)); - CSR_WRITE_4(sc, BWI_MOBJ_DATA, v); - } -} - -int -bwi_mac_lateattach(struct bwi_mac *mac) -{ - int error; - - if (mac->mac_rev >= 5) - CSR_READ_4(mac->mac_sc, BWI_STATE_HI); /* dummy read */ - - bwi_mac_reset(mac, 1); - - error = bwi_phy_attach(mac); - if (error) - return error; - - error = bwi_rf_attach(mac); - if (error) - return error; - - /* Link 11B/G PHY, unlink 11A PHY */ - if (mac->mac_phy.phy_mode == IEEE80211_MODE_11A) - bwi_mac_reset(mac, 0); - else - bwi_mac_reset(mac, 1); - - error = bwi_mac_test(mac); - if (error) - return error; - - error = bwi_mac_get_property(mac); - if (error) - return error; - - error = bwi_rf_map_txpower(mac); - if (error) - return error; - - bwi_rf_off(mac); - CSR_WRITE_2(mac->mac_sc, BWI_BBP_ATTEN, BWI_BBP_ATTEN_MAGIC); - bwi_regwin_disable(mac->mac_sc, &mac->mac_regwin, 0); - - return 0; -} - -int -bwi_mac_init(struct bwi_mac *mac) -{ - struct bwi_softc *sc = mac->mac_sc; - int error, i; - - /* Clear MAC/PHY/RF states */ - bwi_mac_setup_tpctl(mac); - bwi_rf_clear_state(&mac->mac_rf); - bwi_phy_clear_state(&mac->mac_phy); - - /* Enable MAC and linked it to PHY */ - if (!bwi_regwin_is_enabled(sc, &mac->mac_regwin)) - bwi_mac_reset(mac, 1); - - /* Initialize backplane */ - error = bwi_bus_init(sc, mac); - if (error) - return error; - - /* XXX work around for hardware bugs? */ - if (sc->sc_bus_regwin.rw_rev <= 5 && - sc->sc_bus_regwin.rw_type != BWI_REGWIN_T_BUSPCIE) { - CSR_SETBITS_4(sc, BWI_CONF_LO, - __SHIFTIN(BWI_CONF_LO_SERVTO, BWI_CONF_LO_SERVTO_MASK) | - __SHIFTIN(BWI_CONF_LO_REQTO, BWI_CONF_LO_REQTO_MASK)); - } - - /* Calibrate PHY */ - error = bwi_phy_calibrate(mac); - if (error) { - if_printf(&sc->sc_ic.ic_if, "PHY calibrate failed\n"); - return error; - } - - /* Prepare to initialize firmware */ - CSR_WRITE_4(sc, BWI_MAC_STATUS, - BWI_MAC_STATUS_UCODE_JUMP0 | - BWI_MAC_STATUS_IHREN); - - /* - * Load and initialize firmwares - */ - error = bwi_mac_fw_alloc(mac); - if (error) - return error; - - error = bwi_mac_fw_load(mac); - if (error) - return error; - - error = bwi_mac_gpio_init(mac); - if (error) - return error; - - error = bwi_mac_fw_init(mac); - if (error) - return error; - - /* - * Turn on RF - */ - bwi_rf_on(mac); - - /* TODO: LED, hardware rf enabled is only related to LED setting */ - - /* - * Initialize PHY - */ - CSR_WRITE_2(sc, BWI_BBP_ATTEN, 0); - bwi_phy_init(mac); - - /* TODO: interference mitigation */ - - /* - * Setup antenna mode - */ - bwi_rf_set_ant_mode(mac, mac->mac_rf.rf_ant_mode); - - /* - * Initialize operation mode (RX configuration) - */ - bwi_mac_opmode_init(mac); - - /* XXX what's these */ - if (mac->mac_rev < 3) { - CSR_WRITE_2(sc, 0x60e, 0); - CSR_WRITE_2(sc, 0x610, 0x8000); - CSR_WRITE_2(sc, 0x604, 0); - CSR_WRITE_2(sc, 0x606, 0x200); - } else { - CSR_WRITE_4(sc, 0x188, 0x80000000); - CSR_WRITE_4(sc, 0x18c, 0x2000000); - } - - /* - * Initialize TX/RX interrupts' mask - */ - CSR_WRITE_4(sc, BWI_MAC_INTR_STATUS, BWI_INTR_TIMER1); - for (i = 0; i < BWI_TXRX_NRING; ++i) { - uint32_t intrs; - - if (BWI_TXRX_IS_RX(i)) - intrs = BWI_TXRX_RX_INTRS; - else - intrs = BWI_TXRX_TX_INTRS; - CSR_WRITE_4(sc, BWI_TXRX_INTR_MASK(i), intrs); - } - - /* XXX what's this */ - CSR_SETBITS_4(sc, BWI_STATE_LO, 0x100000); - - /* Setup MAC power up delay */ - CSR_WRITE_2(sc, BWI_MAC_POWERUP_DELAY, sc->sc_pwron_delay); - - /* Set MAC regwin revision */ - MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_MACREV, mac->mac_rev); - - /* - * Initialize host flags - */ - bwi_mac_hostflags_init(mac); - - /* - * Initialize BSS parameters - */ - bwi_mac_bss_param_init(mac); - - /* - * Initialize TX rings - */ - for (i = 0; i < BWI_TX_NRING; ++i) { - error = sc->sc_init_tx_ring(sc, i); - if (error) { - if_printf(&sc->sc_ic.ic_if, - "can't initialize %dth TX ring\n", i); - return error; - } - } - - /* - * Initialize RX ring - */ - error = sc->sc_init_rx_ring(sc); - if (error) { - if_printf(&sc->sc_ic.ic_if, "can't initialize RX ring\n"); - return error; - } - - /* - * Initialize TX stats if the current MAC uses that - */ - if (mac->mac_flags & BWI_MAC_F_HAS_TXSTATS) { - error = sc->sc_init_txstats(sc); - if (error) { - if_printf(&sc->sc_ic.ic_if, - "can't initialize TX stats ring\n"); - return error; - } - } - - /* XXX what's these */ - CSR_WRITE_2(sc, 0x612, 0x50); /* Force Pre-TBTT to 80? */ - MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, 0x416, 0x50); - MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, 0x414, 0x1f4); - - mac->mac_flags |= BWI_MAC_F_INITED; - return 0; -} - -void -bwi_mac_reset(struct bwi_mac *mac, int link_phy) -{ - struct bwi_softc *sc = mac->mac_sc; - uint32_t flags, state_lo, status; - - flags = BWI_STATE_LO_FLAG_PHYRST | BWI_STATE_LO_FLAG_PHYCLKEN; - if (link_phy) - flags |= BWI_STATE_LO_FLAG_PHYLNK; - bwi_regwin_enable(sc, &mac->mac_regwin, flags); - DELAY(2000); - - state_lo = CSR_READ_4(sc, BWI_STATE_LO); - state_lo |= BWI_STATE_LO_GATED_CLOCK; - state_lo &= ~__SHIFTIN(BWI_STATE_LO_FLAG_PHYRST, - BWI_STATE_LO_FLAGS_MASK); - CSR_WRITE_4(sc, BWI_STATE_LO, state_lo); - /* Flush pending bus write */ - CSR_READ_4(sc, BWI_STATE_LO); - DELAY(1000); - - state_lo &= ~BWI_STATE_LO_GATED_CLOCK; - CSR_WRITE_4(sc, BWI_STATE_LO, state_lo); - /* Flush pending bus write */ - CSR_READ_4(sc, BWI_STATE_LO); - DELAY(1000); - - CSR_WRITE_2(sc, BWI_BBP_ATTEN, 0); - - status = CSR_READ_4(sc, BWI_MAC_STATUS); - status |= BWI_MAC_STATUS_IHREN; - if (link_phy) - status |= BWI_MAC_STATUS_PHYLNK; - else - status &= ~BWI_MAC_STATUS_PHYLNK; - CSR_WRITE_4(sc, BWI_MAC_STATUS, status); - - if (link_phy) { - DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_ATTACH | BWI_DBG_INIT, - "%s\n", "PHY is linked"); - mac->mac_phy.phy_flags |= BWI_PHY_F_LINKED; - } else { - DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_ATTACH | BWI_DBG_INIT, - "%s\n", "PHY is unlinked"); - mac->mac_phy.phy_flags &= ~BWI_PHY_F_LINKED; - } -} - -void -bwi_mac_set_tpctl_11bg(struct bwi_mac *mac, const struct bwi_tpctl *new_tpctl) -{ - struct bwi_rf *rf = &mac->mac_rf; - struct bwi_tpctl *tpctl = &mac->mac_tpctl; - - if (new_tpctl != NULL) { - KKASSERT(new_tpctl->bbp_atten <= BWI_BBP_ATTEN_MAX); - KKASSERT(new_tpctl->rf_atten <= - (rf->rf_rev < 6 ? BWI_RF_ATTEN_MAX0 - : BWI_RF_ATTEN_MAX1)); - KKASSERT(new_tpctl->tp_ctrl1 <= BWI_TPCTL1_MAX); - - tpctl->bbp_atten = new_tpctl->bbp_atten; - tpctl->rf_atten = new_tpctl->rf_atten; - tpctl->tp_ctrl1 = new_tpctl->tp_ctrl1; - } - - /* Set BBP attenuation */ - bwi_phy_set_bbp_atten(mac, tpctl->bbp_atten); - - /* Set RF attenuation */ - RF_WRITE(mac, BWI_RFR_ATTEN, tpctl->rf_atten); - MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_RF_ATTEN, - tpctl->rf_atten); - - /* Set TX power */ - if (rf->rf_type == BWI_RF_T_BCM2050) { - RF_FILT_SETBITS(mac, BWI_RFR_TXPWR, ~BWI_RFR_TXPWR1_MASK, - __SHIFTIN(tpctl->tp_ctrl1, BWI_RFR_TXPWR1_MASK)); - } - - /* Adjust RF Local Oscillator */ - if (mac->mac_phy.phy_mode == IEEE80211_MODE_11G) - bwi_rf_lo_adjust(mac, tpctl); -} - -static int -bwi_mac_test(struct bwi_mac *mac) -{ - struct bwi_softc *sc = mac->mac_sc; - uint32_t orig_val, val; - -#define TEST_VAL1 0xaa5555aa -#define TEST_VAL2 0x55aaaa55 - - /* Save it for later restoring */ - orig_val = MOBJ_READ_4(mac, BWI_COMM_MOBJ, 0); - - /* Test 1 */ - MOBJ_WRITE_4(mac, BWI_COMM_MOBJ, 0, TEST_VAL1); - val = MOBJ_READ_4(mac, BWI_COMM_MOBJ, 0); - if (val != TEST_VAL1) { - device_printf(sc->sc_dev, "TEST1 failed\n"); - return ENXIO; - } - - /* Test 2 */ - MOBJ_WRITE_4(mac, BWI_COMM_MOBJ, 0, TEST_VAL2); - val = MOBJ_READ_4(mac, BWI_COMM_MOBJ, 0); - if (val != TEST_VAL2) { - device_printf(sc->sc_dev, "TEST2 failed\n"); - return ENXIO; - } - - /* Restore to the original value */ - MOBJ_WRITE_4(mac, BWI_COMM_MOBJ, 0, orig_val); - - val = CSR_READ_4(sc, BWI_MAC_STATUS); - if ((val & ~BWI_MAC_STATUS_PHYLNK) != BWI_MAC_STATUS_IHREN) { - device_printf(sc->sc_dev, "%s failed, MAC status 0x%08x\n", - __func__, val); - return ENXIO; - } - - val = CSR_READ_4(sc, BWI_MAC_INTR_STATUS); - if (val != 0) { - device_printf(sc->sc_dev, "%s failed, intr status %08x\n", - __func__, val); - return ENXIO; - } - -#undef TEST_VAL2 -#undef TEST_VAL1 - - return 0; -} - -static void -bwi_mac_setup_tpctl(struct bwi_mac *mac) -{ - struct bwi_softc *sc = mac->mac_sc; - struct bwi_rf *rf = &mac->mac_rf; - struct bwi_phy *phy = &mac->mac_phy; - struct bwi_tpctl *tpctl = &mac->mac_tpctl; - - /* Calc BBP attenuation */ - if (rf->rf_type == BWI_RF_T_BCM2050 && rf->rf_rev < 6) - tpctl->bbp_atten = 0; - else - tpctl->bbp_atten = 2; - - /* Calc TX power CTRL1?? */ - tpctl->tp_ctrl1 = 0; - if (rf->rf_type == BWI_RF_T_BCM2050) { - if (rf->rf_rev == 1) - tpctl->tp_ctrl1 = 3; - else if (rf->rf_rev < 6) - tpctl->tp_ctrl1 = 2; - else if (rf->rf_rev == 8) - tpctl->tp_ctrl1 = 1; - } - - /* Empty TX power CTRL2?? */ - tpctl->tp_ctrl2 = 0xffff; - - /* - * Calc RF attenuation - */ - if (phy->phy_mode == IEEE80211_MODE_11A) { - tpctl->rf_atten = 0x60; - goto back; - } - - if (BWI_IS_BRCM_BCM4309G(sc) && sc->sc_pci_revid < 0x51) { - tpctl->rf_atten = sc->sc_pci_revid < 0x43 ? 2 : 3; - goto back; - } - - tpctl->rf_atten = 5; - - if (rf->rf_type != BWI_RF_T_BCM2050) { - if (rf->rf_type == BWI_RF_T_BCM2053 && rf->rf_rev == 1) - tpctl->rf_atten = 6; - goto back; - } - - /* - * NB: If we reaches here and the card is BRCM_BCM4309G, - * then the card's PCI revision must >= 0x51 - */ - - /* BCM2050 RF */ - switch (rf->rf_rev) { - case 1: - if (phy->phy_mode == IEEE80211_MODE_11G) { - if (BWI_IS_BRCM_BCM4309G(sc) || BWI_IS_BRCM_BU4306(sc)) - tpctl->rf_atten = 3; - else - tpctl->rf_atten = 1; - } else { - if (BWI_IS_BRCM_BCM4309G(sc)) - tpctl->rf_atten = 7; - else - tpctl->rf_atten = 6; - } - break; - case 2: - if (phy->phy_mode == IEEE80211_MODE_11G) { - /* - * NOTE: Order of following conditions is critical - */ - if (BWI_IS_BRCM_BCM4309G(sc)) - tpctl->rf_atten = 3; - else if (BWI_IS_BRCM_BU4306(sc)) - tpctl->rf_atten = 5; - else if (sc->sc_bbp_id == BWI_BBPID_BCM4320) - tpctl->rf_atten = 4; - else - tpctl->rf_atten = 3; - } else { - tpctl->rf_atten = 6; - } - break; - case 4: - case 5: - tpctl->rf_atten = 1; - break; - case 8: - tpctl->rf_atten = 0x1a; - break; - } -back: - DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_INIT | BWI_DBG_TXPOWER, - "bbp atten: %u, rf atten: %u, ctrl1: %u, ctrl2: %u\n", - tpctl->bbp_atten, tpctl->rf_atten, - tpctl->tp_ctrl1, tpctl->tp_ctrl2); -} - -void -bwi_mac_dummy_xmit(struct bwi_mac *mac) -{ -#define PACKET_LEN 5 - static const uint32_t packet_11a[PACKET_LEN] = - { 0x000201cc, 0x00d40000, 0x00000000, 0x01000000, 0x00000000 }; - static const uint32_t packet_11bg[PACKET_LEN] = - { 0x000b846e, 0x00d40000, 0x00000000, 0x01000000, 0x00000000 }; - - struct bwi_softc *sc = mac->mac_sc; - struct bwi_rf *rf = &mac->mac_rf; - const uint32_t *packet; - uint16_t val_50c; - int wait_max, i; - - if (mac->mac_phy.phy_mode == IEEE80211_MODE_11A) { - wait_max = 30; - packet = packet_11a; - val_50c = 1; - } else { - wait_max = 250; - packet = packet_11bg; - val_50c = 0; - } - - for (i = 0; i < PACKET_LEN; ++i) - TMPLT_WRITE_4(mac, i * 4, packet[i]); - - CSR_READ_4(sc, BWI_MAC_STATUS); /* dummy read */ - - CSR_WRITE_2(sc, 0x568, 0); - CSR_WRITE_2(sc, 0x7c0, 0); - CSR_WRITE_2(sc, 0x50c, val_50c); - CSR_WRITE_2(sc, 0x508, 0); - CSR_WRITE_2(sc, 0x50a, 0); - CSR_WRITE_2(sc, 0x54c, 0); - CSR_WRITE_2(sc, 0x56a, 0x14); - CSR_WRITE_2(sc, 0x568, 0x826); - CSR_WRITE_2(sc, 0x500, 0); - CSR_WRITE_2(sc, 0x502, 0x30); - - if (rf->rf_type == BWI_RF_T_BCM2050 && rf->rf_rev <= 5) - RF_WRITE(mac, 0x51, 0x17); - - for (i = 0; i < wait_max; ++i) { - if (CSR_READ_2(sc, 0x50e) & 0x80) - break; - DELAY(10); - } - for (i = 0; i < 10; ++i) { - if (CSR_READ_2(sc, 0x50e) & 0x400) - break; - DELAY(10); - } - for (i = 0; i < 10; ++i) { - if ((CSR_READ_2(sc, 0x690) & 0x100) == 0) - break; - DELAY(10); - } - - if (rf->rf_type == BWI_RF_T_BCM2050 && rf->rf_rev <= 5) - RF_WRITE(mac, 0x51, 0x37); -#undef PACKET_LEN -} - -void -bwi_mac_init_tpctl_11bg(struct bwi_mac *mac) -{ - struct bwi_softc *sc = mac->mac_sc; - struct bwi_phy *phy = &mac->mac_phy; - struct bwi_rf *rf = &mac->mac_rf; - struct bwi_tpctl tpctl_orig; - int restore_tpctl = 0; - - KKASSERT(phy->phy_mode != IEEE80211_MODE_11A); - - if (BWI_IS_BRCM_BU4306(sc)) - return; - - PHY_WRITE(mac, 0x28, 0x8018); - CSR_CLRBITS_2(sc, BWI_BBP_ATTEN, 0x20); - - if (phy->phy_mode == IEEE80211_MODE_11G) { - if ((phy->phy_flags & BWI_PHY_F_LINKED) == 0) - return; - PHY_WRITE(mac, 0x47a, 0xc111); - } - if (mac->mac_flags & BWI_MAC_F_TPCTL_INITED) - return; - - if (phy->phy_mode == IEEE80211_MODE_11B && phy->phy_rev >= 2 && - rf->rf_type == BWI_RF_T_BCM2050) { - RF_SETBITS(mac, 0x76, 0x84); - } else { - struct bwi_tpctl tpctl; - - /* Backup original TX power control variables */ - bcopy(&mac->mac_tpctl, &tpctl_orig, sizeof(tpctl_orig)); - restore_tpctl = 1; - - bcopy(&mac->mac_tpctl, &tpctl, sizeof(tpctl)); - tpctl.bbp_atten = 11; - tpctl.tp_ctrl1 = 0; -#ifdef notyet - if (rf->rf_rev >= 6 && rf->rf_rev <= 8) - tpctl.rf_atten = 31; - else -#endif - tpctl.rf_atten = 9; - - bwi_mac_set_tpctl_11bg(mac, &tpctl); - } - - bwi_mac_dummy_xmit(mac); - - mac->mac_flags |= BWI_MAC_F_TPCTL_INITED; - rf->rf_base_tssi = PHY_READ(mac, 0x29); - DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_INIT | BWI_DBG_TXPOWER, - "base tssi %d\n", rf->rf_base_tssi); - - if (abs(rf->rf_base_tssi - rf->rf_idle_tssi) >= 20) { - if_printf(&sc->sc_ic.ic_if, "base tssi measure failed\n"); - mac->mac_flags |= BWI_MAC_F_TPCTL_ERROR; - } - - if (restore_tpctl) - bwi_mac_set_tpctl_11bg(mac, &tpctl_orig); - else - RF_CLRBITS(mac, 0x76, 0x84); - - bwi_rf_clear_tssi(mac); -} - -void -bwi_mac_detach(struct bwi_mac *mac) -{ - bwi_mac_fw_free(mac); -} - -static __inline int -bwi_fwimage_is_valid(struct bwi_softc *sc, const struct fw_image *fw, - uint8_t fw_type) -{ - const struct bwi_fwhdr *hdr; - struct ifnet *ifp = &sc->sc_ic.ic_if; - - if (fw->fw_imglen < sizeof(*hdr)) { - if_printf(ifp, "invalid firmware (%s): invalid size %zu\n", - fw->fw_name, fw->fw_imglen); - return 0; - } - - hdr = (const struct bwi_fwhdr *)fw->fw_image; - - if (fw_type != BWI_FW_T_IV) { - /* - * Don't verify IV's size, it has different meaning - */ - if (be32toh(hdr->fw_size) != fw->fw_imglen - sizeof(*hdr)) { - if_printf(ifp, - "invalid firmware (%s): size mismatch, " - "fw %u, real %zu\n", - fw->fw_name, be32toh(hdr->fw_size), - fw->fw_imglen - sizeof(*hdr)); - return 0; - } - } - - if (hdr->fw_type != fw_type) { - if_printf(ifp, "invalid firmware (%s): type mismatch, " - "fw \'%c\', target \'%c\'\n", fw->fw_name, - hdr->fw_type, fw_type); - return 0; - } - - if (hdr->fw_gen != BWI_FW_GEN_1) { - if_printf(ifp, "invalid firmware (%s): wrong generation, " - "fw %d, target %d\n", fw->fw_name, - hdr->fw_gen, BWI_FW_GEN_1); - return 0; - } - return 1; -} - -/* - * XXX Error cleanup - */ -static int -bwi_mac_fw_alloc(struct bwi_mac *mac) -{ - struct bwi_softc *sc = mac->mac_sc; - struct ifnet *ifp = &sc->sc_ic.ic_if; - struct fw_image *img; - char fwname[64]; - int idx; - - /* - * NB: serializer need to be released before loading firmware - * image to avoid possible dead lock - */ - ASSERT_SERIALIZED(ifp->if_serializer); - - if (mac->mac_ucode == NULL) { - ksnprintf(fwname, sizeof(fwname), BWI_FW_UCODE_PATH, - sc->sc_fw_version, - mac->mac_rev >= 5 ? 5 : mac->mac_rev); - - lwkt_serialize_exit(ifp->if_serializer); - img = firmware_image_load(fwname, NULL); - lwkt_serialize_enter(ifp->if_serializer); - - mac->mac_ucode = img; - if (mac->mac_ucode == NULL) { - if_printf(ifp, "request firmware %s failed\n", fwname); - return ENOMEM; - } - - if (!bwi_fwimage_is_valid(sc, mac->mac_ucode, BWI_FW_T_UCODE)) - return EINVAL; - } - - if (mac->mac_pcm == NULL) { - ksnprintf(fwname, sizeof(fwname), BWI_FW_PCM_PATH, - sc->sc_fw_version, - mac->mac_rev < 5 ? 4 : 5); - - lwkt_serialize_exit(ifp->if_serializer); - img = firmware_image_load(fwname, NULL); - lwkt_serialize_enter(ifp->if_serializer); - - mac->mac_pcm = img; - if (mac->mac_pcm == NULL) { - if_printf(ifp, "request firmware %s failed\n", fwname); - return ENOMEM; - } - - if (!bwi_fwimage_is_valid(sc, mac->mac_pcm, BWI_FW_T_PCM)) - return EINVAL; - } - - if (mac->mac_iv == NULL) { - /* TODO: 11A */ - if (mac->mac_rev == 2 || mac->mac_rev == 4) { - idx = 2; - } else if (mac->mac_rev >= 5 && mac->mac_rev <= 10) { - idx = 5; - } else { - if_printf(ifp, "no suitable IV for MAC rev %d\n", - mac->mac_rev); - return ENODEV; - } - - ksnprintf(fwname, sizeof(fwname), BWI_FW_IV_PATH, - sc->sc_fw_version, idx); - - lwkt_serialize_exit(ifp->if_serializer); - img = firmware_image_load(fwname, NULL); - lwkt_serialize_enter(ifp->if_serializer); - - mac->mac_iv = img; - if (mac->mac_iv == NULL) { - if_printf(ifp, "request firmware %s failed\n", fwname); - return ENOMEM; - } - if (!bwi_fwimage_is_valid(sc, mac->mac_iv, BWI_FW_T_IV)) - return EINVAL; - } - - if (mac->mac_iv_ext == NULL) { - /* TODO: 11A */ - if (mac->mac_rev == 2 || mac->mac_rev == 4 || - mac->mac_rev >= 11) { - /* No extended IV */ - goto back; - } else if (mac->mac_rev >= 5 && mac->mac_rev <= 10) { - idx = 5; - } else { - if_printf(ifp, "no suitible ExtIV for MAC rev %d\n", - mac->mac_rev); - return ENODEV; - } - - ksnprintf(fwname, sizeof(fwname), BWI_FW_IV_EXT_PATH, - sc->sc_fw_version, idx); - - lwkt_serialize_exit(ifp->if_serializer); - img = firmware_image_load(fwname, NULL); - lwkt_serialize_enter(ifp->if_serializer); - - mac->mac_iv_ext = img; - if (mac->mac_iv_ext == NULL) { - if_printf(ifp, "request firmware %s failed\n", fwname); - return ENOMEM; - } - if (!bwi_fwimage_is_valid(sc, mac->mac_iv_ext, BWI_FW_T_IV)) - return EINVAL; - } -back: - return 0; -} - -static void -bwi_mac_fw_free(struct bwi_mac *mac) -{ - if (mac->mac_ucode != NULL) { - firmware_image_unload(mac->mac_ucode); - mac->mac_ucode = NULL; - } - - if (mac->mac_pcm != NULL) { - firmware_image_unload(mac->mac_pcm); - mac->mac_pcm = NULL; - } - - if (mac->mac_iv != NULL) { - firmware_image_unload(mac->mac_iv); - mac->mac_iv = NULL; - } - - if (mac->mac_iv_ext != NULL) { - firmware_image_unload(mac->mac_iv_ext); - mac->mac_iv_ext = NULL; - } -} - -static int -bwi_mac_fw_load(struct bwi_mac *mac) -{ - struct bwi_softc *sc = mac->mac_sc; - struct ifnet *ifp = &sc->sc_ic.ic_if; - const uint32_t *fw; - uint16_t fw_rev; - int fw_len, i; - - /* - * Load ucode image - */ - fw = (const uint32_t *) - ((const uint8_t *)mac->mac_ucode->fw_image + BWI_FWHDR_SZ); - fw_len = (mac->mac_ucode->fw_imglen - BWI_FWHDR_SZ) / sizeof(uint32_t); - - CSR_WRITE_4(sc, BWI_MOBJ_CTRL, - BWI_MOBJ_CTRL_VAL( - BWI_FW_UCODE_MOBJ | BWI_WR_MOBJ_AUTOINC, 0)); - for (i = 0; i < fw_len; ++i) { - CSR_WRITE_4(sc, BWI_MOBJ_DATA, be32toh(fw[i])); - DELAY(10); - } - - /* - * Load PCM image - */ - fw = (const uint32_t *) - ((const uint8_t *)mac->mac_pcm->fw_image + BWI_FWHDR_SZ); - fw_len = (mac->mac_pcm->fw_imglen - BWI_FWHDR_SZ) / sizeof(uint32_t); - - CSR_WRITE_4(sc, BWI_MOBJ_CTRL, - BWI_MOBJ_CTRL_VAL(BWI_FW_PCM_MOBJ, 0x01ea)); - CSR_WRITE_4(sc, BWI_MOBJ_DATA, 0x4000); - - CSR_WRITE_4(sc, BWI_MOBJ_CTRL, - BWI_MOBJ_CTRL_VAL(BWI_FW_PCM_MOBJ, 0x01eb)); - for (i = 0; i < fw_len; ++i) { - CSR_WRITE_4(sc, BWI_MOBJ_DATA, be32toh(fw[i])); - DELAY(10); - } - - CSR_WRITE_4(sc, BWI_MAC_INTR_STATUS, BWI_ALL_INTRS); - CSR_WRITE_4(sc, BWI_MAC_STATUS, - BWI_MAC_STATUS_UCODE_START | - BWI_MAC_STATUS_IHREN | - BWI_MAC_STATUS_INFRA); - -#define NRETRY 200 - - for (i = 0; i < NRETRY; ++i) { - uint32_t intr_status; - - intr_status = CSR_READ_4(sc, BWI_MAC_INTR_STATUS); - if (intr_status == BWI_INTR_READY) - break; - DELAY(10); - } - if (i == NRETRY) { - if_printf(ifp, "firmware (ucode&pcm) loading timed out\n"); - return ETIMEDOUT; - } - -#undef NRETRY - - CSR_READ_4(sc, BWI_MAC_INTR_STATUS); /* dummy read */ - - fw_rev = MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_FWREV); - if (fw_rev > BWI_FW_VERSION3_REVMAX) { - if_printf(ifp, "firmware version 4 is not supported yet\n"); - return ENODEV; - } - - if_printf(ifp, "firmware rev 0x%04x, patch level 0x%04x\n", fw_rev, - MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_FWPATCHLV)); - return 0; -} - -static int -bwi_mac_gpio_init(struct bwi_mac *mac) -{ - struct bwi_softc *sc = mac->mac_sc; - struct bwi_regwin *old, *gpio_rw; - uint32_t filt, bits; - int error; - - CSR_CLRBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_GPOSEL_MASK); - /* TODO:LED */ - - CSR_SETBITS_2(sc, BWI_MAC_GPIO_MASK, 0xf); - - filt = 0x1f; - bits = 0xf; - if (sc->sc_bbp_id == BWI_BBPID_BCM4301) { - filt |= 0x60; - bits |= 0x60; - } - if (sc->sc_card_flags & BWI_CARD_F_PA_GPIO9) { - CSR_SETBITS_2(sc, BWI_MAC_GPIO_MASK, 0x200); - filt |= 0x200; - bits |= 0x200; - } - - gpio_rw = BWI_GPIO_REGWIN(sc); - error = bwi_regwin_switch(sc, gpio_rw, &old); - if (error) - return error; - - CSR_FILT_SETBITS_4(sc, BWI_GPIO_CTRL, filt, bits); - - return bwi_regwin_switch(sc, old, NULL); -} - -static int -bwi_mac_gpio_fini(struct bwi_mac *mac) -{ - struct bwi_softc *sc = mac->mac_sc; - struct bwi_regwin *old, *gpio_rw; - int error; - - gpio_rw = BWI_GPIO_REGWIN(sc); - error = bwi_regwin_switch(sc, gpio_rw, &old); - if (error) - return error; - - CSR_WRITE_4(sc, BWI_GPIO_CTRL, 0); - - return bwi_regwin_switch(sc, old, NULL); -} - -static int -bwi_mac_fw_load_iv(struct bwi_mac *mac, const struct fw_image *fw) -{ - struct bwi_softc *sc = mac->mac_sc; - struct ifnet *ifp = &sc->sc_ic.ic_if; - const struct bwi_fwhdr *hdr; - const struct bwi_fw_iv *iv; - int n, i, iv_img_size; - - /* Get the number of IVs in the IV image */ - hdr = (const struct bwi_fwhdr *)fw->fw_image; - n = be32toh(hdr->fw_iv_cnt); - DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_INIT | BWI_DBG_FIRMWARE, - "IV count %d\n", n); - - /* Calculate the IV image size, for later sanity check */ - iv_img_size = fw->fw_imglen - sizeof(*hdr); - - /* Locate the first IV */ - iv = (const struct bwi_fw_iv *) - ((const uint8_t *)fw->fw_image + sizeof(*hdr)); - - for (i = 0; i < n; ++i) { - uint16_t iv_ofs, ofs; - int sz = 0; - - if (iv_img_size < sizeof(iv->iv_ofs)) { - if_printf(ifp, "invalid IV image, ofs\n"); - return EINVAL; - } - iv_img_size -= sizeof(iv->iv_ofs); - sz += sizeof(iv->iv_ofs); - - iv_ofs = be16toh(iv->iv_ofs); - - ofs = __SHIFTOUT(iv_ofs, BWI_FW_IV_OFS_MASK); - if (ofs >= 0x1000) { - if_printf(ifp, "invalid ofs (0x%04x) " - "for %dth iv\n", ofs, i); - return EINVAL; - } - - if (iv_ofs & BWI_FW_IV_IS_32BIT) { - uint32_t val32; - - if (iv_img_size < sizeof(iv->iv_val.val32)) { - if_printf(ifp, "invalid IV image, val32\n"); - return EINVAL; - } - iv_img_size -= sizeof(iv->iv_val.val32); - sz += sizeof(iv->iv_val.val32); - - val32 = be32toh(iv->iv_val.val32); - CSR_WRITE_4(sc, ofs, val32); - } else { - uint16_t val16; - - if (iv_img_size < sizeof(iv->iv_val.val16)) { - if_printf(ifp, "invalid IV image, val16\n"); - return EINVAL; - } - iv_img_size -= sizeof(iv->iv_val.val16); - sz += sizeof(iv->iv_val.val16); - - val16 = be16toh(iv->iv_val.val16); - CSR_WRITE_2(sc, ofs, val16); - } - - iv = (const struct bwi_fw_iv *)((const uint8_t *)iv + sz); - } - - if (iv_img_size != 0) { - if_printf(ifp, "invalid IV image, size left %d\n", iv_img_size); - return EINVAL; - } - return 0; -} - -static int -bwi_mac_fw_init(struct bwi_mac *mac) -{ - struct ifnet *ifp = &mac->mac_sc->sc_ic.ic_if; - int error; - - error = bwi_mac_fw_load_iv(mac, mac->mac_iv); - if (error) { - if_printf(ifp, "load IV failed\n"); - return error; - } - - if (mac->mac_iv_ext != NULL) { - error = bwi_mac_fw_load_iv(mac, mac->mac_iv_ext); - if (error) - if_printf(ifp, "load ExtIV failed\n"); - } - return error; -} - -static void -bwi_mac_opmode_init(struct bwi_mac *mac) -{ - struct bwi_softc *sc = mac->mac_sc; - struct ieee80211com *ic = &sc->sc_ic; - uint32_t mac_status; - uint16_t pre_tbtt; - - CSR_CLRBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_INFRA); - CSR_SETBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_INFRA); - CSR_SETBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_PASS_BCN); - - /* Set probe resp timeout to infinite */ - MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_PROBE_RESP_TO, 0); - - /* - * TODO: factor out following part - */ - - mac_status = CSR_READ_4(sc, BWI_MAC_STATUS); - mac_status &= ~(BWI_MAC_STATUS_OPMODE_HOSTAP | - BWI_MAC_STATUS_PASS_CTL | - BWI_MAC_STATUS_PASS_BADPLCP | - BWI_MAC_STATUS_PASS_BADFCS | - BWI_MAC_STATUS_PROMISC); - mac_status |= BWI_MAC_STATUS_INFRA; - - /* Always turn on PROMISC on old hardware */ - if (mac->mac_rev < 5) - mac_status |= BWI_MAC_STATUS_PROMISC; - - switch (ic->ic_opmode) { - case IEEE80211_M_IBSS: - mac_status &= ~BWI_MAC_STATUS_INFRA; - break; - case IEEE80211_M_HOSTAP: - mac_status |= BWI_MAC_STATUS_OPMODE_HOSTAP; - break; - case IEEE80211_M_MONITOR: -#if 0 - /* Do you want data from your microwave oven? */ - mac_status |= BWI_MAC_STATUS_PASS_CTL | - BWI_MAC_STATUS_PASS_BADPLCP | - BWI_MAC_STATUS_PASS_BADFCS; -#else - mac_status |= BWI_MAC_STATUS_PASS_CTL; -#endif - /* Promisc? */ - break; - default: - break; - } - - if (ic->ic_if.if_flags & IFF_PROMISC) - mac_status |= BWI_MAC_STATUS_PROMISC; - - CSR_WRITE_4(sc, BWI_MAC_STATUS, mac_status); - - if (ic->ic_opmode != IEEE80211_M_IBSS && - ic->ic_opmode != IEEE80211_M_HOSTAP) { - if (sc->sc_bbp_id == BWI_BBPID_BCM4306 && sc->sc_bbp_rev == 3) - pre_tbtt = 100; - else - pre_tbtt = 50; - } else { - pre_tbtt = 2; - } - CSR_WRITE_2(sc, BWI_MAC_PRE_TBTT, pre_tbtt); -} - -static void -bwi_mac_hostflags_init(struct bwi_mac *mac) -{ - struct bwi_softc *sc = mac->mac_sc; - struct bwi_phy *phy = &mac->mac_phy; - struct bwi_rf *rf = &mac->mac_rf; - uint64_t host_flags; - - if (phy->phy_mode == IEEE80211_MODE_11A) - return; - - host_flags = HFLAGS_READ(mac); - host_flags |= BWI_HFLAG_SYM_WA; - - if (phy->phy_mode == IEEE80211_MODE_11G) { - if (phy->phy_rev == 1) - host_flags |= BWI_HFLAG_GDC_WA; - if (sc->sc_card_flags & BWI_CARD_F_PA_GPIO9) - host_flags |= BWI_HFLAG_OFDM_PA; - } else if (phy->phy_mode == IEEE80211_MODE_11B) { - if (phy->phy_rev >= 2 && rf->rf_type == BWI_RF_T_BCM2050) - host_flags &= ~BWI_HFLAG_GDC_WA; - } else { - panic("unknown PHY mode %u", phy->phy_mode); - } - - HFLAGS_WRITE(mac, host_flags); -} - -static void -bwi_mac_bss_param_init(struct bwi_mac *mac) -{ - struct bwi_softc *sc = mac->mac_sc; - struct bwi_phy *phy = &mac->mac_phy; - struct bwi_retry_lim lim; - uint16_t cw_min; - - /* - * Set short/long retry limits - */ - bzero(&lim, sizeof(lim)); - lim.shretry = BWI_SHRETRY; - lim.shretry_fb = BWI_SHRETRY_FB; - lim.lgretry = BWI_LGRETRY; - lim.lgretry_fb = BWI_LGRETRY_FB; - bwi_mac_set_retry_lim(mac, &lim); - - /* - * Implicitly prevent firmware from sending probe response - * by setting its "probe response timeout" to 1us. - */ - MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_PROBE_RESP_TO, 1); - - /* - * XXX MAC level acknowledge and CW min/max should depend - * on the char rateset of the IBSS/BSS to join. - */ - - /* - * Set MAC level acknowledge rates - */ - bwi_mac_set_ackrates(mac, &sc->sc_ic.ic_sup_rates[phy->phy_mode]); - - /* - * Set CW min - */ - if (phy->phy_mode == IEEE80211_MODE_11B) - cw_min = IEEE80211_CW_MIN_0; - else - cw_min = IEEE80211_CW_MIN_1; - MOBJ_WRITE_2(mac, BWI_80211_MOBJ, BWI_80211_MOBJ_CWMIN, cw_min); - - /* - * Set CW max - */ - MOBJ_WRITE_2(mac, BWI_80211_MOBJ, BWI_80211_MOBJ_CWMAX, - IEEE80211_CW_MAX); -} - -static void -bwi_mac_set_retry_lim(struct bwi_mac *mac, const struct bwi_retry_lim *lim) -{ - /* Short/Long retry limit */ - MOBJ_WRITE_2(mac, BWI_80211_MOBJ, BWI_80211_MOBJ_SHRETRY, - lim->shretry); - MOBJ_WRITE_2(mac, BWI_80211_MOBJ, BWI_80211_MOBJ_LGRETRY, - lim->lgretry); - - /* Short/Long retry fallback limit */ - MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_SHRETRY_FB, - lim->shretry_fb); - MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_LGRETEY_FB, - lim->lgretry_fb); -} - -static void -bwi_mac_set_ackrates(struct bwi_mac *mac, const struct ieee80211_rateset *rs) -{ - int i; - - /* XXX not standard conforming */ - for (i = 0; i < rs->rs_nrates; ++i) { - enum ieee80211_modtype modtype; - uint16_t ofs; - - modtype = ieee80211_rate2modtype(rs->rs_rates[i]); - switch (modtype) { - case IEEE80211_MODTYPE_DS: - ofs = 0x4c0; - break; - case IEEE80211_MODTYPE_OFDM: - ofs = 0x480; - break; - default: - panic("unsupported modtype %u", modtype); - } - ofs += (bwi_rate2plcp(rs->rs_rates[i]) & 0xf) * 2; - - MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, ofs + 0x20, - MOBJ_READ_2(mac, BWI_COMM_MOBJ, ofs)); - } -} - -int -bwi_mac_start(struct bwi_mac *mac) -{ - struct bwi_softc *sc = mac->mac_sc; - - CSR_SETBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_ENABLE); - CSR_WRITE_4(sc, BWI_MAC_INTR_STATUS, BWI_INTR_READY); - - /* Flush pending bus writes */ - CSR_READ_4(sc, BWI_MAC_STATUS); - CSR_READ_4(sc, BWI_MAC_INTR_STATUS); - - return bwi_mac_config_ps(mac); -} - -int -bwi_mac_stop(struct bwi_mac *mac) -{ - struct bwi_softc *sc = mac->mac_sc; - int error, i; - - error = bwi_mac_config_ps(mac); - if (error) - return error; - - CSR_CLRBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_ENABLE); - - /* Flush pending bus write */ - CSR_READ_4(sc, BWI_MAC_STATUS); - -#define NRETRY 10000 - for (i = 0; i < NRETRY; ++i) { - if (CSR_READ_4(sc, BWI_MAC_INTR_STATUS) & BWI_INTR_READY) - break; - DELAY(1); - } - if (i == NRETRY) { - if_printf(&sc->sc_ic.ic_if, "can't stop MAC\n"); - return ETIMEDOUT; - } -#undef NRETRY - - return 0; -} - -int -bwi_mac_config_ps(struct bwi_mac *mac) -{ - struct bwi_softc *sc = mac->mac_sc; - uint32_t status; - - status = CSR_READ_4(sc, BWI_MAC_STATUS); - - status &= ~BWI_MAC_STATUS_HW_PS; - status |= BWI_MAC_STATUS_WAKEUP; - CSR_WRITE_4(sc, BWI_MAC_STATUS, status); - - /* Flush pending bus write */ - CSR_READ_4(sc, BWI_MAC_STATUS); - - if (mac->mac_rev >= 5) { - int i; - -#define NRETRY 100 - for (i = 0; i < NRETRY; ++i) { - if (MOBJ_READ_2(mac, BWI_COMM_MOBJ, - BWI_COMM_MOBJ_UCODE_STATE) != BWI_UCODE_STATE_PS) - break; - DELAY(10); - } - if (i == NRETRY) { - if_printf(&sc->sc_ic.ic_if, "config PS failed\n"); - return ETIMEDOUT; - } -#undef NRETRY - } - return 0; -} - -void -bwi_mac_reset_hwkeys(struct bwi_mac *mac) -{ - /* TODO: firmware crypto */ - MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_KEYTABLE_OFS); -} - -void -bwi_mac_shutdown(struct bwi_mac *mac) -{ - struct bwi_softc *sc = mac->mac_sc; - int i; - - if (mac->mac_flags & BWI_MAC_F_HAS_TXSTATS) - sc->sc_free_txstats(sc); - - sc->sc_free_rx_ring(sc); - - for (i = 0; i < BWI_TX_NRING; ++i) - sc->sc_free_tx_ring(sc, i); - - bwi_rf_off(mac); - - /* TODO:LED */ - - bwi_mac_gpio_fini(mac); - - bwi_rf_off(mac); /* XXX again */ - CSR_WRITE_2(sc, BWI_BBP_ATTEN, BWI_BBP_ATTEN_MAGIC); - bwi_regwin_disable(sc, &mac->mac_regwin, 0); - - mac->mac_flags &= ~BWI_MAC_F_INITED; -} - -static int -bwi_mac_get_property(struct bwi_mac *mac) -{ - struct bwi_softc *sc = mac->mac_sc; - enum bwi_bus_space old_bus_space; - uint32_t val; - - /* - * Byte swap - */ - val = CSR_READ_4(sc, BWI_MAC_STATUS); - if (val & BWI_MAC_STATUS_BSWAP) { - DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_ATTACH, "%s\n", - "need byte swap"); - mac->mac_flags |= BWI_MAC_F_BSWAP; - } - - /* - * DMA address space - */ - old_bus_space = sc->sc_bus_space; - - val = CSR_READ_4(sc, BWI_STATE_HI); - if (__SHIFTOUT(val, BWI_STATE_HI_FLAGS_MASK) & - BWI_STATE_HI_FLAG_64BIT) { - /* 64bit address */ - sc->sc_bus_space = BWI_BUS_SPACE_64BIT; - DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_ATTACH, "%s\n", - "64bit bus space"); - } else { - uint32_t txrx_reg = BWI_TXRX_CTRL_BASE + BWI_TX32_CTRL; - - CSR_WRITE_4(sc, txrx_reg, BWI_TXRX32_CTRL_ADDRHI_MASK); - if (CSR_READ_4(sc, txrx_reg) & BWI_TXRX32_CTRL_ADDRHI_MASK) { - /* 32bit address */ - sc->sc_bus_space = BWI_BUS_SPACE_32BIT; - DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_ATTACH, "%s\n", - "32bit bus space"); - } else { - /* 30bit address */ - sc->sc_bus_space = BWI_BUS_SPACE_30BIT; - DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_ATTACH, "%s\n", - "30bit bus space"); - } - } - - if (old_bus_space != 0 && old_bus_space != sc->sc_bus_space) { - device_printf(sc->sc_dev, "MACs bus space mismatch!\n"); - return ENXIO; - } - return 0; -} - -void -bwi_mac_updateslot(struct bwi_mac *mac, int shslot) -{ - uint16_t slot_time; - - if (mac->mac_phy.phy_mode == IEEE80211_MODE_11B) - return; - - if (shslot) - slot_time = IEEE80211_DUR_SHSLOT; - else - slot_time = IEEE80211_DUR_SLOT; - - CSR_WRITE_2(mac->mac_sc, BWI_MAC_SLOTTIME, - slot_time + BWI_MAC_SLOTTIME_ADJUST); - MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_SLOTTIME, slot_time); -} - -int -bwi_mac_attach(struct bwi_softc *sc, int id, uint8_t rev) -{ - struct bwi_mac *mac; - int i; - - KKASSERT(sc->sc_nmac <= BWI_MAC_MAX && sc->sc_nmac >= 0); - - if (sc->sc_nmac == BWI_MAC_MAX) { - device_printf(sc->sc_dev, "too many MACs\n"); - return 0; - } - - /* - * More than one MAC is only supported by BCM4309 - */ - if (sc->sc_nmac != 0 && - pci_get_device(sc->sc_dev) != PCI_PRODUCT_BROADCOM_BCM4309) { - DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_ATTACH, "%s\n", - "ignore second MAC"); - return 0; - } - - mac = &sc->sc_mac[sc->sc_nmac]; - - /* XXX will this happen? */ - if (BWI_REGWIN_EXIST(&mac->mac_regwin)) { - device_printf(sc->sc_dev, "%dth MAC already attached\n", - sc->sc_nmac); - return 0; - } - - /* - * Test whether the revision of this MAC is supported - */ - for (i = 0; i < NELEM(bwi_sup_macrev); ++i) { - if (bwi_sup_macrev[i] == rev) - break; - } - if (i == NELEM(bwi_sup_macrev)) { - device_printf(sc->sc_dev, "MAC rev %u is " - "not supported\n", rev); - return ENXIO; - } - - BWI_CREATE_MAC(mac, sc, id, rev); - sc->sc_nmac++; - - if (mac->mac_rev < 5) { - mac->mac_flags |= BWI_MAC_F_HAS_TXSTATS; - DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_ATTACH, "%s\n", - "has TX stats"); - } else { - mac->mac_flags |= BWI_MAC_F_PHYE_RESET; - } - - device_printf(sc->sc_dev, "MAC: rev %u\n", rev); - return 0; -} - -static __inline void -bwi_mac_balance_atten(int *bbp_atten0, int *rf_atten0) -{ - int bbp_atten, rf_atten, rf_atten_lim = -1; - - bbp_atten = *bbp_atten0; - rf_atten = *rf_atten0; - - /* - * RF attenuation affects TX power BWI_RF_ATTEN_FACTOR times - * as much as BBP attenuation, so we try our best to keep RF - * attenuation within range. BBP attenuation will be clamped - * later if it is out of range during balancing. - * - * BWI_RF_ATTEN_MAX0 is used as RF attenuation upper limit. - */ - - /* - * Use BBP attenuation to balance RF attenuation - */ - if (rf_atten < 0) - rf_atten_lim = 0; - else if (rf_atten > BWI_RF_ATTEN_MAX0) - rf_atten_lim = BWI_RF_ATTEN_MAX0; - - if (rf_atten_lim >= 0) { - bbp_atten += (BWI_RF_ATTEN_FACTOR * (rf_atten - rf_atten_lim)); - rf_atten = rf_atten_lim; - } - - /* - * If possible, use RF attenuation to balance BBP attenuation - * NOTE: RF attenuation is still kept within range. - */ - while (rf_atten < BWI_RF_ATTEN_MAX0 && bbp_atten > BWI_BBP_ATTEN_MAX) { - bbp_atten -= BWI_RF_ATTEN_FACTOR; - ++rf_atten; - } - while (rf_atten > 0 && bbp_atten < 0) { - bbp_atten += BWI_RF_ATTEN_FACTOR; - --rf_atten; - } - - /* RF attenuation MUST be within range */ - KKASSERT(rf_atten >= 0 && rf_atten <= BWI_RF_ATTEN_MAX0); - - /* - * Clamp BBP attenuation - */ - if (bbp_atten < 0) - bbp_atten = 0; - else if (bbp_atten > BWI_BBP_ATTEN_MAX) - bbp_atten = BWI_BBP_ATTEN_MAX; - - *rf_atten0 = rf_atten; - *bbp_atten0 = bbp_atten; -} - -static void -bwi_mac_adjust_tpctl(struct bwi_mac *mac, int rf_atten_adj, int bbp_atten_adj) -{ - struct bwi_softc *sc = mac->mac_sc; - struct bwi_rf *rf = &mac->mac_rf; - struct bwi_tpctl tpctl; - int bbp_atten, rf_atten, tp_ctrl1; - - bcopy(&mac->mac_tpctl, &tpctl, sizeof(tpctl)); - - /* NOTE: Use signed value to do calulation */ - bbp_atten = tpctl.bbp_atten; - rf_atten = tpctl.rf_atten; - tp_ctrl1 = tpctl.tp_ctrl1; - - bbp_atten += bbp_atten_adj; - rf_atten += rf_atten_adj; - - bwi_mac_balance_atten(&bbp_atten, &rf_atten); - - if (rf->rf_type == BWI_RF_T_BCM2050 && rf->rf_rev == 2) { - if (rf_atten <= 1) { - if (tp_ctrl1 == 0) { - tp_ctrl1 = 3; - bbp_atten += 2; - rf_atten += 2; - } else if (sc->sc_card_flags & BWI_CARD_F_PA_GPIO9) { - bbp_atten += - (BWI_RF_ATTEN_FACTOR * (rf_atten - 2)); - rf_atten = 2; - } - } else if (rf_atten > 4 && tp_ctrl1 != 0) { - tp_ctrl1 = 0; - if (bbp_atten < 3) { - bbp_atten += 2; - rf_atten -= 3; - } else { - bbp_atten -= 2; - rf_atten -= 2; - } - } - bwi_mac_balance_atten(&bbp_atten, &rf_atten); - } - - tpctl.bbp_atten = bbp_atten; - tpctl.rf_atten = rf_atten; - tpctl.tp_ctrl1 = tp_ctrl1; - - bwi_mac_lock(mac); - bwi_mac_set_tpctl_11bg(mac, &tpctl); - bwi_mac_unlock(mac); -} - -/* - * http://bcm-specs.sipsolutions.net/RecalculateTransmissionPower - */ -void -bwi_mac_calibrate_txpower(struct bwi_mac *mac, enum bwi_txpwrcb_type type) -{ - struct bwi_softc *sc = mac->mac_sc; - struct bwi_rf *rf = &mac->mac_rf; - int8_t tssi[4], tssi_avg, cur_txpwr; - int error, i, ofdm_tssi; - int txpwr_diff, rf_atten_adj, bbp_atten_adj; - - if (!sc->sc_txpwr_calib) - return; - - if (mac->mac_flags & BWI_MAC_F_TPCTL_ERROR) { - DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_TXPOWER, "%s\n", - "tpctl error happened, can't set txpower"); - return; - } - - if (BWI_IS_BRCM_BU4306(sc)) { - DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_TXPOWER, "%s\n", - "BU4306, can't set txpower"); - return; - } - - /* - * Save latest TSSI and reset the related memory objects - */ - ofdm_tssi = 0; - error = bwi_rf_get_latest_tssi(mac, tssi, BWI_COMM_MOBJ_TSSI_DS); - if (error) { - DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_TXPOWER, "%s\n", - "no DS tssi"); - - if (mac->mac_phy.phy_mode == IEEE80211_MODE_11B) { - if (type == BWI_TXPWR_FORCE) { - rf_atten_adj = 0; - bbp_atten_adj = 1; - goto calib; - } else { - return; - } - } - - error = bwi_rf_get_latest_tssi(mac, tssi, - BWI_COMM_MOBJ_TSSI_OFDM); - if (error) { - DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_TXPOWER, "%s\n", - "no OFDM tssi"); - if (type == BWI_TXPWR_FORCE) { - rf_atten_adj = 0; - bbp_atten_adj = 1; - goto calib; - } else { - return; - } - } - - for (i = 0; i < 4; ++i) { - tssi[i] += 0x20; - tssi[i] &= 0x3f; - } - ofdm_tssi = 1; - } - bwi_rf_clear_tssi(mac); - - DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_TXPOWER, - "tssi0 %d, tssi1 %d, tssi2 %d, tssi3 %d\n", - tssi[0], tssi[1], tssi[2], tssi[3]); - - /* - * Calculate RF/BBP attenuation adjustment based on - * the difference between desired TX power and sampled - * TX power. - */ - /* +8 == "each incremented by 1/2" */ - tssi_avg = (tssi[0] + tssi[1] + tssi[2] + tssi[3] + 8) / 4; - if (ofdm_tssi && (HFLAGS_READ(mac) & BWI_HFLAG_PWR_BOOST_DS)) - tssi_avg -= 13; - - DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_TXPOWER, "tssi avg %d\n", tssi_avg); - - error = bwi_rf_tssi2dbm(mac, tssi_avg, &cur_txpwr); - if (error) - return; - DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_TXPOWER, "current txpower %d\n", - cur_txpwr); - - txpwr_diff = rf->rf_txpower_max - cur_txpwr; /* XXX ni_txpower */ - - rf_atten_adj = -howmany(txpwr_diff, 8); - if (type == BWI_TXPWR_INIT) { - /* - * Move toward EEPROM max TX power as fast as we can - */ - bbp_atten_adj = -txpwr_diff; - } else { - bbp_atten_adj = -(txpwr_diff / 2); - } - bbp_atten_adj -= (BWI_RF_ATTEN_FACTOR * rf_atten_adj); - - if (rf_atten_adj == 0 && bbp_atten_adj == 0) { - DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_TXPOWER, "%s\n", - "no need to adjust RF/BBP attenuation"); - /* TODO: LO */ - return; - } - -calib: - DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_TXPOWER, - "rf atten adjust %d, bbp atten adjust %d\n", - rf_atten_adj, bbp_atten_adj); - bwi_mac_adjust_tpctl(mac, rf_atten_adj, bbp_atten_adj); - /* TODO: LO */ -} - -static void -bwi_mac_lock(struct bwi_mac *mac) -{ - struct bwi_softc *sc = mac->mac_sc; - struct ieee80211com *ic = &sc->sc_ic; - - KKASSERT((mac->mac_flags & BWI_MAC_F_LOCKED) == 0); - - if (mac->mac_rev < 3) - bwi_mac_stop(mac); - else if (ic->ic_opmode != IEEE80211_M_HOSTAP) - bwi_mac_config_ps(mac); - - CSR_SETBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_RFLOCK); - - /* Flush pending bus write */ - CSR_READ_4(sc, BWI_MAC_STATUS); - DELAY(10); - - mac->mac_flags |= BWI_MAC_F_LOCKED; -} - -static void -bwi_mac_unlock(struct bwi_mac *mac) -{ - struct bwi_softc *sc = mac->mac_sc; - struct ieee80211com *ic = &sc->sc_ic; - - KKASSERT(mac->mac_flags & BWI_MAC_F_LOCKED); - - CSR_READ_2(sc, BWI_PHYINFO); /* dummy read */ - - CSR_CLRBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_RFLOCK); - - if (mac->mac_rev < 3) - bwi_mac_start(mac); - else if (ic->ic_opmode != IEEE80211_M_HOSTAP) - bwi_mac_config_ps(mac); - - mac->mac_flags &= ~BWI_MAC_F_LOCKED; -} - -void -bwi_mac_set_promisc(struct bwi_mac *mac, int promisc) -{ - struct bwi_softc *sc = mac->mac_sc; - - if (mac->mac_rev < 5) /* Promisc is always on */ - return; - - if (promisc) - CSR_SETBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_PROMISC); - else - CSR_CLRBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_PROMISC); -} diff --git a/sys/dev/netif/bwi/bwimac.h b/sys/dev/netif/bwi/bwimac.h deleted file mode 100644 index 73add905f7..0000000000 --- a/sys/dev/netif/bwi/bwimac.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2007 The DragonFly Project. All rights reserved. - * - * This code is derived from software contributed to The DragonFly Project - * by Sepherosa Ziehau - * - * 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. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * 3. Neither the name of The DragonFly Project nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific, prior written permission. - * - * 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 MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, 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 DAMAGE. - * - * $DragonFly: src/sys/dev/netif/bwi/bwimac.h,v 1.2 2008/02/15 11:15:38 sephe Exp $ - */ - -#ifndef _BWI_MAC_H -#define _BWI_MAC_H - -int bwi_mac_attach(struct bwi_softc *, int, uint8_t); -int bwi_mac_lateattach(struct bwi_mac *); -void bwi_mac_detach(struct bwi_mac *); -int bwi_mac_init(struct bwi_mac *); -void bwi_mac_reset(struct bwi_mac *, int); -int bwi_mac_start(struct bwi_mac *); -int bwi_mac_stop(struct bwi_mac *); -void bwi_mac_shutdown(struct bwi_mac *); -void bwi_mac_updateslot(struct bwi_mac *, int); -void bwi_mac_set_promisc(struct bwi_mac *, int); - -void bwi_mac_calibrate_txpower(struct bwi_mac *, - enum bwi_txpwrcb_type); -void bwi_mac_set_tpctl_11bg(struct bwi_mac *, - const struct bwi_tpctl *); -void bwi_mac_init_tpctl_11bg(struct bwi_mac *); -void bwi_mac_dummy_xmit(struct bwi_mac *); -void bwi_mac_reset_hwkeys(struct bwi_mac *); -int bwi_mac_config_ps(struct bwi_mac *); - -uint16_t bwi_memobj_read_2(struct bwi_mac *, uint16_t, uint16_t); -uint32_t bwi_memobj_read_4(struct bwi_mac *, uint16_t, uint16_t); -void bwi_memobj_write_2(struct bwi_mac *, uint16_t, uint16_t, - uint16_t); -void bwi_memobj_write_4(struct bwi_mac *, uint16_t, uint16_t, - uint32_t); -void bwi_tmplt_write_4(struct bwi_mac *, uint32_t, uint32_t); -void bwi_hostflags_write(struct bwi_mac *, uint64_t); -uint64_t bwi_hostflags_read(struct bwi_mac *); - -#define MOBJ_WRITE_2(mac, objid, ofs, val) \ - bwi_memobj_write_2((mac), (objid), (ofs), (val)) -#define MOBJ_WRITE_4(mac, objid, ofs, val) \ - bwi_memobj_write_4((mac), (objid), (ofs), (val)) -#define MOBJ_READ_2(mac, objid, ofs) \ - bwi_memobj_read_2((mac), (objid), (ofs)) -#define MOBJ_READ_4(mac, objid, ofs) \ - bwi_memobj_read_4((mac), (objid), (ofs)) - -#define MOBJ_SETBITS_4(mac, objid, ofs, bits) \ - MOBJ_WRITE_4((mac), (objid), (ofs), \ - MOBJ_READ_4((mac), (objid), (ofs)) | (bits)) -#define MOBJ_CLRBITS_4(mac, objid, ofs, bits) \ - MOBJ_WRITE_4((mac), (objid), (ofs), \ - MOBJ_READ_4((mac), (objid), (ofs)) & ~(bits)) - -#define MOBJ_FILT_SETBITS_2(mac, objid, ofs, filt, bits) \ - MOBJ_WRITE_2((mac), (objid), (ofs), \ - (MOBJ_READ_2((mac), (objid), (ofs)) & (filt)) | (bits)) - -#define TMPLT_WRITE_4(mac, ofs, val) bwi_tmplt_write_4((mac), (ofs), (val)) - -#define HFLAGS_WRITE(mac, flags) bwi_hostflags_write((mac), (flags)) -#define HFLAGS_READ(mac) bwi_hostflags_read((mac)) -#define HFLAGS_CLRBITS(mac, bits) \ - HFLAGS_WRITE((mac), HFLAGS_READ((mac)) | (bits)) -#define HFLAGS_SETBITS(mac, bits) \ - HFLAGS_WRITE((mac), HFLAGS_READ((mac)) & ~(bits)) - -#endif /* !_BWI_MAC_H */ diff --git a/sys/dev/netif/bwi/bwiphy.c b/sys/dev/netif/bwi/bwiphy.c deleted file mode 100644 index 46fee66096..0000000000 --- a/sys/dev/netif/bwi/bwiphy.c +++ /dev/null @@ -1,1003 +0,0 @@ -/* - * Copyright (c) 2007 The DragonFly Project. All rights reserved. - * - * This code is derived from software contributed to The DragonFly Project - * by Sepherosa Ziehau - * - * 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. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * 3. Neither the name of The DragonFly Project nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific, prior written permission. - * - * 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 MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, 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 DAMAGE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include "pcidevs.h" - -#include -#include -#include -#include -#include - -static void bwi_phy_init_11a(struct bwi_mac *); -static void bwi_phy_init_11g(struct bwi_mac *); -static void bwi_phy_init_11b_rev2(struct bwi_mac *); -static void bwi_phy_init_11b_rev4(struct bwi_mac *); -static void bwi_phy_init_11b_rev5(struct bwi_mac *); -static void bwi_phy_init_11b_rev6(struct bwi_mac *); - -static void bwi_phy_config_11g(struct bwi_mac *); -static void bwi_phy_config_agc(struct bwi_mac *); - -static void bwi_tbl_write_2(struct bwi_mac *mac, uint16_t, uint16_t); -static void bwi_tbl_write_4(struct bwi_mac *mac, uint16_t, uint32_t); - -#define SUP_BPHY(num) { .rev = num, .init = bwi_phy_init_11b_rev##num } - -static const struct { - uint8_t rev; - void (*init)(struct bwi_mac *); -} bwi_sup_bphy[] = { - SUP_BPHY(2), - SUP_BPHY(4), - SUP_BPHY(5), - SUP_BPHY(6) -}; - -#undef SUP_BPHY - -#define BWI_PHYTBL_WRSSI 0x1000 -#define BWI_PHYTBL_NOISE_SCALE 0x1400 -#define BWI_PHYTBL_NOISE 0x1800 -#define BWI_PHYTBL_ROTOR 0x2000 -#define BWI_PHYTBL_DELAY 0x2400 -#define BWI_PHYTBL_RSSI 0x4000 -#define BWI_PHYTBL_SIGMA_SQ 0x5000 -#define BWI_PHYTBL_WRSSI_REV1 0x5400 -#define BWI_PHYTBL_FREQ 0x5800 - -static const uint16_t bwi_phy_freq_11g_rev1[] = - { BWI_PHY_FREQ_11G_REV1 }; -static const uint16_t bwi_phy_noise_11g_rev1[] = - { BWI_PHY_NOISE_11G_REV1 }; -static const uint16_t bwi_phy_noise_11g[] = - { BWI_PHY_NOISE_11G }; -static const uint32_t bwi_phy_rotor_11g_rev1[] = - { BWI_PHY_ROTOR_11G_REV1 }; -static const uint16_t bwi_phy_noise_scale_11g_rev2[] = - { BWI_PHY_NOISE_SCALE_11G_REV2 }; -static const uint16_t bwi_phy_noise_scale_11g_rev7[] = - { BWI_PHY_NOISE_SCALE_11G_REV7 }; -static const uint16_t bwi_phy_noise_scale_11g[] = - { BWI_PHY_NOISE_SCALE_11G }; -static const uint16_t bwi_phy_sigma_sq_11g_rev2[] = - { BWI_PHY_SIGMA_SQ_11G_REV2 }; -static const uint16_t bwi_phy_sigma_sq_11g_rev7[] = - { BWI_PHY_SIGMA_SQ_11G_REV7 }; -static const uint32_t bwi_phy_delay_11g_rev1[] = - { BWI_PHY_DELAY_11G_REV1 }; - -void -bwi_phy_write(struct bwi_mac *mac, uint16_t ctrl, uint16_t data) -{ - struct bwi_softc *sc = mac->mac_sc; - - /* TODO: 11A */ - CSR_WRITE_2(sc, BWI_PHY_CTRL, ctrl); - CSR_WRITE_2(sc, BWI_PHY_DATA, data); -} - -uint16_t -bwi_phy_read(struct bwi_mac *mac, uint16_t ctrl) -{ - struct bwi_softc *sc = mac->mac_sc; - - /* TODO: 11A */ - CSR_WRITE_2(sc, BWI_PHY_CTRL, ctrl); - return CSR_READ_2(sc, BWI_PHY_DATA); -} - -int -bwi_phy_attach(struct bwi_mac *mac) -{ - struct bwi_softc *sc = mac->mac_sc; - struct bwi_phy *phy = &mac->mac_phy; - uint8_t phyrev, phytype, phyver; - uint16_t val; - int i; - - /* Get PHY type/revision/version */ - val = CSR_READ_2(sc, BWI_PHYINFO); - phyrev = __SHIFTOUT(val, BWI_PHYINFO_REV_MASK); - phytype = __SHIFTOUT(val, BWI_PHYINFO_TYPE_MASK); - phyver = __SHIFTOUT(val, BWI_PHYINFO_VER_MASK); - device_printf(sc->sc_dev, "PHY: type %d, rev %d, ver %d\n", - phytype, phyrev, phyver); - - /* - * Verify whether the revision of the PHY type is supported - * Convert PHY type to ieee80211_phymode - */ - switch (phytype) { - case BWI_PHYINFO_TYPE_11A: - if (phyrev >= 4) { - device_printf(sc->sc_dev, "unsupported 11A PHY, " - "rev %u\n", phyrev); - return ENXIO; - } - phy->phy_init = bwi_phy_init_11a; - phy->phy_mode = IEEE80211_MODE_11A; - phy->phy_tbl_ctrl = BWI_PHYR_TBL_CTRL_11A; - phy->phy_tbl_data_lo = BWI_PHYR_TBL_DATA_LO_11A; - phy->phy_tbl_data_hi = BWI_PHYR_TBL_DATA_HI_11A; - break; - case BWI_PHYINFO_TYPE_11B: - for (i = 0; i < NELEM(bwi_sup_bphy); ++i) { - if (phyrev == bwi_sup_bphy[i].rev) { - phy->phy_init = bwi_sup_bphy[i].init; - break; - } - } - if (i == NELEM(bwi_sup_bphy)) { - device_printf(sc->sc_dev, "unsupported 11B PHY, " - "rev %u\n", phyrev); - return ENXIO; - } - phy->phy_mode = IEEE80211_MODE_11B; - break; - case BWI_PHYINFO_TYPE_11G: - if (phyrev > 8) { - device_printf(sc->sc_dev, "unsupported 11G PHY, " - "rev %u\n", phyrev); - return ENXIO; - } - phy->phy_init = bwi_phy_init_11g; - phy->phy_mode = IEEE80211_MODE_11G; - phy->phy_tbl_ctrl = BWI_PHYR_TBL_CTRL_11G; - phy->phy_tbl_data_lo = BWI_PHYR_TBL_DATA_LO_11G; - phy->phy_tbl_data_hi = BWI_PHYR_TBL_DATA_HI_11G; - break; - default: - device_printf(sc->sc_dev, "unsupported PHY type %d\n", - phytype); - return ENXIO; - } - phy->phy_rev = phyrev; - phy->phy_version = phyver; - return 0; -} - -void -bwi_phy_set_bbp_atten(struct bwi_mac *mac, uint16_t bbp_atten) -{ - struct bwi_phy *phy = &mac->mac_phy; - uint16_t mask = __BITS(3, 0); - - if (phy->phy_version == 0) { - CSR_FILT_SETBITS_2(mac->mac_sc, BWI_BBP_ATTEN, ~mask, - __SHIFTIN(bbp_atten, mask)); - } else { - if (phy->phy_version > 1) - mask <<= 2; - else - mask <<= 3; - PHY_FILT_SETBITS(mac, BWI_PHYR_BBP_ATTEN, ~mask, - __SHIFTIN(bbp_atten, mask)); - } -} - -int -bwi_phy_calibrate(struct bwi_mac *mac) -{ - struct bwi_phy *phy = &mac->mac_phy; - - /* Dummy read */ - CSR_READ_4(mac->mac_sc, BWI_MAC_STATUS); - - /* Don't re-init */ - if (phy->phy_flags & BWI_PHY_F_CALIBRATED) - return 0; - - if (phy->phy_mode == IEEE80211_MODE_11G && phy->phy_rev == 1) { - bwi_mac_reset(mac, 0); - bwi_phy_init_11g(mac); - bwi_mac_reset(mac, 1); - } - - phy->phy_flags |= BWI_PHY_F_CALIBRATED; - return 0; -} - -static void -bwi_tbl_write_2(struct bwi_mac *mac, uint16_t ofs, uint16_t data) -{ - struct bwi_phy *phy = &mac->mac_phy; - - KKASSERT(phy->phy_tbl_ctrl != 0 && phy->phy_tbl_data_lo != 0); - PHY_WRITE(mac, phy->phy_tbl_ctrl, ofs); - PHY_WRITE(mac, phy->phy_tbl_data_lo, data); -} - -static void -bwi_tbl_write_4(struct bwi_mac *mac, uint16_t ofs, uint32_t data) -{ - struct bwi_phy *phy = &mac->mac_phy; - - KKASSERT(phy->phy_tbl_data_lo != 0 && phy->phy_tbl_data_hi != 0 && - phy->phy_tbl_ctrl != 0); - - PHY_WRITE(mac, phy->phy_tbl_ctrl, ofs); - PHY_WRITE(mac, phy->phy_tbl_data_hi, data >> 16); - PHY_WRITE(mac, phy->phy_tbl_data_lo, data & 0xffff); -} - -void -bwi_nrssi_write(struct bwi_mac *mac, uint16_t ofs, int16_t data) -{ - PHY_WRITE(mac, BWI_PHYR_NRSSI_CTRL, ofs); - PHY_WRITE(mac, BWI_PHYR_NRSSI_DATA, (uint16_t)data); -} - -int16_t -bwi_nrssi_read(struct bwi_mac *mac, uint16_t ofs) -{ - PHY_WRITE(mac, BWI_PHYR_NRSSI_CTRL, ofs); - return (int16_t)PHY_READ(mac, BWI_PHYR_NRSSI_DATA); -} - -static void -bwi_phy_init_11a(struct bwi_mac *mac) -{ - /* TODO:11A */ -} - -static void -bwi_phy_init_11g(struct bwi_mac *mac) -{ - struct bwi_softc *sc = mac->mac_sc; - struct bwi_phy *phy = &mac->mac_phy; - struct bwi_rf *rf = &mac->mac_rf; - const struct bwi_tpctl *tpctl = &mac->mac_tpctl; - - if (phy->phy_rev == 1) - bwi_phy_init_11b_rev5(mac); - else - bwi_phy_init_11b_rev6(mac); - - if (phy->phy_rev >= 2 || (phy->phy_flags & BWI_PHY_F_LINKED)) - bwi_phy_config_11g(mac); - - if (phy->phy_rev >= 2) { - PHY_WRITE(mac, 0x814, 0); - PHY_WRITE(mac, 0x815, 0); - - if (phy->phy_rev == 2) { - PHY_WRITE(mac, 0x811, 0); - PHY_WRITE(mac, 0x15, 0xc0); - } else if (phy->phy_rev > 5) { - PHY_WRITE(mac, 0x811, 0x400); - PHY_WRITE(mac, 0x15, 0xc0); - } - } - - if (phy->phy_rev >= 2 || (phy->phy_flags & BWI_PHY_F_LINKED)) { - uint16_t val; - - val = PHY_READ(mac, 0x400) & 0xff; - if (val == 3 || val == 5) { - PHY_WRITE(mac, 0x4c2, 0x1816); - PHY_WRITE(mac, 0x4c3, 0x8006); - if (val == 5) { - PHY_FILT_SETBITS(mac, 0x4cc, - 0xff, 0x1f00); - } - } - } - - if ((phy->phy_rev <= 2 && (phy->phy_flags & BWI_PHY_F_LINKED)) || - phy->phy_rev >= 2) - PHY_WRITE(mac, 0x47e, 0x78); - - if (rf->rf_rev == 8) { - PHY_SETBITS(mac, 0x801, 0x80); - PHY_SETBITS(mac, 0x43e, 0x4); - } - - if (phy->phy_rev >= 2 && (phy->phy_flags & BWI_PHY_F_LINKED)) - bwi_rf_get_gains(mac); - - if (rf->rf_rev != 8) - bwi_rf_init(mac); - - if (tpctl->tp_ctrl2 == 0xffff) { - bwi_rf_lo_update(mac); - } else { - if (rf->rf_type == BWI_RF_T_BCM2050 && rf->rf_rev == 8) { - RF_WRITE(mac, 0x52, - (tpctl->tp_ctrl1 << 4) | tpctl->tp_ctrl2); - } else { - RF_FILT_SETBITS(mac, 0x52, 0xfff0, tpctl->tp_ctrl1); - } - - if (phy->phy_rev >= 6) { - PHY_FILT_SETBITS(mac, 0x36, 0xfff, - tpctl->tp_ctrl2 << 12); - } - - if (sc->sc_card_flags & BWI_CARD_F_PA_GPIO9) - PHY_WRITE(mac, 0x2e, 0x8075); - else - PHY_WRITE(mac, 0x2e, 0x807f); - - if (phy->phy_rev < 2) - PHY_WRITE(mac, 0x2f, 0x101); - else - PHY_WRITE(mac, 0x2f, 0x202); - } - - if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) { - bwi_rf_lo_adjust(mac, tpctl); - PHY_WRITE(mac, 0x80f, 0x8078); - } - - if ((sc->sc_card_flags & BWI_CARD_F_SW_NRSSI) == 0) { - bwi_rf_init_hw_nrssi_table(mac, 0xffff /* XXX */); - bwi_rf_set_nrssi_thr(mac); - } else if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) { - if (rf->rf_nrssi[0] == BWI_INVALID_NRSSI) { - KKASSERT(rf->rf_nrssi[1] == BWI_INVALID_NRSSI); - bwi_rf_calc_nrssi_slope(mac); - } else { - KKASSERT(rf->rf_nrssi[1] != BWI_INVALID_NRSSI); - bwi_rf_set_nrssi_thr(mac); - } - } - - if (rf->rf_rev == 8) - PHY_WRITE(mac, 0x805, 0x3230); - - bwi_mac_init_tpctl_11bg(mac); - - if (sc->sc_bbp_id == BWI_BBPID_BCM4306 && sc->sc_bbp_pkg == 2) { - PHY_CLRBITS(mac, 0x429, 0x4000); - PHY_CLRBITS(mac, 0x4c3, 0x8000); - } -} - -static void -bwi_phy_init_11b_rev2(struct bwi_mac *mac) -{ - /* TODO:11B */ - if_printf(&mac->mac_sc->sc_ic.ic_if, - "%s is not implemented yet\n", __func__); -} - -static void -bwi_phy_init_11b_rev4(struct bwi_mac *mac) -{ - struct bwi_softc *sc = mac->mac_sc; - struct bwi_rf *rf = &mac->mac_rf; - uint16_t val, ofs; - u_int chan; - - CSR_WRITE_2(sc, BWI_BPHY_CTRL, BWI_BPHY_CTRL_INIT); - - PHY_WRITE(mac, 0x20, 0x301c); - PHY_WRITE(mac, 0x26, 0); - PHY_WRITE(mac, 0x30, 0xc6); - PHY_WRITE(mac, 0x88, 0x3e00); - - for (ofs = 0, val = 0x3c3d; ofs < 30; ++ofs, val -= 0x202) - PHY_WRITE(mac, 0x89 + ofs, val); - - CSR_WRITE_2(sc, BWI_PHY_MAGIC_REG1, BWI_PHY_MAGIC_REG1_VAL1); - - chan = rf->rf_curchan; - if (chan == IEEE80211_CHAN_ANY) - chan = 6; /* Force to channel 6 */ - bwi_rf_set_chan(mac, chan, 0); - - if (rf->rf_type != BWI_RF_T_BCM2050) { - RF_WRITE(mac, 0x75, 0x80); - RF_WRITE(mac, 0x79, 0x81); - } - - RF_WRITE(mac, 0x50, 0x20); - RF_WRITE(mac, 0x50, 0x23); - - if (rf->rf_type == BWI_RF_T_BCM2050) { - RF_WRITE(mac, 0x50, 0x20); - RF_WRITE(mac, 0x5a, 0x70); - RF_WRITE(mac, 0x5b, 0x7b); - RF_WRITE(mac, 0x5c, 0xb0); - RF_WRITE(mac, 0x7a, 0xf); - PHY_WRITE(mac, 0x38, 0x677); - bwi_rf_init_bcm2050(mac); - } - - PHY_WRITE(mac, 0x14, 0x80); - PHY_WRITE(mac, 0x32, 0xca); - if (rf->rf_type == BWI_RF_T_BCM2050) - PHY_WRITE(mac, 0x32, 0xe0); - PHY_WRITE(mac, 0x35, 0x7c2); - - bwi_rf_lo_update(mac); - - PHY_WRITE(mac, 0x26, 0xcc00); - if (rf->rf_type == BWI_RF_T_BCM2050) - PHY_WRITE(mac, 0x26, 0xce00); - - CSR_WRITE_2(sc, BWI_RF_CHAN_EX, 0x1100); - - PHY_WRITE(mac, 0x2a, 0x88a3); - if (rf->rf_type == BWI_RF_T_BCM2050) - PHY_WRITE(mac, 0x2a, 0x88c2); - - bwi_mac_set_tpctl_11bg(mac, NULL); - if (sc->sc_card_flags & BWI_CARD_F_SW_NRSSI) { - bwi_rf_calc_nrssi_slope(mac); - bwi_rf_set_nrssi_thr(mac); - } - bwi_mac_init_tpctl_11bg(mac); -} - -static void -bwi_phy_init_11b_rev5(struct bwi_mac *mac) -{ - struct bwi_softc *sc = mac->mac_sc; - struct bwi_rf *rf = &mac->mac_rf; - struct bwi_phy *phy = &mac->mac_phy; - u_int orig_chan; - - if (phy->phy_version == 1) - RF_SETBITS(mac, 0x7a, 0x50); - - if (sc->sc_pci_subvid != PCI_VENDOR_BROADCOM && - sc->sc_pci_subdid != BWI_PCI_SUBDEVICE_BU4306) { - uint16_t ofs, val; - - val = 0x2120; - for (ofs = 0xa8; ofs < 0xc7; ++ofs) { - PHY_WRITE(mac, ofs, val); - val += 0x202; - } - } - - PHY_FILT_SETBITS(mac, 0x35, 0xf0ff, 0x700); - - if (rf->rf_type == BWI_RF_T_BCM2050) - PHY_WRITE(mac, 0x38, 0x667); - - if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) { - if (rf->rf_type == BWI_RF_T_BCM2050) { - RF_SETBITS(mac, 0x7a, 0x20); - RF_SETBITS(mac, 0x51, 0x4); - } - - CSR_WRITE_2(sc, BWI_RF_ANTDIV, 0); - - PHY_SETBITS(mac, 0x802, 0x100); - PHY_SETBITS(mac, 0x42b, 0x2000); - PHY_WRITE(mac, 0x1c, 0x186a); - - PHY_FILT_SETBITS(mac, 0x13, 0xff, 0x1900); - PHY_FILT_SETBITS(mac, 0x35, 0xffc0, 0x64); - PHY_FILT_SETBITS(mac, 0x5d, 0xff80, 0xa); - } - - /* TODO: bad_frame_preempt? */ - - if (phy->phy_version == 1) { - PHY_WRITE(mac, 0x26, 0xce00); - PHY_WRITE(mac, 0x21, 0x3763); - PHY_WRITE(mac, 0x22, 0x1bc3); - PHY_WRITE(mac, 0x23, 0x6f9); - PHY_WRITE(mac, 0x24, 0x37e); - } else { - PHY_WRITE(mac, 0x26, 0xcc00); - } - PHY_WRITE(mac, 0x30, 0xc6); - - CSR_WRITE_2(sc, BWI_BPHY_CTRL, BWI_BPHY_CTRL_INIT); - - if (phy->phy_version == 1) - PHY_WRITE(mac, 0x20, 0x3e1c); - else - PHY_WRITE(mac, 0x20, 0x301c); - - if (phy->phy_version == 0) - CSR_WRITE_2(sc, BWI_PHY_MAGIC_REG1, BWI_PHY_MAGIC_REG1_VAL1); - - /* Force to channel 7 */ - orig_chan = rf->rf_curchan; - bwi_rf_set_chan(mac, 7, 0); - - if (rf->rf_type != BWI_RF_T_BCM2050) { - RF_WRITE(mac, 0x75, 0x80); - RF_WRITE(mac, 0x79, 0x81); - } - - RF_WRITE(mac, 0x50, 0x20); - RF_WRITE(mac, 0x50, 0x23); - - if (rf->rf_type == BWI_RF_T_BCM2050) { - RF_WRITE(mac, 0x50, 0x20); - RF_WRITE(mac, 0x5a, 0x70); - } - - RF_WRITE(mac, 0x5b, 0x7b); - RF_WRITE(mac, 0x5c, 0xb0); - RF_SETBITS(mac, 0x7a, 0x7); - - bwi_rf_set_chan(mac, orig_chan, 0); - - PHY_WRITE(mac, 0x14, 0x80); - PHY_WRITE(mac, 0x32, 0xca); - PHY_WRITE(mac, 0x2a, 0x88a3); - - bwi_mac_set_tpctl_11bg(mac, NULL); - - if (rf->rf_type == BWI_RF_T_BCM2050) - RF_WRITE(mac, 0x5d, 0xd); - - CSR_FILT_SETBITS_2(sc, BWI_PHY_MAGIC_REG1, 0xffc0, 0x4); -} - -static void -bwi_phy_init_11b_rev6(struct bwi_mac *mac) -{ - struct bwi_softc *sc = mac->mac_sc; - struct bwi_rf *rf = &mac->mac_rf; - struct bwi_phy *phy = &mac->mac_phy; - uint16_t val, ofs; - u_int orig_chan; - - PHY_WRITE(mac, 0x3e, 0x817a); - RF_SETBITS(mac, 0x7a, 0x58); - - if (rf->rf_rev == 4 || rf->rf_rev == 5) { - RF_WRITE(mac, 0x51, 0x37); - RF_WRITE(mac, 0x52, 0x70); - RF_WRITE(mac, 0x53, 0xb3); - RF_WRITE(mac, 0x54, 0x9b); - RF_WRITE(mac, 0x5a, 0x88); - RF_WRITE(mac, 0x5b, 0x88); - RF_WRITE(mac, 0x5d, 0x88); - RF_WRITE(mac, 0x5e, 0x88); - RF_WRITE(mac, 0x7d, 0x88); - HFLAGS_SETBITS(mac, BWI_HFLAG_MAGIC1); - } else if (rf->rf_rev == 8) { - RF_WRITE(mac, 0x51, 0); - RF_WRITE(mac, 0x52, 0x40); - RF_WRITE(mac, 0x53, 0xb7); - RF_WRITE(mac, 0x54, 0x98); - RF_WRITE(mac, 0x5a, 0x88); - RF_WRITE(mac, 0x5b, 0x6b); - RF_WRITE(mac, 0x5c, 0xf); - if (sc->sc_card_flags & BWI_CARD_F_ALT_IQ) { - RF_WRITE(mac, 0x5d, 0xfa); - RF_WRITE(mac, 0x5e, 0xd8); - } else { - RF_WRITE(mac, 0x5d, 0xf5); - RF_WRITE(mac, 0x5e, 0xb8); - } - RF_WRITE(mac, 0x73, 0x3); - RF_WRITE(mac, 0x7d, 0xa8); - RF_WRITE(mac, 0x7c, 0x1); - RF_WRITE(mac, 0x7e, 0x8); - } - - val = 0x1e1f; - for (ofs = 0x88; ofs < 0x98; ++ofs) { - PHY_WRITE(mac, ofs, val); - val -= 0x202; - } - - val = 0x3e3f; - for (ofs = 0x98; ofs < 0xa8; ++ofs) { - PHY_WRITE(mac, ofs, val); - val -= 0x202; - } - - val = 0x2120; - for (ofs = 0xa8; ofs < 0xc8; ++ofs) { - PHY_WRITE(mac, ofs, (val & 0x3f3f)); - val += 0x202; - } - - if (phy->phy_mode == IEEE80211_MODE_11G) { - RF_SETBITS(mac, 0x7a, 0x20); - RF_SETBITS(mac, 0x51, 0x4); - PHY_SETBITS(mac, 0x802, 0x100); - PHY_SETBITS(mac, 0x42b, 0x2000); - PHY_WRITE(mac, 0x5b, 0); - PHY_WRITE(mac, 0x5c, 0); - } - - /* Force to channel 7 */ - orig_chan = rf->rf_curchan; - if (orig_chan >= 8) - bwi_rf_set_chan(mac, 1, 0); - else - bwi_rf_set_chan(mac, 13, 0); - - RF_WRITE(mac, 0x50, 0x20); - RF_WRITE(mac, 0x50, 0x23); - - DELAY(40); - - if (rf->rf_rev < 6 || rf->rf_rev == 8) { - RF_SETBITS(mac, 0x7c, 0x2); - RF_WRITE(mac, 0x50, 0x20); - } - if (rf->rf_rev <= 2) { - RF_WRITE(mac, 0x7c, 0x20); - RF_WRITE(mac, 0x5a, 0x70); - RF_WRITE(mac, 0x5b, 0x7b); - RF_WRITE(mac, 0x5c, 0xb0); - } - - RF_FILT_SETBITS(mac, 0x7a, 0xf8, 0x7); - - bwi_rf_set_chan(mac, orig_chan, 0); - - PHY_WRITE(mac, 0x14, 0x200); - if (rf->rf_rev >= 6) - PHY_WRITE(mac, 0x2a, 0x88c2); - else - PHY_WRITE(mac, 0x2a, 0x8ac0); - PHY_WRITE(mac, 0x38, 0x668); - - bwi_mac_set_tpctl_11bg(mac, NULL); - - if (rf->rf_rev <= 5) { - PHY_FILT_SETBITS(mac, 0x5d, 0xff80, 0x3); - if (rf->rf_rev <= 2) - RF_WRITE(mac, 0x5d, 0xd); - } - - if (phy->phy_version == 4) { - CSR_WRITE_2(sc, BWI_PHY_MAGIC_REG1, BWI_PHY_MAGIC_REG1_VAL2); - PHY_CLRBITS(mac, 0x61, 0xf000); - } else { - PHY_FILT_SETBITS(mac, 0x2, 0xffc0, 0x4); - } - - if (phy->phy_mode == IEEE80211_MODE_11B) { - CSR_WRITE_2(sc, BWI_BBP_ATTEN, BWI_BBP_ATTEN_MAGIC2); - PHY_WRITE(mac, 0x16, 0x410); - PHY_WRITE(mac, 0x17, 0x820); - PHY_WRITE(mac, 0x62, 0x7); - - bwi_rf_init_bcm2050(mac); - bwi_rf_lo_update(mac); - if (sc->sc_card_flags & BWI_CARD_F_SW_NRSSI) { - bwi_rf_calc_nrssi_slope(mac); - bwi_rf_set_nrssi_thr(mac); - } - bwi_mac_init_tpctl_11bg(mac); - } else { - CSR_WRITE_2(sc, BWI_BBP_ATTEN, 0); - } -} - -static void -bwi_phy_config_11g(struct bwi_mac *mac) -{ - struct bwi_softc *sc = mac->mac_sc; - struct bwi_phy *phy = &mac->mac_phy; - const uint16_t *tbl; - uint16_t wrd_ofs1, wrd_ofs2; - int i, n; - - if (phy->phy_rev == 1) { - PHY_WRITE(mac, 0x406, 0x4f19); - PHY_FILT_SETBITS(mac, 0x429, 0xfc3f, 0x340); - PHY_WRITE(mac, 0x42c, 0x5a); - PHY_WRITE(mac, 0x427, 0x1a); - - /* Fill frequency table */ - for (i = 0; i < NELEM(bwi_phy_freq_11g_rev1); ++i) { - bwi_tbl_write_2(mac, BWI_PHYTBL_FREQ + i, - bwi_phy_freq_11g_rev1[i]); - } - - /* Fill noise table */ - for (i = 0; i < NELEM(bwi_phy_noise_11g_rev1); ++i) { - bwi_tbl_write_2(mac, BWI_PHYTBL_NOISE + i, - bwi_phy_noise_11g_rev1[i]); - } - - /* Fill rotor table */ - for (i = 0; i < NELEM(bwi_phy_rotor_11g_rev1); ++i) { - /* NB: data length is 4 bytes */ - bwi_tbl_write_4(mac, BWI_PHYTBL_ROTOR + i, - bwi_phy_rotor_11g_rev1[i]); - } - } else { - bwi_nrssi_write(mac, 0xba98, (int16_t)0x7654); /* XXX */ - - if (phy->phy_rev == 2) { - PHY_WRITE(mac, 0x4c0, 0x1861); - PHY_WRITE(mac, 0x4c1, 0x271); - } else if (phy->phy_rev > 2) { - PHY_WRITE(mac, 0x4c0, 0x98); - PHY_WRITE(mac, 0x4c1, 0x70); - PHY_WRITE(mac, 0x4c9, 0x80); - } - PHY_SETBITS(mac, 0x42b, 0x800); - - /* Fill RSSI table */ - for (i = 0; i < 64; ++i) - bwi_tbl_write_2(mac, BWI_PHYTBL_RSSI + i, i); - - /* Fill noise table */ - for (i = 0; i < sizeof(bwi_phy_noise_11g); ++i) { - bwi_tbl_write_2(mac, BWI_PHYTBL_NOISE + i, - bwi_phy_noise_11g[i]); - } - } - - /* - * Fill noise scale table - */ - if (phy->phy_rev <= 2) { - tbl = bwi_phy_noise_scale_11g_rev2; - n = NELEM(bwi_phy_noise_scale_11g_rev2); - } else if (phy->phy_rev >= 7 && (PHY_READ(mac, 0x449) & 0x200)) { - tbl = bwi_phy_noise_scale_11g_rev7; - n = NELEM(bwi_phy_noise_scale_11g_rev7); - } else { - tbl = bwi_phy_noise_scale_11g; - n = NELEM(bwi_phy_noise_scale_11g); - } - for (i = 0; i < n; ++i) - bwi_tbl_write_2(mac, BWI_PHYTBL_NOISE_SCALE + i, tbl[i]); - - /* - * Fill sigma square table - */ - if (phy->phy_rev == 2) { - tbl = bwi_phy_sigma_sq_11g_rev2; - n = NELEM(bwi_phy_sigma_sq_11g_rev2); - } else if (phy->phy_rev > 2 && phy->phy_rev <= 8) { - tbl = bwi_phy_sigma_sq_11g_rev7; - n = NELEM(bwi_phy_sigma_sq_11g_rev7); - } else { - tbl = NULL; - n = 0; - } - for (i = 0; i < n; ++i) - bwi_tbl_write_2(mac, BWI_PHYTBL_SIGMA_SQ + i, tbl[i]); - - if (phy->phy_rev == 1) { - /* Fill delay table */ - for (i = 0; i < NELEM(bwi_phy_delay_11g_rev1); ++i) { - bwi_tbl_write_4(mac, BWI_PHYTBL_DELAY + i, - bwi_phy_delay_11g_rev1[i]); - } - - /* Fill WRSSI (Wide-Band RSSI) table */ - for (i = 4; i < 20; ++i) - bwi_tbl_write_2(mac, BWI_PHYTBL_WRSSI_REV1 + i, 0x20); - - bwi_phy_config_agc(mac); - - wrd_ofs1 = 0x5001; - wrd_ofs2 = 0x5002; - } else { - /* Fill WRSSI (Wide-Band RSSI) table */ - for (i = 0; i < 0x20; ++i) - bwi_tbl_write_2(mac, BWI_PHYTBL_WRSSI + i, 0x820); - - bwi_phy_config_agc(mac); - - PHY_READ(mac, 0x400); /* Dummy read */ - PHY_WRITE(mac, 0x403, 0x1000); - bwi_tbl_write_2(mac, 0x3c02, 0xf); - bwi_tbl_write_2(mac, 0x3c03, 0x14); - - wrd_ofs1 = 0x401; - wrd_ofs2 = 0x402; - } - - if (!(BWI_IS_BRCM_BU4306(sc) && sc->sc_pci_revid == 0x17)) { - bwi_tbl_write_2(mac, wrd_ofs1, 0x2); - bwi_tbl_write_2(mac, wrd_ofs2, 0x1); - } - - /* phy->phy_flags & BWI_PHY_F_LINKED ? */ - if (sc->sc_card_flags & BWI_CARD_F_PA_GPIO9) - PHY_WRITE(mac, 0x46e, 0x3cf); -} - -/* - * Configure Automatic Gain Controller - */ -static void -bwi_phy_config_agc(struct bwi_mac *mac) -{ - struct bwi_phy *phy = &mac->mac_phy; - uint16_t ofs; - - ofs = phy->phy_rev == 1 ? 0x4c00 : 0; - - bwi_tbl_write_2(mac, ofs, 0xfe); - bwi_tbl_write_2(mac, ofs + 1, 0xd); - bwi_tbl_write_2(mac, ofs + 2, 0x13); - bwi_tbl_write_2(mac, ofs + 3, 0x19); - - if (phy->phy_rev == 1) { - bwi_tbl_write_2(mac, 0x1800, 0x2710); - bwi_tbl_write_2(mac, 0x1801, 0x9b83); - bwi_tbl_write_2(mac, 0x1802, 0x9b83); - bwi_tbl_write_2(mac, 0x1803, 0xf8d); - PHY_WRITE(mac, 0x455, 0x4); - } - - PHY_FILT_SETBITS(mac, 0x4a5, 0xff, 0x5700); - PHY_FILT_SETBITS(mac, 0x41a, 0xff80, 0xf); - PHY_FILT_SETBITS(mac, 0x41a, 0xc07f, 0x2b80); - PHY_FILT_SETBITS(mac, 0x48c, 0xf0ff, 0x300); - - RF_SETBITS(mac, 0x7a, 0x8); - - PHY_FILT_SETBITS(mac, 0x4a0, 0xfff0, 0x8); - PHY_FILT_SETBITS(mac, 0x4a1, 0xf0ff, 0x600); - PHY_FILT_SETBITS(mac, 0x4a2, 0xf0ff, 0x700); - PHY_FILT_SETBITS(mac, 0x4a0, 0xf0ff, 0x100); - - if (phy->phy_rev == 1) - PHY_FILT_SETBITS(mac, 0x4a2, 0xfff0, 0x7); - - PHY_FILT_SETBITS(mac, 0x488, 0xff00, 0x1c); - PHY_FILT_SETBITS(mac, 0x488, 0xc0ff, 0x200); - PHY_FILT_SETBITS(mac, 0x496, 0xff00, 0x1c); - PHY_FILT_SETBITS(mac, 0x489, 0xff00, 0x20); - PHY_FILT_SETBITS(mac, 0x489, 0xc0ff, 0x200); - PHY_FILT_SETBITS(mac, 0x482, 0xff00, 0x2e); - PHY_FILT_SETBITS(mac, 0x496, 0xff, 0x1a00); - PHY_FILT_SETBITS(mac, 0x481, 0xff00, 0x28); - PHY_FILT_SETBITS(mac, 0x481, 0xff, 0x2c00); - - if (phy->phy_rev == 1) { - PHY_WRITE(mac, 0x430, 0x92b); - PHY_FILT_SETBITS(mac, 0x41b, 0xffe1, 0x2); - } else { - PHY_CLRBITS(mac, 0x41b, 0x1e); - PHY_WRITE(mac, 0x41f, 0x287a); - PHY_FILT_SETBITS(mac, 0x420, 0xfff0, 0x4); - - if (phy->phy_rev >= 6) { - PHY_WRITE(mac, 0x422, 0x287a); - PHY_FILT_SETBITS(mac, 0x420, 0xfff, 0x3000); - } - } - - PHY_FILT_SETBITS(mac, 0x4a8, 0x8080, 0x7874); - PHY_WRITE(mac, 0x48e, 0x1c00); - - if (phy->phy_rev == 1) { - PHY_FILT_SETBITS(mac, 0x4ab, 0xf0ff, 0x600); - PHY_WRITE(mac, 0x48b, 0x5e); - PHY_FILT_SETBITS(mac, 0x48c, 0xff00, 0x1e); - PHY_WRITE(mac, 0x48d, 0x2); - } - - bwi_tbl_write_2(mac, ofs + 0x800, 0); - bwi_tbl_write_2(mac, ofs + 0x801, 7); - bwi_tbl_write_2(mac, ofs + 0x802, 16); - bwi_tbl_write_2(mac, ofs + 0x803, 28); - - if (phy->phy_rev >= 6) { - PHY_CLRBITS(mac, 0x426, 0x3); - PHY_CLRBITS(mac, 0x426, 0x1000); - } -} - -void -bwi_set_gains(struct bwi_mac *mac, const struct bwi_gains *gains) -{ - struct bwi_phy *phy = &mac->mac_phy; - uint16_t tbl_gain_ofs1, tbl_gain_ofs2, tbl_gain; - int i; - - if (phy->phy_rev <= 1) { - tbl_gain_ofs1 = 0x5000; - tbl_gain_ofs2 = tbl_gain_ofs1 + 16; - } else { - tbl_gain_ofs1 = 0x400; - tbl_gain_ofs2 = tbl_gain_ofs1 + 8; - } - - for (i = 0; i < 4; ++i) { - if (gains != NULL) { - tbl_gain = gains->tbl_gain1; - } else { - /* Bit swap */ - tbl_gain = (i & 0x1) << 1; - tbl_gain |= (i & 0x2) >> 1; - } - bwi_tbl_write_2(mac, tbl_gain_ofs1 + i, tbl_gain); - } - - for (i = 0; i < 16; ++i) { - if (gains != NULL) - tbl_gain = gains->tbl_gain2; - else - tbl_gain = i; - bwi_tbl_write_2(mac, tbl_gain_ofs2 + i, tbl_gain); - } - - if (gains == NULL || (gains != NULL && gains->phy_gain != -1)) { - uint16_t phy_gain1, phy_gain2; - - if (gains != NULL) { - phy_gain1 = - ((uint16_t)gains->phy_gain << 14) | - ((uint16_t)gains->phy_gain << 6); - phy_gain2 = phy_gain1; - } else { - phy_gain1 = 0x4040; - phy_gain2 = 0x4000; - } - PHY_FILT_SETBITS(mac, 0x4a0, 0xbfbf, phy_gain1); - PHY_FILT_SETBITS(mac, 0x4a1, 0xbfbf, phy_gain1); - PHY_FILT_SETBITS(mac, 0x4a2, 0xbfbf, phy_gain2); - } - bwi_mac_dummy_xmit(mac); -} - -void -bwi_phy_clear_state(struct bwi_phy *phy) -{ - phy->phy_flags &= ~BWI_CLEAR_PHY_FLAGS; -} diff --git a/sys/dev/netif/bwi/bwiphy.h b/sys/dev/netif/bwi/bwiphy.h deleted file mode 100644 index 6a90aebac0..0000000000 --- a/sys/dev/netif/bwi/bwiphy.h +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright (c) 2007 The DragonFly Project. All rights reserved. - * - * This code is derived from software contributed to The DragonFly Project - * by Sepherosa Ziehau - * - * 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. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * 3. Neither the name of The DragonFly Project nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific, prior written permission. - * - * 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 MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, 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 DAMAGE. - * - * $DragonFly: src/sys/dev/netif/bwi/bwiphy.h,v 1.1 2007/09/08 06:15:54 sephe Exp $ - */ - -#ifndef _BWI_PHY_H -#define _BWI_PHY_H - -struct bwi_gains { - int16_t tbl_gain1; - int16_t tbl_gain2; - int16_t phy_gain; -}; - -int bwi_phy_attach(struct bwi_mac *); -void bwi_phy_clear_state(struct bwi_phy *); - -int bwi_phy_calibrate(struct bwi_mac *); -void bwi_phy_set_bbp_atten(struct bwi_mac *, uint16_t); - -void bwi_set_gains(struct bwi_mac *, const struct bwi_gains *); -int16_t bwi_nrssi_read(struct bwi_mac *, uint16_t); -void bwi_nrssi_write(struct bwi_mac *, uint16_t, int16_t); - -uint16_t bwi_phy_read(struct bwi_mac *, uint16_t); -void bwi_phy_write(struct bwi_mac *, uint16_t, uint16_t); - -static __inline void -bwi_phy_init(struct bwi_mac *_mac) -{ - _mac->mac_phy.phy_init(_mac); -} - -#define PHY_WRITE(mac, ctrl, val) bwi_phy_write((mac), (ctrl), (val)) -#define PHY_READ(mac, ctrl) bwi_phy_read((mac), (ctrl)) - -#define PHY_SETBITS(mac, ctrl, bits) \ - PHY_WRITE((mac), (ctrl), PHY_READ((mac), (ctrl)) | (bits)) -#define PHY_CLRBITS(mac, ctrl, bits) \ - PHY_WRITE((mac), (ctrl), PHY_READ((mac), (ctrl)) & ~(bits)) -#define PHY_FILT_SETBITS(mac, ctrl, filt, bits) \ - PHY_WRITE((mac), (ctrl), (PHY_READ((mac), (ctrl)) & (filt)) | (bits)) - -#define BWI_PHYR_NRSSI_THR_11B 0x020 -#define BWI_PHYR_BBP_ATTEN 0x060 -#define BWI_PHYR_TBL_CTRL_11A 0x072 -#define BWI_PHYR_TBL_DATA_LO_11A 0x073 -#define BWI_PHYR_TBL_DATA_HI_11A 0x074 -#define BWI_PHYR_TBL_CTRL_11G 0x472 -#define BWI_PHYR_TBL_DATA_LO_11G 0x473 -#define BWI_PHYR_TBL_DATA_HI_11G 0x474 -#define BWI_PHYR_NRSSI_THR_11G 0x48a -#define BWI_PHYR_NRSSI_CTRL 0x803 -#define BWI_PHYR_NRSSI_DATA 0x804 -#define BWI_PHYR_RF_LO 0x810 - -/* - * PHY Tables - */ -/* - * http://bcm-specs.sipsolutions.net/APHYSetup/FineFrequency - * G PHY - */ -#define BWI_PHY_FREQ_11G_REV1 \ - 0x0089, 0x02e9, 0x0409, 0x04e9, 0x05a9, 0x0669, 0x0709, 0x0789, \ - 0x0829, 0x08a9, 0x0929, 0x0989, 0x0a09, 0x0a69, 0x0ac9, 0x0b29, \ - 0x0ba9, 0x0be9, 0x0c49, 0x0ca9, 0x0d09, 0x0d69, 0x0da9, 0x0e09, \ - 0x0e69, 0x0ea9, 0x0f09, 0x0f49, 0x0fa9, 0x0fe9, 0x1029, 0x1089, \ - 0x10c9, 0x1109, 0x1169, 0x11a9, 0x11e9, 0x1229, 0x1289, 0x12c9, \ - 0x1309, 0x1349, 0x1389, 0x13c9, 0x1409, 0x1449, 0x14a9, 0x14e9, \ - 0x1529, 0x1569, 0x15a9, 0x15e9, 0x1629, 0x1669, 0x16a9, 0x16e8, \ - 0x1728, 0x1768, 0x17a8, 0x17e8, 0x1828, 0x1868, 0x18a8, 0x18e8, \ - 0x1928, 0x1968, 0x19a8, 0x19e8, 0x1a28, 0x1a68, 0x1aa8, 0x1ae8, \ - 0x1b28, 0x1b68, 0x1ba8, 0x1be8, 0x1c28, 0x1c68, 0x1ca8, 0x1ce8, \ - 0x1d28, 0x1d68, 0x1dc8, 0x1e08, 0x1e48, 0x1e88, 0x1ec8, 0x1f08, \ - 0x1f48, 0x1f88, 0x1fe8, 0x2028, 0x2068, 0x20a8, 0x2108, 0x2148, \ - 0x2188, 0x21c8, 0x2228, 0x2268, 0x22c8, 0x2308, 0x2348, 0x23a8, \ - 0x23e8, 0x2448, 0x24a8, 0x24e8, 0x2548, 0x25a8, 0x2608, 0x2668, \ - 0x26c8, 0x2728, 0x2787, 0x27e7, 0x2847, 0x28c7, 0x2947, 0x29a7, \ - 0x2a27, 0x2ac7, 0x2b47, 0x2be7, 0x2ca7, 0x2d67, 0x2e47, 0x2f67, \ - 0x3247, 0x3526, 0x3646, 0x3726, 0x3806, 0x38a6, 0x3946, 0x39e6, \ - 0x3a66, 0x3ae6, 0x3b66, 0x3bc6, 0x3c45, 0x3ca5, 0x3d05, 0x3d85, \ - 0x3de5, 0x3e45, 0x3ea5, 0x3ee5, 0x3f45, 0x3fa5, 0x4005, 0x4045, \ - 0x40a5, 0x40e5, 0x4145, 0x4185, 0x41e5, 0x4225, 0x4265, 0x42c5, \ - 0x4305, 0x4345, 0x43a5, 0x43e5, 0x4424, 0x4464, 0x44c4, 0x4504, \ - 0x4544, 0x4584, 0x45c4, 0x4604, 0x4644, 0x46a4, 0x46e4, 0x4724, \ - 0x4764, 0x47a4, 0x47e4, 0x4824, 0x4864, 0x48a4, 0x48e4, 0x4924, \ - 0x4964, 0x49a4, 0x49e4, 0x4a24, 0x4a64, 0x4aa4, 0x4ae4, 0x4b23, \ - 0x4b63, 0x4ba3, 0x4be3, 0x4c23, 0x4c63, 0x4ca3, 0x4ce3, 0x4d23, \ - 0x4d63, 0x4da3, 0x4de3, 0x4e23, 0x4e63, 0x4ea3, 0x4ee3, 0x4f23, \ - 0x4f63, 0x4fc3, 0x5003, 0x5043, 0x5083, 0x50c3, 0x5103, 0x5143, \ - 0x5183, 0x51e2, 0x5222, 0x5262, 0x52a2, 0x52e2, 0x5342, 0x5382, \ - 0x53c2, 0x5402, 0x5462, 0x54a2, 0x5502, 0x5542, 0x55a2, 0x55e2, \ - 0x5642, 0x5682, 0x56e2, 0x5722, 0x5782, 0x57e1, 0x5841, 0x58a1, \ - 0x5901, 0x5961, 0x59c1, 0x5a21, 0x5aa1, 0x5b01, 0x5b81, 0x5be1, \ - 0x5c61, 0x5d01, 0x5d80, 0x5e20, 0x5ee0, 0x5fa0, 0x6080, 0x61c0 - -/* - * http://bcm-specs.sipsolutions.net/APHYSetup/noise_table - */ -/* G PHY Revision 1 */ -#define BWI_PHY_NOISE_11G_REV1 \ - 0x013c, 0x01f5, 0x031a, 0x0631, 0x0001, 0x0001, 0x0001, 0x0001 -/* G PHY generic */ -#define BWI_PHY_NOISE_11G \ - 0x5484, 0x3c40, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 - -/* - * http://bcm-specs.sipsolutions.net/APHYSetup/rotor_table - * G PHY Revision 1 - */ -#define BWI_PHY_ROTOR_11G_REV1 \ - 0xfeb93ffd, 0xfec63ffd, 0xfed23ffd, 0xfedf3ffd, \ - 0xfeec3ffe, 0xfef83ffe, 0xff053ffe, 0xff113ffe, \ - 0xff1e3ffe, 0xff2a3fff, 0xff373fff, 0xff443fff, \ - 0xff503fff, 0xff5d3fff, 0xff693fff, 0xff763fff, \ - 0xff824000, 0xff8f4000, 0xff9b4000, 0xffa84000, \ - 0xffb54000, 0xffc14000, 0xffce4000, 0xffda4000, \ - 0xffe74000, 0xfff34000, 0x00004000, 0x000d4000, \ - 0x00194000, 0x00264000, 0x00324000, 0x003f4000, \ - 0x004b4000, 0x00584000, 0x00654000, 0x00714000, \ - 0x007e4000, 0x008a3fff, 0x00973fff, 0x00a33fff, \ - 0x00b03fff, 0x00bc3fff, 0x00c93fff, 0x00d63fff, \ - 0x00e23ffe, 0x00ef3ffe, 0x00fb3ffe, 0x01083ffe, \ - 0x01143ffe, 0x01213ffd, 0x012e3ffd, 0x013a3ffd, \ - 0x01473ffd - -/* - * http://bcm-specs.sipsolutions.net/APHYSetup/noise_scale_table - */ -/* G PHY Revision [0,2] */ -#define BWI_PHY_NOISE_SCALE_11G_REV2 \ - 0x6c77, 0x5162, 0x3b40, 0x3335, 0x2f2d, 0x2a2a, 0x2527, 0x1f21, \ - 0x1a1d, 0x1719, 0x1616, 0x1414, 0x1414, 0x1400, 0x1414, 0x1614, \ - 0x1716, 0x1a19, 0x1f1d, 0x2521, 0x2a27, 0x2f2a, 0x332d, 0x3b35, \ - 0x5140, 0x6c62, 0x0077 -/* G PHY Revsion 7 */ -#define BWI_PHY_NOISE_SCALE_11G_REV7 \ - 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, \ - 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa400, 0xa4a4, 0xa4a4, \ - 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, \ - 0xa4a4, 0xa4a4, 0x00a4 -/* G PHY generic */ -#define BWI_PHY_NOISE_SCALE_11G \ - 0xd8dd, 0xcbd4, 0xbcc0, 0xb6b7, 0xb2b0, 0xadad, 0xa7a9, 0x9fa1, \ - 0x969b, 0x9195, 0x8f8f, 0x8a8a, 0x8a8a, 0x8a00, 0x8a8a, 0x8f8a, \ - 0x918f, 0x9695, 0x9f9b, 0xa7a1, 0xada9, 0xb2ad, 0xb6b0, 0xbcb7, \ - 0xcbc0, 0xd8d4, 0x00dd - -/* - * http://bcm-specs.sipsolutions.net/APHYSetup/sigma_square_table - */ -/* G PHY Revision 2 */ -#define BWI_PHY_SIGMA_SQ_11G_REV2 \ - 0x007a, 0x0075, 0x0071, 0x006c, 0x0067, 0x0063, 0x005e, 0x0059, \ - 0x0054, 0x0050, 0x004b, 0x0046, 0x0042, 0x003d, 0x003d, 0x003d, \ - 0x003d, 0x003d, 0x003d, 0x003d, 0x003d, 0x003d, 0x003d, 0x003d, \ - 0x003d, 0x003d, 0x0000, 0x003d, 0x003d, 0x003d, 0x003d, 0x003d, \ - 0x003d, 0x003d, 0x003d, 0x003d, 0x003d, 0x003d, 0x003d, 0x003d, \ - 0x0042, 0x0046, 0x004b, 0x0050, 0x0054, 0x0059, 0x005e, 0x0063, \ - 0x0067, 0x006c, 0x0071, 0x0075, 0x007a -/* G PHY Revision (2,7] */ -#define BWI_PHY_SIGMA_SQ_11G_REV7 \ - 0x00de, 0x00dc, 0x00da, 0x00d8, 0x00d6, 0x00d4, 0x00d2, 0x00cf, \ - 0x00cd, 0x00ca, 0x00c7, 0x00c4, 0x00c1, 0x00be, 0x00be, 0x00be, \ - 0x00be, 0x00be, 0x00be, 0x00be, 0x00be, 0x00be, 0x00be, 0x00be, \ - 0x00be, 0x00be, 0x0000, 0x00be, 0x00be, 0x00be, 0x00be, 0x00be, \ - 0x00be, 0x00be, 0x00be, 0x00be, 0x00be, 0x00be, 0x00be, 0x00be, \ - 0x00c1, 0x00c4, 0x00c7, 0x00ca, 0x00cd, 0x00cf, 0x00d2, 0x00d4, \ - 0x00d6, 0x00d8, 0x00da, 0x00dc, 0x00de - -/* - * http://bcm-specs.sipsolutions.net/APHYSetup/retard_table - * G PHY - */ -#define BWI_PHY_DELAY_11G_REV1 \ - 0xdb93cb87, 0xd666cf64, 0xd1fdd358, 0xcda6d826, \ - 0xca38dd9f, 0xc729e2b4, 0xc469e88e, 0xc26aee2b, \ - 0xc0def46c, 0xc073fa62, 0xc01d00d5, 0xc0760743, \ - 0xc1560d1e, 0xc2e51369, 0xc4ed18ff, 0xc7ac1ed7, \ - 0xcb2823b2, 0xcefa28d9, 0xd2f62d3f, 0xd7bb3197, \ - 0xdce53568, 0xe1fe3875, 0xe7d13b35, 0xed663d35, \ - 0xf39b3ec4, 0xf98e3fa7, 0x00004000, 0x06723fa7, \ - 0x0c653ec4, 0x129a3d35, 0x182f3b35, 0x1e023875, \ - 0x231b3568, 0x28453197, 0x2d0a2d3f, 0x310628d9, \ - 0x34d823b2, 0x38541ed7, 0x3b1318ff, 0x3d1b1369, \ - 0x3eaa0d1e, 0x3f8a0743, 0x3fe300d5, 0x3f8dfa62, \ - 0x3f22f46c, 0x3d96ee2b, 0x3b97e88e, 0x38d7e2b4, \ - 0x35c8dd9f, 0x325ad826, 0x2e03d358, 0x299acf64, \ - 0x246dcb87 - -#endif /* !_BWI_PHY_H */ diff --git a/sys/dev/netif/bwi/bwirf.c b/sys/dev/netif/bwi/bwirf.c deleted file mode 100644 index 4bb3e065a5..0000000000 --- a/sys/dev/netif/bwi/bwirf.c +++ /dev/null @@ -1,2664 +0,0 @@ -/* - * Copyright (c) 2007 The DragonFly Project. All rights reserved. - * - * This code is derived from software contributed to The DragonFly Project - * by Sepherosa Ziehau - * - * 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. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * 3. Neither the name of The DragonFly Project nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific, prior written permission. - * - * 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 MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, 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 DAMAGE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include "pcidevs.h" - -#include -#include -#include -#include -#include - -#define RF_LO_WRITE(mac, lo) bwi_rf_lo_write((mac), (lo)) - -#define BWI_RF_2GHZ_CHAN(chan) \ - (ieee80211_ieee2mhz((chan), IEEE80211_CHAN_2GHZ) - 2400) - -#define BWI_DEFAULT_IDLE_TSSI 52 - -struct rf_saveregs { - uint16_t phy_01; - uint16_t phy_03; - uint16_t phy_0a; - uint16_t phy_15; - uint16_t phy_2a; - uint16_t phy_30; - uint16_t phy_35; - uint16_t phy_60; - uint16_t phy_429; - uint16_t phy_802; - uint16_t phy_811; - uint16_t phy_812; - uint16_t phy_814; - uint16_t phy_815; - - uint16_t rf_43; - uint16_t rf_52; - uint16_t rf_7a; -}; - -#define SAVE_RF_REG(mac, regs, n) (regs)->rf_##n = RF_READ((mac), 0x##n) -#define RESTORE_RF_REG(mac, regs, n) RF_WRITE((mac), 0x##n, (regs)->rf_##n) - -#define SAVE_PHY_REG(mac, regs, n) (regs)->phy_##n = PHY_READ((mac), 0x##n) -#define RESTORE_PHY_REG(mac, regs, n) PHY_WRITE((mac), 0x##n, (regs)->phy_##n) - -static int bwi_rf_calc_txpower(int8_t *, uint8_t, const int16_t[]); -static void bwi_rf_workaround(struct bwi_mac *, u_int); -static int bwi_rf_gain_max_reached(struct bwi_mac *, int); -static uint16_t bwi_rf_calibval(struct bwi_mac *); -static uint16_t bwi_rf_get_tp_ctrl2(struct bwi_mac *); - -static void bwi_rf_lo_update_11b(struct bwi_mac *); -static uint16_t bwi_rf_lo_measure_11b(struct bwi_mac *); - -static void bwi_rf_lo_update_11g(struct bwi_mac *); -static uint32_t bwi_rf_lo_devi_measure(struct bwi_mac *, uint16_t); -static void bwi_rf_lo_measure_11g(struct bwi_mac *, - const struct bwi_rf_lo *, struct bwi_rf_lo *, uint8_t); -static uint8_t _bwi_rf_lo_update_11g(struct bwi_mac *, uint16_t); -static void bwi_rf_lo_write(struct bwi_mac *, const struct bwi_rf_lo *); - -static void bwi_rf_set_nrssi_ofs_11g(struct bwi_mac *); -static void bwi_rf_calc_nrssi_slope_11b(struct bwi_mac *); -static void bwi_rf_calc_nrssi_slope_11g(struct bwi_mac *); -static void bwi_rf_set_nrssi_thr_11b(struct bwi_mac *); -static void bwi_rf_set_nrssi_thr_11g(struct bwi_mac *); - -static void bwi_rf_init_sw_nrssi_table(struct bwi_mac *); - -static int bwi_rf_calc_rssi_bcm2050(struct bwi_mac *, - const struct bwi_rxbuf_hdr *); -static int bwi_rf_calc_rssi_bcm2053(struct bwi_mac *, - const struct bwi_rxbuf_hdr *); -static int bwi_rf_calc_rssi_bcm2060(struct bwi_mac *, - const struct bwi_rxbuf_hdr *); - -static void bwi_rf_on_11a(struct bwi_mac *); -static void bwi_rf_on_11bg(struct bwi_mac *); - -static void bwi_rf_off_11a(struct bwi_mac *); -static void bwi_rf_off_11bg(struct bwi_mac *); -static void bwi_rf_off_11g_rev5(struct bwi_mac *); - -static const int8_t bwi_txpower_map_11b[BWI_TSSI_MAX] = - { BWI_TXPOWER_MAP_11B }; -static const int8_t bwi_txpower_map_11g[BWI_TSSI_MAX] = - { BWI_TXPOWER_MAP_11G }; - -static __inline int16_t -bwi_nrssi_11g(struct bwi_mac *mac) -{ - int16_t val; - -#define NRSSI_11G_MASK __BITS(13, 8) - - val = (int16_t)__SHIFTOUT(PHY_READ(mac, 0x47f), NRSSI_11G_MASK); - if (val >= 32) - val -= 64; - return val; - -#undef NRSSI_11G_MASK -} - -static __inline struct bwi_rf_lo * -bwi_get_rf_lo(struct bwi_mac *mac, uint16_t rf_atten, uint16_t bbp_atten) -{ - int n; - - n = rf_atten + (14 * (bbp_atten / 2)); - KKASSERT(n < BWI_RFLO_MAX); - - return &mac->mac_rf.rf_lo[n]; -} - -static __inline int -bwi_rf_lo_isused(struct bwi_mac *mac, const struct bwi_rf_lo *lo) -{ - struct bwi_rf *rf = &mac->mac_rf; - int idx; - - idx = lo - rf->rf_lo; - KKASSERT(idx >= 0 && idx < BWI_RFLO_MAX); - - return isset(rf->rf_lo_used, idx); -} - -void -bwi_rf_write(struct bwi_mac *mac, uint16_t ctrl, uint16_t data) -{ - struct bwi_softc *sc = mac->mac_sc; - - CSR_WRITE_2(sc, BWI_RF_CTRL, ctrl); - CSR_WRITE_2(sc, BWI_RF_DATA_LO, data); -} - -uint16_t -bwi_rf_read(struct bwi_mac *mac, uint16_t ctrl) -{ - struct bwi_rf *rf = &mac->mac_rf; - struct bwi_softc *sc = mac->mac_sc; - - ctrl |= rf->rf_ctrl_rd; - if (rf->rf_ctrl_adj) { - /* XXX */ - if (ctrl < 0x70) - ctrl += 0x80; - else if (ctrl < 0x80) - ctrl += 0x70; - } - - CSR_WRITE_2(sc, BWI_RF_CTRL, ctrl); - return CSR_READ_2(sc, BWI_RF_DATA_LO); -} - -int -bwi_rf_attach(struct bwi_mac *mac) -{ - struct bwi_softc *sc = mac->mac_sc; - struct bwi_phy *phy = &mac->mac_phy; - struct bwi_rf *rf = &mac->mac_rf; - uint16_t type, manu; - uint8_t rev; - - /* - * Get RF manufacture/type/revision - */ - if (sc->sc_bbp_id == BWI_BBPID_BCM4317) { - /* - * Fake a BCM2050 RF - */ - manu = BWI_RF_MANUFACT_BCM; - type = BWI_RF_T_BCM2050; - if (sc->sc_bbp_rev == 0) - rev = 3; - else if (sc->sc_bbp_rev == 1) - rev = 4; - else - rev = 5; - } else { - uint32_t val; - - CSR_WRITE_2(sc, BWI_RF_CTRL, BWI_RF_CTRL_RFINFO); - val = CSR_READ_2(sc, BWI_RF_DATA_HI); - val <<= 16; - - CSR_WRITE_2(sc, BWI_RF_CTRL, BWI_RF_CTRL_RFINFO); - val |= CSR_READ_2(sc, BWI_RF_DATA_LO); - - manu = __SHIFTOUT(val, BWI_RFINFO_MANUFACT_MASK); - type = __SHIFTOUT(val, BWI_RFINFO_TYPE_MASK); - rev = __SHIFTOUT(val, BWI_RFINFO_REV_MASK); - } - device_printf(sc->sc_dev, "RF: manu 0x%03x, type 0x%04x, rev %u\n", - manu, type, rev); - - /* - * Verify whether the RF is supported - */ - rf->rf_ctrl_rd = 0; - rf->rf_ctrl_adj = 0; - switch (phy->phy_mode) { - case IEEE80211_MODE_11A: - if (manu != BWI_RF_MANUFACT_BCM || - type != BWI_RF_T_BCM2060 || - rev != 1) { - device_printf(sc->sc_dev, "only BCM2060 rev 1 RF " - "is supported for 11A PHY\n"); - return ENXIO; - } - rf->rf_ctrl_rd = BWI_RF_CTRL_RD_11A; - rf->rf_on = bwi_rf_on_11a; - rf->rf_off = bwi_rf_off_11a; - rf->rf_calc_rssi = bwi_rf_calc_rssi_bcm2060; - break; - case IEEE80211_MODE_11B: - if (type == BWI_RF_T_BCM2050) { - rf->rf_ctrl_rd = BWI_RF_CTRL_RD_11BG; - rf->rf_calc_rssi = bwi_rf_calc_rssi_bcm2050; - } else if (type == BWI_RF_T_BCM2053) { - rf->rf_ctrl_adj = 1; - rf->rf_calc_rssi = bwi_rf_calc_rssi_bcm2053; - } else { - device_printf(sc->sc_dev, "only BCM2050/BCM2053 RF " - "is supported for 11B PHY\n"); - return ENXIO; - } - rf->rf_on = bwi_rf_on_11bg; - rf->rf_off = bwi_rf_off_11bg; - rf->rf_calc_nrssi_slope = bwi_rf_calc_nrssi_slope_11b; - rf->rf_set_nrssi_thr = bwi_rf_set_nrssi_thr_11b; - if (phy->phy_rev == 6) - rf->rf_lo_update = bwi_rf_lo_update_11g; - else - rf->rf_lo_update = bwi_rf_lo_update_11b; - break; - case IEEE80211_MODE_11G: - if (type != BWI_RF_T_BCM2050) { - device_printf(sc->sc_dev, "only BCM2050 RF " - "is supported for 11G PHY\n"); - return ENXIO; - } - rf->rf_ctrl_rd = BWI_RF_CTRL_RD_11BG; - rf->rf_on = bwi_rf_on_11bg; - if (mac->mac_rev >= 5) - rf->rf_off = bwi_rf_off_11g_rev5; - else - rf->rf_off = bwi_rf_off_11bg; - rf->rf_calc_nrssi_slope = bwi_rf_calc_nrssi_slope_11g; - rf->rf_set_nrssi_thr = bwi_rf_set_nrssi_thr_11g; - rf->rf_calc_rssi = bwi_rf_calc_rssi_bcm2050; - rf->rf_lo_update = bwi_rf_lo_update_11g; - break; - default: - device_printf(sc->sc_dev, "unsupported PHY mode\n"); - return ENXIO; - } - - rf->rf_type = type; - rf->rf_rev = rev; - rf->rf_manu = manu; - rf->rf_curchan = IEEE80211_CHAN_ANY; - rf->rf_ant_mode = BWI_ANT_MODE_AUTO; - return 0; -} - -void -bwi_rf_set_chan(struct bwi_mac *mac, u_int chan, int work_around) -{ - struct bwi_softc *sc = mac->mac_sc; - - if (chan == IEEE80211_CHAN_ANY) - return; - - MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_CHAN, chan); - - /* TODO: 11A */ - - if (work_around) - bwi_rf_workaround(mac, chan); - - CSR_WRITE_2(sc, BWI_RF_CHAN, BWI_RF_2GHZ_CHAN(chan)); - - if (chan == 14) { - if (sc->sc_locale == BWI_SPROM_LOCALE_JAPAN) - HFLAGS_CLRBITS(mac, BWI_HFLAG_NOT_JAPAN); - else - HFLAGS_SETBITS(mac, BWI_HFLAG_NOT_JAPAN); - CSR_SETBITS_2(sc, BWI_RF_CHAN_EX, (1 << 11)); /* XXX */ - } else { - CSR_CLRBITS_2(sc, BWI_RF_CHAN_EX, 0x840); /* XXX */ - } - DELAY(8000); /* DELAY(2000); */ - - mac->mac_rf.rf_curchan = chan; -} - -void -bwi_rf_get_gains(struct bwi_mac *mac) -{ -#define SAVE_PHY_MAX 15 -#define SAVE_RF_MAX 3 - - static const uint16_t save_rf_regs[SAVE_RF_MAX] = - { 0x52, 0x43, 0x7a }; - static const uint16_t save_phy_regs[SAVE_PHY_MAX] = { - 0x0429, 0x0001, 0x0811, 0x0812, - 0x0814, 0x0815, 0x005a, 0x0059, - 0x0058, 0x000a, 0x0003, 0x080f, - 0x0810, 0x002b, 0x0015 - }; - - struct bwi_phy *phy = &mac->mac_phy; - struct bwi_rf *rf = &mac->mac_rf; - uint16_t save_phy[SAVE_PHY_MAX]; - uint16_t save_rf[SAVE_RF_MAX]; - uint16_t trsw; - int i, j, loop1_max, loop1, loop2; - - /* - * Save PHY/RF registers for later restoration - */ - for (i = 0; i < SAVE_PHY_MAX; ++i) - save_phy[i] = PHY_READ(mac, save_phy_regs[i]); - PHY_READ(mac, 0x2d); /* dummy read */ - - for (i = 0; i < SAVE_RF_MAX; ++i) - save_rf[i] = RF_READ(mac, save_rf_regs[i]); - - PHY_CLRBITS(mac, 0x429, 0xc000); - PHY_SETBITS(mac, 0x1, 0x8000); - - PHY_SETBITS(mac, 0x811, 0x2); - PHY_CLRBITS(mac, 0x812, 0x2); - PHY_SETBITS(mac, 0x811, 0x1); - PHY_CLRBITS(mac, 0x812, 0x1); - - PHY_SETBITS(mac, 0x814, 0x1); - PHY_CLRBITS(mac, 0x815, 0x1); - PHY_SETBITS(mac, 0x814, 0x2); - PHY_CLRBITS(mac, 0x815, 0x2); - - PHY_SETBITS(mac, 0x811, 0xc); - PHY_SETBITS(mac, 0x812, 0xc); - PHY_SETBITS(mac, 0x811, 0x30); - PHY_FILT_SETBITS(mac, 0x812, 0xffcf, 0x10); - - PHY_WRITE(mac, 0x5a, 0x780); - PHY_WRITE(mac, 0x59, 0xc810); - PHY_WRITE(mac, 0x58, 0xd); - PHY_SETBITS(mac, 0xa, 0x2000); - - PHY_SETBITS(mac, 0x814, 0x4); - PHY_CLRBITS(mac, 0x815, 0x4); - - PHY_FILT_SETBITS(mac, 0x3, 0xff9f, 0x40); - - if (rf->rf_rev == 8) { - loop1_max = 15; - RF_WRITE(mac, 0x43, loop1_max); - } else { - loop1_max = 9; - RF_WRITE(mac, 0x52, 0x0); - RF_FILT_SETBITS(mac, 0x43, 0xfff0, loop1_max); - } - - bwi_phy_set_bbp_atten(mac, 11); - - if (phy->phy_rev >= 3) - PHY_WRITE(mac, 0x80f, 0xc020); - else - PHY_WRITE(mac, 0x80f, 0x8020); - PHY_WRITE(mac, 0x810, 0); - - PHY_FILT_SETBITS(mac, 0x2b, 0xffc0, 0x1); - PHY_FILT_SETBITS(mac, 0x2b, 0xc0ff, 0x800); - PHY_SETBITS(mac, 0x811, 0x100); - PHY_CLRBITS(mac, 0x812, 0x3000); - - if ((mac->mac_sc->sc_card_flags & BWI_CARD_F_EXT_LNA) && - phy->phy_rev >= 7) { - PHY_SETBITS(mac, 0x811, 0x800); - PHY_SETBITS(mac, 0x812, 0x8000); - } - RF_CLRBITS(mac, 0x7a, 0xff08); - - /* - * Find out 'loop1/loop2', which will be used to calculate - * max loopback gain later - */ - j = 0; - for (i = 0; i < loop1_max; ++i) { - for (j = 0; j < 16; ++j) { - RF_WRITE(mac, 0x43, i); - - if (bwi_rf_gain_max_reached(mac, j)) - goto loop1_exit; - } - } -loop1_exit: - loop1 = i; - loop2 = j; - - /* - * Find out 'trsw', which will be used to calculate - * TRSW(TX/RX switch) RX gain later - */ - if (loop2 >= 8) { - PHY_SETBITS(mac, 0x812, 0x30); - trsw = 0x1b; - for (i = loop2 - 8; i < 16; ++i) { - trsw -= 3; - if (bwi_rf_gain_max_reached(mac, i)) - break; - } - } else { - trsw = 0x18; - } - - /* - * Restore saved PHY/RF registers - */ - /* First 4 saved PHY registers need special processing */ - for (i = 4; i < SAVE_PHY_MAX; ++i) - PHY_WRITE(mac, save_phy_regs[i], save_phy[i]); - - bwi_phy_set_bbp_atten(mac, mac->mac_tpctl.bbp_atten); - - for (i = 0; i < SAVE_RF_MAX; ++i) - RF_WRITE(mac, save_rf_regs[i], save_rf[i]); - - PHY_WRITE(mac, save_phy_regs[2], save_phy[2] | 0x3); - DELAY(10); - PHY_WRITE(mac, save_phy_regs[2], save_phy[2]); - PHY_WRITE(mac, save_phy_regs[3], save_phy[3]); - PHY_WRITE(mac, save_phy_regs[0], save_phy[0]); - PHY_WRITE(mac, save_phy_regs[1], save_phy[1]); - - /* - * Calculate gains - */ - rf->rf_lo_gain = (loop2 * 6) - (loop1 * 4) - 11; - rf->rf_rx_gain = trsw * 2; - DPRINTF(mac->mac_sc, BWI_DBG_RF | BWI_DBG_INIT, - "lo gain: %u, rx gain: %u\n", - rf->rf_lo_gain, rf->rf_rx_gain); - -#undef SAVE_RF_MAX -#undef SAVE_PHY_MAX -} - -void -bwi_rf_init(struct bwi_mac *mac) -{ - struct bwi_rf *rf = &mac->mac_rf; - - if (rf->rf_type == BWI_RF_T_BCM2060) { - /* TODO: 11A */ - } else { - if (rf->rf_flags & BWI_RF_F_INITED) - RF_WRITE(mac, 0x78, rf->rf_calib); - else - bwi_rf_init_bcm2050(mac); - } -} - -static void -bwi_rf_off_11a(struct bwi_mac *mac) -{ - RF_WRITE(mac, 0x4, 0xff); - RF_WRITE(mac, 0x5, 0xfb); - - PHY_SETBITS(mac, 0x10, 0x8); - PHY_SETBITS(mac, 0x11, 0x8); - - PHY_WRITE(mac, 0x15, 0xaa00); -} - -static void -bwi_rf_off_11bg(struct bwi_mac *mac) -{ - PHY_WRITE(mac, 0x15, 0xaa00); -} - -static void -bwi_rf_off_11g_rev5(struct bwi_mac *mac) -{ - PHY_SETBITS(mac, 0x811, 0x8c); - PHY_CLRBITS(mac, 0x812, 0x8c); -} - -static void -bwi_rf_workaround(struct bwi_mac *mac, u_int chan) -{ - struct bwi_softc *sc = mac->mac_sc; - struct bwi_rf *rf = &mac->mac_rf; - - if (chan == IEEE80211_CHAN_ANY) { - if_printf(&mac->mac_sc->sc_ic.ic_if, - "%s invalid channel!!\n", __func__); - return; - } - - if (rf->rf_type != BWI_RF_T_BCM2050 || rf->rf_rev >= 6) - return; - - if (chan <= 10) - CSR_WRITE_2(sc, BWI_RF_CHAN, BWI_RF_2GHZ_CHAN(chan + 4)); - else - CSR_WRITE_2(sc, BWI_RF_CHAN, BWI_RF_2GHZ_CHAN(1)); - DELAY(1000); - CSR_WRITE_2(sc, BWI_RF_CHAN, BWI_RF_2GHZ_CHAN(chan)); -} - -static __inline struct bwi_rf_lo * -bwi_rf_lo_find(struct bwi_mac *mac, const struct bwi_tpctl *tpctl) -{ - uint16_t rf_atten, bbp_atten; - int remap_rf_atten; - - remap_rf_atten = 1; - if (tpctl == NULL) { - bbp_atten = 2; - rf_atten = 3; - } else { - if (tpctl->tp_ctrl1 == 3) - remap_rf_atten = 0; - - bbp_atten = tpctl->bbp_atten; - rf_atten = tpctl->rf_atten; - - if (bbp_atten > 6) - bbp_atten = 6; - } - - if (remap_rf_atten) { -#define MAP_MAX 10 - static const uint16_t map[MAP_MAX] = - { 11, 10, 11, 12, 13, 12, 13, 12, 13, 12 }; - -#if 0 - KKASSERT(rf_atten < MAP_MAX); - rf_atten = map[rf_atten]; -#else - if (rf_atten >= MAP_MAX) { - rf_atten = 0; /* XXX */ - } else { - rf_atten = map[rf_atten]; - } -#endif -#undef MAP_MAX - } - - return bwi_get_rf_lo(mac, rf_atten, bbp_atten); -} - -void -bwi_rf_lo_adjust(struct bwi_mac *mac, const struct bwi_tpctl *tpctl) -{ - const struct bwi_rf_lo *lo; - - lo = bwi_rf_lo_find(mac, tpctl); - RF_LO_WRITE(mac, lo); -} - -static void -bwi_rf_lo_write(struct bwi_mac *mac, const struct bwi_rf_lo *lo) -{ - uint16_t val; - - val = (uint8_t)lo->ctrl_lo; - val |= ((uint8_t)lo->ctrl_hi) << 8; - - PHY_WRITE(mac, BWI_PHYR_RF_LO, val); -} - -static int -bwi_rf_gain_max_reached(struct bwi_mac *mac, int idx) -{ - PHY_FILT_SETBITS(mac, 0x812, 0xf0ff, idx << 8); - PHY_FILT_SETBITS(mac, 0x15, 0xfff, 0xa000); - PHY_SETBITS(mac, 0x15, 0xf000); - - DELAY(20); - - return (PHY_READ(mac, 0x2d) >= 0xdfc); -} - -/* XXX use bitmap array */ -static __inline uint16_t -bitswap4(uint16_t val) -{ - uint16_t ret; - - ret = (val & 0x8) >> 3; - ret |= (val & 0x4) >> 1; - ret |= (val & 0x2) << 1; - ret |= (val & 0x1) << 3; - return ret; -} - -static __inline uint16_t -bwi_phy812_value(struct bwi_mac *mac, uint16_t lpd) -{ - struct bwi_softc *sc = mac->mac_sc; - struct bwi_phy *phy = &mac->mac_phy; - struct bwi_rf *rf = &mac->mac_rf; - uint16_t lo_gain, ext_lna, loop; - - if ((phy->phy_flags & BWI_PHY_F_LINKED) == 0) - return 0; - - lo_gain = rf->rf_lo_gain; - if (rf->rf_rev == 8) - lo_gain += 0x3e; - else - lo_gain += 0x26; - - if (lo_gain >= 0x46) { - lo_gain -= 0x46; - ext_lna = 0x3000; - } else if (lo_gain >= 0x3a) { - lo_gain -= 0x3a; - ext_lna = 0x1000; - } else if (lo_gain >= 0x2e) { - lo_gain -= 0x2e; - ext_lna = 0x2000; - } else { - lo_gain -= 0x10; - ext_lna = 0; - } - - for (loop = 0; loop < 16; ++loop) { - lo_gain -= (6 * loop); - if (lo_gain < 6) - break; - } - - if (phy->phy_rev >= 7 && (sc->sc_card_flags & BWI_CARD_F_EXT_LNA)) { - if (ext_lna) - ext_lna |= 0x8000; - ext_lna |= (loop << 8); - switch (lpd) { - case 0x011: - return 0x8f92; - case 0x001: - return (0x8092 | ext_lna); - case 0x101: - return (0x2092 | ext_lna); - case 0x100: - return (0x2093 | ext_lna); - default: - panic("unsupported lpd"); - } - } else { - ext_lna |= (loop << 8); - switch (lpd) { - case 0x011: - return 0xf92; - case 0x001: - case 0x101: - return (0x92 | ext_lna); - case 0x100: - return (0x93 | ext_lna); - default: - panic("unsupported lpd"); - } - } - - panic("never reached"); - return 0; -} - -void -bwi_rf_init_bcm2050(struct bwi_mac *mac) -{ -#define SAVE_RF_MAX 3 -#define SAVE_PHY_COMM_MAX 4 -#define SAVE_PHY_11G_MAX 6 - - static const uint16_t save_rf_regs[SAVE_RF_MAX] = - { 0x0043, 0x0051, 0x0052 }; - static const uint16_t save_phy_regs_comm[SAVE_PHY_COMM_MAX] = - { 0x0015, 0x005a, 0x0059, 0x0058 }; - static const uint16_t save_phy_regs_11g[SAVE_PHY_11G_MAX] = - { 0x0811, 0x0812, 0x0814, 0x0815, 0x0429, 0x0802 }; - - uint16_t save_rf[SAVE_RF_MAX]; - uint16_t save_phy_comm[SAVE_PHY_COMM_MAX]; - uint16_t save_phy_11g[SAVE_PHY_11G_MAX]; - uint16_t phyr_35, phyr_30 = 0, rfr_78, phyr_80f = 0, phyr_810 = 0; - uint16_t bphy_ctrl = 0, bbp_atten, rf_chan_ex; - uint16_t phy812_val; - uint16_t calib; - uint32_t test_lim, test; - struct bwi_softc *sc = mac->mac_sc; - struct bwi_phy *phy = &mac->mac_phy; - struct bwi_rf *rf = &mac->mac_rf; - int i; - - /* - * Save registers for later restoring - */ - for (i = 0; i < SAVE_RF_MAX; ++i) - save_rf[i] = RF_READ(mac, save_rf_regs[i]); - for (i = 0; i < SAVE_PHY_COMM_MAX; ++i) - save_phy_comm[i] = PHY_READ(mac, save_phy_regs_comm[i]); - - if (phy->phy_mode == IEEE80211_MODE_11B) { - phyr_30 = PHY_READ(mac, 0x30); - bphy_ctrl = CSR_READ_2(sc, BWI_BPHY_CTRL); - - PHY_WRITE(mac, 0x30, 0xff); - CSR_WRITE_2(sc, BWI_BPHY_CTRL, 0x3f3f); - } else if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) { - for (i = 0; i < SAVE_PHY_11G_MAX; ++i) { - save_phy_11g[i] = - PHY_READ(mac, save_phy_regs_11g[i]); - } - - PHY_SETBITS(mac, 0x814, 0x3); - PHY_CLRBITS(mac, 0x815, 0x3); - PHY_CLRBITS(mac, 0x429, 0x8000); - PHY_CLRBITS(mac, 0x802, 0x3); - - phyr_80f = PHY_READ(mac, 0x80f); - phyr_810 = PHY_READ(mac, 0x810); - - if (phy->phy_rev >= 3) - PHY_WRITE(mac, 0x80f, 0xc020); - else - PHY_WRITE(mac, 0x80f, 0x8020); - PHY_WRITE(mac, 0x810, 0); - - phy812_val = bwi_phy812_value(mac, 0x011); - PHY_WRITE(mac, 0x812, phy812_val); - if (phy->phy_rev < 7 || - (sc->sc_card_flags & BWI_CARD_F_EXT_LNA) == 0) - PHY_WRITE(mac, 0x811, 0x1b3); - else - PHY_WRITE(mac, 0x811, 0x9b3); - } - CSR_SETBITS_2(sc, BWI_RF_ANTDIV, 0x8000); - - phyr_35 = PHY_READ(mac, 0x35); - PHY_CLRBITS(mac, 0x35, 0x80); - - bbp_atten = CSR_READ_2(sc, BWI_BBP_ATTEN); - rf_chan_ex = CSR_READ_2(sc, BWI_RF_CHAN_EX); - - if (phy->phy_version == 0) { - CSR_WRITE_2(sc, BWI_BBP_ATTEN, 0x122); - } else { - if (phy->phy_version >= 2) - PHY_FILT_SETBITS(mac, 0x3, 0xffbf, 0x40); - CSR_SETBITS_2(sc, BWI_RF_CHAN_EX, 0x2000); - } - - calib = bwi_rf_calibval(mac); - - if (phy->phy_mode == IEEE80211_MODE_11B) - RF_WRITE(mac, 0x78, 0x26); - - if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) { - phy812_val = bwi_phy812_value(mac, 0x011); - PHY_WRITE(mac, 0x812, phy812_val); - } - - PHY_WRITE(mac, 0x15, 0xbfaf); - PHY_WRITE(mac, 0x2b, 0x1403); - - if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) { - phy812_val = bwi_phy812_value(mac, 0x001); - PHY_WRITE(mac, 0x812, phy812_val); - } - - PHY_WRITE(mac, 0x15, 0xbfa0); - - RF_SETBITS(mac, 0x51, 0x4); - if (rf->rf_rev == 8) { - RF_WRITE(mac, 0x43, 0x1f); - } else { - RF_WRITE(mac, 0x52, 0); - RF_FILT_SETBITS(mac, 0x43, 0xfff0, 0x9); - } - - test_lim = 0; - PHY_WRITE(mac, 0x58, 0); - for (i = 0; i < 16; ++i) { - PHY_WRITE(mac, 0x5a, 0x480); - PHY_WRITE(mac, 0x59, 0xc810); - - PHY_WRITE(mac, 0x58, 0xd); - if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) { - phy812_val = bwi_phy812_value(mac, 0x101); - PHY_WRITE(mac, 0x812, phy812_val); - } - PHY_WRITE(mac, 0x15, 0xafb0); - DELAY(10); - - if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) { - phy812_val = bwi_phy812_value(mac, 0x101); - PHY_WRITE(mac, 0x812, phy812_val); - } - PHY_WRITE(mac, 0x15, 0xefb0); - DELAY(10); - - if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) { - phy812_val = bwi_phy812_value(mac, 0x100); - PHY_WRITE(mac, 0x812, phy812_val); - } - PHY_WRITE(mac, 0x15, 0xfff0); - DELAY(20); - - test_lim += PHY_READ(mac, 0x2d); - - PHY_WRITE(mac, 0x58, 0); - if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) { - phy812_val = bwi_phy812_value(mac, 0x101); - PHY_WRITE(mac, 0x812, phy812_val); - } - PHY_WRITE(mac, 0x15, 0xafb0); - } - ++test_lim; - test_lim >>= 9; - - DELAY(10); - - test = 0; - PHY_WRITE(mac, 0x58, 0); - for (i = 0; i < 16; ++i) { - int j; - - rfr_78 = (bitswap4(i) << 1) | 0x20; - RF_WRITE(mac, 0x78, rfr_78); - DELAY(10); - - /* NB: This block is slight different than the above one */ - for (j = 0; j < 16; ++j) { - PHY_WRITE(mac, 0x5a, 0xd80); - PHY_WRITE(mac, 0x59, 0xc810); - - PHY_WRITE(mac, 0x58, 0xd); - if ((phy->phy_flags & BWI_PHY_F_LINKED) || - phy->phy_rev >= 2) { - phy812_val = bwi_phy812_value(mac, 0x101); - PHY_WRITE(mac, 0x812, phy812_val); - } - PHY_WRITE(mac, 0x15, 0xafb0); - DELAY(10); - - if ((phy->phy_flags & BWI_PHY_F_LINKED) || - phy->phy_rev >= 2) { - phy812_val = bwi_phy812_value(mac, 0x101); - PHY_WRITE(mac, 0x812, phy812_val); - } - PHY_WRITE(mac, 0x15, 0xefb0); - DELAY(10); - - if ((phy->phy_flags & BWI_PHY_F_LINKED) || - phy->phy_rev >= 2) { - phy812_val = bwi_phy812_value(mac, 0x100); - PHY_WRITE(mac, 0x812, phy812_val); - } - PHY_WRITE(mac, 0x15, 0xfff0); - DELAY(10); - - test += PHY_READ(mac, 0x2d); - - PHY_WRITE(mac, 0x58, 0); - if ((phy->phy_flags & BWI_PHY_F_LINKED) || - phy->phy_rev >= 2) { - phy812_val = bwi_phy812_value(mac, 0x101); - PHY_WRITE(mac, 0x812, phy812_val); - } - PHY_WRITE(mac, 0x15, 0xafb0); - } - - ++test; - test >>= 8; - - if (test > test_lim) - break; - } - if (i > 15) - rf->rf_calib = rfr_78; - else - rf->rf_calib = calib; - if (rf->rf_calib != 0xffff) { - DPRINTF(sc, BWI_DBG_RF | BWI_DBG_INIT, - "RF calibration value: 0x%04x\n", rf->rf_calib); - rf->rf_flags |= BWI_RF_F_INITED; - } - - /* - * Restore trashes registers - */ - PHY_WRITE(mac, save_phy_regs_comm[0], save_phy_comm[0]); - - for (i = 0; i < SAVE_RF_MAX; ++i) { - int pos = (i + 1) % SAVE_RF_MAX; - - RF_WRITE(mac, save_rf_regs[pos], save_rf[pos]); - } - for (i = 1; i < SAVE_PHY_COMM_MAX; ++i) - PHY_WRITE(mac, save_phy_regs_comm[i], save_phy_comm[i]); - - CSR_WRITE_2(sc, BWI_BBP_ATTEN, bbp_atten); - if (phy->phy_version != 0) - CSR_WRITE_2(sc, BWI_RF_CHAN_EX, rf_chan_ex); - - PHY_WRITE(mac, 0x35, phyr_35); - bwi_rf_workaround(mac, rf->rf_curchan); - - if (phy->phy_mode == IEEE80211_MODE_11B) { - PHY_WRITE(mac, 0x30, phyr_30); - CSR_WRITE_2(sc, BWI_BPHY_CTRL, bphy_ctrl); - } else if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) { - /* XXX Spec only says when PHY is linked (gmode) */ - CSR_CLRBITS_2(sc, BWI_RF_ANTDIV, 0x8000); - - for (i = 0; i < SAVE_PHY_11G_MAX; ++i) { - PHY_WRITE(mac, save_phy_regs_11g[i], - save_phy_11g[i]); - } - - PHY_WRITE(mac, 0x80f, phyr_80f); - PHY_WRITE(mac, 0x810, phyr_810); - } - -#undef SAVE_PHY_11G_MAX -#undef SAVE_PHY_COMM_MAX -#undef SAVE_RF_MAX -} - -static uint16_t -bwi_rf_calibval(struct bwi_mac *mac) -{ - /* http://bcm-specs.sipsolutions.net/RCCTable */ - static const uint16_t rf_calibvals[] = { - 0x2, 0x3, 0x1, 0xf, 0x6, 0x7, 0x5, 0xf, - 0xa, 0xb, 0x9, 0xf, 0xe, 0xf, 0xd, 0xf - }; - uint16_t val, calib; - int idx; - - val = RF_READ(mac, BWI_RFR_BBP_ATTEN); - idx = __SHIFTOUT(val, BWI_RFR_BBP_ATTEN_CALIB_IDX); - KKASSERT(idx < (int)(NELEM(rf_calibvals))); - - calib = rf_calibvals[idx] << 1; - if (val & BWI_RFR_BBP_ATTEN_CALIB_BIT) - calib |= 0x1; - calib |= 0x20; - - return calib; -} - -static __inline int32_t -_bwi_adjust_devide(int32_t num, int32_t den) -{ - if (num < 0) - return (num / den); - else - return (num + den / 2) / den; -} - -/* - * http://bcm-specs.sipsolutions.net/TSSI_to_DBM_Table - * "calculating table entries" - */ -static int -bwi_rf_calc_txpower(int8_t *txpwr, uint8_t idx, const int16_t pa_params[]) -{ - int32_t m1, m2, f, dbm; - int i; - - m1 = _bwi_adjust_devide(16 * pa_params[0] + idx * pa_params[1], 32); - m2 = imax(_bwi_adjust_devide(32768 + idx * pa_params[2], 256), 1); - -#define ITER_MAX 16 - - f = 256; - for (i = 0; i < ITER_MAX; ++i) { - int32_t q, d; - - q = _bwi_adjust_devide( - f * 4096 - _bwi_adjust_devide(m2 * f, 16) * f, 2048); - d = abs(q - f); - f = q; - - if (d < 2) - break; - } - if (i == ITER_MAX) - return EINVAL; - -#undef ITER_MAX - - dbm = _bwi_adjust_devide(m1 * f, 8192); - if (dbm < -127) - dbm = -127; - else if (dbm > 128) - dbm = 128; - - *txpwr = dbm; - return 0; -} - -int -bwi_rf_map_txpower(struct bwi_mac *mac) -{ - struct bwi_softc *sc = mac->mac_sc; - struct bwi_rf *rf = &mac->mac_rf; - struct bwi_phy *phy = &mac->mac_phy; - uint16_t sprom_ofs, val, mask; - int16_t pa_params[3]; - int error = 0, i, ant_gain, reg_txpower_max; - - /* - * Find out max TX power - */ - val = bwi_read_sprom(sc, BWI_SPROM_MAX_TXPWR); - if (phy->phy_mode == IEEE80211_MODE_11A) { - rf->rf_txpower_max = __SHIFTOUT(val, - BWI_SPROM_MAX_TXPWR_MASK_11A); - } else { - rf->rf_txpower_max = __SHIFTOUT(val, - BWI_SPROM_MAX_TXPWR_MASK_11BG); - - if ((sc->sc_card_flags & BWI_CARD_F_PA_GPIO9) && - phy->phy_mode == IEEE80211_MODE_11G) - rf->rf_txpower_max -= 3; - } - if (rf->rf_txpower_max <= 0) { - device_printf(sc->sc_dev, "invalid max txpower in sprom\n"); - rf->rf_txpower_max = 74; - } - DPRINTF(sc, BWI_DBG_RF | BWI_DBG_TXPOWER | BWI_DBG_ATTACH, - "max txpower from sprom: %d dBm\n", rf->rf_txpower_max); - - /* - * Find out region/domain max TX power, which is adjusted - * by antenna gain and 1.5 dBm fluctuation as mentioned - * in v3 spec. - */ - val = bwi_read_sprom(sc, BWI_SPROM_ANT_GAIN); - if (phy->phy_mode == IEEE80211_MODE_11A) - ant_gain = __SHIFTOUT(val, BWI_SPROM_ANT_GAIN_MASK_11A); - else - ant_gain = __SHIFTOUT(val, BWI_SPROM_ANT_GAIN_MASK_11BG); - if (ant_gain == 0xff) { - device_printf(sc->sc_dev, "invalid antenna gain in sprom\n"); - ant_gain = 2; - } - ant_gain *= 4; - DPRINTF(sc, BWI_DBG_RF | BWI_DBG_TXPOWER | BWI_DBG_ATTACH, - "ant gain %d dBm\n", ant_gain); - - reg_txpower_max = 90 - ant_gain - 6; /* XXX magic number */ - DPRINTF(sc, BWI_DBG_RF | BWI_DBG_TXPOWER | BWI_DBG_ATTACH, - "region/domain max txpower %d dBm\n", reg_txpower_max); - - /* - * Force max TX power within region/domain TX power limit - */ - if (rf->rf_txpower_max > reg_txpower_max) - rf->rf_txpower_max = reg_txpower_max; - DPRINTF(sc, BWI_DBG_RF | BWI_DBG_TXPOWER | BWI_DBG_ATTACH, - "max txpower %d dBm\n", rf->rf_txpower_max); - - /* - * Create TSSI to TX power mapping - */ - - if (sc->sc_bbp_id == BWI_BBPID_BCM4301 && - rf->rf_type != BWI_RF_T_BCM2050) { - rf->rf_idle_tssi0 = BWI_DEFAULT_IDLE_TSSI; - bcopy(bwi_txpower_map_11b, rf->rf_txpower_map0, - sizeof(rf->rf_txpower_map0)); - goto back; - } - -#define IS_VALID_PA_PARAM(p) ((p) != 0 && (p) != -1) - - /* - * Extract PA parameters - */ - if (phy->phy_mode == IEEE80211_MODE_11A) - sprom_ofs = BWI_SPROM_PA_PARAM_11A; - else - sprom_ofs = BWI_SPROM_PA_PARAM_11BG; - for (i = 0; i < NELEM(pa_params); ++i) - pa_params[i] = (int16_t)bwi_read_sprom(sc, sprom_ofs + (i * 2)); - - for (i = 0; i < NELEM(pa_params); ++i) { - /* - * If one of the PA parameters from SPROM is not valid, - * fall back to the default values, if there are any. - */ - if (!IS_VALID_PA_PARAM(pa_params[i])) { - const int8_t *txpower_map; - - if (phy->phy_mode == IEEE80211_MODE_11A) { - if_printf(&sc->sc_ic.ic_if, - "no tssi2dbm table for 11a PHY\n"); - return ENXIO; - } - - if (phy->phy_mode == IEEE80211_MODE_11G) { - DPRINTF(sc, - BWI_DBG_RF | BWI_DBG_TXPOWER | BWI_DBG_ATTACH, - "%s\n", "use default 11g TSSI map"); - txpower_map = bwi_txpower_map_11g; - } else { - DPRINTF(sc, - BWI_DBG_RF | BWI_DBG_TXPOWER | BWI_DBG_ATTACH, - "%s\n", "use default 11b TSSI map"); - txpower_map = bwi_txpower_map_11b; - } - - rf->rf_idle_tssi0 = BWI_DEFAULT_IDLE_TSSI; - bcopy(txpower_map, rf->rf_txpower_map0, - sizeof(rf->rf_txpower_map0)); - goto back; - } - } - - /* - * All of the PA parameters from SPROM are valid. - */ - - /* - * Extract idle TSSI from SPROM. - */ - val = bwi_read_sprom(sc, BWI_SPROM_IDLE_TSSI); - DPRINTF(sc, BWI_DBG_RF | BWI_DBG_TXPOWER | BWI_DBG_ATTACH, - "sprom idle tssi: 0x%04x\n", val); - - if (phy->phy_mode == IEEE80211_MODE_11A) - mask = BWI_SPROM_IDLE_TSSI_MASK_11A; - else - mask = BWI_SPROM_IDLE_TSSI_MASK_11BG; - - rf->rf_idle_tssi0 = (int)__SHIFTOUT(val, mask); - if (!IS_VALID_PA_PARAM(rf->rf_idle_tssi0)) - rf->rf_idle_tssi0 = 62; - -#undef IS_VALID_PA_PARAM - - /* - * Calculate TX power map, which is indexed by TSSI - */ - DPRINTF(sc, BWI_DBG_RF | BWI_DBG_ATTACH | BWI_DBG_TXPOWER, - "%s\n", "TSSI-TX power map:"); - for (i = 0; i < BWI_TSSI_MAX; ++i) { - error = bwi_rf_calc_txpower(&rf->rf_txpower_map0[i], i, - pa_params); - if (error) { - if_printf(&sc->sc_ic.ic_if, - "bwi_rf_calc_txpower failed\n"); - break; - } - -#ifdef BWI_DEBUG - if (i != 0 && i % 8 == 0) { - _DPRINTF(sc, - BWI_DBG_RF | BWI_DBG_ATTACH | BWI_DBG_TXPOWER, - "%s\n", ""); - } -#endif - _DPRINTF(sc, BWI_DBG_RF | BWI_DBG_ATTACH | BWI_DBG_TXPOWER, - "%d ", rf->rf_txpower_map0[i]); - } - _DPRINTF(sc, BWI_DBG_RF | BWI_DBG_ATTACH | BWI_DBG_TXPOWER, - "%s\n", ""); -back: - DPRINTF(sc, BWI_DBG_RF | BWI_DBG_TXPOWER | BWI_DBG_ATTACH, - "idle tssi0: %d\n", rf->rf_idle_tssi0); - return error; -} - -static void -bwi_rf_lo_update_11g(struct bwi_mac *mac) -{ - struct bwi_softc *sc = mac->mac_sc; - struct ifnet *ifp = &sc->sc_ic.ic_if; - struct bwi_rf *rf = &mac->mac_rf; - struct bwi_phy *phy = &mac->mac_phy; - struct bwi_tpctl *tpctl = &mac->mac_tpctl; - struct rf_saveregs regs; - uint16_t ant_div, chan_ex; - uint8_t devi_ctrl; - u_int orig_chan; - - DPRINTF(sc, BWI_DBG_RF | BWI_DBG_INIT, "%s enter\n", __func__); - - /* - * Save RF/PHY registers for later restoration - */ - orig_chan = rf->rf_curchan; - bzero(®s, sizeof(regs)); - - if (phy->phy_flags & BWI_PHY_F_LINKED) { - SAVE_PHY_REG(mac, ®s, 429); - SAVE_PHY_REG(mac, ®s, 802); - - PHY_WRITE(mac, 0x429, regs.phy_429 & 0x7fff); - PHY_WRITE(mac, 0x802, regs.phy_802 & 0xfffc); - } - - ant_div = CSR_READ_2(sc, BWI_RF_ANTDIV); - CSR_WRITE_2(sc, BWI_RF_ANTDIV, ant_div | 0x8000); - chan_ex = CSR_READ_2(sc, BWI_RF_CHAN_EX); - - SAVE_PHY_REG(mac, ®s, 15); - SAVE_PHY_REG(mac, ®s, 2a); - SAVE_PHY_REG(mac, ®s, 35); - SAVE_PHY_REG(mac, ®s, 60); - SAVE_RF_REG(mac, ®s, 43); - SAVE_RF_REG(mac, ®s, 7a); - SAVE_RF_REG(mac, ®s, 52); - if (phy->phy_flags & BWI_PHY_F_LINKED) { - SAVE_PHY_REG(mac, ®s, 811); - SAVE_PHY_REG(mac, ®s, 812); - SAVE_PHY_REG(mac, ®s, 814); - SAVE_PHY_REG(mac, ®s, 815); - } - - /* Force to channel 6 */ - bwi_rf_set_chan(mac, 6, 0); - - if (phy->phy_flags & BWI_PHY_F_LINKED) { - PHY_WRITE(mac, 0x429, regs.phy_429 & 0x7fff); - PHY_WRITE(mac, 0x802, regs.phy_802 & 0xfffc); - bwi_mac_dummy_xmit(mac); - } - RF_WRITE(mac, 0x43, 0x6); - - bwi_phy_set_bbp_atten(mac, 2); - - CSR_WRITE_2(sc, BWI_RF_CHAN_EX, 0); - - PHY_WRITE(mac, 0x2e, 0x7f); - PHY_WRITE(mac, 0x80f, 0x78); - PHY_WRITE(mac, 0x35, regs.phy_35 & 0xff7f); - RF_WRITE(mac, 0x7a, regs.rf_7a & 0xfff0); - PHY_WRITE(mac, 0x2b, 0x203); - PHY_WRITE(mac, 0x2a, 0x8a3); - - if (phy->phy_flags & BWI_PHY_F_LINKED) { - PHY_WRITE(mac, 0x814, regs.phy_814 | 0x3); - PHY_WRITE(mac, 0x815, regs.phy_815 & 0xfffc); - PHY_WRITE(mac, 0x811, 0x1b3); - PHY_WRITE(mac, 0x812, 0xb2); - } - - if ((ifp->if_flags & IFF_RUNNING) == 0) - tpctl->tp_ctrl2 = bwi_rf_get_tp_ctrl2(mac); - PHY_WRITE(mac, 0x80f, 0x8078); - - /* - * Measure all RF LO - */ - devi_ctrl = _bwi_rf_lo_update_11g(mac, regs.rf_7a); - - /* - * Restore saved RF/PHY registers - */ - if (phy->phy_flags & BWI_PHY_F_LINKED) { - PHY_WRITE(mac, 0x15, 0xe300); - PHY_WRITE(mac, 0x812, (devi_ctrl << 8) | 0xa0); - DELAY(5); - PHY_WRITE(mac, 0x812, (devi_ctrl << 8) | 0xa2); - DELAY(2); - PHY_WRITE(mac, 0x812, (devi_ctrl << 8) | 0xa3); - } else { - PHY_WRITE(mac, 0x15, devi_ctrl | 0xefa0); - } - - if ((ifp->if_flags & IFF_RUNNING) == 0) - tpctl = NULL; - bwi_rf_lo_adjust(mac, tpctl); - - PHY_WRITE(mac, 0x2e, 0x807f); - if (phy->phy_flags & BWI_PHY_F_LINKED) - PHY_WRITE(mac, 0x2f, 0x202); - else - PHY_WRITE(mac, 0x2f, 0x101); - - CSR_WRITE_2(sc, BWI_RF_CHAN_EX, chan_ex); - - RESTORE_PHY_REG(mac, ®s, 15); - RESTORE_PHY_REG(mac, ®s, 2a); - RESTORE_PHY_REG(mac, ®s, 35); - RESTORE_PHY_REG(mac, ®s, 60); - - RESTORE_RF_REG(mac, ®s, 43); - RESTORE_RF_REG(mac, ®s, 7a); - - regs.rf_52 &= 0xf0; - regs.rf_52 |= (RF_READ(mac, 0x52) & 0xf); - RF_WRITE(mac, 0x52, regs.rf_52); - - CSR_WRITE_2(sc, BWI_RF_ANTDIV, ant_div); - - if (phy->phy_flags & BWI_PHY_F_LINKED) { - RESTORE_PHY_REG(mac, ®s, 811); - RESTORE_PHY_REG(mac, ®s, 812); - RESTORE_PHY_REG(mac, ®s, 814); - RESTORE_PHY_REG(mac, ®s, 815); - RESTORE_PHY_REG(mac, ®s, 429); - RESTORE_PHY_REG(mac, ®s, 802); - } - - bwi_rf_set_chan(mac, orig_chan, 1); -} - -static uint32_t -bwi_rf_lo_devi_measure(struct bwi_mac *mac, uint16_t ctrl) -{ - struct bwi_phy *phy = &mac->mac_phy; - uint32_t devi = 0; - int i; - - if (phy->phy_flags & BWI_PHY_F_LINKED) - ctrl <<= 8; - - for (i = 0; i < 8; ++i) { - if (phy->phy_flags & BWI_PHY_F_LINKED) { - PHY_WRITE(mac, 0x15, 0xe300); - PHY_WRITE(mac, 0x812, ctrl | 0xb0); - DELAY(5); - PHY_WRITE(mac, 0x812, ctrl | 0xb2); - DELAY(2); - PHY_WRITE(mac, 0x812, ctrl | 0xb3); - DELAY(4); - PHY_WRITE(mac, 0x15, 0xf300); - } else { - PHY_WRITE(mac, 0x15, ctrl | 0xefa0); - DELAY(2); - PHY_WRITE(mac, 0x15, ctrl | 0xefe0); - DELAY(4); - PHY_WRITE(mac, 0x15, ctrl | 0xffe0); - } - DELAY(8); - devi += PHY_READ(mac, 0x2d); - } - return devi; -} - -static uint16_t -bwi_rf_get_tp_ctrl2(struct bwi_mac *mac) -{ - uint32_t devi_min; - uint16_t tp_ctrl2 = 0; - int i; - - RF_WRITE(mac, 0x52, 0); - DELAY(10); - devi_min = bwi_rf_lo_devi_measure(mac, 0); - - for (i = 0; i < 16; ++i) { - uint32_t devi; - - RF_WRITE(mac, 0x52, i); - DELAY(10); - devi = bwi_rf_lo_devi_measure(mac, 0); - - if (devi < devi_min) { - devi_min = devi; - tp_ctrl2 = i; - } - } - return tp_ctrl2; -} - -static uint8_t -_bwi_rf_lo_update_11g(struct bwi_mac *mac, uint16_t orig_rf7a) -{ -#define RF_ATTEN_LISTSZ 14 -#define BBP_ATTEN_MAX 4 /* half */ - - static const int rf_atten_list[RF_ATTEN_LISTSZ] = - { 3, 1, 5, 7, 9, 2, 0, 4, 6, 8, 1, 2, 3, 4 }; - static const int rf_atten_init_list[RF_ATTEN_LISTSZ] = - { 0, 3, 1, 5, 7, 3, 2, 0, 4, 6, -1, -1, -1, -1 }; - static const int rf_lo_measure_order[RF_ATTEN_LISTSZ] = - { 3, 1, 5, 7, 9, 2, 0, 4, 6, 8, 10, 11, 12, 13 }; - - struct ifnet *ifp = &mac->mac_sc->sc_ic.ic_if; - struct bwi_rf_lo lo_save, *lo; - uint8_t devi_ctrl = 0; - int idx, adj_rf7a = 0; - - bzero(&lo_save, sizeof(lo_save)); - for (idx = 0; idx < RF_ATTEN_LISTSZ; ++idx) { - int init_rf_atten = rf_atten_init_list[idx]; - int rf_atten = rf_atten_list[idx]; - int bbp_atten; - - for (bbp_atten = 0; bbp_atten < BBP_ATTEN_MAX; ++bbp_atten) { - uint16_t tp_ctrl2, rf7a; - - if ((ifp->if_flags & IFF_RUNNING) == 0) { - if (idx == 0) { - bzero(&lo_save, sizeof(lo_save)); - } else if (init_rf_atten < 0) { - lo = bwi_get_rf_lo(mac, - rf_atten, 2 * bbp_atten); - bcopy(lo, &lo_save, sizeof(lo_save)); - } else { - lo = bwi_get_rf_lo(mac, - init_rf_atten, 0); - bcopy(lo, &lo_save, sizeof(lo_save)); - } - - devi_ctrl = 0; - adj_rf7a = 0; - - /* - * XXX - * Linux driver overflows 'val' - */ - if (init_rf_atten >= 0) { - int val; - - val = rf_atten * 2 + bbp_atten; - if (val > 14) { - adj_rf7a = 1; - if (val > 17) - devi_ctrl = 1; - if (val > 19) - devi_ctrl = 2; - } - } - } else { - lo = bwi_get_rf_lo(mac, - rf_atten, 2 * bbp_atten); - if (!bwi_rf_lo_isused(mac, lo)) - continue; - bcopy(lo, &lo_save, sizeof(lo_save)); - - devi_ctrl = 3; - adj_rf7a = 0; - } - - RF_WRITE(mac, BWI_RFR_ATTEN, rf_atten); - - tp_ctrl2 = mac->mac_tpctl.tp_ctrl2; - if (init_rf_atten < 0) - tp_ctrl2 |= (3 << 4); - RF_WRITE(mac, BWI_RFR_TXPWR, tp_ctrl2); - - DELAY(10); - - bwi_phy_set_bbp_atten(mac, bbp_atten * 2); - - rf7a = orig_rf7a & 0xfff0; - if (adj_rf7a) - rf7a |= 0x8; - RF_WRITE(mac, 0x7a, rf7a); - - lo = bwi_get_rf_lo(mac, - rf_lo_measure_order[idx], bbp_atten * 2); - bwi_rf_lo_measure_11g(mac, &lo_save, lo, devi_ctrl); - } - } - return devi_ctrl; - -#undef RF_ATTEN_LISTSZ -#undef BBP_ATTEN_MAX -} - -static void -bwi_rf_lo_measure_11g(struct bwi_mac *mac, const struct bwi_rf_lo *src_lo, - struct bwi_rf_lo *dst_lo, uint8_t devi_ctrl) -{ -#define LO_ADJUST_MIN 1 -#define LO_ADJUST_MAX 8 -#define LO_ADJUST(hi, lo) { .ctrl_hi = hi, .ctrl_lo = lo } - static const struct bwi_rf_lo rf_lo_adjust[LO_ADJUST_MAX] = { - LO_ADJUST(1, 1), - LO_ADJUST(1, 0), - LO_ADJUST(1, -1), - LO_ADJUST(0, -1), - LO_ADJUST(-1, -1), - LO_ADJUST(-1, 0), - LO_ADJUST(-1, 1), - LO_ADJUST(0, 1) - }; -#undef LO_ADJUST - - struct bwi_rf_lo lo_min; - uint32_t devi_min; - int found, loop_count, adjust_state; - - bcopy(src_lo, &lo_min, sizeof(lo_min)); - RF_LO_WRITE(mac, &lo_min); - devi_min = bwi_rf_lo_devi_measure(mac, devi_ctrl); - - loop_count = 12; /* XXX */ - adjust_state = 0; - do { - struct bwi_rf_lo lo_base; - int i, fin; - - found = 0; - if (adjust_state == 0) { - i = LO_ADJUST_MIN; - fin = LO_ADJUST_MAX; - } else if (adjust_state % 2 == 0) { - i = adjust_state - 1; - fin = adjust_state + 1; - } else { - i = adjust_state - 2; - fin = adjust_state + 2; - } - - if (i < LO_ADJUST_MIN) - i += LO_ADJUST_MAX; - KKASSERT(i <= LO_ADJUST_MAX && i >= LO_ADJUST_MIN); - - if (fin > LO_ADJUST_MAX) - fin -= LO_ADJUST_MAX; - KKASSERT(fin <= LO_ADJUST_MAX && fin >= LO_ADJUST_MIN); - - bcopy(&lo_min, &lo_base, sizeof(lo_base)); - for (;;) { - struct bwi_rf_lo lo; - - lo.ctrl_hi = lo_base.ctrl_hi + - rf_lo_adjust[i - 1].ctrl_hi; - lo.ctrl_lo = lo_base.ctrl_lo + - rf_lo_adjust[i - 1].ctrl_lo; - - if (abs(lo.ctrl_lo) < 9 && abs(lo.ctrl_hi) < 9) { - uint32_t devi; - - RF_LO_WRITE(mac, &lo); - devi = bwi_rf_lo_devi_measure(mac, devi_ctrl); - if (devi < devi_min) { - devi_min = devi; - adjust_state = i; - found = 1; - bcopy(&lo, &lo_min, sizeof(lo_min)); - } - } - if (i == fin) - break; - if (i == LO_ADJUST_MAX) - i = LO_ADJUST_MIN; - else - ++i; - } - } while (loop_count-- && found); - - bcopy(&lo_min, dst_lo, sizeof(*dst_lo)); - -#undef LO_ADJUST_MIN -#undef LO_ADJUST_MAX -} - -static void -bwi_rf_calc_nrssi_slope_11b(struct bwi_mac *mac) -{ -#define SAVE_RF_MAX 3 -#define SAVE_PHY_MAX 8 - - static const uint16_t save_rf_regs[SAVE_RF_MAX] = - { 0x7a, 0x52, 0x43 }; - static const uint16_t save_phy_regs[SAVE_PHY_MAX] = - { 0x30, 0x26, 0x15, 0x2a, 0x20, 0x5a, 0x59, 0x58 }; - - struct bwi_softc *sc = mac->mac_sc; - struct bwi_rf *rf = &mac->mac_rf; - struct bwi_phy *phy = &mac->mac_phy; - uint16_t save_rf[SAVE_RF_MAX]; - uint16_t save_phy[SAVE_PHY_MAX]; - uint16_t ant_div, bbp_atten, chan_ex; - int16_t nrssi[2]; - int i; - - /* - * Save RF/PHY registers for later restoration - */ - for (i = 0; i < SAVE_RF_MAX; ++i) - save_rf[i] = RF_READ(mac, save_rf_regs[i]); - for (i = 0; i < SAVE_PHY_MAX; ++i) - save_phy[i] = PHY_READ(mac, save_phy_regs[i]); - - ant_div = CSR_READ_2(sc, BWI_RF_ANTDIV); - bbp_atten = CSR_READ_2(sc, BWI_BBP_ATTEN); - chan_ex = CSR_READ_2(sc, BWI_RF_CHAN_EX); - - /* - * Calculate nrssi0 - */ - if (phy->phy_rev >= 5) - RF_CLRBITS(mac, 0x7a, 0xff80); - else - RF_CLRBITS(mac, 0x7a, 0xfff0); - PHY_WRITE(mac, 0x30, 0xff); - - CSR_WRITE_2(sc, BWI_BPHY_CTRL, 0x7f7f); - - PHY_WRITE(mac, 0x26, 0); - PHY_SETBITS(mac, 0x15, 0x20); - PHY_WRITE(mac, 0x2a, 0x8a3); - RF_SETBITS(mac, 0x7a, 0x80); - - nrssi[0] = (int16_t)PHY_READ(mac, 0x27); - - /* - * Calculate nrssi1 - */ - RF_CLRBITS(mac, 0x7a, 0xff80); - if (phy->phy_version >= 2) - CSR_WRITE_2(sc, BWI_BBP_ATTEN, 0x40); - else if (phy->phy_version == 0) - CSR_WRITE_2(sc, BWI_BBP_ATTEN, 0x122); - else - CSR_CLRBITS_2(sc, BWI_RF_CHAN_EX, 0xdfff); - - PHY_WRITE(mac, 0x20, 0x3f3f); - PHY_WRITE(mac, 0x15, 0xf330); - - RF_WRITE(mac, 0x5a, 0x60); - RF_CLRBITS(mac, 0x43, 0xff0f); - - PHY_WRITE(mac, 0x5a, 0x480); - PHY_WRITE(mac, 0x59, 0x810); - PHY_WRITE(mac, 0x58, 0xd); - - DELAY(20); - - nrssi[1] = (int16_t)PHY_READ(mac, 0x27); - - /* - * Restore saved RF/PHY registers - */ - PHY_WRITE(mac, save_phy_regs[0], save_phy[0]); - RF_WRITE(mac, save_rf_regs[0], save_rf[0]); - - CSR_WRITE_2(sc, BWI_RF_ANTDIV, ant_div); - - for (i = 1; i < 4; ++i) - PHY_WRITE(mac, save_phy_regs[i], save_phy[i]); - - bwi_rf_workaround(mac, rf->rf_curchan); - - if (phy->phy_version != 0) - CSR_WRITE_2(sc, BWI_RF_CHAN_EX, chan_ex); - - for (; i < SAVE_PHY_MAX; ++i) - PHY_WRITE(mac, save_phy_regs[i], save_phy[i]); - - for (i = 1; i < SAVE_RF_MAX; ++i) - RF_WRITE(mac, save_rf_regs[i], save_rf[i]); - - /* - * Install calculated narrow RSSI values - */ - if (nrssi[0] == nrssi[1]) - rf->rf_nrssi_slope = 0x10000; - else - rf->rf_nrssi_slope = 0x400000 / (nrssi[0] - nrssi[1]); - if (nrssi[0] <= -4) { - rf->rf_nrssi[0] = nrssi[0]; - rf->rf_nrssi[1] = nrssi[1]; - } - -#undef SAVE_RF_MAX -#undef SAVE_PHY_MAX -} - -static void -bwi_rf_set_nrssi_ofs_11g(struct bwi_mac *mac) -{ -#define SAVE_RF_MAX 2 -#define SAVE_PHY_COMM_MAX 10 -#define SAVE_PHY6_MAX 8 - - static const uint16_t save_rf_regs[SAVE_RF_MAX] = - { 0x7a, 0x43 }; - static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] = { - 0x0001, 0x0811, 0x0812, 0x0814, - 0x0815, 0x005a, 0x0059, 0x0058, - 0x000a, 0x0003 - }; - static const uint16_t save_phy6_regs[SAVE_PHY6_MAX] = { - 0x002e, 0x002f, 0x080f, 0x0810, - 0x0801, 0x0060, 0x0014, 0x0478 - }; - - struct bwi_phy *phy = &mac->mac_phy; - uint16_t save_rf[SAVE_RF_MAX]; - uint16_t save_phy_comm[SAVE_PHY_COMM_MAX]; - uint16_t save_phy6[SAVE_PHY6_MAX]; - uint16_t rf7b = 0xffff; - int16_t nrssi; - int i, phy6_idx = 0; - - for (i = 0; i < SAVE_PHY_COMM_MAX; ++i) - save_phy_comm[i] = PHY_READ(mac, save_phy_comm_regs[i]); - for (i = 0; i < SAVE_RF_MAX; ++i) - save_rf[i] = RF_READ(mac, save_rf_regs[i]); - - PHY_CLRBITS(mac, 0x429, 0x8000); - PHY_FILT_SETBITS(mac, 0x1, 0x3fff, 0x4000); - PHY_SETBITS(mac, 0x811, 0xc); - PHY_FILT_SETBITS(mac, 0x812, 0xfff3, 0x4); - PHY_CLRBITS(mac, 0x802, 0x3); - - if (phy->phy_rev >= 6) { - for (i = 0; i < SAVE_PHY6_MAX; ++i) - save_phy6[i] = PHY_READ(mac, save_phy6_regs[i]); - - PHY_WRITE(mac, 0x2e, 0); - PHY_WRITE(mac, 0x2f, 0); - PHY_WRITE(mac, 0x80f, 0); - PHY_WRITE(mac, 0x810, 0); - PHY_SETBITS(mac, 0x478, 0x100); - PHY_SETBITS(mac, 0x801, 0x40); - PHY_SETBITS(mac, 0x60, 0x40); - PHY_SETBITS(mac, 0x14, 0x200); - } - - RF_SETBITS(mac, 0x7a, 0x70); - RF_SETBITS(mac, 0x7a, 0x80); - - DELAY(30); - - nrssi = bwi_nrssi_11g(mac); - if (nrssi == 31) { - for (i = 7; i >= 4; --i) { - RF_WRITE(mac, 0x7b, i); - DELAY(20); - nrssi = bwi_nrssi_11g(mac); - if (nrssi < 31 && rf7b == 0xffff) - rf7b = i; - } - if (rf7b == 0xffff) - rf7b = 4; - } else { - struct bwi_gains gains; - - RF_CLRBITS(mac, 0x7a, 0xff80); - - PHY_SETBITS(mac, 0x814, 0x1); - PHY_CLRBITS(mac, 0x815, 0x1); - PHY_SETBITS(mac, 0x811, 0xc); - PHY_SETBITS(mac, 0x812, 0xc); - PHY_SETBITS(mac, 0x811, 0x30); - PHY_SETBITS(mac, 0x812, 0x30); - PHY_WRITE(mac, 0x5a, 0x480); - PHY_WRITE(mac, 0x59, 0x810); - PHY_WRITE(mac, 0x58, 0xd); - if (phy->phy_version == 0) - PHY_WRITE(mac, 0x3, 0x122); - else - PHY_SETBITS(mac, 0xa, 0x2000); - PHY_SETBITS(mac, 0x814, 0x4); - PHY_CLRBITS(mac, 0x815, 0x4); - PHY_FILT_SETBITS(mac, 0x3, 0xff9f, 0x40); - RF_SETBITS(mac, 0x7a, 0xf); - - bzero(&gains, sizeof(gains)); - gains.tbl_gain1 = 3; - gains.tbl_gain2 = 0; - gains.phy_gain = 1; - bwi_set_gains(mac, &gains); - - RF_FILT_SETBITS(mac, 0x43, 0xf0, 0xf); - DELAY(30); - - nrssi = bwi_nrssi_11g(mac); - if (nrssi == -32) { - for (i = 0; i < 4; ++i) { - RF_WRITE(mac, 0x7b, i); - DELAY(20); - nrssi = bwi_nrssi_11g(mac); - if (nrssi > -31 && rf7b == 0xffff) - rf7b = i; - } - if (rf7b == 0xffff) - rf7b = 3; - } else { - rf7b = 0; - } - } - RF_WRITE(mac, 0x7b, rf7b); - - /* - * Restore saved RF/PHY registers - */ - if (phy->phy_rev >= 6) { - for (phy6_idx = 0; phy6_idx < 4; ++phy6_idx) { - PHY_WRITE(mac, save_phy6_regs[phy6_idx], - save_phy6[phy6_idx]); - } - } - - /* Saved PHY registers 0, 1, 2 are handled later */ - for (i = 3; i < SAVE_PHY_COMM_MAX; ++i) - PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]); - - for (i = SAVE_RF_MAX - 1; i >= 0; --i) - RF_WRITE(mac, save_rf_regs[i], save_rf[i]); - - PHY_SETBITS(mac, 0x802, 0x3); - PHY_SETBITS(mac, 0x429, 0x8000); - - bwi_set_gains(mac, NULL); - - if (phy->phy_rev >= 6) { - for (; phy6_idx < SAVE_PHY6_MAX; ++phy6_idx) { - PHY_WRITE(mac, save_phy6_regs[phy6_idx], - save_phy6[phy6_idx]); - } - } - - PHY_WRITE(mac, save_phy_comm_regs[0], save_phy_comm[0]); - PHY_WRITE(mac, save_phy_comm_regs[2], save_phy_comm[2]); - PHY_WRITE(mac, save_phy_comm_regs[1], save_phy_comm[1]); - -#undef SAVE_RF_MAX -#undef SAVE_PHY_COMM_MAX -#undef SAVE_PHY6_MAX -} - -static void -bwi_rf_calc_nrssi_slope_11g(struct bwi_mac *mac) -{ -#define SAVE_RF_MAX 3 -#define SAVE_PHY_COMM_MAX 4 -#define SAVE_PHY3_MAX 8 - - static const uint16_t save_rf_regs[SAVE_RF_MAX] = - { 0x7a, 0x52, 0x43 }; - static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] = - { 0x15, 0x5a, 0x59, 0x58 }; - static const uint16_t save_phy3_regs[SAVE_PHY3_MAX] = { - 0x002e, 0x002f, 0x080f, 0x0810, - 0x0801, 0x0060, 0x0014, 0x0478 - }; - - struct bwi_softc *sc = mac->mac_sc; - struct bwi_phy *phy = &mac->mac_phy; - struct bwi_rf *rf = &mac->mac_rf; - uint16_t save_rf[SAVE_RF_MAX]; - uint16_t save_phy_comm[SAVE_PHY_COMM_MAX]; - uint16_t save_phy3[SAVE_PHY3_MAX]; - uint16_t ant_div, bbp_atten, chan_ex; - struct bwi_gains gains; - int16_t nrssi[2]; - int i, phy3_idx = 0; - - if (rf->rf_rev >= 9) - return; - else if (rf->rf_rev == 8) - bwi_rf_set_nrssi_ofs_11g(mac); - - PHY_CLRBITS(mac, 0x429, 0x8000); - PHY_CLRBITS(mac, 0x802, 0x3); - - /* - * Save RF/PHY registers for later restoration - */ - ant_div = CSR_READ_2(sc, BWI_RF_ANTDIV); - CSR_SETBITS_2(sc, BWI_RF_ANTDIV, 0x8000); - - for (i = 0; i < SAVE_RF_MAX; ++i) - save_rf[i] = RF_READ(mac, save_rf_regs[i]); - for (i = 0; i < SAVE_PHY_COMM_MAX; ++i) - save_phy_comm[i] = PHY_READ(mac, save_phy_comm_regs[i]); - - bbp_atten = CSR_READ_2(sc, BWI_BBP_ATTEN); - chan_ex = CSR_READ_2(sc, BWI_RF_CHAN_EX); - - if (phy->phy_rev >= 3) { - for (i = 0; i < SAVE_PHY3_MAX; ++i) - save_phy3[i] = PHY_READ(mac, save_phy3_regs[i]); - - PHY_WRITE(mac, 0x2e, 0); - PHY_WRITE(mac, 0x810, 0); - - if (phy->phy_rev == 4 || phy->phy_rev == 6 || - phy->phy_rev == 7) { - PHY_SETBITS(mac, 0x478, 0x100); - PHY_SETBITS(mac, 0x810, 0x40); - } else if (phy->phy_rev == 3 || phy->phy_rev == 5) { - PHY_CLRBITS(mac, 0x810, 0x40); - } - - PHY_SETBITS(mac, 0x60, 0x40); - PHY_SETBITS(mac, 0x14, 0x200); - } - - /* - * Calculate nrssi0 - */ - RF_SETBITS(mac, 0x7a, 0x70); - - bzero(&gains, sizeof(gains)); - gains.tbl_gain1 = 0; - gains.tbl_gain2 = 8; - gains.phy_gain = 0; - bwi_set_gains(mac, &gains); - - RF_CLRBITS(mac, 0x7a, 0xff08); - if (phy->phy_rev >= 2) { - PHY_FILT_SETBITS(mac, 0x811, 0xffcf, 0x30); - PHY_FILT_SETBITS(mac, 0x812, 0xffcf, 0x10); - } - - RF_SETBITS(mac, 0x7a, 0x80); - DELAY(20); - nrssi[0] = bwi_nrssi_11g(mac); - - /* - * Calculate nrssi1 - */ - RF_CLRBITS(mac, 0x7a, 0xff80); - if (phy->phy_version >= 2) - PHY_FILT_SETBITS(mac, 0x3, 0xff9f, 0x40); - CSR_SETBITS_2(sc, BWI_RF_CHAN_EX, 0x2000); - - RF_SETBITS(mac, 0x7a, 0xf); - PHY_WRITE(mac, 0x15, 0xf330); - if (phy->phy_rev >= 2) { - PHY_FILT_SETBITS(mac, 0x812, 0xffcf, 0x20); - PHY_FILT_SETBITS(mac, 0x811, 0xffcf, 0x20); - } - - bzero(&gains, sizeof(gains)); - gains.tbl_gain1 = 3; - gains.tbl_gain2 = 0; - gains.phy_gain = 1; - bwi_set_gains(mac, &gains); - - if (rf->rf_rev == 8) { - RF_WRITE(mac, 0x43, 0x1f); - } else { - RF_FILT_SETBITS(mac, 0x52, 0xff0f, 0x60); - RF_FILT_SETBITS(mac, 0x43, 0xfff0, 0x9); - } - PHY_WRITE(mac, 0x5a, 0x480); - PHY_WRITE(mac, 0x59, 0x810); - PHY_WRITE(mac, 0x58, 0xd); - DELAY(20); - - nrssi[1] = bwi_nrssi_11g(mac); - - /* - * Install calculated narrow RSSI values - */ - if (nrssi[1] == nrssi[0]) - rf->rf_nrssi_slope = 0x10000; - else - rf->rf_nrssi_slope = 0x400000 / (nrssi[0] - nrssi[1]); - if (nrssi[0] >= -4) { - rf->rf_nrssi[0] = nrssi[1]; - rf->rf_nrssi[1] = nrssi[0]; - } - - /* - * Restore saved RF/PHY registers - */ - if (phy->phy_rev >= 3) { - for (phy3_idx = 0; phy3_idx < 4; ++phy3_idx) { - PHY_WRITE(mac, save_phy3_regs[phy3_idx], - save_phy3[phy3_idx]); - } - } - if (phy->phy_rev >= 2) { - PHY_CLRBITS(mac, 0x812, 0x30); - PHY_CLRBITS(mac, 0x811, 0x30); - } - - for (i = 0; i < SAVE_RF_MAX; ++i) - RF_WRITE(mac, save_rf_regs[i], save_rf[i]); - - CSR_WRITE_2(sc, BWI_RF_ANTDIV, ant_div); - CSR_WRITE_2(sc, BWI_BBP_ATTEN, bbp_atten); - CSR_WRITE_2(sc, BWI_RF_CHAN_EX, chan_ex); - - for (i = 0; i < SAVE_PHY_COMM_MAX; ++i) - PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]); - - bwi_rf_workaround(mac, rf->rf_curchan); - PHY_SETBITS(mac, 0x802, 0x3); - bwi_set_gains(mac, NULL); - PHY_SETBITS(mac, 0x429, 0x8000); - - if (phy->phy_rev >= 3) { - for (; phy3_idx < SAVE_PHY3_MAX; ++phy3_idx) { - PHY_WRITE(mac, save_phy3_regs[phy3_idx], - save_phy3[phy3_idx]); - } - } - - bwi_rf_init_sw_nrssi_table(mac); - bwi_rf_set_nrssi_thr_11g(mac); - -#undef SAVE_RF_MAX -#undef SAVE_PHY_COMM_MAX -#undef SAVE_PHY3_MAX -} - -static void -bwi_rf_init_sw_nrssi_table(struct bwi_mac *mac) -{ - struct bwi_rf *rf = &mac->mac_rf; - int d, i; - - d = 0x1f - rf->rf_nrssi[0]; - for (i = 0; i < BWI_NRSSI_TBLSZ; ++i) { - int val; - - val = (((i - d) * rf->rf_nrssi_slope) / 0x10000) + 0x3a; - if (val < 0) - val = 0; - else if (val > 0x3f) - val = 0x3f; - - rf->rf_nrssi_table[i] = val; - } -} - -void -bwi_rf_init_hw_nrssi_table(struct bwi_mac *mac, uint16_t adjust) -{ - int i; - - for (i = 0; i < BWI_NRSSI_TBLSZ; ++i) { - int16_t val; - - val = bwi_nrssi_read(mac, i); - - val -= adjust; - if (val < -32) - val = -32; - else if (val > 31) - val = 31; - - bwi_nrssi_write(mac, i, val); - } -} - -static void -bwi_rf_set_nrssi_thr_11b(struct bwi_mac *mac) -{ - struct bwi_rf *rf = &mac->mac_rf; - int32_t thr; - - if (rf->rf_type != BWI_RF_T_BCM2050 || - (mac->mac_sc->sc_card_flags & BWI_CARD_F_SW_NRSSI) == 0) - return; - - /* - * Calculate nrssi threshold - */ - if (rf->rf_rev >= 6) { - thr = (rf->rf_nrssi[1] - rf->rf_nrssi[0]) * 32; - thr += 20 * (rf->rf_nrssi[0] + 1); - thr /= 40; - } else { - thr = rf->rf_nrssi[1] - 5; - } - if (thr < 0) - thr = 0; - else if (thr > 0x3e) - thr = 0x3e; - - PHY_READ(mac, BWI_PHYR_NRSSI_THR_11B); /* dummy read */ - PHY_WRITE(mac, BWI_PHYR_NRSSI_THR_11B, (((uint16_t)thr) << 8) | 0x1c); - - if (rf->rf_rev >= 6) { - PHY_WRITE(mac, 0x87, 0xe0d); - PHY_WRITE(mac, 0x86, 0xc0b); - PHY_WRITE(mac, 0x85, 0xa09); - PHY_WRITE(mac, 0x84, 0x808); - PHY_WRITE(mac, 0x83, 0x808); - PHY_WRITE(mac, 0x82, 0x604); - PHY_WRITE(mac, 0x81, 0x302); - PHY_WRITE(mac, 0x80, 0x100); - } -} - -static __inline int32_t -_nrssi_threshold(const struct bwi_rf *rf, int32_t val) -{ - val *= (rf->rf_nrssi[1] - rf->rf_nrssi[0]); - val += (rf->rf_nrssi[0] << 6); - if (val < 32) - val += 31; - else - val += 32; - val >>= 6; - if (val < -31) - val = -31; - else if (val > 31) - val = 31; - return val; -} - -static void -bwi_rf_set_nrssi_thr_11g(struct bwi_mac *mac) -{ - int32_t thr1, thr2; - uint16_t thr; - - /* - * Find the two nrssi thresholds - */ - if ((mac->mac_phy.phy_flags & BWI_PHY_F_LINKED) == 0 || - (mac->mac_sc->sc_card_flags & BWI_CARD_F_SW_NRSSI) == 0) { - int16_t nrssi; - - nrssi = bwi_nrssi_read(mac, 0x20); - if (nrssi >= 32) - nrssi -= 64; - - if (nrssi < 3) { - thr1 = 0x2b; - thr2 = 0x27; - } else { - thr1 = 0x2d; - thr2 = 0x2b; - } - } else { - /* TODO Interfere mode */ - thr1 = _nrssi_threshold(&mac->mac_rf, 0x11); - thr2 = _nrssi_threshold(&mac->mac_rf, 0xe); - } - -#define NRSSI_THR1_MASK __BITS(5, 0) -#define NRSSI_THR2_MASK __BITS(11, 6) - - thr = __SHIFTIN((uint32_t)thr1, NRSSI_THR1_MASK) | - __SHIFTIN((uint32_t)thr2, NRSSI_THR2_MASK); - PHY_FILT_SETBITS(mac, BWI_PHYR_NRSSI_THR_11G, 0xf000, thr); - -#undef NRSSI_THR1_MASK -#undef NRSSI_THR2_MASK -} - -void -bwi_rf_clear_tssi(struct bwi_mac *mac) -{ - /* XXX use function pointer */ - if (mac->mac_phy.phy_mode == IEEE80211_MODE_11A) { - /* TODO:11A */ - } else { - uint16_t val; - int i; - - val = __SHIFTIN(BWI_INVALID_TSSI, BWI_LO_TSSI_MASK) | - __SHIFTIN(BWI_INVALID_TSSI, BWI_HI_TSSI_MASK); - - for (i = 0; i < 2; ++i) { - MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, - BWI_COMM_MOBJ_TSSI_DS + (i * 2), val); - } - - for (i = 0; i < 2; ++i) { - MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, - BWI_COMM_MOBJ_TSSI_OFDM + (i * 2), val); - } - } -} - -void -bwi_rf_clear_state(struct bwi_rf *rf) -{ - int i; - - rf->rf_flags &= ~BWI_RF_CLEAR_FLAGS; - bzero(rf->rf_lo, sizeof(rf->rf_lo)); - bzero(rf->rf_lo_used, sizeof(rf->rf_lo_used)); - - rf->rf_nrssi_slope = 0; - rf->rf_nrssi[0] = BWI_INVALID_NRSSI; - rf->rf_nrssi[1] = BWI_INVALID_NRSSI; - - for (i = 0; i < BWI_NRSSI_TBLSZ; ++i) - rf->rf_nrssi_table[i] = i; - - rf->rf_lo_gain = 0; - rf->rf_rx_gain = 0; - - bcopy(rf->rf_txpower_map0, rf->rf_txpower_map, - sizeof(rf->rf_txpower_map)); - rf->rf_idle_tssi = rf->rf_idle_tssi0; -} - -static void -bwi_rf_on_11a(struct bwi_mac *mac) -{ - /* TODO:11A */ -} - -static void -bwi_rf_on_11bg(struct bwi_mac *mac) -{ - struct bwi_phy *phy = &mac->mac_phy; - - PHY_WRITE(mac, 0x15, 0x8000); - PHY_WRITE(mac, 0x15, 0xcc00); - if (phy->phy_flags & BWI_PHY_F_LINKED) - PHY_WRITE(mac, 0x15, 0xc0); - else - PHY_WRITE(mac, 0x15, 0); - - bwi_rf_set_chan(mac, 6 /* XXX */, 1); -} - -void -bwi_rf_set_ant_mode(struct bwi_mac *mac, int ant_mode) -{ - struct bwi_softc *sc = mac->mac_sc; - struct bwi_phy *phy = &mac->mac_phy; - uint16_t val; - - KKASSERT(ant_mode == BWI_ANT_MODE_0 || - ant_mode == BWI_ANT_MODE_1 || - ant_mode == BWI_ANT_MODE_AUTO); - - HFLAGS_CLRBITS(mac, BWI_HFLAG_AUTO_ANTDIV); - - if (phy->phy_mode == IEEE80211_MODE_11B) { - /* NOTE: v4/v3 conflicts, take v3 */ - if (mac->mac_rev == 2) - val = BWI_ANT_MODE_AUTO; - else - val = ant_mode; - val <<= 7; - PHY_FILT_SETBITS(mac, 0x3e2, 0xfe7f, val); - } else { /* 11a/g */ - /* XXX reg/value naming */ - val = ant_mode << 7; - PHY_FILT_SETBITS(mac, 0x401, 0x7e7f, val); - - if (ant_mode == BWI_ANT_MODE_AUTO) - PHY_CLRBITS(mac, 0x42b, 0x100); - - if (phy->phy_mode == IEEE80211_MODE_11A) { - /* TODO:11A */ - } else { /* 11g */ - if (ant_mode == BWI_ANT_MODE_AUTO) - PHY_SETBITS(mac, 0x48c, 0x2000); - else - PHY_CLRBITS(mac, 0x48c, 0x2000); - - if (phy->phy_rev >= 2) { - PHY_SETBITS(mac, 0x461, 0x10); - PHY_FILT_SETBITS(mac, 0x4ad, 0xff00, 0x15); - if (phy->phy_rev == 2) { - PHY_WRITE(mac, 0x427, 0x8); - } else { - PHY_FILT_SETBITS(mac, 0x427, - 0xff00, 0x8); - } - - if (phy->phy_rev >= 6) - PHY_WRITE(mac, 0x49b, 0xdc); - } - } - } - - /* XXX v4 set AUTO_ANTDIV unconditionally */ - if (ant_mode == BWI_ANT_MODE_AUTO) - HFLAGS_SETBITS(mac, BWI_HFLAG_AUTO_ANTDIV); - - val = ant_mode << 8; - MOBJ_FILT_SETBITS_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_TX_BEACON, - 0xfc3f, val); - MOBJ_FILT_SETBITS_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_TX_ACK, - 0xfc3f, val); - MOBJ_FILT_SETBITS_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_TX_PROBE_RESP, - 0xfc3f, val); - - /* XXX what's these */ - if (phy->phy_mode == IEEE80211_MODE_11B) - CSR_SETBITS_2(sc, 0x5e, 0x4); - - CSR_WRITE_4(sc, 0x100, 0x1000000); - if (mac->mac_rev < 5) - CSR_WRITE_4(sc, 0x10c, 0x1000000); - - mac->mac_rf.rf_ant_mode = ant_mode; -} - -int -bwi_rf_get_latest_tssi(struct bwi_mac *mac, int8_t tssi[], uint16_t ofs) -{ - int i; - - for (i = 0; i < 4; ) { - uint16_t val; - - val = MOBJ_READ_2(mac, BWI_COMM_MOBJ, ofs + i); - tssi[i++] = (int8_t)__SHIFTOUT(val, BWI_LO_TSSI_MASK); - tssi[i++] = (int8_t)__SHIFTOUT(val, BWI_HI_TSSI_MASK); - } - - for (i = 0; i < 4; ++i) { - if (tssi[i] == BWI_INVALID_TSSI) - return EINVAL; - } - return 0; -} - -int -bwi_rf_tssi2dbm(struct bwi_mac *mac, int8_t tssi, int8_t *txpwr) -{ - struct bwi_rf *rf = &mac->mac_rf; - int pwr_idx; - - pwr_idx = rf->rf_idle_tssi + (int)tssi - rf->rf_base_tssi; -#if 0 - if (pwr_idx < 0 || pwr_idx >= BWI_TSSI_MAX) - return EINVAL; -#else - if (pwr_idx < 0) - pwr_idx = 0; - else if (pwr_idx >= BWI_TSSI_MAX) - pwr_idx = BWI_TSSI_MAX - 1; -#endif - - *txpwr = rf->rf_txpower_map[pwr_idx]; - return 0; -} - -static int -bwi_rf_calc_rssi_bcm2050(struct bwi_mac *mac, const struct bwi_rxbuf_hdr *hdr) -{ - uint16_t flags1, flags3; - int rssi, lna_gain; - - rssi = hdr->rxh_rssi; - flags1 = le16toh(hdr->rxh_flags1); - flags3 = le16toh(hdr->rxh_flags3); - -#define NEW_BCM2050_RSSI -#ifdef NEW_BCM2050_RSSI - if (flags1 & BWI_RXH_F1_OFDM) { - if (rssi > 127) - rssi -= 256; - if (flags3 & BWI_RXH_F3_BCM2050_RSSI) - rssi += 17; - else - rssi -= 4; - return rssi; - } - - if (mac->mac_sc->sc_card_flags & BWI_CARD_F_SW_NRSSI) { - struct bwi_rf *rf = &mac->mac_rf; - - if (rssi >= BWI_NRSSI_TBLSZ) - rssi = BWI_NRSSI_TBLSZ - 1; - - rssi = ((31 - (int)rf->rf_nrssi_table[rssi]) * -131) / 128; - rssi -= 67; - } else { - rssi = ((31 - rssi) * -149) / 128; - rssi -= 68; - } - - if (mac->mac_phy.phy_mode != IEEE80211_MODE_11G) - return rssi; - - if (flags3 & BWI_RXH_F3_BCM2050_RSSI) - rssi += 20; - - lna_gain = __SHIFTOUT(le16toh(hdr->rxh_phyinfo), - BWI_RXH_PHYINFO_LNAGAIN); - DPRINTF(mac->mac_sc, BWI_DBG_RF | BWI_DBG_RX, - "lna_gain %d, phyinfo 0x%04x\n", - lna_gain, le16toh(hdr->rxh_phyinfo)); - switch (lna_gain) { - case 0: - rssi += 27; - break; - case 1: - rssi += 6; - break; - case 2: - rssi += 12; - break; - case 3: - /* - * XXX - * According to v3 spec, we should do _nothing_ here, - * but it seems that the result RSSI will be too low - * (relative to what ath(4) says). Raise it a little - * bit. - */ - rssi += 5; - break; - default: - panic("impossible lna gain %d", lna_gain); - } -#else /* !NEW_BCM2050_RSSI */ - lna_gain = 0; /* shut up gcc warning */ - - if (flags1 & BWI_RXH_F1_OFDM) { - if (rssi > 127) - rssi -= 256; - rssi = (rssi * 73) / 64; - - if (flags3 & BWI_RXH_F3_BCM2050_RSSI) - rssi += 25; - else - rssi -= 3; - return rssi; - } - - if (mac->mac_sc->sc_card_flags & BWI_CARD_F_SW_NRSSI) { - struct bwi_rf *rf = &mac->mac_rf; - - if (rssi >= BWI_NRSSI_TBLSZ) - rssi = BWI_NRSSI_TBLSZ - 1; - - rssi = ((31 - (int)rf->rf_nrssi_table[rssi]) * -131) / 128; - rssi -= 57; - } else { - rssi = ((31 - rssi) * -149) / 128; - rssi -= 68; - } - - if (mac->mac_phy.phy_mode != IEEE80211_MODE_11G) - return rssi; - - if (flags3 & BWI_RXH_F3_BCM2050_RSSI) - rssi += 25; -#endif /* NEW_BCM2050_RSSI */ - return rssi; -} - -static int -bwi_rf_calc_rssi_bcm2053(struct bwi_mac *mac, const struct bwi_rxbuf_hdr *hdr) -{ - uint16_t flags1; - int rssi; - - rssi = (((int)hdr->rxh_rssi - 11) * 103) / 64; - - flags1 = le16toh(hdr->rxh_flags1); - if (flags1 & BWI_RXH_F1_BCM2053_RSSI) - rssi -= 109; - else - rssi -= 83; - return rssi; -} - -static int -bwi_rf_calc_rssi_bcm2060(struct bwi_mac *mac, const struct bwi_rxbuf_hdr *hdr) -{ - int rssi; - - rssi = hdr->rxh_rssi; - if (rssi > 127) - rssi -= 256; - return rssi; -} - -static uint16_t -bwi_rf_lo_measure_11b(struct bwi_mac *mac) -{ - uint16_t val; - int i; - - val = 0; - for (i = 0; i < 10; ++i) { - PHY_WRITE(mac, 0x15, 0xafa0); - DELAY(1); - PHY_WRITE(mac, 0x15, 0xefa0); - DELAY(10); - PHY_WRITE(mac, 0x15, 0xffa0); - DELAY(40); - - val += PHY_READ(mac, 0x2c); - } - return val; -} - -static void -bwi_rf_lo_update_11b(struct bwi_mac *mac) -{ - struct bwi_softc *sc = mac->mac_sc; - struct bwi_rf *rf = &mac->mac_rf; - struct rf_saveregs regs; - uint16_t rf_val, phy_val, min_val, val; - uint16_t rf52, bphy_ctrl; - int i; - - DPRINTF(sc, BWI_DBG_RF | BWI_DBG_INIT, "%s enter\n", __func__); - - bzero(®s, sizeof(regs)); - bphy_ctrl = 0; - - /* - * Save RF/PHY registers for later restoration - */ - SAVE_PHY_REG(mac, ®s, 15); - rf52 = RF_READ(mac, 0x52) & 0xfff0; - if (rf->rf_type == BWI_RF_T_BCM2050) { - SAVE_PHY_REG(mac, ®s, 0a); - SAVE_PHY_REG(mac, ®s, 2a); - SAVE_PHY_REG(mac, ®s, 35); - SAVE_PHY_REG(mac, ®s, 03); - SAVE_PHY_REG(mac, ®s, 01); - SAVE_PHY_REG(mac, ®s, 30); - - SAVE_RF_REG(mac, ®s, 43); - SAVE_RF_REG(mac, ®s, 7a); - - bphy_ctrl = CSR_READ_2(sc, BWI_BPHY_CTRL); - - SAVE_RF_REG(mac, ®s, 52); - regs.rf_52 &= 0xf0; - - PHY_WRITE(mac, 0x30, 0xff); - CSR_WRITE_2(sc, BWI_PHY_CTRL, 0x3f3f); - PHY_WRITE(mac, 0x35, regs.phy_35 & 0xff7f); - RF_WRITE(mac, 0x7a, regs.rf_7a & 0xfff0); - } - - PHY_WRITE(mac, 0x15, 0xb000); - - if (rf->rf_type == BWI_RF_T_BCM2050) { - PHY_WRITE(mac, 0x2b, 0x203); - PHY_WRITE(mac, 0x2a, 0x8a3); - } else { - PHY_WRITE(mac, 0x2b, 0x1402); - } - - /* - * Setup RF signal - */ - rf_val = 0; - min_val = UINT16_MAX; - - for (i = 0; i < 4; ++i) { - RF_WRITE(mac, 0x52, rf52 | i); - bwi_rf_lo_measure_11b(mac); /* Ignore return value */ - } - for (i = 0; i < 10; ++i) { - RF_WRITE(mac, 0x52, rf52 | i); - - val = bwi_rf_lo_measure_11b(mac) / 10; - if (val < min_val) { - min_val = val; - rf_val = i; - } - } - RF_WRITE(mac, 0x52, rf52 | rf_val); - - /* - * Setup PHY signal - */ - phy_val = 0; - min_val = UINT16_MAX; - - for (i = -4; i < 5; i += 2) { - int j; - - for (j = -4; j < 5; j += 2) { - uint16_t phy2f; - - phy2f = (0x100 * i) + j; - if (j < 0) - phy2f += 0x100; - PHY_WRITE(mac, 0x2f, phy2f); - - val = bwi_rf_lo_measure_11b(mac) / 10; - if (val < min_val) { - min_val = val; - phy_val = phy2f; - } - } - } - PHY_WRITE(mac, 0x2f, phy_val + 0x101); - - /* - * Restore saved RF/PHY registers - */ - if (rf->rf_type == BWI_RF_T_BCM2050) { - RESTORE_PHY_REG(mac, ®s, 0a); - RESTORE_PHY_REG(mac, ®s, 2a); - RESTORE_PHY_REG(mac, ®s, 35); - RESTORE_PHY_REG(mac, ®s, 03); - RESTORE_PHY_REG(mac, ®s, 01); - RESTORE_PHY_REG(mac, ®s, 30); - - RESTORE_RF_REG(mac, ®s, 43); - RESTORE_RF_REG(mac, ®s, 7a); - - RF_FILT_SETBITS(mac, 0x52, 0xf, regs.rf_52); - - CSR_WRITE_2(sc, BWI_BPHY_CTRL, bphy_ctrl); - } - RESTORE_PHY_REG(mac, ®s, 15); - - bwi_rf_workaround(mac, rf->rf_curchan); -} diff --git a/sys/dev/netif/bwi/bwirf.h b/sys/dev/netif/bwi/bwirf.h deleted file mode 100644 index d926e37dd0..0000000000 --- a/sys/dev/netif/bwi/bwirf.h +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright (c) 2007 The DragonFly Project. All rights reserved. - * - * This code is derived from software contributed to The DragonFly Project - * by Sepherosa Ziehau - * - * 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. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * 3. Neither the name of The DragonFly Project nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific, prior written permission. - * - * 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 MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, 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 DAMAGE. - * - * $DragonFly: src/sys/dev/netif/bwi/bwirf.h,v 1.3 2007/10/03 04:53:19 sephe Exp $ - */ - -#ifndef _BWI_RF_H -#define _BWI_RF_H - -int bwi_rf_attach(struct bwi_mac *); -void bwi_rf_clear_state(struct bwi_rf *); - -int bwi_rf_map_txpower(struct bwi_mac *); -void bwi_rf_lo_adjust(struct bwi_mac *, const struct bwi_tpctl *); -void bwi_rf_set_chan(struct bwi_mac *, u_int, int); -void bwi_rf_get_gains(struct bwi_mac *); -void bwi_rf_init(struct bwi_mac *); -void bwi_rf_init_bcm2050(struct bwi_mac *); -void bwi_rf_init_hw_nrssi_table(struct bwi_mac *, uint16_t); -void bwi_rf_set_ant_mode(struct bwi_mac *, int); - -void bwi_rf_clear_tssi(struct bwi_mac *); -int bwi_rf_get_latest_tssi(struct bwi_mac *, int8_t[], uint16_t); -int bwi_rf_tssi2dbm(struct bwi_mac *, int8_t, int8_t *); - -void bwi_rf_write(struct bwi_mac *, uint16_t, uint16_t); -uint16_t bwi_rf_read(struct bwi_mac *, uint16_t); - -static __inline void -bwi_rf_off(struct bwi_mac *_mac) -{ - _mac->mac_rf.rf_off(_mac); - /* TODO:LED */ - - _mac->mac_rf.rf_flags &= ~BWI_RF_F_ON; -} - -static __inline void -bwi_rf_on(struct bwi_mac *_mac) -{ - if (_mac->mac_rf.rf_flags & BWI_RF_F_ON) - return; - - _mac->mac_rf.rf_on(_mac); - /* TODO: LED */ - - _mac->mac_rf.rf_flags |= BWI_RF_F_ON; -} - -static __inline void -bwi_rf_calc_nrssi_slope(struct bwi_mac *_mac) -{ - _mac->mac_rf.rf_calc_nrssi_slope(_mac); -} - -static __inline void -bwi_rf_set_nrssi_thr(struct bwi_mac *_mac) -{ - _mac->mac_rf.rf_set_nrssi_thr(_mac); -} - -static __inline int -bwi_rf_calc_rssi(struct bwi_mac *_mac, const struct bwi_rxbuf_hdr *_hdr) -{ - return _mac->mac_rf.rf_calc_rssi(_mac, _hdr); -} - -static __inline void -bwi_rf_lo_update(struct bwi_mac *_mac) -{ - return _mac->mac_rf.rf_lo_update(_mac); -} - -#define RF_WRITE(mac, ofs, val) bwi_rf_write((mac), (ofs), (val)) -#define RF_READ(mac, ofs) bwi_rf_read((mac), (ofs)) - -#define RF_SETBITS(mac, ofs, bits) \ - RF_WRITE((mac), (ofs), RF_READ((mac), (ofs)) | (bits)) -#define RF_CLRBITS(mac, ofs, bits) \ - RF_WRITE((mac), (ofs), RF_READ((mac), (ofs)) & ~(bits)) -#define RF_FILT_SETBITS(mac, ofs, filt, bits) \ - RF_WRITE((mac), (ofs), (RF_READ((mac), (ofs)) & (filt)) | (bits)) - -#define BWI_RFR_ATTEN 0x43 - -#define BWI_RFR_TXPWR 0x52 -#define BWI_RFR_TXPWR1_MASK __BITS(6, 4) - -#define BWI_RFR_BBP_ATTEN 0x60 -#define BWI_RFR_BBP_ATTEN_CALIB_BIT __BIT(0) -#define BWI_RFR_BBP_ATTEN_CALIB_IDX __BITS(4, 1) - -/* - * TSSI -- TX power maps - */ -/* - * http://bcm-specs.sipsolutions.net/TSSI_to_DBM_Table - * B PHY - */ -#define BWI_TXPOWER_MAP_11B \ - 0x4d, 0x4c, 0x4b, 0x4a, 0x4a, 0x49, 0x48, 0x47, \ - 0x47, 0x46, 0x45, 0x45, 0x44, 0x43, 0x42, 0x42, \ - 0x41, 0x40, 0x3f, 0x3e, 0x3d, 0x3c, 0x3b, 0x3a, \ - 0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x32, 0x31, \ - 0x30, 0x2f, 0x2d, 0x2c, 0x2b, 0x29, 0x28, 0x26, \ - 0x25, 0x23, 0x21, 0x1f, 0x1d, 0x1a, 0x17, 0x14, \ - 0x10, 0x0c, 0x06, 0x00, -7, -7, -7, -7, \ - -7, -7, -7, -7, -7, -7, -7, -7 -/* - * http://bcm-specs.sipsolutions.net/TSSI_to_DBM_Table - * G PHY - */ -#define BWI_TXPOWER_MAP_11G \ - 77, 77, 77, 76, 76, 76, 75, 75, \ - 74, 74, 73, 73, 73, 72, 72, 71, \ - 71, 70, 70, 69, 68, 68, 67, 67, \ - 66, 65, 65, 64, 63, 63, 62, 61, \ - 60, 59, 58, 57, 56, 55, 54, 53, \ - 52, 50, 49, 47, 45, 43, 40, 37, \ - 33, 28, 22, 14, 5, -7, -20, -20, \ - -20, -20, -20, -20, -20, -20, -20, -20 - -#endif /* !_BWI_RF_H */ diff --git a/sys/dev/netif/bwi/if_bwi.c b/sys/dev/netif/bwi/if_bwi.c deleted file mode 100644 index cde7360924..0000000000 --- a/sys/dev/netif/bwi/if_bwi.c +++ /dev/null @@ -1,3959 +0,0 @@ -/* - * Copyright (c) 2007 The DragonFly Project. All rights reserved. - * - * This code is derived from software contributed to The DragonFly Project - * by Sepherosa Ziehau - * - * 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. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * 3. Neither the name of The DragonFly Project nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific, prior written permission. - * - * 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 MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, 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 DAMAGE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include "pcidevs.h" - -#include -#include -#include -#include - -struct bwi_clock_freq { - u_int clkfreq_min; - u_int clkfreq_max; -}; - -struct bwi_myaddr_bssid { - uint8_t myaddr[IEEE80211_ADDR_LEN]; - uint8_t bssid[IEEE80211_ADDR_LEN]; -} __packed; - -static int bwi_probe(device_t); -static int bwi_attach(device_t); -static int bwi_detach(device_t); -static int bwi_shutdown(device_t); - -static void bwi_init(void *); -static int bwi_ioctl(struct ifnet *, u_long, caddr_t, struct ucred *); -static void bwi_start(struct ifnet *, struct ifaltq_subque *); -static void bwi_watchdog(struct ifnet *); -static int bwi_newstate(struct ieee80211com *, enum ieee80211_state, int); -static void bwi_updateslot(struct ifnet *); -static int bwi_media_change(struct ifnet *); -static void *bwi_ratectl_attach(struct ieee80211com *, u_int); - -static void bwi_next_scan(void *); -static void bwi_calibrate(void *); - -static void bwi_newstate_begin(struct bwi_softc *, enum ieee80211_state); -static void bwi_init_statechg(struct bwi_softc *, int); -static int bwi_stop(struct bwi_softc *, int); -static int bwi_newbuf(struct bwi_softc *, int, int); -static int bwi_encap(struct bwi_softc *, int, struct mbuf *, - struct ieee80211_node **, int); - -static void bwi_init_rxdesc_ring32(struct bwi_softc *, uint32_t, - bus_addr_t, int, int); -static void bwi_reset_rx_ring32(struct bwi_softc *, uint32_t); - -static int bwi_init_tx_ring32(struct bwi_softc *, int); -static int bwi_init_rx_ring32(struct bwi_softc *); -static int bwi_init_txstats32(struct bwi_softc *); -static void bwi_free_tx_ring32(struct bwi_softc *, int); -static void bwi_free_rx_ring32(struct bwi_softc *); -static void bwi_free_txstats32(struct bwi_softc *); -static void bwi_setup_rx_desc32(struct bwi_softc *, int, bus_addr_t, int); -static void bwi_setup_tx_desc32(struct bwi_softc *, struct bwi_ring_data *, - int, bus_addr_t, int); -static int bwi_rxeof32(struct bwi_softc *); -static void bwi_start_tx32(struct bwi_softc *, uint32_t, int); -static void bwi_txeof_status32(struct bwi_softc *); - -static int bwi_init_tx_ring64(struct bwi_softc *, int); -static int bwi_init_rx_ring64(struct bwi_softc *); -static int bwi_init_txstats64(struct bwi_softc *); -static void bwi_free_tx_ring64(struct bwi_softc *, int); -static void bwi_free_rx_ring64(struct bwi_softc *); -static void bwi_free_txstats64(struct bwi_softc *); -static void bwi_setup_rx_desc64(struct bwi_softc *, int, bus_addr_t, int); -static void bwi_setup_tx_desc64(struct bwi_softc *, struct bwi_ring_data *, - int, bus_addr_t, int); -static int bwi_rxeof64(struct bwi_softc *); -static void bwi_start_tx64(struct bwi_softc *, uint32_t, int); -static void bwi_txeof_status64(struct bwi_softc *); - -static void bwi_intr(void *); -static int bwi_rxeof(struct bwi_softc *, int); -static void _bwi_txeof(struct bwi_softc *, uint16_t, int, int); -static void bwi_txeof(struct bwi_softc *); -static void bwi_txeof_status(struct bwi_softc *, int); -static void bwi_enable_intrs(struct bwi_softc *, uint32_t); -static void bwi_disable_intrs(struct bwi_softc *, uint32_t); -static int bwi_calc_rssi(struct bwi_softc *, const struct bwi_rxbuf_hdr *); -static void bwi_rx_radiotap(struct bwi_softc *, struct mbuf *, - struct bwi_rxbuf_hdr *, const void *, int, int); - -static int bwi_dma_alloc(struct bwi_softc *); -static void bwi_dma_free(struct bwi_softc *); -static int bwi_dma_ring_alloc(struct bwi_softc *, bus_dma_tag_t, - struct bwi_ring_data *, bus_size_t, - uint32_t); -static int bwi_dma_mbuf_create(struct bwi_softc *); -static void bwi_dma_mbuf_destroy(struct bwi_softc *, int, int); -static int bwi_dma_txstats_alloc(struct bwi_softc *, uint32_t, bus_size_t); -static void bwi_dma_txstats_free(struct bwi_softc *); -static void bwi_dma_ring_addr(void *, bus_dma_segment_t *, int, int); -static void bwi_dma_buf_addr(void *, bus_dma_segment_t *, int, - bus_size_t, int); - -static void bwi_power_on(struct bwi_softc *, int); -static int bwi_power_off(struct bwi_softc *, int); -static int bwi_set_clock_mode(struct bwi_softc *, enum bwi_clock_mode); -static int bwi_set_clock_delay(struct bwi_softc *); -static void bwi_get_clock_freq(struct bwi_softc *, struct bwi_clock_freq *); -static int bwi_get_pwron_delay(struct bwi_softc *sc); -static void bwi_set_addr_filter(struct bwi_softc *, uint16_t, - const uint8_t *); -static void bwi_set_bssid(struct bwi_softc *, const uint8_t *); -static int bwi_set_chan(struct bwi_softc *, struct ieee80211_channel *); - -static void bwi_get_card_flags(struct bwi_softc *); -static void bwi_get_eaddr(struct bwi_softc *, uint16_t, uint8_t *); - -static int bwi_bus_attach(struct bwi_softc *); -static int bwi_bbp_attach(struct bwi_softc *); -static int bwi_bbp_power_on(struct bwi_softc *, enum bwi_clock_mode); -static void bwi_bbp_power_off(struct bwi_softc *); - -static const char *bwi_regwin_name(const struct bwi_regwin *); -static uint32_t bwi_regwin_disable_bits(struct bwi_softc *); -static void bwi_regwin_info(struct bwi_softc *, uint16_t *, uint8_t *); -static int bwi_regwin_select(struct bwi_softc *, int); - -static void bwi_led_attach(struct bwi_softc *); -static void bwi_led_newstate(struct bwi_softc *, enum ieee80211_state); -static void bwi_led_event(struct bwi_softc *, int); -static void bwi_led_blink_start(struct bwi_softc *, int, int); -static void bwi_led_blink_next(void *); -static void bwi_led_blink_end(void *); - -static const struct bwi_dev { - uint16_t vid; - uint16_t did; - const char *desc; -} bwi_devices[] = { - { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM4301, - "Broadcom BCM4301 802.11 Wireless Lan" }, - - { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM4307, - "Broadcom BCM4307 802.11 Wireless Lan" }, - - { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM4311, - "Broadcom BCM4311 802.11 Wireless Lan" }, - - { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM4312, - "Broadcom BCM4312 802.11 Wireless Lan" }, - - { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM4306_1, - "Broadcom BCM4306 802.11 Wireless Lan" }, - - { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM4306_2, - "Broadcom BCM4306 802.11 Wireless Lan" }, - - { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM4306_3, - "Broadcom BCM4306 802.11 Wireless Lan" }, - - { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM4309, - "Broadcom BCM4309 802.11 Wireless Lan" }, - - { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM4318, - "Broadcom BCM4318 802.11 Wireless Lan" }, - - { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM4319, - "Broadcom BCM4319 802.11 Wireless Lan" } -}; - -static device_method_t bwi_methods[] = { - DEVMETHOD(device_probe, bwi_probe), - DEVMETHOD(device_attach, bwi_attach), - DEVMETHOD(device_detach, bwi_detach), - DEVMETHOD(device_shutdown, bwi_shutdown), -#if 0 - DEVMETHOD(device_suspend, bwi_suspend), - DEVMETHOD(device_resume, bwi_resume), -#endif - DEVMETHOD_END -}; - -static driver_t bwi_driver = { - "bwi", - bwi_methods, - sizeof(struct bwi_softc) -}; - -static devclass_t bwi_devclass; - -DRIVER_MODULE(bwi, pci, bwi_driver, bwi_devclass, NULL, NULL); -DRIVER_MODULE(bwi, cardbus, bwi_driver, bwi_devclass, NULL, NULL); - -MODULE_DEPEND(bwi, wlan, 1, 1, 1); -MODULE_DEPEND(bwi, wlan_ratectl_onoe, 1, 1, 1); -#if 0 -MODULE_DEPEND(bwi, wlan_ratectl_amrr, 1, 1, 1); -#endif -MODULE_DEPEND(bwi, pci, 1, 1, 1); -MODULE_DEPEND(bwi, cardbus, 1, 1, 1); - -static const struct { - uint16_t did_min; - uint16_t did_max; - uint16_t bbp_id; -} bwi_bbpid_map[] = { - { 0x4301, 0x4301, 0x4301 }, - { 0x4305, 0x4307, 0x4307 }, - { 0x4403, 0x4403, 0x4402 }, - { 0x4610, 0x4615, 0x4610 }, - { 0x4710, 0x4715, 0x4710 }, - { 0x4720, 0x4725, 0x4309 } -}; - -static const struct { - uint16_t bbp_id; - int nregwin; -} bwi_regwin_count[] = { - { 0x4301, 5 }, - { 0x4306, 6 }, - { 0x4307, 5 }, - { 0x4310, 8 }, - { 0x4401, 3 }, - { 0x4402, 3 }, - { 0x4610, 9 }, - { 0x4704, 9 }, - { 0x4710, 9 }, - { 0x5365, 7 } -}; - -#define CLKSRC(src) \ -[BWI_CLKSRC_ ## src] = { \ - .freq_min = BWI_CLKSRC_ ##src## _FMIN, \ - .freq_max = BWI_CLKSRC_ ##src## _FMAX \ -} - -static const struct { - u_int freq_min; - u_int freq_max; -} bwi_clkfreq[BWI_CLKSRC_MAX] = { - CLKSRC(LP_OSC), - CLKSRC(CS_OSC), - CLKSRC(PCI) -}; - -#undef CLKSRC - -#define VENDOR_LED_ACT(vendor) \ -{ \ - .vid = PCI_VENDOR_##vendor, \ - .led_act = { BWI_VENDOR_LED_ACT_##vendor } \ -} - -static const struct { - uint16_t vid; - uint8_t led_act[BWI_LED_MAX]; -} bwi_vendor_led_act[] = { - VENDOR_LED_ACT(COMPAQ), - VENDOR_LED_ACT(LINKSYS) -}; - -static const uint8_t bwi_default_led_act[BWI_LED_MAX] = - { BWI_VENDOR_LED_ACT_DEFAULT }; - -#undef VENDOR_LED_ACT - -static const struct { - int on_dur; - int off_dur; -} bwi_led_duration[109] = { - [0] = { 400, 100 }, - [2] = { 150, 75 }, - [4] = { 90, 45 }, - [11] = { 66, 34 }, - [12] = { 53, 26 }, - [18] = { 42, 21 }, - [22] = { 35, 17 }, - [24] = { 32, 16 }, - [36] = { 21, 10 }, - [48] = { 16, 8 }, - [72] = { 11, 5 }, - [96] = { 9, 4 }, - [108] = { 7, 3 } -}; - -#ifdef BWI_DEBUG -#ifdef BWI_DEBUG_VERBOSE -static uint32_t bwi_debug = BWI_DBG_ATTACH | BWI_DBG_INIT | BWI_DBG_TXPOWER; -#else -static uint32_t bwi_debug; -#endif -TUNABLE_INT("hw.bwi.debug", (int *)&bwi_debug); -#endif /* BWI_DEBUG */ - -static const uint8_t bwi_zero_addr[IEEE80211_ADDR_LEN]; - -static const struct ieee80211_rateset bwi_rateset_11b = - { 4, { 2, 4, 11, 22 } }; -static const struct ieee80211_rateset bwi_rateset_11g = - { 12, { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 } }; - -uint16_t -bwi_read_sprom(struct bwi_softc *sc, uint16_t ofs) -{ - return CSR_READ_2(sc, ofs + BWI_SPROM_START); -} - -static __inline void -bwi_setup_desc32(struct bwi_softc *sc, struct bwi_desc32 *desc_array, - int ndesc, int desc_idx, bus_addr_t paddr, int buf_len, - int tx) -{ - struct bwi_desc32 *desc = &desc_array[desc_idx]; - uint32_t ctrl, addr, addr_hi, addr_lo; - - addr_lo = __SHIFTOUT(paddr, BWI_DESC32_A_ADDR_MASK); - addr_hi = __SHIFTOUT(paddr, BWI_DESC32_A_FUNC_MASK); - - addr = __SHIFTIN(addr_lo, BWI_DESC32_A_ADDR_MASK) | - __SHIFTIN(BWI_DESC32_A_FUNC_TXRX, BWI_DESC32_A_FUNC_MASK); - - ctrl = __SHIFTIN(buf_len, BWI_DESC32_C_BUFLEN_MASK) | - __SHIFTIN(addr_hi, BWI_DESC32_C_ADDRHI_MASK); - if (desc_idx == ndesc - 1) - ctrl |= BWI_DESC32_C_EOR; - if (tx) { - /* XXX */ - ctrl |= BWI_DESC32_C_FRAME_START | - BWI_DESC32_C_FRAME_END | - BWI_DESC32_C_INTR; - } - - desc->addr = htole32(addr); - desc->ctrl = htole32(ctrl); -} - -/* XXX does not belong here */ -uint8_t -bwi_rate2plcp(uint8_t rate) -{ - rate &= IEEE80211_RATE_VAL; - - switch (rate) { - case 2: return 0xa; - case 4: return 0x14; - case 11: return 0x37; - case 22: return 0x6e; - case 44: return 0xdc; - - case 12: return 0xb; - case 18: return 0xf; - case 24: return 0xa; - case 36: return 0xe; - case 48: return 0x9; - case 72: return 0xd; - case 96: return 0x8; - case 108: return 0xc; - - default: - panic("unsupported rate %u", rate); - } -} - -/* XXX does not belong here */ -#define IEEE80211_OFDM_PLCP_RATE_MASK __BITS(3, 0) -#define IEEE80211_OFDM_PLCP_LEN_MASK __BITS(16, 5) - -static __inline void -bwi_ofdm_plcp_header(uint32_t *plcp0, int pkt_len, uint8_t rate) -{ - uint32_t plcp; - - plcp = __SHIFTIN(bwi_rate2plcp(rate), IEEE80211_OFDM_PLCP_RATE_MASK) | - __SHIFTIN(pkt_len, IEEE80211_OFDM_PLCP_LEN_MASK); - *plcp0 = htole32(plcp); -} - -/* XXX does not belong here */ -struct ieee80211_ds_plcp_hdr { - uint8_t i_signal; - uint8_t i_service; - uint16_t i_length; - uint16_t i_crc; -} __packed; - -#define IEEE80211_DS_PLCP_SERVICE_LOCKED 0x04 -#define IEEE80211_DS_PLCL_SERVICE_PBCC 0x08 -#define IEEE80211_DS_PLCP_SERVICE_LENEXT5 0x20 -#define IEEE80211_DS_PLCP_SERVICE_LENEXT6 0x40 -#define IEEE80211_DS_PLCP_SERVICE_LENEXT7 0x80 - -static __inline void -bwi_ds_plcp_header(struct ieee80211_ds_plcp_hdr *plcp, int pkt_len, - uint8_t rate) -{ - int len, service, pkt_bitlen; - - pkt_bitlen = pkt_len * NBBY; - len = howmany(pkt_bitlen * 2, rate); - - service = IEEE80211_DS_PLCP_SERVICE_LOCKED; - if (rate == (11 * 2)) { - int pkt_bitlen1; - - /* - * PLCP service field needs to be adjusted, - * if TX rate is 11Mbytes/s - */ - pkt_bitlen1 = len * 11; - if (pkt_bitlen1 - pkt_bitlen >= NBBY) - service |= IEEE80211_DS_PLCP_SERVICE_LENEXT7; - } - - plcp->i_signal = bwi_rate2plcp(rate); - plcp->i_service = service; - plcp->i_length = htole16(len); - /* NOTE: do NOT touch i_crc */ -} - -static __inline void -bwi_plcp_header(void *plcp, int pkt_len, uint8_t rate) -{ - enum ieee80211_modtype modtype; - - /* - * Assume caller has zeroed 'plcp' - */ - - modtype = ieee80211_rate2modtype(rate); - if (modtype == IEEE80211_MODTYPE_OFDM) - bwi_ofdm_plcp_header(plcp, pkt_len, rate); - else if (modtype == IEEE80211_MODTYPE_DS) - bwi_ds_plcp_header(plcp, pkt_len, rate); - else - panic("unsupport modulation type %u", modtype); -} - -static __inline uint8_t -bwi_ofdm_plcp2rate(const uint32_t *plcp0) -{ - uint32_t plcp; - uint8_t plcp_rate; - - plcp = le32toh(*plcp0); - plcp_rate = __SHIFTOUT(plcp, IEEE80211_OFDM_PLCP_RATE_MASK); - return ieee80211_plcp2rate(plcp_rate, 1); -} - -static __inline uint8_t -bwi_ds_plcp2rate(const struct ieee80211_ds_plcp_hdr *hdr) -{ - return ieee80211_plcp2rate(hdr->i_signal, 0); -} - -static int -bwi_probe(device_t dev) -{ - const struct bwi_dev *b; - uint16_t did, vid; - - did = pci_get_device(dev); - vid = pci_get_vendor(dev); - - for (b = bwi_devices; b->desc != NULL; ++b) { - if (b->did == did && b->vid == vid) { - device_set_desc(dev, b->desc); - return 0; - } - } - return ENXIO; -} - -static int -bwi_attach(device_t dev) -{ - struct bwi_softc *sc = device_get_softc(dev); - struct ieee80211com *ic = &sc->sc_ic; - struct ifnet *ifp = &ic->ic_if; - struct bwi_mac *mac; - struct bwi_phy *phy; - struct sysctl_ctx_list *ctx; - struct sysctl_oid_list *tree; - char ethstr[ETHER_ADDRSTRLEN + 1]; - int i, error; - - if_initname(ifp, device_get_name(dev), device_get_unit(dev)); - sc->sc_dev = dev; - - /* - * Initialize sysctl variables - */ - sc->sc_fw_version = BWI_FW_VERSION3; - sc->sc_dwell_time = 200; - sc->sc_led_idle = (2350 * hz) / 1000; - sc->sc_led_blink = 1; - sc->sc_txpwr_calib = 1; -#ifdef BWI_DEBUG - sc->sc_debug = bwi_debug; -#endif - - callout_init(&sc->sc_scan_ch); - callout_init(&sc->sc_calib_ch); - -#ifndef BURN_BRIDGES - if (pci_get_powerstate(dev) != PCI_POWERSTATE_D0) { - uint32_t irq, mem; - - /* XXX Save more PCIR */ - irq = pci_read_config(dev, PCIR_INTLINE, 4); - mem = pci_read_config(dev, BWI_PCIR_BAR, 4); - - device_printf(dev, "chip is in D%d power mode " - "-- setting to D0\n", pci_get_powerstate(dev)); - - pci_set_powerstate(dev, PCI_POWERSTATE_D0); - - pci_write_config(dev, PCIR_INTLINE, irq, 4); - pci_write_config(dev, BWI_PCIR_BAR, mem, 4); - } -#endif /* !BURN_BRIDGE */ - - pci_enable_busmaster(dev); - - /* Get more PCI information */ - sc->sc_pci_revid = pci_get_revid(dev); - sc->sc_pci_subvid = pci_get_subvendor(dev); - sc->sc_pci_subdid = pci_get_subdevice(dev); - - /* - * Allocate IO memory - */ - sc->sc_mem_rid = BWI_PCIR_BAR; - sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, - &sc->sc_mem_rid, RF_ACTIVE); - if (sc->sc_mem_res == NULL) { - device_printf(dev, "can't allocate IO memory\n"); - return ENXIO; - } - sc->sc_mem_bt = rman_get_bustag(sc->sc_mem_res); - sc->sc_mem_bh = rman_get_bushandle(sc->sc_mem_res); - - /* - * Allocate IRQ - */ - sc->sc_irq_rid = 0; - sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, - &sc->sc_irq_rid, - RF_SHAREABLE | RF_ACTIVE); - if (sc->sc_irq_res == NULL) { - device_printf(dev, "can't allocate irq\n"); - error = ENXIO; - goto fail; - } - - /* - * Create sysctl tree - */ - ctx = device_get_sysctl_ctx(sc->bge_dev); - tree = device_get_sysctl_tree(sc->bge_dev); - - SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, - "dwell_time", CTLFLAG_RW, &sc->sc_dwell_time, 0, - "Channel dwell time during scan (msec)"); - SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, - "fw_version", CTLFLAG_RD, &sc->sc_fw_version, 0, - "Firmware version"); - SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, - "led_idle", CTLFLAG_RW, &sc->sc_led_idle, 0, - "# ticks before LED enters idle state"); - SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, - "led_blink", CTLFLAG_RW, &sc->sc_led_blink, 0, - "Allow LED to blink"); - SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, - "txpwr_calib", CTLFLAG_RW, &sc->sc_txpwr_calib, 0, - "Enable software TX power calibration"); -#ifdef BWI_DEBUG - SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, - "debug", CTLFLAG_RW, &sc->sc_debug, 0, "Debug flags"); -#endif - - bwi_power_on(sc, 1); - - error = bwi_bbp_attach(sc); - if (error) - goto fail; - - error = bwi_bbp_power_on(sc, BWI_CLOCK_MODE_FAST); - if (error) - goto fail; - - if (BWI_REGWIN_EXIST(&sc->sc_com_regwin)) { - error = bwi_set_clock_delay(sc); - if (error) - goto fail; - - error = bwi_set_clock_mode(sc, BWI_CLOCK_MODE_FAST); - if (error) - goto fail; - - error = bwi_get_pwron_delay(sc); - if (error) - goto fail; - } - - error = bwi_bus_attach(sc); - if (error) - goto fail; - - bwi_get_card_flags(sc); - - bwi_led_attach(sc); - - for (i = 0; i < sc->sc_nmac; ++i) { - struct bwi_regwin *old; - - mac = &sc->sc_mac[i]; - error = bwi_regwin_switch(sc, &mac->mac_regwin, &old); - if (error) - goto fail; - - error = bwi_mac_lateattach(mac); - if (error) - goto fail; - - error = bwi_regwin_switch(sc, old, NULL); - if (error) - goto fail; - } - - /* - * XXX First MAC is known to exist - * TODO2 - */ - mac = &sc->sc_mac[0]; - phy = &mac->mac_phy; - - bwi_bbp_power_off(sc); - - error = bwi_dma_alloc(sc); - if (error) - goto fail; - - ifp->if_softc = sc; - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; - ifp->if_init = bwi_init; - ifp->if_ioctl = bwi_ioctl; - ifp->if_start = bwi_start; - ifp->if_watchdog = bwi_watchdog; - ifq_set_maxlen(&ifp->if_snd, IFQ_MAXLEN); -#ifdef notyet - ifq_set_ready(&ifp->if_snd); -#endif - - /* Get locale */ - sc->sc_locale = __SHIFTOUT(bwi_read_sprom(sc, BWI_SPROM_CARD_INFO), - BWI_SPROM_CARD_INFO_LOCALE); - DPRINTF(sc, BWI_DBG_ATTACH, "locale: %d\n", sc->sc_locale); - - /* - * Setup ratesets, phytype, channels and get MAC address - */ - if (phy->phy_mode == IEEE80211_MODE_11B || - phy->phy_mode == IEEE80211_MODE_11G) { - uint16_t chan_flags; - - ic->ic_sup_rates[IEEE80211_MODE_11B] = bwi_rateset_11b; - - if (phy->phy_mode == IEEE80211_MODE_11B) { - chan_flags = IEEE80211_CHAN_B; - ic->ic_phytype = IEEE80211_T_DS; - } else { - chan_flags = IEEE80211_CHAN_CCK | - IEEE80211_CHAN_OFDM | - IEEE80211_CHAN_DYN | - IEEE80211_CHAN_2GHZ; - ic->ic_phytype = IEEE80211_T_OFDM; - ic->ic_sup_rates[IEEE80211_MODE_11G] = - bwi_rateset_11g; - } - - /* XXX depend on locale */ - for (i = 1; i <= 14; ++i) { - ic->ic_channels[i].ic_freq = - ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ); - ic->ic_channels[i].ic_flags = chan_flags; - } - - bwi_get_eaddr(sc, BWI_SPROM_11BG_EADDR, ic->ic_myaddr); - if (IEEE80211_IS_MULTICAST(ic->ic_myaddr)) { - bwi_get_eaddr(sc, BWI_SPROM_11A_EADDR, ic->ic_myaddr); - if (IEEE80211_IS_MULTICAST(ic->ic_myaddr)) { - device_printf(dev, "invalid MAC address: " - "%s\n", kether_ntoa(ic->ic_myaddr, ethstr)); - } - } - } else if (phy->phy_mode == IEEE80211_MODE_11A) { - /* TODO:11A */ - error = ENXIO; - goto fail; - } else { - panic("unknown phymode %d", phy->phy_mode); - } - - ic->ic_caps = IEEE80211_C_SHSLOT | - IEEE80211_C_SHPREAMBLE | - IEEE80211_C_WPA | - IEEE80211_C_MONITOR; - ic->ic_state = IEEE80211_S_INIT; - ic->ic_opmode = IEEE80211_M_STA; - - IEEE80211_ONOE_PARAM_SETUP(&sc->sc_onoe_param); - ic->ic_ratectl.rc_st_ratectl_cap = IEEE80211_RATECTL_CAP_ONOE; - ic->ic_ratectl.rc_st_ratectl = IEEE80211_RATECTL_ONOE; - ic->ic_ratectl.rc_st_attach = bwi_ratectl_attach; - - ic->ic_updateslot = bwi_updateslot; - - ieee80211_ifattach(ic); - - ic->ic_headroom = sizeof(struct bwi_txbuf_hdr); - ic->ic_flags_ext |= IEEE80211_FEXT_SWBMISS; - - sc->sc_newstate = ic->ic_newstate; - ic->ic_newstate = bwi_newstate; - - ieee80211_media_init(ic, bwi_media_change, ieee80211_media_status); - - /* - * Attach radio tap - */ - bpfattach_dlt(ifp, DLT_IEEE802_11_RADIO, - sizeof(struct ieee80211_frame) + sizeof(sc->sc_tx_th), - &sc->sc_drvbpf); - - sc->sc_tx_th_len = roundup(sizeof(sc->sc_tx_th), sizeof(uint32_t)); - sc->sc_tx_th.wt_ihdr.it_len = htole16(sc->sc_tx_th_len); - sc->sc_tx_th.wt_ihdr.it_present = htole32(BWI_TX_RADIOTAP_PRESENT); - - sc->sc_rx_th_len = roundup(sizeof(sc->sc_rx_th), sizeof(uint32_t)); - sc->sc_rx_th.wr_ihdr.it_len = htole16(sc->sc_rx_th_len); - sc->sc_rx_th.wr_ihdr.it_present = htole32(BWI_RX_RADIOTAP_PRESENT); - - ifq_set_cpuid(&ifp->if_snd, rman_get_cpuid(sc->sc_irq_res)); - - error = bus_setup_intr(dev, sc->sc_irq_res, INTR_MPSAFE, bwi_intr, sc, - &sc->sc_irq_handle, ifp->if_serializer); - if (error) { - device_printf(dev, "can't setup intr\n"); - bpfdetach(ifp); - ieee80211_ifdetach(ic); - goto fail; - } - - if (bootverbose) - ieee80211_announce(ic); - - return 0; -fail: - bwi_detach(dev); - return error; -} - -static int -bwi_detach(device_t dev) -{ - struct bwi_softc *sc = device_get_softc(dev); - - if (device_is_attached(dev)) { - struct ifnet *ifp = &sc->sc_ic.ic_if; - int i; - - lwkt_serialize_enter(ifp->if_serializer); - bwi_stop(sc, 1); - bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_irq_handle); - lwkt_serialize_exit(ifp->if_serializer); - - bpfdetach(ifp); - ieee80211_ifdetach(&sc->sc_ic); - - for (i = 0; i < sc->sc_nmac; ++i) - bwi_mac_detach(&sc->sc_mac[i]); - } - - if (sc->sc_irq_res != NULL) { - bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irq_rid, - sc->sc_irq_res); - } - - if (sc->sc_mem_res != NULL) { - bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_mem_rid, - sc->sc_mem_res); - } - - bwi_dma_free(sc); - - return 0; -} - -static int -bwi_shutdown(device_t dev) -{ - struct bwi_softc *sc = device_get_softc(dev); - struct ifnet *ifp = &sc->sc_ic.ic_if; - - lwkt_serialize_enter(ifp->if_serializer); - bwi_stop(sc, 1); - lwkt_serialize_exit(ifp->if_serializer); - return 0; -} - -static void -bwi_power_on(struct bwi_softc *sc, int with_pll) -{ - uint32_t gpio_in, gpio_out, gpio_en; - uint16_t status; - - gpio_in = pci_read_config(sc->sc_dev, BWI_PCIR_GPIO_IN, 4); - if (gpio_in & BWI_PCIM_GPIO_PWR_ON) - goto back; - - gpio_out = pci_read_config(sc->sc_dev, BWI_PCIR_GPIO_OUT, 4); - gpio_en = pci_read_config(sc->sc_dev, BWI_PCIR_GPIO_ENABLE, 4); - - gpio_out |= BWI_PCIM_GPIO_PWR_ON; - gpio_en |= BWI_PCIM_GPIO_PWR_ON; - if (with_pll) { - /* Turn off PLL first */ - gpio_out |= BWI_PCIM_GPIO_PLL_PWR_OFF; - gpio_en |= BWI_PCIM_GPIO_PLL_PWR_OFF; - } - - pci_write_config(sc->sc_dev, BWI_PCIR_GPIO_OUT, gpio_out, 4); - pci_write_config(sc->sc_dev, BWI_PCIR_GPIO_ENABLE, gpio_en, 4); - DELAY(1000); - - if (with_pll) { - /* Turn on PLL */ - gpio_out &= ~BWI_PCIM_GPIO_PLL_PWR_OFF; - pci_write_config(sc->sc_dev, BWI_PCIR_GPIO_OUT, gpio_out, 4); - DELAY(5000); - } - -back: - /* Clear "Signaled Target Abort" */ - status = pci_read_config(sc->sc_dev, PCIR_STATUS, 2); - status &= ~PCIM_STATUS_STABORT; - pci_write_config(sc->sc_dev, PCIR_STATUS, status, 2); -} - -static int -bwi_power_off(struct bwi_softc *sc, int with_pll) -{ - uint32_t gpio_out, gpio_en; - - pci_read_config(sc->sc_dev, BWI_PCIR_GPIO_IN, 4); /* dummy read */ - gpio_out = pci_read_config(sc->sc_dev, BWI_PCIR_GPIO_OUT, 4); - gpio_en = pci_read_config(sc->sc_dev, BWI_PCIR_GPIO_ENABLE, 4); - - gpio_out &= ~BWI_PCIM_GPIO_PWR_ON; - gpio_en |= BWI_PCIM_GPIO_PWR_ON; - if (with_pll) { - gpio_out |= BWI_PCIM_GPIO_PLL_PWR_OFF; - gpio_en |= BWI_PCIM_GPIO_PLL_PWR_OFF; - } - - pci_write_config(sc->sc_dev, BWI_PCIR_GPIO_OUT, gpio_out, 4); - pci_write_config(sc->sc_dev, BWI_PCIR_GPIO_ENABLE, gpio_en, 4); - return 0; -} - -int -bwi_regwin_switch(struct bwi_softc *sc, struct bwi_regwin *rw, - struct bwi_regwin **old_rw) -{ - int error; - - if (old_rw != NULL) - *old_rw = NULL; - - if (!BWI_REGWIN_EXIST(rw)) - return EINVAL; - - if (sc->sc_cur_regwin != rw) { - error = bwi_regwin_select(sc, rw->rw_id); - if (error) { - if_printf(&sc->sc_ic.ic_if, "can't select regwin %d\n", - rw->rw_id); - return error; - } - } - - if (old_rw != NULL) - *old_rw = sc->sc_cur_regwin; - sc->sc_cur_regwin = rw; - return 0; -} - -static int -bwi_regwin_select(struct bwi_softc *sc, int id) -{ - uint32_t win = BWI_PCIM_REGWIN(id); - int i; - -#define RETRY_MAX 50 - for (i = 0; i < RETRY_MAX; ++i) { - pci_write_config(sc->sc_dev, BWI_PCIR_SEL_REGWIN, win, 4); - if (pci_read_config(sc->sc_dev, BWI_PCIR_SEL_REGWIN, 4) == win) - return 0; - DELAY(10); - } -#undef RETRY_MAX - - return ENXIO; -} - -static void -bwi_regwin_info(struct bwi_softc *sc, uint16_t *type, uint8_t *rev) -{ - uint32_t val; - - val = CSR_READ_4(sc, BWI_ID_HI); - *type = BWI_ID_HI_REGWIN_TYPE(val); - *rev = BWI_ID_HI_REGWIN_REV(val); - - DPRINTF(sc, BWI_DBG_ATTACH, "regwin: type 0x%03x, rev %d, " - "vendor 0x%04x\n", *type, *rev, - __SHIFTOUT(val, BWI_ID_HI_REGWIN_VENDOR_MASK)); -} - -static int -bwi_bbp_attach(struct bwi_softc *sc) -{ - uint16_t bbp_id, rw_type; - uint8_t rw_rev; - uint32_t info; - int error, nregwin, i; - - /* - * Get 0th regwin information - * NOTE: 0th regwin should exist - */ - error = bwi_regwin_select(sc, 0); - if (error) { - device_printf(sc->sc_dev, "can't select regwin 0\n"); - return error; - } - bwi_regwin_info(sc, &rw_type, &rw_rev); - - /* - * Find out BBP id - */ - bbp_id = 0; - info = 0; - if (rw_type == BWI_REGWIN_T_COM) { - info = CSR_READ_4(sc, BWI_INFO); - bbp_id = __SHIFTOUT(info, BWI_INFO_BBPID_MASK); - - BWI_CREATE_REGWIN(&sc->sc_com_regwin, 0, rw_type, rw_rev); - - sc->sc_cap = CSR_READ_4(sc, BWI_CAPABILITY); - } else { - uint16_t did = pci_get_device(sc->sc_dev); - uint8_t revid = pci_get_revid(sc->sc_dev); - - for (i = 0; i < NELEM(bwi_bbpid_map); ++i) { - if (did >= bwi_bbpid_map[i].did_min && - did <= bwi_bbpid_map[i].did_max) { - bbp_id = bwi_bbpid_map[i].bbp_id; - break; - } - } - if (bbp_id == 0) { - device_printf(sc->sc_dev, "no BBP id for device id " - "0x%04x\n", did); - return ENXIO; - } - - info = __SHIFTIN(revid, BWI_INFO_BBPREV_MASK) | - __SHIFTIN(0, BWI_INFO_BBPPKG_MASK); - } - - /* - * Find out number of regwins - */ - nregwin = 0; - if (rw_type == BWI_REGWIN_T_COM && rw_rev >= 4) { - nregwin = __SHIFTOUT(info, BWI_INFO_NREGWIN_MASK); - } else { - for (i = 0; i < NELEM(bwi_regwin_count); ++i) { - if (bwi_regwin_count[i].bbp_id == bbp_id) { - nregwin = bwi_regwin_count[i].nregwin; - break; - } - } - if (nregwin == 0) { - device_printf(sc->sc_dev, "no number of win for " - "BBP id 0x%04x\n", bbp_id); - return ENXIO; - } - } - - /* Record BBP id/rev for later using */ - sc->sc_bbp_id = bbp_id; - sc->sc_bbp_rev = __SHIFTOUT(info, BWI_INFO_BBPREV_MASK); - sc->sc_bbp_pkg = __SHIFTOUT(info, BWI_INFO_BBPPKG_MASK); - device_printf(sc->sc_dev, "BBP: id 0x%04x, rev 0x%x, pkg %d\n", - sc->sc_bbp_id, sc->sc_bbp_rev, sc->sc_bbp_pkg); - - DPRINTF(sc, BWI_DBG_ATTACH, "nregwin %d, cap 0x%08x\n", - nregwin, sc->sc_cap); - - /* - * Create rest of the regwins - */ - - /* Don't re-create common regwin, if it is already created */ - i = BWI_REGWIN_EXIST(&sc->sc_com_regwin) ? 1 : 0; - - for (; i < nregwin; ++i) { - /* - * Get regwin information - */ - error = bwi_regwin_select(sc, i); - if (error) { - device_printf(sc->sc_dev, - "can't select regwin %d\n", i); - return error; - } - bwi_regwin_info(sc, &rw_type, &rw_rev); - - /* - * Try attach: - * 1) Bus (PCI/PCIE) regwin - * 2) MAC regwin - * Ignore rest types of regwin - */ - if (rw_type == BWI_REGWIN_T_BUSPCI || - rw_type == BWI_REGWIN_T_BUSPCIE) { - if (BWI_REGWIN_EXIST(&sc->sc_bus_regwin)) { - device_printf(sc->sc_dev, - "bus regwin already exists\n"); - } else { - BWI_CREATE_REGWIN(&sc->sc_bus_regwin, i, - rw_type, rw_rev); - } - } else if (rw_type == BWI_REGWIN_T_MAC) { - /* XXX ignore return value */ - bwi_mac_attach(sc, i, rw_rev); - } - } - - /* At least one MAC shold exist */ - if (!BWI_REGWIN_EXIST(&sc->sc_mac[0].mac_regwin)) { - device_printf(sc->sc_dev, "no MAC was found\n"); - return ENXIO; - } - KKASSERT(sc->sc_nmac > 0); - - /* Bus regwin must exist */ - if (!BWI_REGWIN_EXIST(&sc->sc_bus_regwin)) { - device_printf(sc->sc_dev, "no bus regwin was found\n"); - return ENXIO; - } - - /* Start with first MAC */ - error = bwi_regwin_switch(sc, &sc->sc_mac[0].mac_regwin, NULL); - if (error) - return error; - - return 0; -} - -int -bwi_bus_init(struct bwi_softc *sc, struct bwi_mac *mac) -{ - struct bwi_regwin *old, *bus; - uint32_t val; - int error; - - bus = &sc->sc_bus_regwin; - KKASSERT(sc->sc_cur_regwin == &mac->mac_regwin); - - /* - * Tell bus to generate requested interrupts - */ - if (bus->rw_rev < 6 && bus->rw_type == BWI_REGWIN_T_BUSPCI) { - /* - * NOTE: Read BWI_FLAGS from MAC regwin - */ - val = CSR_READ_4(sc, BWI_FLAGS); - - error = bwi_regwin_switch(sc, bus, &old); - if (error) - return error; - - CSR_SETBITS_4(sc, BWI_INTRVEC, (val & BWI_FLAGS_INTR_MASK)); - } else { - uint32_t mac_mask; - - mac_mask = 1 << mac->mac_id; - - error = bwi_regwin_switch(sc, bus, &old); - if (error) - return error; - - val = pci_read_config(sc->sc_dev, BWI_PCIR_INTCTL, 4); - val |= mac_mask << 8; - pci_write_config(sc->sc_dev, BWI_PCIR_INTCTL, val, 4); - } - - if (sc->sc_flags & BWI_F_BUS_INITED) - goto back; - - if (bus->rw_type == BWI_REGWIN_T_BUSPCI) { - /* - * Enable prefetch and burst - */ - CSR_SETBITS_4(sc, BWI_BUS_CONFIG, - BWI_BUS_CONFIG_PREFETCH | BWI_BUS_CONFIG_BURST); - - if (bus->rw_rev < 5) { - struct bwi_regwin *com = &sc->sc_com_regwin; - - /* - * Configure timeouts for bus operation - */ - - /* - * Set service timeout and request timeout - */ - CSR_SETBITS_4(sc, BWI_CONF_LO, - __SHIFTIN(BWI_CONF_LO_SERVTO, BWI_CONF_LO_SERVTO_MASK) | - __SHIFTIN(BWI_CONF_LO_REQTO, BWI_CONF_LO_REQTO_MASK)); - - /* - * If there is common regwin, we switch to that regwin - * and switch back to bus regwin once we have done. - */ - if (BWI_REGWIN_EXIST(com)) { - error = bwi_regwin_switch(sc, com, NULL); - if (error) - return error; - } - - /* Let bus know what we have changed */ - CSR_WRITE_4(sc, BWI_BUS_ADDR, BWI_BUS_ADDR_MAGIC); - CSR_READ_4(sc, BWI_BUS_ADDR); /* Flush */ - CSR_WRITE_4(sc, BWI_BUS_DATA, 0); - CSR_READ_4(sc, BWI_BUS_DATA); /* Flush */ - - if (BWI_REGWIN_EXIST(com)) { - error = bwi_regwin_switch(sc, bus, NULL); - if (error) - return error; - } - } else if (bus->rw_rev >= 11) { - /* - * Enable memory read multiple - */ - CSR_SETBITS_4(sc, BWI_BUS_CONFIG, BWI_BUS_CONFIG_MRM); - } - } else { - /* TODO:PCIE */ - } - - sc->sc_flags |= BWI_F_BUS_INITED; -back: - return bwi_regwin_switch(sc, old, NULL); -} - -static void -bwi_get_card_flags(struct bwi_softc *sc) -{ - sc->sc_card_flags = bwi_read_sprom(sc, BWI_SPROM_CARD_FLAGS); - if (sc->sc_card_flags == 0xffff) - sc->sc_card_flags = 0; - - if (sc->sc_pci_subvid == PCI_VENDOR_APPLE && - sc->sc_pci_subdid == 0x4e && /* XXX */ - sc->sc_pci_revid > 0x40) - sc->sc_card_flags |= BWI_CARD_F_PA_GPIO9; - - DPRINTF(sc, BWI_DBG_ATTACH, "card flags 0x%04x\n", sc->sc_card_flags); -} - -static void -bwi_get_eaddr(struct bwi_softc *sc, uint16_t eaddr_ofs, uint8_t *eaddr) -{ - int i; - - for (i = 0; i < 3; ++i) { - *((uint16_t *)eaddr + i) = - htobe16(bwi_read_sprom(sc, eaddr_ofs + 2 * i)); - } -} - -static void -bwi_get_clock_freq(struct bwi_softc *sc, struct bwi_clock_freq *freq) -{ - struct bwi_regwin *com; - uint32_t val; - u_int div; - int src; - - bzero(freq, sizeof(*freq)); - com = &sc->sc_com_regwin; - - KKASSERT(BWI_REGWIN_EXIST(com)); - KKASSERT(sc->sc_cur_regwin == com); - KKASSERT(sc->sc_cap & BWI_CAP_CLKMODE); - - /* - * Calculate clock frequency - */ - src = -1; - div = 0; - if (com->rw_rev < 6) { - val = pci_read_config(sc->sc_dev, BWI_PCIR_GPIO_OUT, 4); - if (val & BWI_PCIM_GPIO_OUT_CLKSRC) { - src = BWI_CLKSRC_PCI; - div = 64; - } else { - src = BWI_CLKSRC_CS_OSC; - div = 32; - } - } else if (com->rw_rev < 10) { - val = CSR_READ_4(sc, BWI_CLOCK_CTRL); - - src = __SHIFTOUT(val, BWI_CLOCK_CTRL_CLKSRC); - if (src == BWI_CLKSRC_LP_OSC) { - div = 1; - } else { - div = (__SHIFTOUT(val, BWI_CLOCK_CTRL_FDIV) + 1) << 2; - - /* Unknown source */ - if (src >= BWI_CLKSRC_MAX) - src = BWI_CLKSRC_CS_OSC; - } - } else { - val = CSR_READ_4(sc, BWI_CLOCK_INFO); - - src = BWI_CLKSRC_CS_OSC; - div = (__SHIFTOUT(val, BWI_CLOCK_INFO_FDIV) + 1) << 2; - } - - KKASSERT(src >= 0 && src < BWI_CLKSRC_MAX); - KKASSERT(div != 0); - - DPRINTF(sc, BWI_DBG_ATTACH, "clksrc %s\n", - src == BWI_CLKSRC_PCI ? "PCI" : - (src == BWI_CLKSRC_LP_OSC ? "LP_OSC" : "CS_OSC")); - - freq->clkfreq_min = bwi_clkfreq[src].freq_min / div; - freq->clkfreq_max = bwi_clkfreq[src].freq_max / div; - - DPRINTF(sc, BWI_DBG_ATTACH, "clkfreq min %u, max %u\n", - freq->clkfreq_min, freq->clkfreq_max); -} - -static int -bwi_set_clock_mode(struct bwi_softc *sc, enum bwi_clock_mode clk_mode) -{ - struct bwi_regwin *old, *com; - uint32_t clk_ctrl, clk_src; - int error, pwr_off = 0; - - com = &sc->sc_com_regwin; - if (!BWI_REGWIN_EXIST(com)) - return 0; - - if (com->rw_rev >= 10 || com->rw_rev < 6) - return 0; - - /* - * For common regwin whose rev is [6, 10), the chip - * must be capable to change clock mode. - */ - if ((sc->sc_cap & BWI_CAP_CLKMODE) == 0) - return 0; - - error = bwi_regwin_switch(sc, com, &old); - if (error) - return error; - - if (clk_mode == BWI_CLOCK_MODE_FAST) - bwi_power_on(sc, 0); /* Don't turn on PLL */ - - clk_ctrl = CSR_READ_4(sc, BWI_CLOCK_CTRL); - clk_src = __SHIFTOUT(clk_ctrl, BWI_CLOCK_CTRL_CLKSRC); - - switch (clk_mode) { - case BWI_CLOCK_MODE_FAST: - clk_ctrl &= ~BWI_CLOCK_CTRL_SLOW; - clk_ctrl |= BWI_CLOCK_CTRL_IGNPLL; - break; - case BWI_CLOCK_MODE_SLOW: - clk_ctrl |= BWI_CLOCK_CTRL_SLOW; - break; - case BWI_CLOCK_MODE_DYN: - clk_ctrl &= ~(BWI_CLOCK_CTRL_SLOW | - BWI_CLOCK_CTRL_IGNPLL | - BWI_CLOCK_CTRL_NODYN); - if (clk_src != BWI_CLKSRC_CS_OSC) { - clk_ctrl |= BWI_CLOCK_CTRL_NODYN; - pwr_off = 1; - } - break; - } - CSR_WRITE_4(sc, BWI_CLOCK_CTRL, clk_ctrl); - - if (pwr_off) - bwi_power_off(sc, 0); /* Leave PLL as it is */ - - return bwi_regwin_switch(sc, old, NULL); -} - -static int -bwi_set_clock_delay(struct bwi_softc *sc) -{ - struct bwi_regwin *old, *com; - int error; - - com = &sc->sc_com_regwin; - if (!BWI_REGWIN_EXIST(com)) - return 0; - - error = bwi_regwin_switch(sc, com, &old); - if (error) - return error; - - if (sc->sc_bbp_id == BWI_BBPID_BCM4321) { - if (sc->sc_bbp_rev == 0) - CSR_WRITE_4(sc, BWI_CONTROL, BWI_CONTROL_MAGIC0); - else if (sc->sc_bbp_rev == 1) - CSR_WRITE_4(sc, BWI_CONTROL, BWI_CONTROL_MAGIC1); - } - - if (sc->sc_cap & BWI_CAP_CLKMODE) { - if (com->rw_rev >= 10) { - CSR_FILT_SETBITS_4(sc, BWI_CLOCK_INFO, 0xffff, 0x40000); - } else { - struct bwi_clock_freq freq; - - bwi_get_clock_freq(sc, &freq); - CSR_WRITE_4(sc, BWI_PLL_ON_DELAY, - howmany(freq.clkfreq_max * 150, 1000000)); - CSR_WRITE_4(sc, BWI_FREQ_SEL_DELAY, - howmany(freq.clkfreq_max * 15, 1000000)); - } - } - - return bwi_regwin_switch(sc, old, NULL); -} - -static void -bwi_init(void *xsc) -{ - bwi_init_statechg(xsc, 1); -} - -static void -bwi_init_statechg(struct bwi_softc *sc, int statechg) -{ - struct ieee80211com *ic = &sc->sc_ic; - struct ifnet *ifp = &ic->ic_if; - struct bwi_mac *mac; - int error; - - ASSERT_SERIALIZED(ifp->if_serializer); - - error = bwi_stop(sc, statechg); - if (error) { - if_printf(ifp, "can't stop\n"); - return; - } - - bwi_bbp_power_on(sc, BWI_CLOCK_MODE_FAST); - - /* TODO: 2 MAC */ - - mac = &sc->sc_mac[0]; - error = bwi_regwin_switch(sc, &mac->mac_regwin, NULL); - if (error) - goto back; - - error = bwi_mac_init(mac); - if (error) - goto back; - - bwi_bbp_power_on(sc, BWI_CLOCK_MODE_DYN); - - bcopy(IF_LLADDR(ifp), ic->ic_myaddr, sizeof(ic->ic_myaddr)); - - bwi_set_bssid(sc, bwi_zero_addr); /* Clear BSSID */ - bwi_set_addr_filter(sc, BWI_ADDR_FILTER_MYADDR, ic->ic_myaddr); - - bwi_mac_reset_hwkeys(mac); - - if ((mac->mac_flags & BWI_MAC_F_HAS_TXSTATS) == 0) { - int i; - -#define NRETRY 1000 - /* - * Drain any possible pending TX status - */ - for (i = 0; i < NRETRY; ++i) { - if ((CSR_READ_4(sc, BWI_TXSTATUS0) & - BWI_TXSTATUS0_VALID) == 0) - break; - CSR_READ_4(sc, BWI_TXSTATUS1); - } - if (i == NRETRY) - if_printf(ifp, "can't drain TX status\n"); -#undef NRETRY - } - - if (mac->mac_phy.phy_mode == IEEE80211_MODE_11G) - bwi_mac_updateslot(mac, 1); - - /* Start MAC */ - error = bwi_mac_start(mac); - if (error) - goto back; - - /* Enable intrs */ - bwi_enable_intrs(sc, BWI_INIT_INTRS); - - ifp->if_flags |= IFF_RUNNING; - ifq_clr_oactive(&ifp->if_snd); - - if (statechg) { - if (ic->ic_opmode != IEEE80211_M_MONITOR) { - if (ic->ic_roaming != IEEE80211_ROAMING_MANUAL) - ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); - } else { - ieee80211_new_state(ic, IEEE80211_S_RUN, -1); - } - } else { - ieee80211_new_state(ic, ic->ic_state, -1); - } -back: - if (error) - bwi_stop(sc, 1); - else - ifp->if_start(ifp); -} - -static int -bwi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t req, struct ucred *cr) -{ - struct bwi_softc *sc = ifp->if_softc; - int error = 0; - - ASSERT_SERIALIZED(ifp->if_serializer); - - switch (cmd) { - case SIOCSIFFLAGS: - if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == - (IFF_UP | IFF_RUNNING)) { - struct bwi_mac *mac; - int promisc = -1; - - KKASSERT(sc->sc_cur_regwin->rw_type == - BWI_REGWIN_T_MAC); - mac = (struct bwi_mac *)sc->sc_cur_regwin; - - if ((ifp->if_flags & IFF_PROMISC) && - (sc->sc_flags & BWI_F_PROMISC) == 0) { - promisc = 1; - sc->sc_flags |= BWI_F_PROMISC; - } else if ((ifp->if_flags & IFF_PROMISC) == 0 && - (sc->sc_flags & BWI_F_PROMISC)) { - promisc = 0; - sc->sc_flags &= ~BWI_F_PROMISC; - } - - if (promisc >= 0) - bwi_mac_set_promisc(mac, promisc); - } - - if (ifp->if_flags & IFF_UP) { - if ((ifp->if_flags & IFF_RUNNING) == 0) - bwi_init(sc); - } else { - if (ifp->if_flags & IFF_RUNNING) - bwi_stop(sc, 1); - } - break; - default: - error = ieee80211_ioctl(&sc->sc_ic, cmd, req, cr); - break; - } - - if (error == ENETRESET) { - if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == - (IFF_UP | IFF_RUNNING)) - bwi_init(sc); - error = 0; - } - return error; -} - -static void -bwi_start(struct ifnet *ifp, struct ifaltq_subque *ifsq) -{ - struct bwi_softc *sc = ifp->if_softc; - struct ieee80211com *ic = &sc->sc_ic; - struct bwi_txbuf_data *tbd = &sc->sc_tx_bdata[BWI_TX_DATA_RING]; - int trans, idx; - - ASSERT_ALTQ_SQ_DEFAULT(ifp, ifsq); - ASSERT_SERIALIZED(ifp->if_serializer); - - if (ifq_is_oactive(&ifp->if_snd) || (ifp->if_flags & IFF_RUNNING) == 0) - return; - - trans = 0; - idx = tbd->tbd_idx; - - while (tbd->tbd_buf[idx].tb_mbuf == NULL) { - struct ieee80211_frame *wh; - struct ieee80211_node *ni; - struct mbuf *m; - int mgt_pkt = 0; - - if (!IF_QEMPTY(&ic->ic_mgtq)) { - IF_DEQUEUE(&ic->ic_mgtq, m); - - ni = (struct ieee80211_node *)m->m_pkthdr.rcvif; - m->m_pkthdr.rcvif = NULL; - - mgt_pkt = 1; - } else if (!ifq_is_empty(&ifp->if_snd)) { - struct ether_header *eh; - - if (ic->ic_state != IEEE80211_S_RUN) { - ifq_purge(&ifp->if_snd); - break; - } - - m = ifq_dequeue(&ifp->if_snd); - if (m == NULL) - break; - - if (m->m_len < sizeof(*eh)) { - m = m_pullup(m, sizeof(*eh)); - if (m == NULL) { - IFNET_STAT_INC(ifp, oerrors, 1); - continue; - } - } - eh = mtod(m, struct ether_header *); - - ni = ieee80211_find_txnode(ic, eh->ether_dhost); - if (ni == NULL) { - m_freem(m); - IFNET_STAT_INC(ifp, oerrors, 1); - continue; - } - - /* TODO: PS */ - - BPF_MTAP(ifp, m); - - m = ieee80211_encap(ic, m, ni); - if (m == NULL) { - ieee80211_free_node(ni); - IFNET_STAT_INC(ifp, oerrors, 1); - continue; - } - } else { - break; - } - - if (ic->ic_rawbpf != NULL) - bpf_mtap(ic->ic_rawbpf, m); - - wh = mtod(m, struct ieee80211_frame *); - if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { - if (ieee80211_crypto_encap(ic, ni, m) == NULL) { - ieee80211_free_node(ni); - m_freem(m); - IFNET_STAT_INC(ifp, oerrors, 1); - continue; - } - } - wh = NULL; /* Catch any invalid use */ - - if (bwi_encap(sc, idx, m, &ni, mgt_pkt) != 0) { - /* 'm' is freed in bwi_encap() if we reach here */ - if (ni != NULL) - ieee80211_free_node(ni); - IFNET_STAT_INC(ifp, oerrors, 1); - continue; - } - - trans = 1; - tbd->tbd_used++; - idx = (idx + 1) % BWI_TX_NDESC; - - if (tbd->tbd_used + BWI_TX_NSPRDESC >= BWI_TX_NDESC) { - ifq_set_oactive(&ifp->if_snd); - break; - } - } - tbd->tbd_idx = idx; - - if (trans) - sc->sc_tx_timer = 5; - ifp->if_timer = 1; -} - -static void -bwi_watchdog(struct ifnet *ifp) -{ - struct bwi_softc *sc = ifp->if_softc; - - ASSERT_SERIALIZED(ifp->if_serializer); - - ifp->if_timer = 0; - - if ((ifp->if_flags & IFF_RUNNING) == 0) - return; - - if (sc->sc_tx_timer) { - if (--sc->sc_tx_timer == 0) { - if_printf(ifp, "watchdog timeout\n"); - IFNET_STAT_INC(ifp, oerrors, 1); - /* TODO */ - } else { - ifp->if_timer = 1; - } - } - ieee80211_watchdog(&sc->sc_ic); -} - -static int -bwi_stop(struct bwi_softc *sc, int state_chg) -{ - struct ieee80211com *ic = &sc->sc_ic; - struct ifnet *ifp = &ic->ic_if; - struct bwi_mac *mac; - int i, error, pwr_off = 0; - - ASSERT_SERIALIZED(ifp->if_serializer); - - if (state_chg) - ieee80211_new_state(ic, IEEE80211_S_INIT, -1); - else - bwi_newstate_begin(sc, IEEE80211_S_INIT); - - if (ifp->if_flags & IFF_RUNNING) { - KKASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC); - mac = (struct bwi_mac *)sc->sc_cur_regwin; - - bwi_disable_intrs(sc, BWI_ALL_INTRS); - CSR_READ_4(sc, BWI_MAC_INTR_MASK); - bwi_mac_stop(mac); - } - - for (i = 0; i < sc->sc_nmac; ++i) { - struct bwi_regwin *old_rw; - - mac = &sc->sc_mac[i]; - if ((mac->mac_flags & BWI_MAC_F_INITED) == 0) - continue; - - error = bwi_regwin_switch(sc, &mac->mac_regwin, &old_rw); - if (error) - continue; - - bwi_mac_shutdown(mac); - pwr_off = 1; - - bwi_regwin_switch(sc, old_rw, NULL); - } - - if (pwr_off) - bwi_bbp_power_off(sc); - - sc->sc_tx_timer = 0; - ifp->if_timer = 0; - ifp->if_flags &= ~IFF_RUNNING; - ifq_clr_oactive(&ifp->if_snd); - return 0; -} - -static void -bwi_intr(void *xsc) -{ - struct bwi_softc *sc = xsc; - struct bwi_mac *mac; - struct ifnet *ifp = &sc->sc_ic.ic_if; - uint32_t intr_status; - uint32_t txrx_intr_status[BWI_TXRX_NRING]; - int i, txrx_error, tx = 0, rx_data = -1; - - ASSERT_SERIALIZED(ifp->if_serializer); - - if ((ifp->if_flags & IFF_RUNNING) == 0) - return; - - /* - * Get interrupt status - */ - intr_status = CSR_READ_4(sc, BWI_MAC_INTR_STATUS); - if (intr_status == 0xffffffff) /* Not for us */ - return; - - DPRINTF(sc, BWI_DBG_INTR, "intr status 0x%08x\n", intr_status); - - intr_status &= CSR_READ_4(sc, BWI_MAC_INTR_MASK); - if (intr_status == 0) /* Nothing is interesting */ - return; - - KKASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC); - mac = (struct bwi_mac *)sc->sc_cur_regwin; - - txrx_error = 0; - DPRINTF(sc, BWI_DBG_INTR, "%s\n", "TX/RX intr"); - for (i = 0; i < BWI_TXRX_NRING; ++i) { - uint32_t mask; - - if (BWI_TXRX_IS_RX(i)) - mask = BWI_TXRX_RX_INTRS; - else - mask = BWI_TXRX_TX_INTRS; - - txrx_intr_status[i] = - CSR_READ_4(sc, BWI_TXRX_INTR_STATUS(i)) & mask; - - _DPRINTF(sc, BWI_DBG_INTR, ", %d 0x%08x", - i, txrx_intr_status[i]); - - if (txrx_intr_status[i] & BWI_TXRX_INTR_ERROR) { - if_printf(ifp, "intr fatal TX/RX (%d) error 0x%08x\n", - i, txrx_intr_status[i]); - txrx_error = 1; - } - } - _DPRINTF(sc, BWI_DBG_INTR, "%s\n", ""); - - /* - * Acknowledge interrupt - */ - CSR_WRITE_4(sc, BWI_MAC_INTR_STATUS, intr_status); - - for (i = 0; i < BWI_TXRX_NRING; ++i) - CSR_WRITE_4(sc, BWI_TXRX_INTR_STATUS(i), txrx_intr_status[i]); - - /* Disable all interrupts */ - bwi_disable_intrs(sc, BWI_ALL_INTRS); - - if (intr_status & BWI_INTR_PHY_TXERR) { - if (mac->mac_flags & BWI_MAC_F_PHYE_RESET) { - if_printf(ifp, "intr PHY TX error\n"); - /* XXX to netisr0? */ - bwi_init_statechg(sc, 0); - return; - } - } - - if (txrx_error) { - /* TODO: reset device */ - } - - if (intr_status & BWI_INTR_TBTT) - bwi_mac_config_ps(mac); - - if (intr_status & BWI_INTR_EO_ATIM) - if_printf(ifp, "EO_ATIM\n"); - - if (intr_status & BWI_INTR_PMQ) { - for (;;) { - if ((CSR_READ_4(sc, BWI_MAC_PS_STATUS) & 0x8) == 0) - break; - } - CSR_WRITE_2(sc, BWI_MAC_PS_STATUS, 0x2); - } - - if (intr_status & BWI_INTR_NOISE) - if_printf(ifp, "intr noise\n"); - - if (txrx_intr_status[0] & BWI_TXRX_INTR_RX) - rx_data = sc->sc_rxeof(sc); - - if (txrx_intr_status[3] & BWI_TXRX_INTR_RX) { - sc->sc_txeof_status(sc); - tx = 1; - } - - if (intr_status & BWI_INTR_TX_DONE) { - bwi_txeof(sc); - tx = 1; - } - - /* Re-enable interrupts */ - bwi_enable_intrs(sc, BWI_INIT_INTRS); - - if (sc->sc_blink_led != NULL && sc->sc_led_blink) { - int evt = BWI_LED_EVENT_NONE; - - if (tx && rx_data > 0) { - if (sc->sc_rx_rate > sc->sc_tx_rate) - evt = BWI_LED_EVENT_RX; - else - evt = BWI_LED_EVENT_TX; - } else if (tx) { - evt = BWI_LED_EVENT_TX; - } else if (rx_data > 0) { - evt = BWI_LED_EVENT_RX; - } else if (rx_data == 0) { - evt = BWI_LED_EVENT_POLL; - } - - if (evt != BWI_LED_EVENT_NONE) - bwi_led_event(sc, evt); - } -} - -static void -bwi_newstate_begin(struct bwi_softc *sc, enum ieee80211_state nstate) -{ - callout_stop(&sc->sc_scan_ch); - callout_stop(&sc->sc_calib_ch); - - ieee80211_ratectl_newstate(&sc->sc_ic, nstate); - bwi_led_newstate(sc, nstate); - - if (nstate == IEEE80211_S_INIT) - sc->sc_txpwrcb_type = BWI_TXPWR_INIT; -} - -static int -bwi_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg) -{ - struct bwi_softc *sc = ic->ic_if.if_softc; - struct ifnet *ifp = &ic->ic_if; - int error; - - ASSERT_SERIALIZED(ifp->if_serializer); - - bwi_newstate_begin(sc, nstate); - - if (nstate == IEEE80211_S_INIT) - goto back; - - error = bwi_set_chan(sc, ic->ic_curchan); - if (error) { - if_printf(ifp, "can't set channel to %u\n", - ieee80211_chan2ieee(ic, ic->ic_curchan)); - return error; - } - - if (ic->ic_opmode == IEEE80211_M_MONITOR) { - /* Nothing to do */ - } else if (nstate == IEEE80211_S_RUN) { - struct bwi_mac *mac; - - bwi_set_bssid(sc, ic->ic_bss->ni_bssid); - - KKASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC); - mac = (struct bwi_mac *)sc->sc_cur_regwin; - - /* Initial TX power calibration */ - bwi_mac_calibrate_txpower(mac, BWI_TXPWR_INIT); -#ifdef notyet - sc->sc_txpwrcb_type = BWI_TXPWR_FORCE; -#else - sc->sc_txpwrcb_type = BWI_TXPWR_CALIB; -#endif - } else { - bwi_set_bssid(sc, bwi_zero_addr); - } - -back: - error = sc->sc_newstate(ic, nstate, arg); - - if (nstate == IEEE80211_S_SCAN) { - callout_reset(&sc->sc_scan_ch, - (sc->sc_dwell_time * hz) / 1000, - bwi_next_scan, sc); - } else if (nstate == IEEE80211_S_RUN) { - callout_reset(&sc->sc_calib_ch, hz, bwi_calibrate, sc); - } - return error; -} - -static int -bwi_media_change(struct ifnet *ifp) -{ - int error; - - ASSERT_SERIALIZED(ifp->if_serializer); - - error = ieee80211_media_change(ifp); - if (error != ENETRESET) - return error; - - if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING)) - bwi_init(ifp->if_softc); - return 0; -} - -static int -bwi_dma_alloc(struct bwi_softc *sc) -{ - int error, i, has_txstats; - bus_addr_t lowaddr = 0; - bus_size_t tx_ring_sz, rx_ring_sz, desc_sz = 0; - uint32_t txrx_ctrl_step = 0; - - has_txstats = 0; - for (i = 0; i < sc->sc_nmac; ++i) { - if (sc->sc_mac[i].mac_flags & BWI_MAC_F_HAS_TXSTATS) { - has_txstats = 1; - break; - } - } - - switch (sc->sc_bus_space) { - case BWI_BUS_SPACE_30BIT: - case BWI_BUS_SPACE_32BIT: - if (sc->sc_bus_space == BWI_BUS_SPACE_30BIT) - lowaddr = BWI_BUS_SPACE_MAXADDR; - else - lowaddr = BUS_SPACE_MAXADDR_32BIT; - desc_sz = sizeof(struct bwi_desc32); - txrx_ctrl_step = 0x20; - - sc->sc_init_tx_ring = bwi_init_tx_ring32; - sc->sc_free_tx_ring = bwi_free_tx_ring32; - sc->sc_init_rx_ring = bwi_init_rx_ring32; - sc->sc_free_rx_ring = bwi_free_rx_ring32; - sc->sc_setup_rxdesc = bwi_setup_rx_desc32; - sc->sc_setup_txdesc = bwi_setup_tx_desc32; - sc->sc_rxeof = bwi_rxeof32; - sc->sc_start_tx = bwi_start_tx32; - if (has_txstats) { - sc->sc_init_txstats = bwi_init_txstats32; - sc->sc_free_txstats = bwi_free_txstats32; - sc->sc_txeof_status = bwi_txeof_status32; - } - break; - - case BWI_BUS_SPACE_64BIT: - lowaddr = BUS_SPACE_MAXADDR; /* XXX */ - desc_sz = sizeof(struct bwi_desc64); - txrx_ctrl_step = 0x40; - - sc->sc_init_tx_ring = bwi_init_tx_ring64; - sc->sc_free_tx_ring = bwi_free_tx_ring64; - sc->sc_init_rx_ring = bwi_init_rx_ring64; - sc->sc_free_rx_ring = bwi_free_rx_ring64; - sc->sc_setup_rxdesc = bwi_setup_rx_desc64; - sc->sc_setup_txdesc = bwi_setup_tx_desc64; - sc->sc_rxeof = bwi_rxeof64; - sc->sc_start_tx = bwi_start_tx64; - if (has_txstats) { - sc->sc_init_txstats = bwi_init_txstats64; - sc->sc_free_txstats = bwi_free_txstats64; - sc->sc_txeof_status = bwi_txeof_status64; - } - break; - } - - KKASSERT(lowaddr != 0); - KKASSERT(desc_sz != 0); - KKASSERT(txrx_ctrl_step != 0); - - tx_ring_sz = roundup(desc_sz * BWI_TX_NDESC, BWI_RING_ALIGN); - rx_ring_sz = roundup(desc_sz * BWI_RX_NDESC, BWI_RING_ALIGN); - - /* - * Create top level DMA tag - */ - error = bus_dma_tag_create(NULL, BWI_ALIGN, 0, - lowaddr, BUS_SPACE_MAXADDR, - NULL, NULL, - MAXBSIZE, - BUS_SPACE_UNRESTRICTED, - BUS_SPACE_MAXSIZE_32BIT, - 0, &sc->sc_parent_dtag); - if (error) { - device_printf(sc->sc_dev, "can't create parent DMA tag\n"); - return error; - } - -#define TXRX_CTRL(idx) (BWI_TXRX_CTRL_BASE + (idx) * txrx_ctrl_step) - - /* - * Create TX ring DMA stuffs - */ - error = bus_dma_tag_create(sc->sc_parent_dtag, BWI_RING_ALIGN, 0, - BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, - NULL, NULL, - tx_ring_sz, 1, BUS_SPACE_MAXSIZE_32BIT, - 0, &sc->sc_txring_dtag); - if (error) { - device_printf(sc->sc_dev, "can't create TX ring DMA tag\n"); - return error; - } - - for (i = 0; i < BWI_TX_NRING; ++i) { - error = bwi_dma_ring_alloc(sc, sc->sc_txring_dtag, - &sc->sc_tx_rdata[i], tx_ring_sz, - TXRX_CTRL(i)); - if (error) { - device_printf(sc->sc_dev, "%dth TX ring " - "DMA alloc failed\n", i); - return error; - } - } - - /* - * Create RX ring DMA stuffs - */ - error = bus_dma_tag_create(sc->sc_parent_dtag, BWI_RING_ALIGN, 0, - BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, - NULL, NULL, - rx_ring_sz, 1, BUS_SPACE_MAXSIZE_32BIT, - 0, &sc->sc_rxring_dtag); - if (error) { - device_printf(sc->sc_dev, "can't create RX ring DMA tag\n"); - return error; - } - - error = bwi_dma_ring_alloc(sc, sc->sc_rxring_dtag, &sc->sc_rx_rdata, - rx_ring_sz, TXRX_CTRL(0)); - if (error) { - device_printf(sc->sc_dev, "RX ring DMA alloc failed\n"); - return error; - } - - if (has_txstats) { - error = bwi_dma_txstats_alloc(sc, TXRX_CTRL(3), desc_sz); - if (error) { - device_printf(sc->sc_dev, - "TX stats DMA alloc failed\n"); - return error; - } - } - -#undef TXRX_CTRL - - return bwi_dma_mbuf_create(sc); -} - -static void -bwi_dma_free(struct bwi_softc *sc) -{ - if (sc->sc_txring_dtag != NULL) { - int i; - - for (i = 0; i < BWI_TX_NRING; ++i) { - struct bwi_ring_data *rd = &sc->sc_tx_rdata[i]; - - if (rd->rdata_desc != NULL) { - bus_dmamap_unload(sc->sc_txring_dtag, - rd->rdata_dmap); - bus_dmamem_free(sc->sc_txring_dtag, - rd->rdata_desc, - rd->rdata_dmap); - } - } - bus_dma_tag_destroy(sc->sc_txring_dtag); - } - - if (sc->sc_rxring_dtag != NULL) { - struct bwi_ring_data *rd = &sc->sc_rx_rdata; - - if (rd->rdata_desc != NULL) { - bus_dmamap_unload(sc->sc_rxring_dtag, rd->rdata_dmap); - bus_dmamem_free(sc->sc_rxring_dtag, rd->rdata_desc, - rd->rdata_dmap); - } - bus_dma_tag_destroy(sc->sc_rxring_dtag); - } - - bwi_dma_txstats_free(sc); - bwi_dma_mbuf_destroy(sc, BWI_TX_NRING, 1); - - if (sc->sc_parent_dtag != NULL) - bus_dma_tag_destroy(sc->sc_parent_dtag); -} - -static int -bwi_dma_ring_alloc(struct bwi_softc *sc, bus_dma_tag_t dtag, - struct bwi_ring_data *rd, bus_size_t size, - uint32_t txrx_ctrl) -{ - int error; - - error = bus_dmamem_alloc(dtag, &rd->rdata_desc, - BUS_DMA_WAITOK | BUS_DMA_ZERO, - &rd->rdata_dmap); - if (error) { - device_printf(sc->sc_dev, "can't allocate DMA mem\n"); - return error; - } - - error = bus_dmamap_load(dtag, rd->rdata_dmap, rd->rdata_desc, size, - bwi_dma_ring_addr, &rd->rdata_paddr, - BUS_DMA_WAITOK); - if (error) { - device_printf(sc->sc_dev, "can't load DMA mem\n"); - bus_dmamem_free(dtag, rd->rdata_desc, rd->rdata_dmap); - rd->rdata_desc = NULL; - return error; - } - - rd->rdata_txrx_ctrl = txrx_ctrl; - return 0; -} - -static int -bwi_dma_txstats_alloc(struct bwi_softc *sc, uint32_t ctrl_base, - bus_size_t desc_sz) -{ - struct bwi_txstats_data *st; - bus_size_t dma_size; - int error; - - st = kmalloc(sizeof(*st), M_DEVBUF, M_WAITOK | M_ZERO); - sc->sc_txstats = st; - - /* - * Create TX stats descriptor DMA stuffs - */ - dma_size = roundup(desc_sz * BWI_TXSTATS_NDESC, BWI_RING_ALIGN); - - error = bus_dma_tag_create(sc->sc_parent_dtag, BWI_RING_ALIGN, 0, - BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, - NULL, NULL, - dma_size, 1, BUS_SPACE_MAXSIZE_32BIT, - 0, &st->stats_ring_dtag); - if (error) { - device_printf(sc->sc_dev, "can't create txstats ring " - "DMA tag\n"); - return error; - } - - error = bus_dmamem_alloc(st->stats_ring_dtag, &st->stats_ring, - BUS_DMA_WAITOK | BUS_DMA_ZERO, - &st->stats_ring_dmap); - if (error) { - device_printf(sc->sc_dev, "can't allocate txstats ring " - "DMA mem\n"); - bus_dma_tag_destroy(st->stats_ring_dtag); - st->stats_ring_dtag = NULL; - return error; - } - - error = bus_dmamap_load(st->stats_ring_dtag, st->stats_ring_dmap, - st->stats_ring, dma_size, - bwi_dma_ring_addr, &st->stats_ring_paddr, - BUS_DMA_WAITOK); - if (error) { - device_printf(sc->sc_dev, "can't load txstats ring DMA mem\n"); - bus_dmamem_free(st->stats_ring_dtag, st->stats_ring, - st->stats_ring_dmap); - bus_dma_tag_destroy(st->stats_ring_dtag); - st->stats_ring_dtag = NULL; - return error; - } - - /* - * Create TX stats DMA stuffs - */ - dma_size = roundup(sizeof(struct bwi_txstats) * BWI_TXSTATS_NDESC, - BWI_ALIGN); - - error = bus_dma_tag_create(sc->sc_parent_dtag, BWI_ALIGN, 0, - BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, - NULL, NULL, - dma_size, 1, BUS_SPACE_MAXSIZE_32BIT, - 0, &st->stats_dtag); - if (error) { - device_printf(sc->sc_dev, "can't create txstats DMA tag\n"); - return error; - } - - error = bus_dmamem_alloc(st->stats_dtag, (void **)&st->stats, - BUS_DMA_WAITOK | BUS_DMA_ZERO, - &st->stats_dmap); - if (error) { - device_printf(sc->sc_dev, "can't allocate txstats DMA mem\n"); - bus_dma_tag_destroy(st->stats_dtag); - st->stats_dtag = NULL; - return error; - } - - error = bus_dmamap_load(st->stats_dtag, st->stats_dmap, st->stats, - dma_size, bwi_dma_ring_addr, &st->stats_paddr, - BUS_DMA_WAITOK); - if (error) { - device_printf(sc->sc_dev, "can't load txstats DMA mem\n"); - bus_dmamem_free(st->stats_dtag, st->stats, st->stats_dmap); - bus_dma_tag_destroy(st->stats_dtag); - st->stats_dtag = NULL; - return error; - } - - st->stats_ctrl_base = ctrl_base; - return 0; -} - -static void -bwi_dma_txstats_free(struct bwi_softc *sc) -{ - struct bwi_txstats_data *st; - - if (sc->sc_txstats == NULL) - return; - st = sc->sc_txstats; - - if (st->stats_ring_dtag != NULL) { - bus_dmamap_unload(st->stats_ring_dtag, st->stats_ring_dmap); - bus_dmamem_free(st->stats_ring_dtag, st->stats_ring, - st->stats_ring_dmap); - bus_dma_tag_destroy(st->stats_ring_dtag); - } - - if (st->stats_dtag != NULL) { - bus_dmamap_unload(st->stats_dtag, st->stats_dmap); - bus_dmamem_free(st->stats_dtag, st->stats, st->stats_dmap); - bus_dma_tag_destroy(st->stats_dtag); - } - - kfree(st, M_DEVBUF); -} - -static void -bwi_dma_ring_addr(void *arg, bus_dma_segment_t *seg, int nseg, int error) -{ - KASSERT(nseg == 1, ("too many segments")); - *((bus_addr_t *)arg) = seg->ds_addr; -} - -static int -bwi_dma_mbuf_create(struct bwi_softc *sc) -{ - struct bwi_rxbuf_data *rbd = &sc->sc_rx_bdata; - int i, j, k, ntx, error; - - /* - * Create TX/RX mbuf DMA tag - */ - error = bus_dma_tag_create(sc->sc_parent_dtag, 1, 0, - BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, - NULL, NULL, MCLBYTES, 1, - BUS_SPACE_MAXSIZE_32BIT, - 0, &sc->sc_buf_dtag); - if (error) { - device_printf(sc->sc_dev, "can't create mbuf DMA tag\n"); - return error; - } - - ntx = 0; - - /* - * Create TX mbuf DMA map - */ - for (i = 0; i < BWI_TX_NRING; ++i) { - struct bwi_txbuf_data *tbd = &sc->sc_tx_bdata[i]; - - for (j = 0; j < BWI_TX_NDESC; ++j) { - error = bus_dmamap_create(sc->sc_buf_dtag, 0, - &tbd->tbd_buf[j].tb_dmap); - if (error) { - device_printf(sc->sc_dev, "can't create " - "%dth tbd, %dth DMA map\n", i, j); - - ntx = i; - for (k = 0; k < j; ++k) { - bus_dmamap_destroy(sc->sc_buf_dtag, - tbd->tbd_buf[k].tb_dmap); - } - goto fail; - } - } - } - ntx = BWI_TX_NRING; - - /* - * Create RX mbuf DMA map and a spare DMA map - */ - error = bus_dmamap_create(sc->sc_buf_dtag, 0, - &rbd->rbd_tmp_dmap); - if (error) { - device_printf(sc->sc_dev, - "can't create spare RX buf DMA map\n"); - goto fail; - } - - for (j = 0; j < BWI_RX_NDESC; ++j) { - error = bus_dmamap_create(sc->sc_buf_dtag, 0, - &rbd->rbd_buf[j].rb_dmap); - if (error) { - device_printf(sc->sc_dev, "can't create %dth " - "RX buf DMA map\n", j); - - for (k = 0; k < j; ++k) { - bus_dmamap_destroy(sc->sc_buf_dtag, - rbd->rbd_buf[j].rb_dmap); - } - bus_dmamap_destroy(sc->sc_buf_dtag, - rbd->rbd_tmp_dmap); - goto fail; - } - } - - return 0; -fail: - bwi_dma_mbuf_destroy(sc, ntx, 0); - return error; -} - -static void -bwi_dma_mbuf_destroy(struct bwi_softc *sc, int ntx, int nrx) -{ - int i, j; - - if (sc->sc_buf_dtag == NULL) - return; - - for (i = 0; i < ntx; ++i) { - struct bwi_txbuf_data *tbd = &sc->sc_tx_bdata[i]; - - for (j = 0; j < BWI_TX_NDESC; ++j) { - struct bwi_txbuf *tb = &tbd->tbd_buf[j]; - - if (tb->tb_mbuf != NULL) { - bus_dmamap_unload(sc->sc_buf_dtag, - tb->tb_dmap); - m_freem(tb->tb_mbuf); - } - if (tb->tb_ni != NULL) - ieee80211_free_node(tb->tb_ni); - bus_dmamap_destroy(sc->sc_buf_dtag, tb->tb_dmap); - } - } - - if (nrx) { - struct bwi_rxbuf_data *rbd = &sc->sc_rx_bdata; - - bus_dmamap_destroy(sc->sc_buf_dtag, rbd->rbd_tmp_dmap); - for (j = 0; j < BWI_RX_NDESC; ++j) { - struct bwi_rxbuf *rb = &rbd->rbd_buf[j]; - - if (rb->rb_mbuf != NULL) { - bus_dmamap_unload(sc->sc_buf_dtag, - rb->rb_dmap); - m_freem(rb->rb_mbuf); - } - bus_dmamap_destroy(sc->sc_buf_dtag, rb->rb_dmap); - } - } - - bus_dma_tag_destroy(sc->sc_buf_dtag); - sc->sc_buf_dtag = NULL; -} - -static void -bwi_enable_intrs(struct bwi_softc *sc, uint32_t enable_intrs) -{ - CSR_SETBITS_4(sc, BWI_MAC_INTR_MASK, enable_intrs); -} - -static void -bwi_disable_intrs(struct bwi_softc *sc, uint32_t disable_intrs) -{ - CSR_CLRBITS_4(sc, BWI_MAC_INTR_MASK, disable_intrs); -} - -static int -bwi_init_tx_ring32(struct bwi_softc *sc, int ring_idx) -{ - struct bwi_ring_data *rd; - struct bwi_txbuf_data *tbd; - uint32_t val, addr_hi, addr_lo; - - KKASSERT(ring_idx < BWI_TX_NRING); - rd = &sc->sc_tx_rdata[ring_idx]; - tbd = &sc->sc_tx_bdata[ring_idx]; - - tbd->tbd_idx = 0; - tbd->tbd_used = 0; - - bzero(rd->rdata_desc, sizeof(struct bwi_desc32) * BWI_TX_NDESC); - bus_dmamap_sync(sc->sc_txring_dtag, rd->rdata_dmap, - BUS_DMASYNC_PREWRITE); - - addr_lo = __SHIFTOUT(rd->rdata_paddr, BWI_TXRX32_RINGINFO_ADDR_MASK); - addr_hi = __SHIFTOUT(rd->rdata_paddr, BWI_TXRX32_RINGINFO_FUNC_MASK); - - val = __SHIFTIN(addr_lo, BWI_TXRX32_RINGINFO_ADDR_MASK) | - __SHIFTIN(BWI_TXRX32_RINGINFO_FUNC_TXRX, - BWI_TXRX32_RINGINFO_FUNC_MASK); - CSR_WRITE_4(sc, rd->rdata_txrx_ctrl + BWI_TX32_RINGINFO, val); - - val = __SHIFTIN(addr_hi, BWI_TXRX32_CTRL_ADDRHI_MASK) | - BWI_TXRX32_CTRL_ENABLE; - CSR_WRITE_4(sc, rd->rdata_txrx_ctrl + BWI_TX32_CTRL, val); - - return 0; -} - -static void -bwi_init_rxdesc_ring32(struct bwi_softc *sc, uint32_t ctrl_base, - bus_addr_t paddr, int hdr_size, int ndesc) -{ - uint32_t val, addr_hi, addr_lo; - - addr_lo = __SHIFTOUT(paddr, BWI_TXRX32_RINGINFO_ADDR_MASK); - addr_hi = __SHIFTOUT(paddr, BWI_TXRX32_RINGINFO_FUNC_MASK); - - val = __SHIFTIN(addr_lo, BWI_TXRX32_RINGINFO_ADDR_MASK) | - __SHIFTIN(BWI_TXRX32_RINGINFO_FUNC_TXRX, - BWI_TXRX32_RINGINFO_FUNC_MASK); - CSR_WRITE_4(sc, ctrl_base + BWI_RX32_RINGINFO, val); - - val = __SHIFTIN(hdr_size, BWI_RX32_CTRL_HDRSZ_MASK) | - __SHIFTIN(addr_hi, BWI_TXRX32_CTRL_ADDRHI_MASK) | - BWI_TXRX32_CTRL_ENABLE; - CSR_WRITE_4(sc, ctrl_base + BWI_RX32_CTRL, val); - - CSR_WRITE_4(sc, ctrl_base + BWI_RX32_INDEX, - (ndesc - 1) * sizeof(struct bwi_desc32)); -} - -static int -bwi_init_rx_ring32(struct bwi_softc *sc) -{ - struct bwi_ring_data *rd = &sc->sc_rx_rdata; - int i, error; - - sc->sc_rx_bdata.rbd_idx = 0; - - for (i = 0; i < BWI_RX_NDESC; ++i) { - error = bwi_newbuf(sc, i, 1); - if (error) { - if_printf(&sc->sc_ic.ic_if, - "can't allocate %dth RX buffer\n", i); - return error; - } - } - bus_dmamap_sync(sc->sc_rxring_dtag, rd->rdata_dmap, - BUS_DMASYNC_PREWRITE); - - bwi_init_rxdesc_ring32(sc, rd->rdata_txrx_ctrl, rd->rdata_paddr, - sizeof(struct bwi_rxbuf_hdr), BWI_RX_NDESC); - return 0; -} - -static int -bwi_init_txstats32(struct bwi_softc *sc) -{ - struct bwi_txstats_data *st = sc->sc_txstats; - bus_addr_t stats_paddr; - int i; - - bzero(st->stats, BWI_TXSTATS_NDESC * sizeof(struct bwi_txstats)); - bus_dmamap_sync(st->stats_dtag, st->stats_dmap, BUS_DMASYNC_PREWRITE); - - st->stats_idx = 0; - - stats_paddr = st->stats_paddr; - for (i = 0; i < BWI_TXSTATS_NDESC; ++i) { - bwi_setup_desc32(sc, st->stats_ring, BWI_TXSTATS_NDESC, i, - stats_paddr, sizeof(struct bwi_txstats), 0); - stats_paddr += sizeof(struct bwi_txstats); - } - bus_dmamap_sync(st->stats_ring_dtag, st->stats_ring_dmap, - BUS_DMASYNC_PREWRITE); - - bwi_init_rxdesc_ring32(sc, st->stats_ctrl_base, - st->stats_ring_paddr, 0, BWI_TXSTATS_NDESC); - return 0; -} - -static void -bwi_setup_rx_desc32(struct bwi_softc *sc, int buf_idx, bus_addr_t paddr, - int buf_len) -{ - struct bwi_ring_data *rd = &sc->sc_rx_rdata; - - KKASSERT(buf_idx < BWI_RX_NDESC); - bwi_setup_desc32(sc, rd->rdata_desc, BWI_RX_NDESC, buf_idx, - paddr, buf_len, 0); -} - -static void -bwi_setup_tx_desc32(struct bwi_softc *sc, struct bwi_ring_data *rd, - int buf_idx, bus_addr_t paddr, int buf_len) -{ - KKASSERT(buf_idx < BWI_TX_NDESC); - bwi_setup_desc32(sc, rd->rdata_desc, BWI_TX_NDESC, buf_idx, - paddr, buf_len, 1); -} - -static int -bwi_init_tx_ring64(struct bwi_softc *sc, int ring_idx) -{ - /* TODO:64 */ - return EOPNOTSUPP; -} - -static int -bwi_init_rx_ring64(struct bwi_softc *sc) -{ - /* TODO:64 */ - return EOPNOTSUPP; -} - -static int -bwi_init_txstats64(struct bwi_softc *sc) -{ - /* TODO:64 */ - return EOPNOTSUPP; -} - -static void -bwi_setup_rx_desc64(struct bwi_softc *sc, int buf_idx, bus_addr_t paddr, - int buf_len) -{ - /* TODO:64 */ -} - -static void -bwi_setup_tx_desc64(struct bwi_softc *sc, struct bwi_ring_data *rd, - int buf_idx, bus_addr_t paddr, int buf_len) -{ - /* TODO:64 */ -} - -static void -bwi_dma_buf_addr(void *arg, bus_dma_segment_t *seg, int nseg, - bus_size_t mapsz __unused, int error) -{ - if (!error) { - KASSERT(nseg == 1, ("too many segments(%d)", nseg)); - *((bus_addr_t *)arg) = seg->ds_addr; - } -} - -static int -bwi_newbuf(struct bwi_softc *sc, int buf_idx, int init) -{ - struct bwi_rxbuf_data *rbd = &sc->sc_rx_bdata; - struct bwi_rxbuf *rxbuf = &rbd->rbd_buf[buf_idx]; - struct bwi_rxbuf_hdr *hdr; - bus_dmamap_t map; - bus_addr_t paddr; - struct mbuf *m; - int error; - - KKASSERT(buf_idx < BWI_RX_NDESC); - - m = m_getcl(init ? M_WAITOK : M_NOWAIT, MT_DATA, M_PKTHDR); - if (m == NULL) { - error = ENOBUFS; - - /* - * If the NIC is up and running, we need to: - * - Clear RX buffer's header. - * - Restore RX descriptor settings. - */ - if (init) - return error; - else - goto back; - } - m->m_len = m->m_pkthdr.len = MCLBYTES; - - /* - * Try to load RX buf into temporary DMA map - */ - error = bus_dmamap_load_mbuf(sc->sc_buf_dtag, rbd->rbd_tmp_dmap, m, - bwi_dma_buf_addr, &paddr, - init ? BUS_DMA_WAITOK : BUS_DMA_NOWAIT); - if (error) { - m_freem(m); - - /* - * See the comment above - */ - if (init) - return error; - else - goto back; - } - - if (!init) - bus_dmamap_unload(sc->sc_buf_dtag, rxbuf->rb_dmap); - rxbuf->rb_mbuf = m; - rxbuf->rb_paddr = paddr; - - /* - * Swap RX buf's DMA map with the loaded temporary one - */ - map = rxbuf->rb_dmap; - rxbuf->rb_dmap = rbd->rbd_tmp_dmap; - rbd->rbd_tmp_dmap = map; - -back: - /* - * Clear RX buf header - */ - hdr = mtod(rxbuf->rb_mbuf, struct bwi_rxbuf_hdr *); - bzero(hdr, sizeof(*hdr)); - bus_dmamap_sync(sc->sc_buf_dtag, rxbuf->rb_dmap, BUS_DMASYNC_PREWRITE); - - /* - * Setup RX buf descriptor - */ - sc->sc_setup_rxdesc(sc, buf_idx, rxbuf->rb_paddr, - rxbuf->rb_mbuf->m_len - sizeof(*hdr)); - return error; -} - -static void -bwi_set_addr_filter(struct bwi_softc *sc, uint16_t addr_ofs, - const uint8_t *addr) -{ - int i; - - CSR_WRITE_2(sc, BWI_ADDR_FILTER_CTRL, - BWI_ADDR_FILTER_CTRL_SET | addr_ofs); - - for (i = 0; i < (IEEE80211_ADDR_LEN / 2); ++i) { - uint16_t addr_val; - - addr_val = (uint16_t)addr[i * 2] | - (((uint16_t)addr[(i * 2) + 1]) << 8); - CSR_WRITE_2(sc, BWI_ADDR_FILTER_DATA, addr_val); - } -} - -static int -bwi_set_chan(struct bwi_softc *sc, struct ieee80211_channel *c) -{ - struct ieee80211com *ic = &sc->sc_ic; -#ifdef INVARIANTS - struct ifnet *ifp = &ic->ic_if; -#endif - struct bwi_mac *mac; - uint16_t flags; - u_int chan; - - ASSERT_SERIALIZED(ifp->if_serializer); - - KKASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC); - mac = (struct bwi_mac *)sc->sc_cur_regwin; - - chan = ieee80211_chan2ieee(ic, c); - - bwi_rf_set_chan(mac, chan, 0); - - /* - * Setup radio tap channel freq and flags - */ - if (IEEE80211_IS_CHAN_G(c)) - flags = IEEE80211_CHAN_G; - else - flags = IEEE80211_CHAN_B; - - sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq = - htole16(c->ic_freq); - sc->sc_tx_th.wt_chan_flags = sc->sc_rx_th.wr_chan_flags = - htole16(flags); - - return 0; -} - -static void -bwi_next_scan(void *xsc) -{ - struct bwi_softc *sc = xsc; - struct ieee80211com *ic = &sc->sc_ic; - struct ifnet *ifp = &ic->ic_if; - - lwkt_serialize_enter(ifp->if_serializer); - - if (ic->ic_state == IEEE80211_S_SCAN) - ieee80211_next_scan(ic); - - lwkt_serialize_exit(ifp->if_serializer); -} - -static int -bwi_rxeof(struct bwi_softc *sc, int end_idx) -{ - struct bwi_ring_data *rd = &sc->sc_rx_rdata; - struct bwi_rxbuf_data *rbd = &sc->sc_rx_bdata; - struct ieee80211com *ic = &sc->sc_ic; - struct ifnet *ifp = &ic->ic_if; - int idx, rx_data = 0; - - idx = rbd->rbd_idx; - while (idx != end_idx) { - struct bwi_rxbuf *rb = &rbd->rbd_buf[idx]; - struct bwi_rxbuf_hdr *hdr; - struct ieee80211_frame_min *wh; - struct ieee80211_node *ni; - struct mbuf *m; - const void *plcp; - uint16_t flags2; - int buflen, wh_ofs, hdr_extra, rssi, type, rate; - - m = rb->rb_mbuf; - bus_dmamap_sync(sc->sc_buf_dtag, rb->rb_dmap, - BUS_DMASYNC_POSTREAD); - - if (bwi_newbuf(sc, idx, 0)) { - IFNET_STAT_INC(ifp, ierrors, 1); - goto next; - } - - hdr = mtod(m, struct bwi_rxbuf_hdr *); - flags2 = le16toh(hdr->rxh_flags2); - - hdr_extra = 0; - if (flags2 & BWI_RXH_F2_TYPE2FRAME) - hdr_extra = 2; - wh_ofs = hdr_extra + 6; /* XXX magic number */ - - buflen = le16toh(hdr->rxh_buflen); - if (buflen < BWI_FRAME_MIN_LEN(wh_ofs)) { - if_printf(ifp, "short frame %d, hdr_extra %d\n", - buflen, hdr_extra); - IFNET_STAT_INC(ifp, ierrors, 1); - m_freem(m); - goto next; - } - - plcp = ((const uint8_t *)(hdr + 1) + hdr_extra); - rssi = bwi_calc_rssi(sc, hdr); - - m->m_pkthdr.rcvif = ifp; - m->m_len = m->m_pkthdr.len = buflen + sizeof(*hdr); - m_adj(m, sizeof(*hdr) + wh_ofs); - - if (htole16(hdr->rxh_flags1) & BWI_RXH_F1_OFDM) - rate = bwi_ofdm_plcp2rate(plcp); - else - rate = bwi_ds_plcp2rate(plcp); - - /* RX radio tap */ - if (sc->sc_drvbpf != NULL) - bwi_rx_radiotap(sc, m, hdr, plcp, rate, rssi); - - m_adj(m, -IEEE80211_CRC_LEN); - - wh = mtod(m, struct ieee80211_frame_min *); - ni = ieee80211_find_rxnode(ic, wh); - - type = ieee80211_input(ic, m, ni, rssi - BWI_NOISE_FLOOR, - le16toh(hdr->rxh_tsf)); - ieee80211_free_node(ni); - - if (type == IEEE80211_FC0_TYPE_DATA) { - rx_data = 1; - sc->sc_rx_rate = rate; - } -next: - idx = (idx + 1) % BWI_RX_NDESC; - } - - rbd->rbd_idx = idx; - bus_dmamap_sync(sc->sc_rxring_dtag, rd->rdata_dmap, - BUS_DMASYNC_PREWRITE); - return rx_data; -} - -static int -bwi_rxeof32(struct bwi_softc *sc) -{ - uint32_t val, rx_ctrl; - int end_idx, rx_data; - - rx_ctrl = sc->sc_rx_rdata.rdata_txrx_ctrl; - - val = CSR_READ_4(sc, rx_ctrl + BWI_RX32_STATUS); - end_idx = __SHIFTOUT(val, BWI_RX32_STATUS_INDEX_MASK) / - sizeof(struct bwi_desc32); - - rx_data = bwi_rxeof(sc, end_idx); - - CSR_WRITE_4(sc, rx_ctrl + BWI_RX32_INDEX, - end_idx * sizeof(struct bwi_desc32)); - - return rx_data; -} - -static int -bwi_rxeof64(struct bwi_softc *sc) -{ - /* TODO:64 */ - return 0; -} - -static void -bwi_reset_rx_ring32(struct bwi_softc *sc, uint32_t rx_ctrl) -{ - int i; - - CSR_WRITE_4(sc, rx_ctrl + BWI_RX32_CTRL, 0); - -#define NRETRY 10 - - for (i = 0; i < NRETRY; ++i) { - uint32_t status; - - status = CSR_READ_4(sc, rx_ctrl + BWI_RX32_STATUS); - if (__SHIFTOUT(status, BWI_RX32_STATUS_STATE_MASK) == - BWI_RX32_STATUS_STATE_DISABLED) - break; - - DELAY(1000); - } - if (i == NRETRY) - if_printf(&sc->sc_ic.ic_if, "reset rx ring timedout\n"); - -#undef NRETRY - - CSR_WRITE_4(sc, rx_ctrl + BWI_RX32_RINGINFO, 0); -} - -static void -bwi_free_txstats32(struct bwi_softc *sc) -{ - bwi_reset_rx_ring32(sc, sc->sc_txstats->stats_ctrl_base); -} - -static void -bwi_free_rx_ring32(struct bwi_softc *sc) -{ - struct bwi_ring_data *rd = &sc->sc_rx_rdata; - struct bwi_rxbuf_data *rbd = &sc->sc_rx_bdata; - int i; - - bwi_reset_rx_ring32(sc, rd->rdata_txrx_ctrl); - - for (i = 0; i < BWI_RX_NDESC; ++i) { - struct bwi_rxbuf *rb = &rbd->rbd_buf[i]; - - if (rb->rb_mbuf != NULL) { - bus_dmamap_unload(sc->sc_buf_dtag, rb->rb_dmap); - m_freem(rb->rb_mbuf); - rb->rb_mbuf = NULL; - } - } -} - -static void -bwi_free_tx_ring32(struct bwi_softc *sc, int ring_idx) -{ - struct bwi_ring_data *rd; - struct bwi_txbuf_data *tbd; - struct ifnet *ifp = &sc->sc_ic.ic_if; - uint32_t state, val; - int i; - - KKASSERT(ring_idx < BWI_TX_NRING); - rd = &sc->sc_tx_rdata[ring_idx]; - tbd = &sc->sc_tx_bdata[ring_idx]; - -#define NRETRY 10 - - for (i = 0; i < NRETRY; ++i) { - val = CSR_READ_4(sc, rd->rdata_txrx_ctrl + BWI_TX32_STATUS); - state = __SHIFTOUT(val, BWI_TX32_STATUS_STATE_MASK); - if (state == BWI_TX32_STATUS_STATE_DISABLED || - state == BWI_TX32_STATUS_STATE_IDLE || - state == BWI_TX32_STATUS_STATE_STOPPED) - break; - - DELAY(1000); - } - if (i == NRETRY) { - if_printf(ifp, "wait for TX ring(%d) stable timed out\n", - ring_idx); - } - - CSR_WRITE_4(sc, rd->rdata_txrx_ctrl + BWI_TX32_CTRL, 0); - for (i = 0; i < NRETRY; ++i) { - val = CSR_READ_4(sc, rd->rdata_txrx_ctrl + BWI_TX32_STATUS); - state = __SHIFTOUT(val, BWI_TX32_STATUS_STATE_MASK); - if (state == BWI_TX32_STATUS_STATE_DISABLED) - break; - - DELAY(1000); - } - if (i == NRETRY) - if_printf(ifp, "reset TX ring (%d) timed out\n", ring_idx); - -#undef NRETRY - - DELAY(1000); - - CSR_WRITE_4(sc, rd->rdata_txrx_ctrl + BWI_TX32_RINGINFO, 0); - - for (i = 0; i < BWI_TX_NDESC; ++i) { - struct bwi_txbuf *tb = &tbd->tbd_buf[i]; - - if (tb->tb_mbuf != NULL) { - bus_dmamap_unload(sc->sc_buf_dtag, tb->tb_dmap); - m_freem(tb->tb_mbuf); - tb->tb_mbuf = NULL; - } - if (tb->tb_ni != NULL) { - ieee80211_free_node(tb->tb_ni); - tb->tb_ni = NULL; - } - } -} - -static void -bwi_free_txstats64(struct bwi_softc *sc) -{ - /* TODO:64 */ -} - -static void -bwi_free_rx_ring64(struct bwi_softc *sc) -{ - /* TODO:64 */ -} - -static void -bwi_free_tx_ring64(struct bwi_softc *sc, int ring_idx) -{ - /* TODO:64 */ -} - -static int -bwi_encap(struct bwi_softc *sc, int idx, struct mbuf *m, - struct ieee80211_node **ni0, int mgt_pkt) -{ - struct ieee80211com *ic = &sc->sc_ic; - struct ieee80211_node *ni = *ni0; - struct bwi_ring_data *rd = &sc->sc_tx_rdata[BWI_TX_DATA_RING]; - struct bwi_txbuf_data *tbd = &sc->sc_tx_bdata[BWI_TX_DATA_RING]; - struct bwi_txbuf *tb = &tbd->tbd_buf[idx]; - struct bwi_mac *mac; - struct bwi_txbuf_hdr *hdr; - struct ieee80211_frame *wh; - uint8_t rate, rate_fb; - uint32_t mac_ctrl; - uint16_t phy_ctrl; - bus_addr_t paddr; - int pkt_len, error, mcast_pkt = 0; -#if 0 - const uint8_t *p; - int i; -#endif - - KKASSERT(ni != NULL); - KKASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC); - mac = (struct bwi_mac *)sc->sc_cur_regwin; - - wh = mtod(m, struct ieee80211_frame *); - - /* Get 802.11 frame len before prepending TX header */ - pkt_len = m->m_pkthdr.len + IEEE80211_CRC_LEN; - - /* - * Find TX rate - */ - bzero(tb->tb_rateidx, sizeof(tb->tb_rateidx)); - if (!mgt_pkt) { - if (ic->ic_fixed_rate != IEEE80211_FIXED_RATE_NONE) { - int idx; - - rate = IEEE80211_RS_RATE(&ni->ni_rates, - ic->ic_fixed_rate); - - if (ic->ic_fixed_rate >= 1) - idx = ic->ic_fixed_rate - 1; - else - idx = 0; - rate_fb = IEEE80211_RS_RATE(&ni->ni_rates, idx); - } else { - tb->tb_rateidx_cnt = ieee80211_ratectl_findrate(ni, - m->m_pkthdr.len, tb->tb_rateidx, BWI_NTXRATE); - - rate = IEEE80211_RS_RATE(&ni->ni_rates, - tb->tb_rateidx[0]); - if (tb->tb_rateidx_cnt == BWI_NTXRATE) { - rate_fb = IEEE80211_RS_RATE(&ni->ni_rates, - tb->tb_rateidx[1]); - } else { - rate_fb = rate; - } - tb->tb_buflen = m->m_pkthdr.len; - } - } else { - /* Fixed at 1Mbits/s for mgt frames */ - rate = rate_fb = (1 * 2); - } - - if (IEEE80211_IS_MULTICAST(wh->i_addr1)) { - rate = rate_fb = ic->ic_mcast_rate; - mcast_pkt = 1; - } - - if (rate == 0 || rate_fb == 0) { - /* XXX this should not happen */ - if_printf(&ic->ic_if, "invalid rate %u or fallback rate %u", - rate, rate_fb); - rate = rate_fb = (1 * 2); /* Force 1Mbits/s */ - } - sc->sc_tx_rate = rate; - - /* - * TX radio tap - */ - if (sc->sc_drvbpf != NULL) { - sc->sc_tx_th.wt_flags = 0; - if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) - sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP; - if (ieee80211_rate2modtype(rate) == IEEE80211_MODTYPE_DS && - (ic->ic_flags & IEEE80211_F_SHPREAMBLE) && - rate != (1 * 2)) { - sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE; - } - sc->sc_tx_th.wt_rate = rate; - - bpf_ptap(sc->sc_drvbpf, m, &sc->sc_tx_th, sc->sc_tx_th_len); - } - - /* - * Setup the embedded TX header - */ - M_PREPEND(m, sizeof(*hdr), M_NOWAIT); - if (m == NULL) { - if_printf(&ic->ic_if, "prepend TX header failed\n"); - return ENOBUFS; - } - hdr = mtod(m, struct bwi_txbuf_hdr *); - - bzero(hdr, sizeof(*hdr)); - - bcopy(wh->i_fc, hdr->txh_fc, sizeof(hdr->txh_fc)); - bcopy(wh->i_addr1, hdr->txh_addr1, sizeof(hdr->txh_addr1)); - - if (!mcast_pkt) { - uint16_t dur; - uint8_t ack_rate; - - ack_rate = ieee80211_ack_rate(ni, rate_fb); - dur = ieee80211_txtime(ni, - sizeof(struct ieee80211_frame_ack) + IEEE80211_CRC_LEN, - ack_rate, ic->ic_flags & IEEE80211_F_SHPREAMBLE); - - hdr->txh_fb_duration = htole16(dur); - } - - hdr->txh_id = __SHIFTIN(BWI_TX_DATA_RING, BWI_TXH_ID_RING_MASK) | - __SHIFTIN(idx, BWI_TXH_ID_IDX_MASK); - - bwi_plcp_header(hdr->txh_plcp, pkt_len, rate); - bwi_plcp_header(hdr->txh_fb_plcp, pkt_len, rate_fb); - - phy_ctrl = __SHIFTIN(mac->mac_rf.rf_ant_mode, - BWI_TXH_PHY_C_ANTMODE_MASK); - if (ieee80211_rate2modtype(rate) == IEEE80211_MODTYPE_OFDM) - phy_ctrl |= BWI_TXH_PHY_C_OFDM; - else if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) && rate != (2 * 1)) - phy_ctrl |= BWI_TXH_PHY_C_SHPREAMBLE; - - mac_ctrl = BWI_TXH_MAC_C_HWSEQ | BWI_TXH_MAC_C_FIRST_FRAG; - if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) - mac_ctrl |= BWI_TXH_MAC_C_ACK; - if (ieee80211_rate2modtype(rate_fb) == IEEE80211_MODTYPE_OFDM) - mac_ctrl |= BWI_TXH_MAC_C_FB_OFDM; - - hdr->txh_mac_ctrl = htole32(mac_ctrl); - hdr->txh_phy_ctrl = htole16(phy_ctrl); - - /* Catch any further usage */ - hdr = NULL; - wh = NULL; - - /* DMA load */ - error = bus_dmamap_load_mbuf(sc->sc_buf_dtag, tb->tb_dmap, m, - bwi_dma_buf_addr, &paddr, BUS_DMA_NOWAIT); - if (error && error != EFBIG) { - if_printf(&ic->ic_if, "can't load TX buffer (1) %d\n", error); - goto back; - } - - if (error) { /* error == EFBIG */ - struct mbuf *m_new; - - m_new = m_defrag(m, M_NOWAIT); - if (m_new == NULL) { - if_printf(&ic->ic_if, "can't defrag TX buffer\n"); - error = ENOBUFS; - goto back; - } else { - m = m_new; - } - - error = bus_dmamap_load_mbuf(sc->sc_buf_dtag, tb->tb_dmap, m, - bwi_dma_buf_addr, &paddr, - BUS_DMA_NOWAIT); - if (error) { - if_printf(&ic->ic_if, "can't load TX buffer (2) %d\n", - error); - goto back; - } - } - error = 0; - - bus_dmamap_sync(sc->sc_buf_dtag, tb->tb_dmap, BUS_DMASYNC_PREWRITE); - - if (mgt_pkt || mcast_pkt) { - /* Don't involve mcast/mgt packets into TX rate control */ - ieee80211_free_node(ni); - *ni0 = ni = NULL; - } - tb->tb_mbuf = m; - tb->tb_ni = ni; - -#if 0 - p = mtod(m, const uint8_t *); - for (i = 0; i < m->m_pkthdr.len; ++i) { - if (i != 0 && i % 8 == 0) - kprintf("\n"); - kprintf("%02x ", p[i]); - } - kprintf("\n"); -#endif - - DPRINTF(sc, BWI_DBG_TX, "idx %d, pkt_len %d, buflen %d\n", - idx, pkt_len, m->m_pkthdr.len); - - /* Setup TX descriptor */ - sc->sc_setup_txdesc(sc, rd, idx, paddr, m->m_pkthdr.len); - bus_dmamap_sync(sc->sc_txring_dtag, rd->rdata_dmap, - BUS_DMASYNC_PREWRITE); - - /* Kick start */ - sc->sc_start_tx(sc, rd->rdata_txrx_ctrl, idx); - -back: - if (error) - m_freem(m); - return error; -} - -static void -bwi_start_tx32(struct bwi_softc *sc, uint32_t tx_ctrl, int idx) -{ - idx = (idx + 1) % BWI_TX_NDESC; - CSR_WRITE_4(sc, tx_ctrl + BWI_TX32_INDEX, - idx * sizeof(struct bwi_desc32)); -} - -static void -bwi_start_tx64(struct bwi_softc *sc, uint32_t tx_ctrl, int idx) -{ - /* TODO:64 */ -} - -static void -bwi_txeof_status32(struct bwi_softc *sc) -{ - struct ifnet *ifp = &sc->sc_ic.ic_if; - uint32_t val, ctrl_base; - int end_idx; - - ctrl_base = sc->sc_txstats->stats_ctrl_base; - - val = CSR_READ_4(sc, ctrl_base + BWI_RX32_STATUS); - end_idx = __SHIFTOUT(val, BWI_RX32_STATUS_INDEX_MASK) / - sizeof(struct bwi_desc32); - - bwi_txeof_status(sc, end_idx); - - CSR_WRITE_4(sc, ctrl_base + BWI_RX32_INDEX, - end_idx * sizeof(struct bwi_desc32)); - - if (!ifq_is_oactive(&ifp->if_snd)) - ifp->if_start(ifp); -} - -static void -bwi_txeof_status64(struct bwi_softc *sc) -{ - /* TODO:64 */ -} - -static void -_bwi_txeof(struct bwi_softc *sc, uint16_t tx_id, int acked, int data_txcnt) -{ - struct ifnet *ifp = &sc->sc_ic.ic_if; - struct bwi_txbuf_data *tbd; - struct bwi_txbuf *tb; - int ring_idx, buf_idx; - - if (tx_id == 0) { - if_printf(ifp, "zero tx id\n"); - return; - } - - ring_idx = __SHIFTOUT(tx_id, BWI_TXH_ID_RING_MASK); - buf_idx = __SHIFTOUT(tx_id, BWI_TXH_ID_IDX_MASK); - - KKASSERT(ring_idx == BWI_TX_DATA_RING); - KKASSERT(buf_idx < BWI_TX_NDESC); - - tbd = &sc->sc_tx_bdata[ring_idx]; - KKASSERT(tbd->tbd_used > 0); - tbd->tbd_used--; - - tb = &tbd->tbd_buf[buf_idx]; - - DPRINTF(sc, BWI_DBG_TXEOF, "txeof idx %d, " - "acked %d, data_txcnt %d, ni %p\n", - buf_idx, acked, data_txcnt, tb->tb_ni); - - bus_dmamap_unload(sc->sc_buf_dtag, tb->tb_dmap); - m_freem(tb->tb_mbuf); - tb->tb_mbuf = NULL; - - if (tb->tb_ni != NULL) { - struct ieee80211_ratectl_res res[BWI_NTXRATE]; - int res_len, retry; - - if (data_txcnt <= BWI_SHRETRY_FB || tb->tb_rateidx_cnt == 1) { - res_len = 1; - res[0].rc_res_rateidx = tb->tb_rateidx[0]; - res[0].rc_res_tries = data_txcnt; - } else { - res_len = BWI_NTXRATE; - res[0].rc_res_rateidx = tb->tb_rateidx[0]; - res[0].rc_res_tries = BWI_SHRETRY_FB; - res[1].rc_res_rateidx = tb->tb_rateidx[1]; - res[1].rc_res_tries = data_txcnt - BWI_SHRETRY_FB; - } - - if (acked) { - IFNET_STAT_INC(ifp, opackets, 1); - retry = data_txcnt > 0 ? data_txcnt - 1 : 0; - } else { - IFNET_STAT_INC(ifp, oerrors, 1); - retry = data_txcnt; - } - - ieee80211_ratectl_tx_complete(tb->tb_ni, tb->tb_buflen, - res, res_len, retry, 0, !acked); - - ieee80211_free_node(tb->tb_ni); - tb->tb_ni = NULL; - } else { - /* XXX mgt packet error */ - IFNET_STAT_INC(ifp, opackets, 1); - } - - if (tbd->tbd_used == 0) - sc->sc_tx_timer = 0; - - ifq_clr_oactive(&ifp->if_snd); -} - -static void -bwi_txeof_status(struct bwi_softc *sc, int end_idx) -{ - struct bwi_txstats_data *st = sc->sc_txstats; - int idx; - - bus_dmamap_sync(st->stats_dtag, st->stats_dmap, BUS_DMASYNC_POSTREAD); - - idx = st->stats_idx; - while (idx != end_idx) { - const struct bwi_txstats *stats = &st->stats[idx]; - - if ((stats->txs_flags & BWI_TXS_F_PENDING) == 0) { - int data_txcnt; - - data_txcnt = __SHIFTOUT(stats->txs_txcnt, - BWI_TXS_TXCNT_DATA); - _bwi_txeof(sc, le16toh(stats->txs_id), - stats->txs_flags & BWI_TXS_F_ACKED, - data_txcnt); - } - idx = (idx + 1) % BWI_TXSTATS_NDESC; - } - st->stats_idx = idx; -} - -static void -bwi_txeof(struct bwi_softc *sc) -{ - struct ifnet *ifp = &sc->sc_ic.ic_if; - - for (;;) { - uint32_t tx_status0, tx_status1; - uint16_t tx_id; - int data_txcnt; - - tx_status0 = CSR_READ_4(sc, BWI_TXSTATUS0); - if ((tx_status0 & BWI_TXSTATUS0_VALID) == 0) - break; - tx_status1 = CSR_READ_4(sc, BWI_TXSTATUS1); - - tx_id = __SHIFTOUT(tx_status0, BWI_TXSTATUS0_TXID_MASK); - data_txcnt = __SHIFTOUT(tx_status0, - BWI_TXSTATUS0_DATA_TXCNT_MASK); - - if (tx_status0 & (BWI_TXSTATUS0_AMPDU | BWI_TXSTATUS0_PENDING)) - continue; - - _bwi_txeof(sc, tx_id, tx_status0 & BWI_TXSTATUS0_ACKED, - data_txcnt); - } - - if (!ifq_is_oactive(&ifp->if_snd)) - ifp->if_start(ifp); -} - -static int -bwi_bbp_power_on(struct bwi_softc *sc, enum bwi_clock_mode clk_mode) -{ - bwi_power_on(sc, 1); - return bwi_set_clock_mode(sc, clk_mode); -} - -static void -bwi_bbp_power_off(struct bwi_softc *sc) -{ - bwi_set_clock_mode(sc, BWI_CLOCK_MODE_SLOW); - bwi_power_off(sc, 1); -} - -static int -bwi_get_pwron_delay(struct bwi_softc *sc) -{ - struct bwi_regwin *com, *old; - struct bwi_clock_freq freq; - uint32_t val; - int error; - - com = &sc->sc_com_regwin; - KKASSERT(BWI_REGWIN_EXIST(com)); - - if ((sc->sc_cap & BWI_CAP_CLKMODE) == 0) - return 0; - - error = bwi_regwin_switch(sc, com, &old); - if (error) - return error; - - bwi_get_clock_freq(sc, &freq); - - val = CSR_READ_4(sc, BWI_PLL_ON_DELAY); - sc->sc_pwron_delay = howmany((val + 2) * 1000000, freq.clkfreq_min); - DPRINTF(sc, BWI_DBG_ATTACH, "power on delay %u\n", sc->sc_pwron_delay); - - return bwi_regwin_switch(sc, old, NULL); -} - -static int -bwi_bus_attach(struct bwi_softc *sc) -{ - struct bwi_regwin *bus, *old; - int error; - - bus = &sc->sc_bus_regwin; - - error = bwi_regwin_switch(sc, bus, &old); - if (error) - return error; - - if (!bwi_regwin_is_enabled(sc, bus)) - bwi_regwin_enable(sc, bus, 0); - - /* Disable interripts */ - CSR_WRITE_4(sc, BWI_INTRVEC, 0); - - return bwi_regwin_switch(sc, old, NULL); -} - -static const char * -bwi_regwin_name(const struct bwi_regwin *rw) -{ - switch (rw->rw_type) { - case BWI_REGWIN_T_COM: - return "COM"; - case BWI_REGWIN_T_BUSPCI: - return "PCI"; - case BWI_REGWIN_T_MAC: - return "MAC"; - case BWI_REGWIN_T_BUSPCIE: - return "PCIE"; - } - panic("unknown regwin type 0x%04x", rw->rw_type); - return NULL; -} - -static uint32_t -bwi_regwin_disable_bits(struct bwi_softc *sc) -{ - uint32_t busrev; - - /* XXX cache this */ - busrev = __SHIFTOUT(CSR_READ_4(sc, BWI_ID_LO), BWI_ID_LO_BUSREV_MASK); - DPRINTF(sc, BWI_DBG_ATTACH | BWI_DBG_INIT | BWI_DBG_MISC, - "bus rev %u\n", busrev); - - if (busrev == BWI_BUSREV_0) - return BWI_STATE_LO_DISABLE1; - else if (busrev == BWI_BUSREV_1) - return BWI_STATE_LO_DISABLE2; - else - return (BWI_STATE_LO_DISABLE1 | BWI_STATE_LO_DISABLE2); -} - -int -bwi_regwin_is_enabled(struct bwi_softc *sc, struct bwi_regwin *rw) -{ - uint32_t val, disable_bits; - - disable_bits = bwi_regwin_disable_bits(sc); - val = CSR_READ_4(sc, BWI_STATE_LO); - - if ((val & (BWI_STATE_LO_CLOCK | - BWI_STATE_LO_RESET | - disable_bits)) == BWI_STATE_LO_CLOCK) { - DPRINTF(sc, BWI_DBG_ATTACH | BWI_DBG_INIT, "%s is enabled\n", - bwi_regwin_name(rw)); - return 1; - } else { - DPRINTF(sc, BWI_DBG_ATTACH | BWI_DBG_INIT, "%s is disabled\n", - bwi_regwin_name(rw)); - return 0; - } -} - -void -bwi_regwin_disable(struct bwi_softc *sc, struct bwi_regwin *rw, uint32_t flags) -{ - uint32_t state_lo, disable_bits; - int i; - - state_lo = CSR_READ_4(sc, BWI_STATE_LO); - - /* - * If current regwin is in 'reset' state, it was already disabled. - */ - if (state_lo & BWI_STATE_LO_RESET) { - DPRINTF(sc, BWI_DBG_ATTACH | BWI_DBG_INIT, - "%s was already disabled\n", bwi_regwin_name(rw)); - return; - } - - disable_bits = bwi_regwin_disable_bits(sc); - - /* - * Disable normal clock - */ - state_lo = BWI_STATE_LO_CLOCK | disable_bits; - CSR_WRITE_4(sc, BWI_STATE_LO, state_lo); - - /* - * Wait until normal clock is disabled - */ -#define NRETRY 1000 - for (i = 0; i < NRETRY; ++i) { - state_lo = CSR_READ_4(sc, BWI_STATE_LO); - if (state_lo & disable_bits) - break; - DELAY(10); - } - if (i == NRETRY) { - device_printf(sc->sc_dev, "%s disable clock timeout\n", - bwi_regwin_name(rw)); - } - - for (i = 0; i < NRETRY; ++i) { - uint32_t state_hi; - - state_hi = CSR_READ_4(sc, BWI_STATE_HI); - if ((state_hi & BWI_STATE_HI_BUSY) == 0) - break; - DELAY(10); - } - if (i == NRETRY) { - device_printf(sc->sc_dev, "%s wait BUSY unset timeout\n", - bwi_regwin_name(rw)); - } -#undef NRETRY - - /* - * Reset and disable regwin with gated clock - */ - state_lo = BWI_STATE_LO_RESET | disable_bits | - BWI_STATE_LO_CLOCK | BWI_STATE_LO_GATED_CLOCK | - __SHIFTIN(flags, BWI_STATE_LO_FLAGS_MASK); - CSR_WRITE_4(sc, BWI_STATE_LO, state_lo); - - /* Flush pending bus write */ - CSR_READ_4(sc, BWI_STATE_LO); - DELAY(1); - - /* Reset and disable regwin */ - state_lo = BWI_STATE_LO_RESET | disable_bits | - __SHIFTIN(flags, BWI_STATE_LO_FLAGS_MASK); - CSR_WRITE_4(sc, BWI_STATE_LO, state_lo); - - /* Flush pending bus write */ - CSR_READ_4(sc, BWI_STATE_LO); - DELAY(1); -} - -void -bwi_regwin_enable(struct bwi_softc *sc, struct bwi_regwin *rw, uint32_t flags) -{ - uint32_t state_lo, state_hi, imstate; - - bwi_regwin_disable(sc, rw, flags); - - /* Reset regwin with gated clock */ - state_lo = BWI_STATE_LO_RESET | - BWI_STATE_LO_CLOCK | - BWI_STATE_LO_GATED_CLOCK | - __SHIFTIN(flags, BWI_STATE_LO_FLAGS_MASK); - CSR_WRITE_4(sc, BWI_STATE_LO, state_lo); - - /* Flush pending bus write */ - CSR_READ_4(sc, BWI_STATE_LO); - DELAY(1); - - state_hi = CSR_READ_4(sc, BWI_STATE_HI); - if (state_hi & BWI_STATE_HI_SERROR) - CSR_WRITE_4(sc, BWI_STATE_HI, 0); - - imstate = CSR_READ_4(sc, BWI_IMSTATE); - if (imstate & (BWI_IMSTATE_INBAND_ERR | BWI_IMSTATE_TIMEOUT)) { - imstate &= ~(BWI_IMSTATE_INBAND_ERR | BWI_IMSTATE_TIMEOUT); - CSR_WRITE_4(sc, BWI_IMSTATE, imstate); - } - - /* Enable regwin with gated clock */ - state_lo = BWI_STATE_LO_CLOCK | - BWI_STATE_LO_GATED_CLOCK | - __SHIFTIN(flags, BWI_STATE_LO_FLAGS_MASK); - CSR_WRITE_4(sc, BWI_STATE_LO, state_lo); - - /* Flush pending bus write */ - CSR_READ_4(sc, BWI_STATE_LO); - DELAY(1); - - /* Enable regwin with normal clock */ - state_lo = BWI_STATE_LO_CLOCK | - __SHIFTIN(flags, BWI_STATE_LO_FLAGS_MASK); - CSR_WRITE_4(sc, BWI_STATE_LO, state_lo); - - /* Flush pending bus write */ - CSR_READ_4(sc, BWI_STATE_LO); - DELAY(1); -} - -static void -bwi_set_bssid(struct bwi_softc *sc, const uint8_t *bssid) -{ - struct ieee80211com *ic = &sc->sc_ic; - struct bwi_mac *mac; - struct bwi_myaddr_bssid buf; - const uint8_t *p; - uint32_t val; - int n, i; - - KKASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC); - mac = (struct bwi_mac *)sc->sc_cur_regwin; - - bwi_set_addr_filter(sc, BWI_ADDR_FILTER_BSSID, bssid); - - bcopy(ic->ic_myaddr, buf.myaddr, sizeof(buf.myaddr)); - bcopy(bssid, buf.bssid, sizeof(buf.bssid)); - - n = sizeof(buf) / sizeof(val); - p = (const uint8_t *)&buf; - for (i = 0; i < n; ++i) { - int j; - - val = 0; - for (j = 0; j < sizeof(val); ++j) - val |= ((uint32_t)(*p++)) << (j * 8); - - TMPLT_WRITE_4(mac, 0x20 + (i * sizeof(val)), val); - } -} - -static void -bwi_updateslot(struct ifnet *ifp) -{ - struct bwi_softc *sc = ifp->if_softc; - struct ieee80211com *ic = &sc->sc_ic; - struct bwi_mac *mac; - - if ((ifp->if_flags & IFF_RUNNING) == 0) - return; - - ASSERT_SERIALIZED(ifp->if_serializer); - - DPRINTF(sc, BWI_DBG_80211, "%s\n", __func__); - - KKASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC); - mac = (struct bwi_mac *)sc->sc_cur_regwin; - - bwi_mac_updateslot(mac, (ic->ic_flags & IEEE80211_F_SHSLOT)); -} - -static void -bwi_calibrate(void *xsc) -{ - struct bwi_softc *sc = xsc; - struct ieee80211com *ic = &sc->sc_ic; - struct ifnet *ifp = &ic->ic_if; - - lwkt_serialize_enter(ifp->if_serializer); - - if (ic->ic_state == IEEE80211_S_RUN) { - struct bwi_mac *mac; - - KKASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC); - mac = (struct bwi_mac *)sc->sc_cur_regwin; - - if (ic->ic_opmode != IEEE80211_M_MONITOR) { - bwi_mac_calibrate_txpower(mac, sc->sc_txpwrcb_type); - sc->sc_txpwrcb_type = BWI_TXPWR_CALIB; - } - - /* XXX 15 seconds */ - callout_reset(&sc->sc_calib_ch, hz * 15, bwi_calibrate, sc); - } - - lwkt_serialize_exit(ifp->if_serializer); -} - -static int -bwi_calc_rssi(struct bwi_softc *sc, const struct bwi_rxbuf_hdr *hdr) -{ - struct bwi_mac *mac; - - KKASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC); - mac = (struct bwi_mac *)sc->sc_cur_regwin; - - return bwi_rf_calc_rssi(mac, hdr); -} - -static void -bwi_rx_radiotap(struct bwi_softc *sc, struct mbuf *m, - struct bwi_rxbuf_hdr *hdr, const void *plcp, - int rate, int rssi) -{ - const struct ieee80211_frame_min *wh; - - KKASSERT(sc->sc_drvbpf != NULL); - - sc->sc_rx_th.wr_flags = IEEE80211_RADIOTAP_F_FCS; - if (htole16(hdr->rxh_flags1) & BWI_RXH_F1_SHPREAMBLE) - sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE; - - wh = mtod(m, const struct ieee80211_frame_min *); - if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) - sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_WEP; - - sc->sc_rx_th.wr_tsf = hdr->rxh_tsf; /* No endian convertion */ - sc->sc_rx_th.wr_rate = rate; - sc->sc_rx_th.wr_antsignal = rssi; - sc->sc_rx_th.wr_antnoise = BWI_NOISE_FLOOR; - - bpf_ptap(sc->sc_drvbpf, m, &sc->sc_rx_th, sc->sc_rx_th_len); -} - -static void -bwi_led_attach(struct bwi_softc *sc) -{ - const uint8_t *led_act = NULL; - uint16_t gpio, val[BWI_LED_MAX]; - int i; - - for (i = 0; i < NELEM(bwi_vendor_led_act); ++i) { - if (sc->sc_pci_subvid == bwi_vendor_led_act[i].vid) { - led_act = bwi_vendor_led_act[i].led_act; - break; - } - } - if (led_act == NULL) - led_act = bwi_default_led_act; - - gpio = bwi_read_sprom(sc, BWI_SPROM_GPIO01); - val[0] = __SHIFTOUT(gpio, BWI_SPROM_GPIO_0); - val[1] = __SHIFTOUT(gpio, BWI_SPROM_GPIO_1); - - gpio = bwi_read_sprom(sc, BWI_SPROM_GPIO23); - val[2] = __SHIFTOUT(gpio, BWI_SPROM_GPIO_2); - val[3] = __SHIFTOUT(gpio, BWI_SPROM_GPIO_3); - - for (i = 0; i < BWI_LED_MAX; ++i) { - struct bwi_led *led = &sc->sc_leds[i]; - - if (val[i] == 0xff) { - led->l_act = led_act[i]; - } else { - if (val[i] & BWI_LED_ACT_LOW) - led->l_flags |= BWI_LED_F_ACTLOW; - led->l_act = __SHIFTOUT(val[i], BWI_LED_ACT_MASK); - } - led->l_mask = (1 << i); - - if (led->l_act == BWI_LED_ACT_BLINK_SLOW || - led->l_act == BWI_LED_ACT_BLINK_POLL || - led->l_act == BWI_LED_ACT_BLINK) { - led->l_flags |= BWI_LED_F_BLINK; - if (led->l_act == BWI_LED_ACT_BLINK_POLL) - led->l_flags |= BWI_LED_F_POLLABLE; - else if (led->l_act == BWI_LED_ACT_BLINK_SLOW) - led->l_flags |= BWI_LED_F_SLOW; - - if (sc->sc_blink_led == NULL) { - sc->sc_blink_led = led; - if (led->l_flags & BWI_LED_F_SLOW) - BWI_LED_SLOWDOWN(sc->sc_led_idle); - } - } - - DPRINTF(sc, BWI_DBG_LED | BWI_DBG_ATTACH, - "%dth led, act %d, lowact %d\n", i, - led->l_act, led->l_flags & BWI_LED_F_ACTLOW); - } - callout_init(&sc->sc_led_blink_ch); -} - -static __inline uint16_t -bwi_led_onoff(const struct bwi_led *led, uint16_t val, int on) -{ - if (led->l_flags & BWI_LED_F_ACTLOW) - on = !on; - if (on) - val |= led->l_mask; - else - val &= ~led->l_mask; - return val; -} - -static void -bwi_led_newstate(struct bwi_softc *sc, enum ieee80211_state nstate) -{ - struct ieee80211com *ic = &sc->sc_ic; - uint16_t val; - int i; - - if (nstate == IEEE80211_S_INIT) { - callout_stop(&sc->sc_led_blink_ch); - sc->sc_led_blinking = 0; - } - - if ((ic->ic_if.if_flags & IFF_RUNNING) == 0) - return; - - val = CSR_READ_2(sc, BWI_MAC_GPIO_CTRL); - for (i = 0; i < BWI_LED_MAX; ++i) { - struct bwi_led *led = &sc->sc_leds[i]; - int on; - - if (led->l_act == BWI_LED_ACT_UNKN || - led->l_act == BWI_LED_ACT_NULL) - continue; - - if ((led->l_flags & BWI_LED_F_BLINK) && - nstate != IEEE80211_S_INIT) - continue; - - switch (led->l_act) { - case BWI_LED_ACT_ON: /* Always on */ - on = 1; - break; - case BWI_LED_ACT_OFF: /* Always off */ - case BWI_LED_ACT_5GHZ: /* TODO: 11A */ - on = 0; - break; - default: - on = 1; - switch (nstate) { - case IEEE80211_S_INIT: - on = 0; - break; - case IEEE80211_S_RUN: - if (led->l_act == BWI_LED_ACT_11G && - ic->ic_curmode != IEEE80211_MODE_11G) - on = 0; - break; - default: - if (led->l_act == BWI_LED_ACT_ASSOC) - on = 0; - break; - } - break; - } - - val = bwi_led_onoff(led, val, on); - } - CSR_WRITE_2(sc, BWI_MAC_GPIO_CTRL, val); -} - -static void -bwi_led_event(struct bwi_softc *sc, int event) -{ - struct bwi_led *led = sc->sc_blink_led; - int rate; - - if (event == BWI_LED_EVENT_POLL) { - if ((led->l_flags & BWI_LED_F_POLLABLE) == 0) - return; - if (ticks - sc->sc_led_ticks < sc->sc_led_idle) - return; - } - - sc->sc_led_ticks = ticks; - if (sc->sc_led_blinking) - return; - - switch (event) { - case BWI_LED_EVENT_RX: - rate = sc->sc_rx_rate; - break; - case BWI_LED_EVENT_TX: - rate = sc->sc_tx_rate; - break; - case BWI_LED_EVENT_POLL: - rate = 0; - break; - default: - panic("unknown LED event %d", event); - break; - } - bwi_led_blink_start(sc, bwi_led_duration[rate].on_dur, - bwi_led_duration[rate].off_dur); -} - -static void -bwi_led_blink_start(struct bwi_softc *sc, int on_dur, int off_dur) -{ - struct bwi_led *led = sc->sc_blink_led; - uint16_t val; - - val = CSR_READ_2(sc, BWI_MAC_GPIO_CTRL); - val = bwi_led_onoff(led, val, 1); - CSR_WRITE_2(sc, BWI_MAC_GPIO_CTRL, val); - - if (led->l_flags & BWI_LED_F_SLOW) { - BWI_LED_SLOWDOWN(on_dur); - BWI_LED_SLOWDOWN(off_dur); - } - - sc->sc_led_blinking = 1; - sc->sc_led_blink_offdur = off_dur; - - callout_reset(&sc->sc_led_blink_ch, on_dur, bwi_led_blink_next, sc); -} - -static void -bwi_led_blink_next(void *xsc) -{ - struct bwi_softc *sc = xsc; - uint16_t val; - - val = CSR_READ_2(sc, BWI_MAC_GPIO_CTRL); - val = bwi_led_onoff(sc->sc_blink_led, val, 0); - CSR_WRITE_2(sc, BWI_MAC_GPIO_CTRL, val); - - callout_reset(&sc->sc_led_blink_ch, sc->sc_led_blink_offdur, - bwi_led_blink_end, sc); -} - -static void -bwi_led_blink_end(void *xsc) -{ - struct bwi_softc *sc = xsc; - - sc->sc_led_blinking = 0; -} - -static void * -bwi_ratectl_attach(struct ieee80211com *ic, u_int rc) -{ - struct bwi_softc *sc = ic->ic_if.if_softc; - - switch (rc) { - case IEEE80211_RATECTL_ONOE: - return &sc->sc_onoe_param; - case IEEE80211_RATECTL_NONE: - /* This could only happen during detaching */ - return NULL; - default: - panic("unknown rate control algo %u", rc); - return NULL; - } -} diff --git a/sys/dev/netif/bwi/if_bwireg.h b/sys/dev/netif/bwi/if_bwireg.h deleted file mode 100644 index 8abd31efdf..0000000000 --- a/sys/dev/netif/bwi/if_bwireg.h +++ /dev/null @@ -1,490 +0,0 @@ -/* - * Copyright (c) 2007 The DragonFly Project. All rights reserved. - * - * This code is derived from software contributed to The DragonFly Project - * by Sepherosa Ziehau - * - * 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. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * 3. Neither the name of The DragonFly Project nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific, prior written permission. - * - * 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 MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, 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 DAMAGE. - * - * $DragonFly: src/sys/dev/netif/bwi/if_bwireg.h,v 1.4 2007/10/19 14:27:04 sephe Exp $ - */ - -#ifndef _IF_BWIREG_H -#define _IF_BWIREG_H - -/* - * Registers for all of the register windows - */ -#define BWI_FLAGS 0xf18 -#define BWI_FLAGS_INTR_MASK __BITS(5, 0) - -#define BWI_IMSTATE 0xf90 -#define BWI_IMSTATE_INBAND_ERR __BIT(17) -#define BWI_IMSTATE_TIMEOUT __BIT(18) - -#define BWI_INTRVEC 0xf94 - -#define BWI_STATE_LO 0xf98 -#define BWI_STATE_LO_RESET __BIT(0) -#define BWI_STATE_LO_DISABLE1 __BIT(1) -#define BWI_STATE_LO_DISABLE2 __BIT(2) -#define BWI_STATE_LO_CLOCK __BIT(16) -#define BWI_STATE_LO_GATED_CLOCK __BIT(17) -#define BWI_STATE_LO_FLAG_PHYCLKEN __BIT(0) -#define BWI_STATE_LO_FLAG_PHYRST __BIT(1) -#define BWI_STATE_LO_FLAG_PHYLNK __BIT(11) -#define BWI_STATE_LO_FLAGS_MASK __BITS(29, 18) - -#define BWI_STATE_HI 0xf9c -#define BWI_STATE_HI_SERROR __BIT(0) -#define BWI_STATE_HI_BUSY __BIT(2) -#define BWI_STATE_HI_FLAG_MAGIC1 0x1 -#define BWI_STATE_HI_FLAG_MAGIC2 0x2 -#define BWI_STATE_HI_FLAG_64BIT 0x1000 -#define BWI_STATE_HI_FLAGS_MASK __BITS(28, 16) - -#define BWI_CONF_LO 0xfa8 -#define BWI_CONF_LO_SERVTO_MASK __BITS(2, 0) /* service timeout */ -#define BWI_CONF_LO_SERVTO 2 -#define BWI_CONF_LO_REQTO_MASK __BITS(6, 4) /* request timeout */ -#define BWI_CONF_LO_REQTO 3 - - -#define BWI_ID_LO 0xff8 -#define BWI_ID_LO_BUSREV_MASK __BITS(31, 28) -/* Bus revision */ -#define BWI_BUSREV_0 0 -#define BWI_BUSREV_1 1 - -#define BWI_ID_HI 0xffc -#define BWI_ID_HI_REGWIN_REV(v) (((v) & 0xf) | (((v) & 0x7000) >> 8)) -#define BWI_ID_HI_REGWIN_TYPE(v) (((v) & 0x8ff0) >> 4) -#define BWI_ID_HI_REGWIN_VENDOR_MASK __BITS(31, 16) - -/* - * Registers for common register window - */ -#define BWI_INFO 0x0 -#define BWI_INFO_BBPID_MASK __BITS(15, 0) -#define BWI_INFO_BBPREV_MASK __BITS(19, 16) -#define BWI_INFO_BBPPKG_MASK __BITS(23, 20) -#define BWI_INFO_NREGWIN_MASK __BITS(27, 24) - -#define BWI_CAPABILITY 0x4 -#define BWI_CAP_CLKMODE __BIT(18) - -#define BWI_CONTROL 0x28 -#define BWI_CONTROL_MAGIC0 0x3a4 -#define BWI_CONTROL_MAGIC1 0xa4 -#define BWI_PLL_ON_DELAY 0xb0 -#define BWI_FREQ_SEL_DELAY 0xb4 - -#define BWI_CLOCK_CTRL 0xb8 -#define BWI_CLOCK_CTRL_CLKSRC __BITS(2, 0) -#define BWI_CLOCK_CTRL_SLOW __BIT(11) -#define BWI_CLOCK_CTRL_IGNPLL __BIT(12) -#define BWI_CLOCK_CTRL_NODYN __BIT(13) -#define BWI_CLOCK_CTRL_FDIV __BITS(31, 16) /* freq divisor */ - -/* Possible values for BWI_CLOCK_CTRL_CLKSRC */ -#define BWI_CLKSRC_LP_OSC 0 /* Low power oscillator */ -#define BWI_CLKSRC_CS_OSC 1 /* Crystal oscillator */ -#define BWI_CLKSRC_PCI 2 -#define BWI_CLKSRC_MAX 3 /* Maximum of clock source */ -/* Min/Max frequency for given clock source */ -#define BWI_CLKSRC_LP_OSC_FMIN 25000 -#define BWI_CLKSRC_LP_OSC_FMAX 43000 -#define BWI_CLKSRC_CS_OSC_FMIN 19800000 -#define BWI_CLKSRC_CS_OSC_FMAX 20200000 -#define BWI_CLKSRC_PCI_FMIN 25000000 -#define BWI_CLKSRC_PCI_FMAX 34000000 - -#define BWI_CLOCK_INFO 0xc0 -#define BWI_CLOCK_INFO_FDIV __BITS(31, 16) /* freq divisor */ - -/* - * Registers for bus register window - */ -#define BWI_BUS_ADDR 0x50 -#define BWI_BUS_ADDR_MAGIC 0xfd8 - -#define BWI_BUS_DATA 0x54 - -#define BWI_BUS_CONFIG 0x108 -#define BWI_BUS_CONFIG_PREFETCH __BIT(2) -#define BWI_BUS_CONFIG_BURST __BIT(3) -#define BWI_BUS_CONFIG_MRM __BIT(5) - -/* - * Register for MAC - */ -#define BWI_TXRX_INTR_STATUS_BASE 0x20 -#define BWI_TXRX_INTR_MASK_BASE 0x24 -#define BWI_TXRX_INTR_STATUS(i) (BWI_TXRX_INTR_STATUS_BASE + ((i) * 8)) -#define BWI_TXRX_INTR_MASK(i) (BWI_TXRX_INTR_MASK_BASE + ((i) * 8)) - -#define BWI_MAC_STATUS 0x120 -#define BWI_MAC_STATUS_ENABLE __BIT(0) -#define BWI_MAC_STATUS_UCODE_START __BIT(1) -#define BWI_MAC_STATUS_UCODE_JUMP0 __BIT(2) -#define BWI_MAC_STATUS_IHREN __BIT(10) -#define BWI_MAC_STATUS_GPOSEL_MASK __BITS(15, 14) -#define BWI_MAC_STATUS_BSWAP __BIT(16) -#define BWI_MAC_STATUS_INFRA __BIT(17) -#define BWI_MAC_STATUS_OPMODE_HOSTAP __BIT(18) -#define BWI_MAC_STATUS_RFLOCK __BIT(19) -#define BWI_MAC_STATUS_PASS_BCN __BIT(20) -#define BWI_MAC_STATUS_PASS_BADPLCP __BIT(21) -#define BWI_MAC_STATUS_PASS_CTL __BIT(22) -#define BWI_MAC_STATUS_PASS_BADFCS __BIT(23) -#define BWI_MAC_STATUS_PROMISC __BIT(24) -#define BWI_MAC_STATUS_HW_PS __BIT(25) -#define BWI_MAC_STATUS_WAKEUP __BIT(26) -#define BWI_MAC_STATUS_PHYLNK __BIT(31) - -#define BWI_MAC_INTR_STATUS 0x128 -#define BWI_MAC_INTR_MASK 0x12c - -#define BWI_MAC_TMPLT_CTRL 0x130 -#define BWI_MAC_TMPLT_DATA 0x134 - -#define BWI_MAC_PS_STATUS 0x140 - -#define BWI_MOBJ_CTRL 0x160 -#define BWI_MOBJ_CTRL_VAL(objid, ofs) ((objid) << 16 | (ofs)) -#define BWI_MOBJ_DATA 0x164 -#define BWI_MOBJ_DATA_UNALIGN 0x166 -/* - * Memory object IDs - */ -#define BWI_WR_MOBJ_AUTOINC 0x100 /* Auto-increment wr */ -#define BWI_RD_MOBJ_AUTOINC 0x200 /* Auto-increment rd */ -/* Firmware ucode object */ -#define BWI_FW_UCODE_MOBJ 0x0 -/* Common object */ -#define BWI_COMM_MOBJ 0x1 -#define BWI_COMM_MOBJ_FWREV 0x0 -#define BWI_COMM_MOBJ_FWPATCHLV 0x2 -#define BWI_COMM_MOBJ_SLOTTIME 0x10 -#define BWI_COMM_MOBJ_MACREV 0x16 -#define BWI_COMM_MOBJ_TX_ACK 0x22 -#define BWI_COMM_MOBJ_UCODE_STATE 0x40 -#define BWI_COMM_MOBJ_SHRETRY_FB 0x44 -#define BWI_COMM_MOBJ_LGRETEY_FB 0x46 -#define BWI_COMM_MOBJ_TX_BEACON 0x54 -#define BWI_COMM_MOBJ_KEYTABLE_OFS 0x56 -#define BWI_COMM_MOBJ_TSSI_DS 0x58 -#define BWI_COMM_MOBJ_HFLAGS_LO 0x5e -#define BWI_COMM_MOBJ_HFLAGS_MI 0x60 -#define BWI_COMM_MOBJ_HFLAGS_HI 0x62 -#define BWI_COMM_MOBJ_RF_ATTEN 0x64 -#define BWI_COMM_MOBJ_TSSI_OFDM 0x70 -#define BWI_COMM_MOBJ_PROBE_RESP_TO 0x74 -#define BWI_COMM_MOBJ_CHAN 0xa0 -#define BWI_COMM_MOBJ_KEY_ALGO 0x100 -#define BWI_COMM_MOBJ_TX_PROBE_RESP 0x188 -#define BWI_HFLAG_AUTO_ANTDIV 0x1ULL -#define BWI_HFLAG_SYM_WA 0x2ULL /* ??? SYM work around */ -#define BWI_HFLAG_PWR_BOOST_DS 0x8ULL -#define BWI_HFLAG_GDC_WA 0x20ULL /* ??? GDC work around */ -#define BWI_HFLAG_OFDM_PA 0x40ULL -#define BWI_HFLAG_NOT_JAPAN 0x80ULL -#define BWI_HFLAG_MAGIC1 0x200ULL -#define BWI_UCODE_STATE_PS 4 -#define BWI_LO_TSSI_MASK __BITS(7, 0) -#define BWI_HI_TSSI_MASK __BITS(15, 8) -#define BWI_INVALID_TSSI 0x7f -/* 802.11 object */ -#define BWI_80211_MOBJ 0x2 -#define BWI_80211_MOBJ_CWMIN 0xc -#define BWI_80211_MOBJ_CWMAX 0x10 -#define BWI_80211_MOBJ_SHRETRY 0x18 -#define BWI_80211_MOBJ_LGRETRY 0x1c -/* Firmware PCM object */ -#define BWI_FW_PCM_MOBJ 0x3 -/* MAC address of pairwise keys */ -#define BWI_PKEY_ADDR_MOBJ 0x4 - -#define BWI_TXSTATUS0 0x170 -#define BWI_TXSTATUS0_VALID __BIT(0) -#define BWI_TXSTATUS0_ACKED __BIT(1) -#define BWI_TXSTATUS0_FREASON_MASK __BITS(4, 2) /* Failure reason */ -#define BWI_TXSTATUS0_AMPDU __BIT(5) -#define BWI_TXSTATUS0_PENDING __BIT(6) -#define BWI_TXSTATUS0_PM __BIT(7) -#define BWI_TXSTATUS0_RTS_TXCNT_MASK __BITS(11, 8) -#define BWI_TXSTATUS0_DATA_TXCNT_MASK __BITS(15, 12) -#define BWI_TXSTATUS0_TXID_MASK __BITS(31, 16) -#define BWI_TXSTATUS1 0x174 - -#define BWI_TXRX_CTRL_BASE 0x200 -#define BWI_TX32_CTRL 0x0 -#define BWI_TX32_RINGINFO 0x4 -#define BWI_TX32_INDEX 0x8 -#define BWI_TX32_STATUS 0xc -#define BWI_TX32_STATUS_STATE_MASK __BITS(15, 12) -#define BWI_TX32_STATUS_STATE_DISABLED 0 -#define BWI_TX32_STATUS_STATE_IDLE 2 -#define BWI_TX32_STATUS_STATE_STOPPED 3 -#define BWI_RX32_CTRL 0x10 -#define BWI_RX32_CTRL_HDRSZ_MASK __BITS(7, 1) -#define BWI_RX32_RINGINFO 0x14 -#define BWI_RX32_INDEX 0x18 -#define BWI_RX32_STATUS 0x1c -#define BWI_RX32_STATUS_INDEX_MASK __BITS(11, 0) -#define BWI_RX32_STATUS_STATE_MASK __BITS(15, 12) -#define BWI_RX32_STATUS_STATE_DISABLED 0 -/* Shared by 32bit TX/RX CTRL */ -#define BWI_TXRX32_CTRL_ENABLE __BIT(0) -#define BWI_TXRX32_CTRL_ADDRHI_MASK __BITS(17, 16) -/* Shared by 32bit TX/RX RINGINFO */ -#define BWI_TXRX32_RINGINFO_FUNC_TXRX 0x1 -#define BWI_TXRX32_RINGINFO_FUNC_MASK __BITS(31, 30) -#define BWI_TXRX32_RINGINFO_ADDR_MASK __BITS(29, 0) - -#define BWI_PHYINFO 0x3e0 -#define BWI_PHYINFO_REV_MASK __BITS(3, 0) -#define BWI_PHYINFO_TYPE_MASK __BITS(11, 8) -#define BWI_PHYINFO_TYPE_11A 0 -#define BWI_PHYINFO_TYPE_11B 1 -#define BWI_PHYINFO_TYPE_11G 2 -#define BWI_PHYINFO_TYPE_11N 5 -#define BWI_PHYINFO_VER_MASK __BITS(15, 12) - -#define BWI_RF_ANTDIV 0x3e2 /* Antenna Diversity?? */ - -#define BWI_PHY_MAGIC_REG1 0x3e4 -#define BWI_PHY_MAGIC_REG1_VAL1 0x3000 -#define BWI_PHY_MAGIC_REG1_VAL2 0x9 - -#define BWI_BBP_ATTEN 0x3e6 -#define BWI_BBP_ATTEN_MAGIC 0xf4 -#define BWI_BBP_ATTEN_MAGIC2 0x8140 - -#define BWI_BPHY_CTRL 0x3ec -#define BWI_BPHY_CTRL_INIT 0x3f22 - -#define BWI_RF_CHAN 0x3f0 -#define BWI_RF_CHAN_EX 0x3f4 - -#define BWI_RF_CTRL 0x3f6 -/* Register values for BWI_RF_CTRL */ -#define BWI_RF_CTRL_RFINFO 0x1 -/* XXX extra bits for reading from radio */ -#define BWI_RF_CTRL_RD_11A 0x40 -#define BWI_RF_CTRL_RD_11BG 0x80 -#define BWI_RF_DATA_HI 0x3f8 -#define BWI_RF_DATA_LO 0x3fa -/* Values read from BWI_RF_DATA_{HI,LO} after BWI_RF_CTRL_RFINFO */ -#define BWI_RFINFO_MANUFACT_MASK __BITS(11, 0) -#define BWI_RF_MANUFACT_BCM 0x17f /* XXX */ -#define BWI_RFINFO_TYPE_MASK __BITS(27, 12) -#define BWI_RF_T_BCM2050 0x2050 -#define BWI_RF_T_BCM2053 0x2053 -#define BWI_RF_T_BCM2060 0x2060 -#define BWI_RFINFO_REV_MASK __BITS(31, 28) - -#define BWI_PHY_CTRL 0x3fc -#define BWI_PHY_DATA 0x3fe - -#define BWI_ADDR_FILTER_CTRL 0x420 -#define BWI_ADDR_FILTER_CTRL_SET 0x20 -#define BWI_ADDR_FILTER_MYADDR 0 -#define BWI_ADDR_FILTER_BSSID 3 -#define BWI_ADDR_FILTER_DATA 0x422 - -#define BWI_MAC_GPIO_CTRL 0x49c -#define BWI_MAC_GPIO_MASK 0x49e -#define BWI_MAC_PRE_TBTT 0x612 -#define BWI_MAC_SLOTTIME 0x684 -#define BWI_MAC_SLOTTIME_ADJUST 510 -#define BWI_MAC_POWERUP_DELAY 0x6a8 - -/* - * Special registers - */ -/* - * GPIO control - * If common regwin exists, then it is within common regwin, - * else it is in bus regwin. - */ -#define BWI_GPIO_CTRL 0x6c - -/* - * Extended PCI registers - */ -#define BWI_PCIR_BAR PCIR_BAR(0) -#define BWI_PCIR_SEL_REGWIN 0x80 -/* Register value for BWI_PCIR_SEL_REGWIN */ -#define BWI_PCIM_REGWIN(id) (((id) * 0x1000) + 0x18000000) -#define BWI_PCIR_GPIO_IN 0xb0 -#define BWI_PCIR_GPIO_OUT 0xb4 -#define BWI_PCIM_GPIO_OUT_CLKSRC __BIT(4) -#define BWI_PCIR_GPIO_ENABLE 0xb8 -/* Register values for BWI_PCIR_GPIO_{IN,OUT,ENABLE} */ -#define BWI_PCIM_GPIO_PWR_ON __BIT(6) -#define BWI_PCIM_GPIO_PLL_PWR_OFF __BIT(7) -#define BWI_PCIR_INTCTL 0x94 - -/* - * PCI subdevice IDs - */ -#define BWI_PCI_SUBDEVICE_BU4306 0x416 -#define BWI_PCI_SUBDEVICE_BCM4309G 0x421 - -#define BWI_IS_BRCM_BU4306(sc) \ - ((sc)->sc_pci_subvid == PCI_VENDOR_BROADCOM && \ - (sc)->sc_pci_subdid == BWI_PCI_SUBDEVICE_BU4306) -#define BWI_IS_BRCM_BCM4309G(sc) \ - ((sc)->sc_pci_subvid == PCI_VENDOR_BROADCOM && \ - (sc)->sc_pci_subdid == BWI_PCI_SUBDEVICE_BCM4309G) - -/* - * EEPROM start address - */ -#define BWI_SPROM_START 0x1000 -#define BWI_SPROM_11BG_EADDR 0x48 -#define BWI_SPROM_11A_EADDR 0x54 -#define BWI_SPROM_CARD_INFO 0x5c -#define BWI_SPROM_CARD_INFO_LOCALE __BITS(11, 8) -#define BWI_SPROM_LOCALE_JAPAN 5 -#define BWI_SPROM_PA_PARAM_11BG 0x5e -#define BWI_SPROM_GPIO01 0x64 -#define BWI_SPROM_GPIO_0 __BITS(7, 0) -#define BWI_SPROM_GPIO_1 __BITS(15, 8) -#define BWI_SPROM_GPIO23 0x66 -#define BWI_SPROM_GPIO_2 __BITS(7, 0) -#define BWI_SPROM_GPIO_3 __BITS(15, 8) -#define BWI_SPROM_MAX_TXPWR 0x68 -#define BWI_SPROM_MAX_TXPWR_MASK_11BG __BITS(7, 0) /* XXX */ -#define BWI_SPROM_MAX_TXPWR_MASK_11A __BITS(15, 8) /* XXX */ -#define BWI_SPROM_PA_PARAM_11A 0x6a -#define BWI_SPROM_IDLE_TSSI 0x70 -#define BWI_SPROM_IDLE_TSSI_MASK_11BG __BITS(7, 0) /* XXX */ -#define BWI_SPROM_IDLE_TSSI_MASK_11A __BITS(15, 8) /* XXX */ -#define BWI_SPROM_CARD_FLAGS 0x72 -#define BWI_SPROM_ANT_GAIN 0x74 -#define BWI_SPROM_ANT_GAIN_MASK_11A __BITS(7, 0) -#define BWI_SPROM_ANT_GAIN_MASK_11BG __BITS(15, 8) - -/* - * SPROM card flags - */ -#define BWI_CARD_F_PA_GPIO9 __BIT(1) /* GPIO 9 controls PA */ -#define BWI_CARD_F_SW_NRSSI __BIT(3) -#define BWI_CARD_F_NO_SLOWCLK __BIT(5) /* no slow clock */ -#define BWI_CARD_F_EXT_LNA __BIT(12) /* external LNA */ -#define BWI_CARD_F_ALT_IQ __BIT(15) /* alternate I/Q */ - -/* - * SPROM GPIO - */ -#define BWI_LED_ACT_LOW __BIT(7) -#define BWI_LED_ACT_MASK __BITS(6, 0) -#define BWI_LED_ACT_OFF 0 -#define BWI_LED_ACT_ON 1 -#define BWI_LED_ACT_BLINK 2 -#define BWI_LED_ACT_RF_ENABLED 3 -#define BWI_LED_ACT_5GHZ 4 -#define BWI_LED_ACT_2GHZ 5 -#define BWI_LED_ACT_11G 6 -#define BWI_LED_ACT_BLINK_SLOW 7 -#define BWI_LED_ACT_BLINK_POLL 8 -#define BWI_LED_ACT_UNKN 9 -#define BWI_LED_ACT_ASSOC 10 -#define BWI_LED_ACT_NULL 11 - -#define BWI_VENDOR_LED_ACT_COMPAQ \ - BWI_LED_ACT_RF_ENABLED, \ - BWI_LED_ACT_2GHZ, \ - BWI_LED_ACT_5GHZ, \ - BWI_LED_ACT_OFF - -#define BWI_VENDOR_LED_ACT_LINKSYS \ - BWI_LED_ACT_ASSOC, \ - BWI_LED_ACT_2GHZ, \ - BWI_LED_ACT_5GHZ, \ - BWI_LED_ACT_OFF - -#define BWI_VENDOR_LED_ACT_DEFAULT \ - BWI_LED_ACT_BLINK, \ - BWI_LED_ACT_2GHZ, \ - BWI_LED_ACT_5GHZ, \ - BWI_LED_ACT_OFF - -/* - * BBP IDs - */ -#define BWI_BBPID_BCM4301 0x4301 -#define BWI_BBPID_BCM4306 0x4306 -#define BWI_BBPID_BCM4317 0x4317 -#define BWI_BBPID_BCM4320 0x4320 -#define BWI_BBPID_BCM4321 0x4321 - -/* - * Register window types - */ -#define BWI_REGWIN_T_COM 0x800 -#define BWI_REGWIN_T_BUSPCI 0x804 -#define BWI_REGWIN_T_MAC 0x812 -#define BWI_REGWIN_T_BUSPCIE 0x820 - -/* - * MAC interrupts - */ -#define BWI_INTR_READY __BIT(0) -#define BWI_INTR_BEACON __BIT(1) -#define BWI_INTR_TBTT __BIT(2) -#define BWI_INTR_EO_ATIM __BIT(5) /* End of ATIM */ -#define BWI_INTR_PMQ __BIT(6) /* XXX?? */ -#define BWI_INTR_MAC_TXERR __BIT(9) -#define BWI_INTR_PHY_TXERR __BIT(11) -#define BWI_INTR_TIMER1 __BIT(14) -#define BWI_INTR_RX_DONE __BIT(15) -#define BWI_INTR_TX_FIFO __BIT(16) /* XXX?? */ -#define BWI_INTR_NOISE __BIT(18) -#define BWI_INTR_RF_DISABLED __BIT(28) -#define BWI_INTR_TX_DONE __BIT(29) - -#define BWI_INIT_INTRS \ - (BWI_INTR_READY | BWI_INTR_BEACON | BWI_INTR_TBTT | \ - BWI_INTR_EO_ATIM | BWI_INTR_PMQ | BWI_INTR_MAC_TXERR | \ - BWI_INTR_PHY_TXERR | BWI_INTR_RX_DONE | BWI_INTR_TX_FIFO | \ - BWI_INTR_NOISE | BWI_INTR_RF_DISABLED | BWI_INTR_TX_DONE) -#define BWI_ALL_INTRS 0xffffffff - -/* - * TX/RX interrupts - */ -#define BWI_TXRX_INTR_ERROR (__BIT(15) | __BIT(14) | __BITS(12, 10)) -#define BWI_TXRX_INTR_RX __BIT(16) -#define BWI_TXRX_TX_INTRS BWI_TXRX_INTR_ERROR -#define BWI_TXRX_RX_INTRS (BWI_TXRX_INTR_ERROR | BWI_TXRX_INTR_RX) -#define BWI_TXRX_IS_RX(i) ((i) % 3 == 0) - -#endif /* !_IF_BWIREG_H */ diff --git a/sys/dev/netif/bwi/if_bwivar.h b/sys/dev/netif/bwi/if_bwivar.h deleted file mode 100644 index dfe3a608b4..0000000000 --- a/sys/dev/netif/bwi/if_bwivar.h +++ /dev/null @@ -1,684 +0,0 @@ -/* - * Copyright (c) 2007 The DragonFly Project. All rights reserved. - * - * This code is derived from software contributed to The DragonFly Project - * by Sepherosa Ziehau - * - * 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. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * 3. Neither the name of The DragonFly Project nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific, prior written permission. - * - * 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 MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, 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 DAMAGE. - */ - -#ifndef _IF_BWIVAR_H -#define _IF_BWIVAR_H - -#define BWI_ALIGN 0x1000 -#define BWI_RING_ALIGN BWI_ALIGN -#define BWI_BUS_SPACE_MAXADDR 0x3fffffff - -#define BWI_TX_NRING 6 -#define BWI_TXRX_NRING 6 -#define BWI_TX_NDESC 128 -#define BWI_RX_NDESC 64 -#define BWI_TXSTATS_NDESC 64 -#define BWI_TX_NSPRDESC 2 -#define BWI_TX_DATA_RING 1 - -/* XXX Onoe/Sample/AMRR probably need different configuration */ -#define BWI_SHRETRY 7 -#define BWI_LGRETRY 4 -#define BWI_SHRETRY_FB 3 -#define BWI_LGRETRY_FB 2 - -#define BWI_LED_EVENT_NONE -1 -#define BWI_LED_EVENT_POLL 0 -#define BWI_LED_EVENT_TX 1 -#define BWI_LED_EVENT_RX 2 -#define BWI_LED_SLOWDOWN(dur) (dur) = (((dur) * 3) / 2) - -enum bwi_txpwrcb_type { - BWI_TXPWR_INIT = 0, - BWI_TXPWR_FORCE = 1, - BWI_TXPWR_CALIB = 2 -}; - -#define BWI_NOISE_FLOOR -95 /* TODO: noise floor calc */ -#define BWI_FRAME_MIN_LEN(hdr) \ - ((hdr) + sizeof(struct ieee80211_frame_ack) + IEEE80211_CRC_LEN) - -#define CSR_READ_4(sc, reg) \ - bus_space_read_4((sc)->sc_mem_bt, (sc)->sc_mem_bh, (reg)) -#define CSR_READ_2(sc, reg) \ - bus_space_read_2((sc)->sc_mem_bt, (sc)->sc_mem_bh, (reg)) - -#define CSR_WRITE_4(sc, reg, val) \ - bus_space_write_4((sc)->sc_mem_bt, (sc)->sc_mem_bh, (reg), (val)) -#define CSR_WRITE_2(sc, reg, val) \ - bus_space_write_2((sc)->sc_mem_bt, (sc)->sc_mem_bh, (reg), (val)) - -#define CSR_SETBITS_4(sc, reg, bits) \ - CSR_WRITE_4((sc), (reg), CSR_READ_4((sc), (reg)) | (bits)) -#define CSR_SETBITS_2(sc, reg, bits) \ - CSR_WRITE_2((sc), (reg), CSR_READ_2((sc), (reg)) | (bits)) - -#define CSR_FILT_SETBITS_4(sc, reg, filt, bits) \ - CSR_WRITE_4((sc), (reg), (CSR_READ_4((sc), (reg)) & (filt)) | (bits)) -#define CSR_FILT_SETBITS_2(sc, reg, filt, bits) \ - CSR_WRITE_2((sc), (reg), (CSR_READ_2((sc), (reg)) & (filt)) | (bits)) - -#define CSR_CLRBITS_4(sc, reg, bits) \ - CSR_WRITE_4((sc), (reg), CSR_READ_4((sc), (reg)) & ~(bits)) -#define CSR_CLRBITS_2(sc, reg, bits) \ - CSR_WRITE_2((sc), (reg), CSR_READ_2((sc), (reg)) & ~(bits)) - -#define BWI_DEBUG -#ifdef BWI_DEBUG - -#define DPRINTF(sc, dbg, fmt, ...) \ -do { \ - if ((sc)->sc_debug & (dbg)) \ - if_printf(&(sc)->sc_ic.ic_if, fmt, __VA_ARGS__); \ -} while (0) - -#define _DPRINTF(sc, dbg, fmt, ...) \ -do { \ - if ((sc)->sc_debug & (dbg)) \ - kprintf(fmt, __VA_ARGS__); \ -} while (0) - -#else /* !BWI_DEBUG */ - -#define DPRINTF(sc, dbg, fmt, ...) ((void)0) -#define _DPRINTF(sc, dbg, fmt, ...) ((void)0) - -#endif /* BWI_DEBUG */ - -struct bwi_desc32 { - /* Little endian */ - uint32_t ctrl; - uint32_t addr; /* BWI_DESC32_A_ */ -} __packed; - -#define BWI_DESC32_A_FUNC_TXRX 0x1 -#define BWI_DESC32_A_FUNC_MASK __BITS(31, 30) -#define BWI_DESC32_A_ADDR_MASK __BITS(29, 0) - -#define BWI_DESC32_C_BUFLEN_MASK __BITS(12, 0) -#define BWI_DESC32_C_ADDRHI_MASK __BITS(17, 16) -#define BWI_DESC32_C_EOR __BIT(28) -#define BWI_DESC32_C_INTR __BIT(29) -#define BWI_DESC32_C_FRAME_END __BIT(30) -#define BWI_DESC32_C_FRAME_START __BIT(31) - -struct bwi_desc64 { - /* Little endian */ - uint32_t ctrl0; - uint32_t ctrl1; - uint32_t addr_lo; - uint32_t addr_hi; -} __packed; - -struct bwi_rxbuf_hdr { - /* Little endian */ - uint16_t rxh_buflen; /* exclude bwi_rxbuf_hdr */ - uint8_t rxh_pad1[2]; - uint16_t rxh_flags1; /* BWI_RXH_F1_ */ - uint8_t rxh_rssi; - uint8_t rxh_sq; - uint16_t rxh_phyinfo; /* BWI_RXH_PHYINFO_ */ - uint16_t rxh_flags3; /* BWI_RXH_F3_ */ - uint16_t rxh_flags2; /* BWI_RXH_F2_ */ - uint16_t rxh_tsf; - uint8_t rxh_pad3[14]; /* Padded to 30bytes */ -} __packed; - -#define BWI_RXH_F1_BCM2053_RSSI __BIT(14) -#define BWI_RXH_F1_SHPREAMBLE __BIT(7) -#define BWI_RXH_F1_OFDM __BIT(0) - -#define BWI_RXH_F2_TYPE2FRAME __BIT(2) - -#define BWI_RXH_F3_BCM2050_RSSI __BIT(10) - -#define BWI_RXH_PHYINFO_LNAGAIN __BITS(15, 14) - -struct bwi_txbuf_hdr { - /* Little endian */ - uint32_t txh_mac_ctrl; /* BWI_TXH_MAC_C_ */ - uint8_t txh_fc[2]; - uint16_t txh_unknown1; - uint16_t txh_phy_ctrl; /* BWI_TXH_PHY_C_ */ - uint8_t txh_ivs[16]; - uint8_t txh_addr1[IEEE80211_ADDR_LEN]; - uint16_t txh_unknown2; - uint8_t txh_rts_fb_plcp[4]; - uint16_t txh_rts_fb_duration; - uint8_t txh_fb_plcp[4]; - uint16_t txh_fb_duration; - uint8_t txh_pad2[2]; - uint16_t txh_id; /* BWI_TXH_ID_ */ - uint16_t txh_unknown3; - uint8_t txh_rts_plcp[6]; - uint8_t txh_rts_fc[2]; - uint16_t txh_rts_duration; - uint8_t txh_rts_ra[IEEE80211_ADDR_LEN]; - uint8_t txh_rts_ta[IEEE80211_ADDR_LEN]; - uint8_t txh_pad3[2]; - uint8_t txh_plcp[6]; -} __packed; - -#define BWI_TXH_ID_RING_MASK __BITS(15, 13) -#define BWI_TXH_ID_IDX_MASK __BITS(12, 0) - -#define BWI_TXH_PHY_C_OFDM __BIT(0) -#define BWI_TXH_PHY_C_SHPREAMBLE __BIT(4) -#define BWI_TXH_PHY_C_ANTMODE_MASK __BITS(9, 8) - -#define BWI_TXH_MAC_C_ACK __BIT(0) -#define BWI_TXH_MAC_C_FIRST_FRAG __BIT(3) -#define BWI_TXH_MAC_C_HWSEQ __BIT(4) -#define BWI_TXH_MAC_C_FB_OFDM __BIT(8) - -struct bwi_txstats { - /* Little endian */ - uint8_t txs_pad1[4]; - uint16_t txs_id; - uint8_t txs_flags; /* BWI_TXS_F_ */ - uint8_t txs_txcnt; /* BWI_TXS_TXCNT_ */ - uint8_t txs_pad2[2]; - uint16_t txs_seq; - uint16_t txs_unknown; - uint8_t txs_pad3[2]; /* Padded to 16bytes */ -} __packed; - -#define BWI_TXS_TXCNT_DATA __BITS(7, 4) - -#define BWI_TXS_F_ACKED __BIT(0) -#define BWI_TXS_F_PENDING __BIT(5) - -struct bwi_ring_data { - uint32_t rdata_txrx_ctrl; - bus_dmamap_t rdata_dmap; - bus_addr_t rdata_paddr; - void *rdata_desc; -}; - -struct bwi_txbuf { - struct mbuf *tb_mbuf; - bus_dmamap_t tb_dmap; - - struct ieee80211_node *tb_ni; - int tb_buflen; -#define BWI_NTXRATE 2 - int tb_rateidx_cnt; - int tb_rateidx[BWI_NTXRATE]; -}; - -struct bwi_txbuf_data { - struct bwi_txbuf tbd_buf[BWI_TX_NDESC]; - int tbd_used; - int tbd_idx; -}; - -struct bwi_rxbuf { - struct mbuf *rb_mbuf; - bus_addr_t rb_paddr; - bus_dmamap_t rb_dmap; -}; - -struct bwi_rxbuf_data { - struct bwi_rxbuf rbd_buf[BWI_RX_NDESC]; - bus_dmamap_t rbd_tmp_dmap; - int rbd_idx; -}; - -struct bwi_txstats_data { - bus_dma_tag_t stats_ring_dtag; - bus_dmamap_t stats_ring_dmap; - bus_addr_t stats_ring_paddr; - void *stats_ring; - - bus_dma_tag_t stats_dtag; - bus_dmamap_t stats_dmap; - bus_addr_t stats_paddr; - struct bwi_txstats *stats; - - uint32_t stats_ctrl_base; - int stats_idx; -}; - -struct bwi_fwhdr { - /* Big endian */ - uint8_t fw_type; /* BWI_FW_T_ */ - uint8_t fw_gen; /* BWI_FW_GEN */ - uint8_t fw_pad[2]; - uint32_t fw_size; -#define fw_iv_cnt fw_size -} __packed; - -#define BWI_FWHDR_SZ sizeof(struct bwi_fwhdr) - -#define BWI_FW_T_UCODE 'u' -#define BWI_FW_T_PCM 'p' -#define BWI_FW_T_IV 'i' - -#define BWI_FW_GEN_1 1 - -#define BWI_FW_VERSION3 3 -#define BWI_FW_VERSION4 4 -#define BWI_FW_VERSION3_REVMAX 0x128 - -#define BWI_FW_PATH "bwi/v%d/" -#define BWI_FW_UCODE_PATH BWI_FW_PATH "ucode%d.fw" -#define BWI_FW_PCM_PATH BWI_FW_PATH "pcm%d.fw" -#define BWI_FW_IV_PATH BWI_FW_PATH "b0g0initvals%d.fw" -#define BWI_FW_IV_EXT_PATH BWI_FW_PATH "b0g0bsinitvals%d.fw" - -struct bwi_fw_iv { - /* Big endian */ - uint16_t iv_ofs; - union { - uint32_t val32; - uint16_t val16; - } iv_val; -} __packed; - -#define BWI_FW_IV_OFS_MASK __BITS(14, 0) -#define BWI_FW_IV_IS_32BIT __BIT(15) - -struct bwi_led { - uint8_t l_flags; /* BWI_LED_F_ */ - uint8_t l_act; /* BWI_LED_ACT_ */ - uint8_t l_mask; -}; - -#define BWI_LED_F_ACTLOW 0x1 -#define BWI_LED_F_BLINK 0x2 -#define BWI_LED_F_POLLABLE 0x4 -#define BWI_LED_F_SLOW 0x8 - -enum bwi_clock_mode { - BWI_CLOCK_MODE_SLOW, - BWI_CLOCK_MODE_FAST, - BWI_CLOCK_MODE_DYN -}; - -struct bwi_regwin { - uint32_t rw_flags; /* BWI_REGWIN_F_ */ - uint16_t rw_type; /* BWI_REGWIN_T_ */ - uint8_t rw_id; - uint8_t rw_rev; -}; - -#define BWI_REGWIN_F_EXIST 0x1 - -#define BWI_CREATE_REGWIN(rw, id, type, rev) \ -do { \ - (rw)->rw_flags = BWI_REGWIN_F_EXIST; \ - (rw)->rw_type = (type); \ - (rw)->rw_id = (id); \ - (rw)->rw_rev = (rev); \ -} while (0) - -#define BWI_REGWIN_EXIST(rw) ((rw)->rw_flags & BWI_REGWIN_F_EXIST) -#define BWI_GPIO_REGWIN(sc) \ - (BWI_REGWIN_EXIST(&(sc)->sc_com_regwin) ? \ - &(sc)->sc_com_regwin : &(sc)->sc_bus_regwin) - -struct bwi_mac; - -struct bwi_phy { - enum ieee80211_phymode phy_mode; - int phy_rev; - int phy_version; - - uint32_t phy_flags; /* BWI_PHY_F_ */ - uint16_t phy_tbl_ctrl; - uint16_t phy_tbl_data_lo; - uint16_t phy_tbl_data_hi; - - void (*phy_init)(struct bwi_mac *); -}; - -#define BWI_PHY_F_CALIBRATED 0x1 -#define BWI_PHY_F_LINKED 0x2 -#define BWI_CLEAR_PHY_FLAGS (BWI_PHY_F_CALIBRATED) - -/* TX power control */ -struct bwi_tpctl { - uint16_t bbp_atten; /* BBP attenuation: 4bits */ - uint16_t rf_atten; /* RF attenuation */ - uint16_t tp_ctrl1; /* ??: 3bits */ - uint16_t tp_ctrl2; /* ??: 4bits */ -}; - -#define BWI_RF_ATTEN_FACTOR 4 -#define BWI_RF_ATTEN_MAX0 9 -#define BWI_RF_ATTEN_MAX1 31 -#define BWI_BBP_ATTEN_MAX 11 -#define BWI_TPCTL1_MAX 7 - -struct bwi_rf_lo { - int8_t ctrl_lo; - int8_t ctrl_hi; -}; - -struct bwi_rf { - uint16_t rf_type; /* BWI_RF_T_ */ - uint16_t rf_manu; - int rf_rev; - - uint32_t rf_flags; /* BWI_RF_F_ */ - -#define BWI_RFLO_MAX 56 - struct bwi_rf_lo rf_lo[BWI_RFLO_MAX]; - uint8_t rf_lo_used[8]; - -#define BWI_INVALID_NRSSI -1000 - int16_t rf_nrssi[2]; /* Narrow RSSI */ - int32_t rf_nrssi_slope; - -#define BWI_NRSSI_TBLSZ 64 - int8_t rf_nrssi_table[BWI_NRSSI_TBLSZ]; - - uint16_t rf_lo_gain; /* loopback gain */ - uint16_t rf_rx_gain; /* TRSW RX gain */ - - uint16_t rf_calib; /* RF calibration value */ - u_int rf_curchan; /* current channel */ - - uint16_t rf_ctrl_rd; - int rf_ctrl_adj; - void (*rf_off)(struct bwi_mac *); - void (*rf_on)(struct bwi_mac *); - - void (*rf_set_nrssi_thr)(struct bwi_mac *); - void (*rf_calc_nrssi_slope)(struct bwi_mac *); - int (*rf_calc_rssi) - (struct bwi_mac *, - const struct bwi_rxbuf_hdr *); - - void (*rf_lo_update)(struct bwi_mac *); - -#define BWI_TSSI_MAX 64 - int8_t rf_txpower_map0[BWI_TSSI_MAX]; - /* Indexed by TSSI */ - int rf_idle_tssi0; - - int8_t rf_txpower_map[BWI_TSSI_MAX]; - int rf_idle_tssi; - - int rf_base_tssi; - - int rf_txpower_max; /* dBm */ - - int rf_ant_mode; /* BWI_ANT_MODE_ */ -}; - -#define BWI_RF_F_INITED 0x1 -#define BWI_RF_F_ON 0x2 -#define BWI_RF_CLEAR_FLAGS (BWI_RF_F_INITED) - -#define BWI_ANT_MODE_0 0 -#define BWI_ANT_MODE_1 1 -#define BWI_ANT_MODE_UNKN 2 -#define BWI_ANT_MODE_AUTO 3 - -struct bwi_softc; -struct fw_image; - -struct bwi_mac { - struct bwi_regwin mac_regwin; /* MUST be first field */ -#define mac_rw_flags mac_regwin.rw_flags -#define mac_type mac_regwin.rw_type -#define mac_id mac_regwin.rw_id -#define mac_rev mac_regwin.rw_rev - - struct bwi_softc *mac_sc; - - struct bwi_phy mac_phy; /* PHY I/F */ - struct bwi_rf mac_rf; /* RF I/F */ - - struct bwi_tpctl mac_tpctl; /* TX power control */ - uint32_t mac_flags; /* BWI_MAC_F_ */ - - struct fw_image *mac_ucode; - struct fw_image *mac_pcm; - struct fw_image *mac_iv; - struct fw_image *mac_iv_ext; -}; - -#define BWI_MAC_F_BSWAP 0x1 -#define BWI_MAC_F_TPCTL_INITED 0x2 -#define BWI_MAC_F_HAS_TXSTATS 0x4 -#define BWI_MAC_F_INITED 0x8 -#define BWI_MAC_F_ENABLED 0x10 -#define BWI_MAC_F_LOCKED 0x20 /* for debug */ -#define BWI_MAC_F_TPCTL_ERROR 0x40 -#define BWI_MAC_F_PHYE_RESET 0x80 - -#define BWI_CREATE_MAC(mac, sc, id, rev) \ -do { \ - BWI_CREATE_REGWIN(&(mac)->mac_regwin, \ - (id), \ - BWI_REGWIN_T_MAC, \ - (rev)); \ - (mac)->mac_sc = (sc); \ -} while (0) - -#define BWI_MAC_MAX 2 -#define BWI_LED_MAX 4 - -enum bwi_bus_space { - BWI_BUS_SPACE_30BIT = 1, - BWI_BUS_SPACE_32BIT, - BWI_BUS_SPACE_64BIT -}; - -#define BWI_TX_RADIOTAP_PRESENT \ - ((1 << IEEE80211_RADIOTAP_FLAGS) | \ - (1 << IEEE80211_RADIOTAP_RATE) | \ - (1 << IEEE80211_RADIOTAP_CHANNEL)) - -struct bwi_tx_radiotap_hdr { - struct ieee80211_radiotap_header wt_ihdr; - uint8_t wt_flags; - uint8_t wt_rate; - uint16_t wt_chan_freq; - uint16_t wt_chan_flags; -}; - -#define BWI_RX_RADIOTAP_PRESENT \ - ((1 << IEEE80211_RADIOTAP_TSFT) | \ - (1 << IEEE80211_RADIOTAP_FLAGS) | \ - (1 << IEEE80211_RADIOTAP_RATE) | \ - (1 << IEEE80211_RADIOTAP_CHANNEL) | \ - (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | \ - (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE)) - -struct bwi_rx_radiotap_hdr { - struct ieee80211_radiotap_header wr_ihdr; - uint64_t wr_tsf; - uint8_t wr_flags; - uint8_t wr_rate; - uint16_t wr_chan_freq; - uint16_t wr_chan_flags; - int8_t wr_antsignal; - int8_t wr_antnoise; - /* TODO: sq */ -}; - -struct bwi_softc { - struct ieee80211com sc_ic; - uint32_t sc_flags; /* BWI_F_ */ - device_t sc_dev; - - uint32_t sc_cap; /* BWI_CAP_ */ - uint16_t sc_bbp_id; /* BWI_BBPID_ */ - uint8_t sc_bbp_rev; - uint8_t sc_bbp_pkg; - - uint8_t sc_pci_revid; - uint16_t sc_pci_subvid; - uint16_t sc_pci_subdid; - - uint16_t sc_card_flags; /* BWI_CARD_F_ */ - uint16_t sc_pwron_delay; - int sc_locale; - - int sc_irq_rid; - struct resource *sc_irq_res; - void *sc_irq_handle; - - int sc_mem_rid; - struct resource *sc_mem_res; - bus_space_tag_t sc_mem_bt; - bus_space_handle_t sc_mem_bh; - - struct callout sc_scan_ch; - struct callout sc_calib_ch; - - struct bwi_regwin *sc_cur_regwin; - struct bwi_regwin sc_com_regwin; - struct bwi_regwin sc_bus_regwin; - - int sc_nmac; - struct bwi_mac sc_mac[BWI_MAC_MAX]; - - int sc_rx_rate; - int sc_tx_rate; - enum bwi_txpwrcb_type sc_txpwrcb_type; - - int sc_led_blinking; - int sc_led_ticks; - struct bwi_led *sc_blink_led; - struct callout sc_led_blink_ch; - int sc_led_blink_offdur; - struct bwi_led sc_leds[BWI_LED_MAX]; - - enum bwi_bus_space sc_bus_space; - bus_dma_tag_t sc_parent_dtag; - - bus_dma_tag_t sc_buf_dtag; - struct bwi_txbuf_data sc_tx_bdata[BWI_TX_NRING]; - struct bwi_rxbuf_data sc_rx_bdata; - - bus_dma_tag_t sc_txring_dtag; - struct bwi_ring_data sc_tx_rdata[BWI_TX_NRING]; - bus_dma_tag_t sc_rxring_dtag; - struct bwi_ring_data sc_rx_rdata; - - struct bwi_txstats_data *sc_txstats; - - int sc_tx_timer; - - struct bpf_if *sc_drvbpf; - - union { - struct bwi_tx_radiotap_hdr u_tx_th; - uint8_t u_pad[IEEE80211_RADIOTAP_HDRLEN]; - } sc_u_tx_th; -#define sc_tx_th sc_u_tx_th.u_tx_th - int sc_tx_th_len; - - union { - struct bwi_rx_radiotap_hdr u_rx_th; - uint8_t u_pad[IEEE80211_RADIOTAP_HDRLEN]; - } sc_u_rx_th; -#define sc_rx_th sc_u_rx_th.u_rx_th - int sc_rx_th_len; - - int (*sc_newstate) - (struct ieee80211com *, - enum ieee80211_state, int); - - int (*sc_init_tx_ring)(struct bwi_softc *, int); - void (*sc_free_tx_ring)(struct bwi_softc *, int); - - int (*sc_init_rx_ring)(struct bwi_softc *); - void (*sc_free_rx_ring)(struct bwi_softc *); - - int (*sc_init_txstats)(struct bwi_softc *); - void (*sc_free_txstats)(struct bwi_softc *); - - void (*sc_setup_rxdesc) - (struct bwi_softc *, int, bus_addr_t, int); - int (*sc_rxeof)(struct bwi_softc *); - - void (*sc_setup_txdesc) - (struct bwi_softc *, struct bwi_ring_data *, - int, bus_addr_t, int); - void (*sc_start_tx) - (struct bwi_softc *, uint32_t, int); - - void (*sc_txeof_status)(struct bwi_softc *); - - struct ieee80211_onoe_param sc_onoe_param; - - /* - * Sysctl variables - */ - int sc_fw_version; /* BWI_FW_VERSION[34] */ - int sc_dwell_time; /* milliseconds */ - uint32_t sc_debug; /* BWI_DBG_ */ - int sc_led_idle; - int sc_led_blink; - int sc_txpwr_calib; -}; - -#define BWI_F_BUS_INITED 0x1 -#define BWI_F_PROMISC 0x2 - -#define BWI_DBG_MAC 0x00000001 -#define BWI_DBG_RF 0x00000002 -#define BWI_DBG_PHY 0x00000004 -#define BWI_DBG_MISC 0x00000008 - -#define BWI_DBG_ATTACH 0x00000010 -#define BWI_DBG_INIT 0x00000020 -#define BWI_DBG_FIRMWARE 0x00000040 -#define BWI_DBG_80211 0x00000080 -#define BWI_DBG_TXPOWER 0x00000100 -#define BWI_DBG_INTR 0x00000200 -#define BWI_DBG_RX 0x00000400 -#define BWI_DBG_TX 0x00000800 -#define BWI_DBG_TXEOF 0x00001000 -#define BWI_DBG_LED 0x00002000 - -uint16_t bwi_read_sprom(struct bwi_softc *, uint16_t); -int bwi_regwin_switch(struct bwi_softc *, struct bwi_regwin *, - struct bwi_regwin **); -int bwi_regwin_is_enabled(struct bwi_softc *, struct bwi_regwin *); -void bwi_regwin_enable(struct bwi_softc *, struct bwi_regwin *, - uint32_t); -void bwi_regwin_disable(struct bwi_softc *, struct bwi_regwin *, - uint32_t); -int bwi_bus_init(struct bwi_softc *, struct bwi_mac *); -uint8_t bwi_rate2plcp(uint8_t); /* XXX belongs to 802.11 */ - -#define abs(a) __builtin_abs(a) - -#endif /* !_IF_BWIVAR_H */ diff --git a/sys/dev/netif/iwl/Makefile b/sys/dev/netif/iwl/Makefile deleted file mode 100644 index 9cb3a40f1f..0000000000 --- a/sys/dev/netif/iwl/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -KMOD= if_iwl -SRCS= if_iwl.c iwl2100.c -SRCS+= device_if.h bus_if.h pci_if.h pcidevs.h - -.include diff --git a/sys/dev/netif/iwl/if_iwl.c b/sys/dev/netif/iwl/if_iwl.c deleted file mode 100644 index 2cf3384b6c..0000000000 --- a/sys/dev/netif/iwl/if_iwl.c +++ /dev/null @@ -1,530 +0,0 @@ -/* - * Copyright (c) 2008 The DragonFly Project. All rights reserved. - * - * This code is derived from software contributed to The DragonFly Project - * by Sepherosa Ziehau - * - * 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. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * 3. Neither the name of The DragonFly Project nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific, prior written permission. - * - * 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 MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, 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 DAMAGE. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "pcidevs.h" -#include -#include - -#include "if_iwlreg.h" -#include "if_iwlvar.h" -#include "iwl2100var.h" - -struct iwl_devinfo { - const char *desc; - int bar; - int (*attach)(device_t); - void (*detach)(device_t); - int (*shutdown)(device_t); -}; - -struct iwl_softc { - union { - struct iwlcom common; - struct iwl2100_softc sc2100; - } u; - const struct iwl_devinfo *sc_info; -}; - -static int iwl_probe(device_t); -static int iwl_attach(device_t); -static int iwl_detach(device_t); -static int iwl_shutdown(device_t); - -static void iwl_dma_ring_addr(void *, bus_dma_segment_t *, int, int); -static void iwl_service_loop(void *); -static int iwl_put_port(struct lwkt_port *, struct lwkt_msg *); -static void iwl_destroy_thread_dispatch(struct netmsg *); - -static const struct iwl_devinfo iwl2100_devinfo = { - .desc = IWL2100_DESC, - .bar = IWL2100_PCIR_BAR, - .attach = iwl2100_attach, - .detach = iwl2100_detach, - .shutdown = iwl2100_shutdown -}; - -static const struct iwl_dev { - uint16_t vid; - uint16_t did; - const struct iwl_devinfo *info; -} iwl_devices[] = { - { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_PRO_WL_2100, &iwl2100_devinfo }, - { 0, 0, NULL } -}; - -static device_method_t iwl_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, iwl_probe), - DEVMETHOD(device_attach, iwl_attach), - DEVMETHOD(device_detach, iwl_detach), - DEVMETHOD(device_shutdown, iwl_shutdown), - - DEVMETHOD_END -}; - -static driver_t iwl_driver = { - "iwl", - iwl_methods, - sizeof(struct iwl_softc) -}; - -static devclass_t iwl_devclass; - -DRIVER_MODULE(iwl, pci, iwl_driver, iwl_devclass, NULL, NULL); - -MODULE_DEPEND(iwl, wlan, 1, 1, 1); -MODULE_DEPEND(iwl, pci, 1, 1, 1); - -const struct ieee80211_rateset iwl_rateset_11b = { 4, { 2, 4, 11, 22 } }; - -static int -iwl_probe(device_t dev) -{ - const struct iwl_dev *d; - uint16_t did, vid; - - vid = pci_get_vendor(dev); - did = pci_get_device(dev); - - for (d = iwl_devices; d->info != NULL; ++d) { - if (d->did == did && d->vid == vid) { - struct iwl_softc *sc = device_get_softc(dev); - - device_set_desc(dev, d->info->desc); - sc->sc_info = d->info; - return 0; - } - } - return ENXIO; -} - -static int -iwl_attach(device_t dev) -{ - struct iwl_softc *sc = device_get_softc(dev); - struct iwlcom *iwl = &sc->u.common; - struct ifnet *ifp = &iwl->iwl_ic.ic_if; - int error, bar; - - if_initname(ifp, device_get_name(dev), device_get_unit(dev)); - bar = sc->sc_info->bar; - -#ifndef BURN_BRIDGES - if (pci_get_powerstate(dev) != PCI_POWERSTATE_D0) { - uint32_t irq, mem; - - irq = pci_read_config(dev, PCIR_INTLINE, 4); - mem = pci_read_config(dev, bar, 4); - - device_printf(dev, "chip is in D%d power mode " - "-- setting to D0\n", pci_get_powerstate(dev)); - - pci_set_powerstate(dev, PCI_POWERSTATE_D0); - - pci_write_config(dev, PCIR_INTLINE, irq, 4); - pci_write_config(dev, bar, mem, 4); - } -#endif /* !BURN_BRIDGES */ - - /* Enable bus mastering */ - pci_enable_busmaster(dev); - - /* - * Allocate IO memory - */ - iwl->iwl_mem_rid = bar; - iwl->iwl_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, - &iwl->iwl_mem_rid, RF_ACTIVE); - if (iwl->iwl_mem_res == NULL) { - device_printf(dev, "can't allocate IO memory\n"); - return ENXIO; - } - iwl->iwl_mem_bt = rman_get_bustag(iwl->iwl_mem_res); - iwl->iwl_mem_bh = rman_get_bushandle(iwl->iwl_mem_res); - - /* - * Allocate IRQ - */ - iwl->iwl_irq_rid = 0; - iwl->iwl_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, - &iwl->iwl_irq_rid, - RF_SHAREABLE | RF_ACTIVE); - if (iwl->iwl_irq_res == NULL) { - device_printf(dev, "can't allocate irq\n"); - error = ENXIO; - goto back; - } - - /* - * Device specific attach - */ - error = sc->sc_info->attach(dev); -back: - if (error) - iwl_detach(dev); - return error; -} - -static int -iwl_detach(device_t dev) -{ - struct iwl_softc *sc = device_get_softc(dev); - struct iwlcom *iwl = &sc->u.common; - - sc->sc_info->detach(dev); - - if (iwl->iwl_irq_res != NULL) { - bus_release_resource(dev, SYS_RES_IRQ, iwl->iwl_irq_rid, - iwl->iwl_irq_res); - } - - if (iwl->iwl_mem_res != NULL) { - bus_release_resource(dev, SYS_RES_MEMORY, iwl->iwl_mem_rid, - iwl->iwl_mem_res); - } - return 0; -} - -static int -iwl_shutdown(device_t dev) -{ - struct iwl_softc *sc = device_get_softc(dev); - - return sc->sc_info->shutdown(dev); -} - -void -iwl_ind_write_4(struct iwlcom *iwl, uint32_t addr, uint32_t data) -{ - IWL_WRITE_4(iwl, IWL_IND_ADDR, addr); - IWL_WRITE_4(iwl, IWL_IND_DATA, data); -} - -void -iwl_ind_write_2(struct iwlcom *iwl, uint32_t addr, uint16_t data) -{ - IWL_WRITE_4(iwl, IWL_IND_ADDR, addr); - IWL_WRITE_2(iwl, IWL_IND_DATA, data); -} - -void -iwl_ind_write_1(struct iwlcom *iwl, uint32_t addr, uint8_t data) -{ - IWL_WRITE_4(iwl, IWL_IND_ADDR, addr); - IWL_WRITE_1(iwl, IWL_IND_DATA, data); -} - -uint32_t -iwl_ind_read_4(struct iwlcom *iwl, uint32_t addr) -{ - IWL_WRITE_4(iwl, IWL_IND_ADDR, addr); - return IWL_READ_4(iwl, IWL_IND_DATA); -} - -uint16_t -iwl_ind_read_2(struct iwlcom *iwl, uint32_t addr) -{ - IWL_WRITE_4(iwl, IWL_IND_ADDR, addr); - return IWL_READ_2(iwl, IWL_IND_DATA); -} - -uint8_t -iwl_ind_read_1(struct iwlcom *iwl, uint32_t addr) -{ - IWL_WRITE_4(iwl, IWL_IND_ADDR, addr); - return IWL_READ_1(iwl, IWL_IND_DATA); -} - -#define EEPROM_WRITE(iwl, data) \ -do { \ - iwl_ind_write_4((iwl), IWL_EEPROM_IND_CSR, (data)); \ - DELAY(1); \ -} while (0) - -#define EEPROM_SET_BIT(iwl) \ -do { \ - EEPROM_WRITE((iwl), IWL_EEBIT_CS | IWL_EEBIT_DI); \ - EEPROM_WRITE((iwl), IWL_EEBIT_CS | IWL_EEBIT_DI | IWL_EEBIT_SK); \ -} while (0) - -#define EEPROM_CLR_BIT(iwl) \ -do { \ - EEPROM_WRITE((iwl), IWL_EEBIT_CS); \ - EEPROM_WRITE((iwl), IWL_EEBIT_CS | IWL_EEBIT_SK); \ -} while (0) - -uint16_t -iwl_read_eeprom(struct iwlcom *iwl, uint8_t ofs) -{ - uint16_t ret; - int i; - - /* Chip select */ - EEPROM_WRITE(iwl, 0); - EEPROM_WRITE(iwl, IWL_EEBIT_CS); - EEPROM_WRITE(iwl, IWL_EEBIT_CS | IWL_EEBIT_SK); - EEPROM_WRITE(iwl, IWL_EEBIT_CS); - - /* Send READ opcode (0x2) */ - EEPROM_SET_BIT(iwl); - EEPROM_SET_BIT(iwl); /* READ opcode */ - EEPROM_CLR_BIT(iwl); /* READ opcode */ - - /* Send offset */ - for (i = NBBY - 1; i >= 0; --i) { - if (ofs & (1 << i)) - EEPROM_SET_BIT(iwl); - else - EEPROM_CLR_BIT(iwl); - } - - /* Kick start */ - EEPROM_WRITE(iwl, IWL_EEBIT_CS); - - /* Read data */ - ret = 0; - for (i = 0; i < (sizeof(ret) * NBBY); ++i) { - EEPROM_WRITE(iwl, IWL_EEBIT_CS | IWL_EEBIT_SK); - EEPROM_WRITE(iwl, IWL_EEBIT_CS); - - ret <<= 1; - if (iwl_ind_read_4(iwl, IWL_EEPROM_IND_CSR) & IWL_EEBIT_DO) - ret |= 1; - } - - /* Stop */ - EEPROM_WRITE(iwl, 0); - - /* Chip de-select */ - EEPROM_WRITE(iwl, IWL_EEBIT_CS); - EEPROM_WRITE(iwl, 0); - EEPROM_WRITE(iwl, IWL_EEBIT_SK); - - return le16toh(ret); -} - -static void -iwl_dma_ring_addr(void *arg, bus_dma_segment_t *seg, int nseg, int error) -{ - KASSERT(nseg == 1, ("too many segments")); - *((bus_addr_t *)arg) = seg->ds_addr; -} - -int -iwl_dma_mem_create(device_t dev, bus_dma_tag_t parent, bus_size_t size, - bus_dma_tag_t *dtag, void **addr, bus_addr_t *paddr, - bus_dmamap_t *dmap) -{ - int error; - - error = bus_dma_tag_create(parent, IWL_ALIGN, 0, - BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, - NULL, NULL, - size, 1, BUS_SPACE_MAXSIZE_32BIT, - 0, dtag); - if (error) { - device_printf(dev, "can't create DMA tag\n"); - return error; - } - - error = bus_dmamem_alloc(*dtag, addr, BUS_DMA_WAITOK | BUS_DMA_ZERO, - dmap); - if (error) { - device_printf(dev, "can't allocate DMA mem\n"); - bus_dma_tag_destroy(*dtag); - *dtag = NULL; - return error; - } - - error = bus_dmamap_load(*dtag, *dmap, *addr, size, - iwl_dma_ring_addr, paddr, BUS_DMA_WAITOK); - if (error) { - device_printf(dev, "can't load DMA mem\n"); - bus_dmamem_free(*dtag, *addr, *dmap); - bus_dma_tag_destroy(*dtag); - *dtag = NULL; - return error; - } - return 0; -} - -void -iwl_dma_mem_destroy(bus_dma_tag_t dtag, void *addr, bus_dmamap_t dmap) -{ - if (dtag != NULL) { - bus_dmamap_unload(dtag, dmap); - bus_dmamem_free(dtag, addr, dmap); - bus_dma_tag_destroy(dtag); - } -} - -void -iwl_dma_buf_addr(void *xctx, bus_dma_segment_t *segs, int nsegs, - bus_size_t mapsz __unused, int error) -{ - struct iwl_dmamap_ctx *ctx = xctx; - int i; - - if (error) - return; - - if (nsegs > ctx->nsegs) { - ctx->nsegs = 0; - return; - } - - ctx->nsegs = nsegs; - for (i = 0; i < nsegs; ++i) - ctx->segs[i] = segs[i]; -} - -static int -iwl_put_port(struct lwkt_port *port, struct lwkt_msg *lmsg) -{ - struct iwlmsg *msg = (struct iwlmsg *)lmsg; - struct iwlcom *iwl = msg->iwlm_softc; - - ASSERT_SERIALIZED(port->mpu_serialize); - - if ((lmsg->ms_flags & MSGF_SYNC) && curthread == &iwl->iwl_thread) { - msg->iwlm_nmsg.nm_dispatch(&msg->iwlm_nmsg); - if ((lmsg->ms_flags & MSGF_DONE) == 0) { - panic("%s: self-referential deadlock on " - "iwl thread port\n", __func__); - } - return EASYNC; - } else { - return iwl->iwl_fwd_port(port, lmsg); - } -} - -static void -iwl_service_loop(void *arg) -{ - struct iwlcom *iwl = arg; - struct ifnet *ifp = &iwl->iwl_ic.ic_if; - struct netmsg *nmsg; - - get_mplock(); - lwkt_serialize_enter(ifp->if_serializer); - while ((nmsg = lwkt_waitport(&iwl->iwl_thread_port, 0))) { - nmsg->nm_dispatch(nmsg); - if (iwl->iwl_end) - break; - } - lwkt_serialize_exit(ifp->if_serializer); - rel_mplock(); -} - -void -iwl_create_thread(struct iwlcom *iwl, int unit) -{ - struct ifnet *ifp = &iwl->iwl_ic.ic_if; - - lwkt_initport_serialize(&iwl->iwl_reply_port, ifp->if_serializer); - lwkt_initport_serialize(&iwl->iwl_thread_port, ifp->if_serializer); - - /* NB: avoid self-reference domsg */ - iwl->iwl_fwd_port = iwl->iwl_thread_port.mp_putport; - iwl->iwl_thread_port.mp_putport = iwl_put_port; - - lwkt_create(iwl_service_loop, iwl, NULL, &iwl->iwl_thread, - 0, unit % ncpus, "iwl%d", unit); -} - -static void -iwl_destroy_thread_dispatch(struct netmsg *nmsg) -{ - struct iwlmsg *msg = (struct iwlmsg *)nmsg; - struct iwlcom *iwl = msg->iwlm_softc; - - ASSERT_SERIALIZED(iwl->iwl_ic.ic_if.if_serializer); - - iwl->iwl_end = 1; - lwkt_replymsg(&nmsg->nm_lmsg, 0); -} - -void -iwl_destroy_thread(struct iwlcom *iwl) -{ - struct iwlmsg msg; - - ASSERT_SERIALIZED(iwl->iwl_ic.ic_if.if_serializer); - - iwlmsg_init(&msg, &iwl->iwl_reply_port, - iwl_destroy_thread_dispatch, iwl); - lwkt_domsg(&iwl->iwl_thread_port, &msg.iwlm_nmsg.nm_lmsg, 0); -} - -void -iwlmsg_init(struct iwlmsg *msg, struct lwkt_port *rport, netisr_fn_t dispatch, - void *sc) -{ - netmsg_init(&msg->iwlm_nmsg, NULL, rport, 0, dispatch); - msg->iwlm_softc = sc; -} - -void -iwlmsg_send(struct iwlmsg *msg, struct lwkt_port *port) -{ - struct lwkt_msg *lmsg; - - lmsg = &msg->iwlm_nmsg.nm_lmsg; - if (lmsg->ms_flags & MSGF_DONE) - lwkt_sendmsg(port, lmsg); -} diff --git a/sys/dev/netif/iwl/if_iwlreg.h b/sys/dev/netif/iwl/if_iwlreg.h deleted file mode 100644 index b9370c196b..0000000000 --- a/sys/dev/netif/iwl/if_iwlreg.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2008 The DragonFly Project. All rights reserved. - * - * This code is derived from software contributed to The DragonFly Project - * by Sepherosa Ziehau - * - * 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. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * 3. Neither the name of The DragonFly Project nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific, prior written permission. - * - * 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 MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, 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 DAMAGE. - * - * $DragonFly: src/sys/dev/netif/iwl/if_iwlreg.h,v 1.1 2008/03/05 14:10:39 sephe Exp $ - */ - -#ifndef _IF_IWLREG_H -#define _IF_IWLREG_H - -#define IWL_IND_ADDR 0x10 -#define IWL_IND_DATA 0x14 - -#define IWL_EEPROM_IND_CSR 0x300040 -#define IWL_EEBIT_SK (1 << 0) -#define IWL_EEBIT_CS (1 << 1) -#define IWL_EEBIT_DI (1 << 2) -#define IWL_EEBIT_DO (1 << 4) - -#endif /* !_IF_IWLREG_H */ diff --git a/sys/dev/netif/iwl/if_iwlvar.h b/sys/dev/netif/iwl/if_iwlvar.h deleted file mode 100644 index e620be8788..0000000000 --- a/sys/dev/netif/iwl/if_iwlvar.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (c) 2008 The DragonFly Project. All rights reserved. - * - * This code is derived from software contributed to The DragonFly Project - * by Sepherosa Ziehau - * - * 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. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * 3. Neither the name of The DragonFly Project nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific, prior written permission. - * - * 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 MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, 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 DAMAGE. - */ - -#ifndef _IF_IWLVAR_H -#define _IF_IWLVAR_H - -#define IWL_ALIGN 0x1000 /* XXX */ - -struct iwl_dmamap_ctx { - int nsegs; - bus_dma_segment_t *segs; -}; - -struct iwlmsg { - struct netmsg iwlm_nmsg; - void *iwlm_softc; - - /* For newstate() */ - enum ieee80211_state iwlm_nstate; - int iwlm_arg; -}; - -struct iwlcom { - struct ieee80211com iwl_ic; - int iwl_end; - - int iwl_mem_rid; - struct resource *iwl_mem_res; - bus_space_tag_t iwl_mem_bt; - bus_space_handle_t iwl_mem_bh; - - int iwl_irq_rid; - struct resource *iwl_irq_res; - void *iwl_irq_handle; - - int iwl_tx_timer; - - struct lwkt_port iwl_reply_port; - struct lwkt_port iwl_thread_port; - struct thread iwl_thread; - int (*iwl_fwd_port) - (struct lwkt_port *, struct lwkt_msg *); -}; - -#define sc_ic iwlcom.iwl_ic -#define sc_irq_res iwlcom.iwl_irq_res -#define sc_irq_handle iwlcom.iwl_irq_handle -#define sc_thread iwlcom.iwl_thread -#define sc_thread_port iwlcom.iwl_thread_port -#define sc_reply_port iwlcom.iwl_reply_port -#define sc_tx_timer iwlcom.iwl_tx_timer -#define sc_sysctl_ctx iwlcom.iwl_sysctl_ctx -#define sc_sysctl_tree iwlcom.iwl_sysctl_tree - -#define IWL_FW_PATH "iwl/" - -#define IWL_WRITE_4(iwl, reg, val) \ - bus_space_write_4((iwl)->iwl_mem_bt, (iwl)->iwl_mem_bh, (reg), (val)) -#define IWL_WRITE_2(iwl, reg, val) \ - bus_space_write_2((iwl)->iwl_mem_bt, (iwl)->iwl_mem_bh, (reg), (val)) -#define IWL_WRITE_1(iwl, reg, val) \ - bus_space_write_1((iwl)->iwl_mem_bt, (iwl)->iwl_mem_bh, (reg), (val)) -#define IWL_READ_4(iwl, reg) \ - bus_space_read_4((iwl)->iwl_mem_bt, (iwl)->iwl_mem_bh, (reg)) -#define IWL_READ_2(iwl, reg) \ - bus_space_read_2((iwl)->iwl_mem_bt, (iwl)->iwl_mem_bh, (reg)) -#define IWL_READ_1(iwl, reg) \ - bus_space_read_1((iwl)->iwl_mem_bt, (iwl)->iwl_mem_bh, (reg)) - -#define IND_WRITE_4(sc, reg, val) \ - iwl_ind_write_4(&(sc)->iwlcom, (reg), (val)) -#define IND_WRITE_2(sc, reg, val) \ - iwl_ind_write_2(&(sc)->iwlcom, (reg), (val)) -#define IND_WRITE_1(sc, reg, val) \ - iwl_ind_write_1(&(sc)->iwlcom, (reg), (val)) -#define IND_READ_4(sc, reg) \ - iwl_ind_read_4(&(sc)->iwlcom, (reg)) -#define IND_READ_2(sc, reg) \ - iwl_ind_read_2(&(sc)->iwlcom, (reg)) -#define IND_READ_1(sc, reg) \ - iwl_ind_read_1(&(sc)->iwlcom, (reg)) - -#define CSR_READ_1(sc, reg) IWL_READ_1(&(sc)->iwlcom, (reg)) - -#define CSR_WRITE_4(sc, reg, val) IWL_WRITE_4(&(sc)->iwlcom, (reg), (val)) -#define CSR_READ_4(sc, reg) IWL_READ_4(&(sc)->iwlcom, (reg)) -#define CSR_SETBITS_4(sc, reg, bit) \ - CSR_WRITE_4((sc), (reg), CSR_READ_4((sc), (reg)) | (bit)) - -extern const struct ieee80211_rateset iwl_rateset_11b; - -void iwl_ind_write_4(struct iwlcom *, uint32_t, uint32_t); -void iwl_ind_write_2(struct iwlcom *, uint32_t, uint16_t); -void iwl_ind_write_1(struct iwlcom *, uint32_t, uint8_t); -uint32_t iwl_ind_read_4(struct iwlcom *, uint32_t); -uint16_t iwl_ind_read_2(struct iwlcom *, uint32_t); -uint8_t iwl_ind_read_1(struct iwlcom *, uint32_t); -uint16_t iwl_read_eeprom(struct iwlcom *, uint8_t); -int iwl_dma_mem_create(device_t, bus_dma_tag_t, bus_size_t, - bus_dma_tag_t *, void **, bus_addr_t *, - bus_dmamap_t *); -void iwl_dma_mem_destroy(bus_dma_tag_t, void *, bus_dmamap_t); -void iwl_dma_buf_addr(void *, bus_dma_segment_t *, int, - bus_size_t, int); -void iwl_create_thread(struct iwlcom *, int); -void iwl_destroy_thread(struct iwlcom *); - -void iwlmsg_send(struct iwlmsg *, struct lwkt_port *); -void iwlmsg_init(struct iwlmsg *, struct lwkt_port *, - netisr_fn_t, void *); - -#endif /* !_IF_IWLVAR_H */ diff --git a/sys/dev/netif/iwl/iwl2100.c b/sys/dev/netif/iwl/iwl2100.c deleted file mode 100644 index 02b608f957..0000000000 --- a/sys/dev/netif/iwl/iwl2100.c +++ /dev/null @@ -1,3677 +0,0 @@ -/* - * Copyright (c) 2008 The DragonFly Project. All rights reserved. - * - * This code is derived from software contributed to The DragonFly Project - * by Sepherosa Ziehau - * - * 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. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * 3. Neither the name of The DragonFly Project nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific, prior written permission. - * - * 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 MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, 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 DAMAGE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include "if_iwlvar.h" -#include "iwl2100reg.h" -#include "iwl2100var.h" - -#define IWL2100_INIT_F_ENABLE 0x1 -#define IWL2100_INIT_F_IBSSCHAN 0x2 - -#define sc_tx_th sc_u_tx_th.u_tx_th -#define sc_rx_th sc_u_rx_th.u_rx_th - -static void iwl2100_init(void *); -static int iwl2100_ioctl(struct ifnet *, u_long, caddr_t, struct ucred *); -static void iwl2100_start(struct ifnet *, struct ifaltq_subque *); -static void iwl2100_watchdog(struct ifnet *); -static int iwl2100_newstate(struct ieee80211com *, enum ieee80211_state, int); -static int iwl2100_media_change(struct ifnet *); -static void iwl2100_media_status(struct ifnet *, struct ifmediareq *); -static void iwl2100_stop(struct iwl2100_softc *); -static void iwl2100_restart(struct iwl2100_softc *); -static void iwl2100_reinit(struct iwl2100_softc *); - -static void iwl2100_intr(void *); -static void iwl2100_txeof(struct iwl2100_softc *); -static void iwl2100_rxeof(struct iwl2100_softc *); -static void iwl2100_rxeof_status(struct iwl2100_softc *, int); -static void iwl2100_rxeof_note(struct iwl2100_softc *, int); -static void iwl2100_rxeof_cmd(struct iwl2100_softc *, int); -static void iwl2100_rxeof_data(struct iwl2100_softc *, int); - -static void iwl2100_init_dispatch(struct netmsg *); -static void iwl2100_reinit_dispatch(struct netmsg *); -static void iwl2100_stop_dispatch(struct netmsg *); -static void iwl2100_newstate_dispatch(struct netmsg *); -static void iwl2100_scanend_dispatch(struct netmsg *); -static void iwl2100_restart_dispatch(struct netmsg *); -static void iwl2100_bmiss_dispatch(struct netmsg *); - -static void iwl2100_stop_callouts(struct iwl2100_softc *); -static void iwl2100_restart_bmiss(void *); -static void iwl2100_ibss_bssid(void *); -static void iwl2100_reinit_callout(void *); - -static int iwl2100_dma_alloc(device_t); -static void iwl2100_dma_free(device_t); -static int iwl2100_dma_mbuf_create(device_t); -static void iwl2100_dma_mbuf_destroy(device_t, int, int); -static int iwl2100_init_tx_ring(struct iwl2100_softc *); -static int iwl2100_init_rx_ring(struct iwl2100_softc *); -static void iwl2100_free_tx_ring(struct iwl2100_softc *); -static void iwl2100_free_rx_ring(struct iwl2100_softc *); - -static int iwl2100_alloc_cmd(struct iwl2100_softc *); -static void iwl2100_free_cmd(struct iwl2100_softc *); -static int iwl2100_wait_cmd(struct iwl2100_softc *); - -static void iwl2100_rxdesc_setup(struct iwl2100_softc *, int); -static int iwl2100_newbuf(struct iwl2100_softc *, int, int); -static int iwl2100_encap(struct iwl2100_softc *, struct mbuf *); - -static void iwl2100_chan_change(struct iwl2100_softc *, - const struct ieee80211_channel *); - -static int iwl2100_alloc_firmware(struct iwl2100_softc *, - enum ieee80211_opmode); -static void iwl2100_free_firmware(struct iwl2100_softc *); -static int iwl2100_load_firmware(struct iwl2100_softc *, - enum ieee80211_opmode); -static int iwl2100_load_fw_ucode(struct iwl2100_softc *, - const struct iwl2100_firmware *); -static int iwl2100_load_fw_data(struct iwl2100_softc *, - const struct iwl2100_firmware *); -static int iwl2100_init_firmware(struct iwl2100_softc *); - -static int iwl2100_read_ord2(struct iwl2100_softc *, uint32_t, - void *, int); -static uint32_t iwl2100_read_ord1(struct iwl2100_softc *, uint32_t); -static void iwl2100_write_ord1(struct iwl2100_softc *, uint32_t, uint32_t); - -static int iwl2100_reset(struct iwl2100_softc *); -static int iwl2100_hw_reset(struct iwl2100_softc *); -static int iwl2100_rfkilled(struct iwl2100_softc *); - -static int iwl2100_scan(struct iwl2100_softc *); -static int iwl2100_auth(struct iwl2100_softc *); -static int iwl2100_ibss(struct iwl2100_softc *); - -static int iwl2100_hw_init(struct iwl2100_softc *, const uint8_t *, - const uint8_t *, uint8_t, uint32_t); -static void iwl2100_hw_stop(struct iwl2100_softc *); -static int iwl2100_config(struct iwl2100_softc *, const uint8_t *, - const uint8_t *, uint8_t, int); -static int iwl2100_start_scan(struct iwl2100_softc *, uint32_t, uint32_t); - -static int iwl2100_config_op(struct iwl2100_softc *, uint32_t); -static int iwl2100_set_addr(struct iwl2100_softc *, const uint8_t *); -static int iwl2100_set_opmode(struct iwl2100_softc *, - enum ieee80211_opmode); -static int iwl2100_set_80211(struct iwl2100_softc *); -static int iwl2100_set_basicrates(struct iwl2100_softc *); -static int iwl2100_set_txrates(struct iwl2100_softc *); -static int iwl2100_set_powersave(struct iwl2100_softc *, int); -static int iwl2100_set_rtsthreshold(struct iwl2100_softc *, uint16_t); -static int iwl2100_set_bssid(struct iwl2100_softc *, const uint8_t *); -static int iwl2100_set_essid(struct iwl2100_softc *, const uint8_t *, int); -static int iwl2100_set_auth_ciphers(struct iwl2100_softc *, - enum ieee80211_authmode); -static int iwl2100_set_wepkey(struct iwl2100_softc *, - const struct ieee80211_key *); -static int iwl2100_set_weptxkey(struct iwl2100_softc *, ieee80211_keyix); -static int iwl2100_set_privacy(struct iwl2100_softc *, int); -static int iwl2100_set_chan(struct iwl2100_softc *, - const struct ieee80211_channel *); -static int iwl2100_set_scanopt(struct iwl2100_softc *, uint32_t, uint32_t); -static int iwl2100_set_scan(struct iwl2100_softc *); -static int iwl2100_set_optie(struct iwl2100_softc *, void *, uint16_t); -static int iwl2100_set_bintval(struct iwl2100_softc *, uint16_t); -static int iwl2100_set_txpower(struct iwl2100_softc *, uint16_t); - -static __inline int -iwl2100_config_done(struct iwl2100_softc *sc) -{ - return iwl2100_config_op(sc, IWL2100_CMD_CONF_DONE); -} - -static __inline int -iwl2100_config_start(struct iwl2100_softc *sc) -{ - return iwl2100_config_op(sc, IWL2100_CMD_CONF_START); -} - -static __inline void -iwl2100_restart_done(struct iwl2100_softc *sc) -{ - callout_stop(&sc->sc_restart_bmiss); - sc->sc_flags &= ~IWL2100_F_RESTARTING; -} - -int -iwl2100_attach(device_t dev) -{ - struct iwl2100_softc *sc = device_get_softc(dev); - struct ieee80211com *ic = &sc->sc_ic; - struct ifnet *ifp = &ic->ic_if; - uint16_t val; - int error, i; - - /* - * Linux voodoo: - * Clear the retry timeout PCI configuration register to keep - * PCI TX retries from interfering with C3 CPU state. - */ - pci_write_config(dev, IWL2100_PCIR_RETRY_TIMEOUT, 0, 1); - - /* - * Allocate DMA stuffs - */ - error = iwl2100_dma_alloc(dev); - if (error) - return error; - - /* Disable interrupts */ - CSR_WRITE_4(sc, IWL2100_INTR_MASK, 0); - - /* - * SW reset before reading EEPROM - */ - error = iwl2100_reset(sc); - if (error) - return error; - - ifp->if_softc = sc; - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; - ifp->if_init = iwl2100_init; - ifp->if_ioctl = iwl2100_ioctl; - ifp->if_start = iwl2100_start; - ifp->if_watchdog = iwl2100_watchdog; - ifq_set_maxlen(&ifp->if_snd, IWL2100_TX_USED_MAX); -#ifdef notyet - ifq_set_ready(&ifp->if_snd); -#endif - -#ifdef DUMP_EEPROM - device_printf(dev, "eeprom\n"); - for (i = 0; i < 128; ++i) { - if (i != 0 && i % 8 == 0) - kprintf("\n"); - val = iwl_read_eeprom(&sc->iwlcom, i); - kprintf("%04x ", val); - } - kprintf("\n"); -#endif - - /* IBSS channel mask */ - sc->sc_ibss_chans = iwl_read_eeprom(&sc->iwlcom, - IWL2100_EEPROM_IBSS_CHANS) & IWL2100_CFG_CHANMASK; - - /* BSS channel mask */ - sc->sc_bss_chans = iwl_read_eeprom(&sc->iwlcom, IWL2100_EEPROM_CHANS); - - /* - * Set MAC address - */ - for (i = 0; i < ETHER_ADDR_LEN / 2; ++i) { - val = iwl_read_eeprom(&sc->iwlcom, IWL2100_EEPROM_MAC + i); - ic->ic_myaddr[i * 2] = val >> 8; - ic->ic_myaddr[(i * 2) + 1] = val & 0xff; - } - - /* - * Set supported channels - */ - for (i = 0; i < 14; ++i) { - if (sc->sc_bss_chans & (1 << i)) { - int chan = i + 1; - - ic->ic_channels[chan].ic_freq = - ieee80211_ieee2mhz(chan, IEEE80211_CHAN_2GHZ); - ic->ic_channels[chan].ic_flags = IEEE80211_CHAN_B; - } - } - - ic->ic_sup_rates[IEEE80211_MODE_11B] = iwl_rateset_11b; - ic->ic_phytype = IEEE80211_T_DS; - ic->ic_caps = IEEE80211_C_MONITOR | - IEEE80211_C_IBSS | - IEEE80211_C_SHPREAMBLE | - IEEE80211_C_WPA; - ic->ic_caps_ext = IEEE80211_CEXT_AUTOSCAN; - ic->ic_state = IEEE80211_S_INIT; - ic->ic_opmode = IEEE80211_M_STA; - - ieee80211_ifattach(ic); - - /* - * ieee80211_frame will be stripped on TX path, so only - * extra space needs to be reserved. - */ - ic->ic_headroom = sizeof(struct iwl2100_tx_hdr) - - sizeof(struct ieee80211_frame); - - sc->sc_newstate = ic->ic_newstate; - ic->ic_newstate = iwl2100_newstate; - - ieee80211_media_init(ic, iwl2100_media_change, iwl2100_media_status); - - ifq_set_cpuid(&ifp->if_snd, rman_get_cpuid(sc->sc_irq_res)); - - error = bus_setup_intr(dev, sc->sc_irq_res, INTR_MPSAFE, - iwl2100_intr, sc, &sc->sc_irq_handle, - ifp->if_serializer); - if (error) { - device_printf(dev, "can't setup intr\n"); - ieee80211_ifdetach(ic); - return ENXIO; - } - - /* - * Attach radio tap - */ - bpfattach_dlt(ifp, DLT_IEEE802_11_RADIO, - sizeof(struct ieee80211_frame) + sizeof(sc->sc_tx_th), - &sc->sc_drvbpf); - - sc->sc_tx_th_len = roundup(sizeof(sc->sc_tx_th), sizeof(uint32_t)); - sc->sc_tx_th.wt_ihdr.it_len = htole16(sc->sc_tx_th_len); - sc->sc_tx_th.wt_ihdr.it_present = htole32(IWL2100_TX_RADIOTAP_PRESENT); - - sc->sc_rx_th_len = roundup(sizeof(sc->sc_rx_th), sizeof(uint32_t)); - sc->sc_rx_th.wr_ihdr.it_len = htole16(sc->sc_rx_th_len); - sc->sc_rx_th.wr_ihdr.it_present = htole32(IWL2100_RX_RADIOTAP_PRESENT); - - sc->sc_tx_th.wt_chan_flags = sc->sc_rx_th.wr_chan_flags = - htole16(IEEE80211_CHAN_B); - - /* - * Create worker thread and initialize all necessary messages - */ - iwl_create_thread(&sc->iwlcom, device_get_unit(dev)); - - iwlmsg_init(&sc->sc_scanend_msg, &netisr_adone_rport, - iwl2100_scanend_dispatch, sc); - iwlmsg_init(&sc->sc_restart_msg, &netisr_adone_rport, - iwl2100_restart_dispatch, sc); - iwlmsg_init(&sc->sc_bmiss_msg, &netisr_adone_rport, - iwl2100_bmiss_dispatch, sc); - iwlmsg_init(&sc->sc_reinit_msg, &netisr_adone_rport, - iwl2100_reinit_dispatch, sc); - - iwlmsg_init(&sc->sc_assoc_msg, &netisr_adone_rport, - iwl2100_newstate_dispatch, sc); - sc->sc_assoc_msg.iwlm_nstate = IEEE80211_S_ASSOC; - sc->sc_assoc_msg.iwlm_arg = -1; - - iwlmsg_init(&sc->sc_run_msg, &netisr_adone_rport, - iwl2100_newstate_dispatch, sc); - sc->sc_run_msg.iwlm_nstate = IEEE80211_S_RUN; - sc->sc_run_msg.iwlm_arg = -1; - - /* - * Initialize callouts - */ - callout_init(&sc->sc_restart_bmiss); - callout_init(&sc->sc_ibss); - callout_init(&sc->sc_reinit); - - /* Add sysctl node */ - SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), - SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, - "debug", CTLFLAG_RW, &sc->sc_debug, 0, "debug flags"); - - if (bootverbose) - ieee80211_announce(ic); - return 0; -} - -void -iwl2100_detach(device_t dev) -{ - struct iwl2100_softc *sc = device_get_softc(dev); - - if (device_is_attached(dev)) { - struct ifnet *ifp = &sc->sc_ic.ic_if; - - lwkt_serialize_enter(ifp->if_serializer); - - sc->sc_flags |= IWL2100_F_DETACH; - iwl2100_stop(sc); - bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_irq_handle); - iwl_destroy_thread(&sc->iwlcom); - - lwkt_serialize_exit(ifp->if_serializer); - - iwl2100_free_firmware(sc); - - bpfdetach(ifp); - ieee80211_ifdetach(&sc->sc_ic); - } - iwl2100_dma_free(dev); -} - -int -iwl2100_shutdown(device_t dev) -{ - struct iwl2100_softc *sc = device_get_softc(dev); - struct ifnet *ifp = &sc->sc_ic.ic_if; - - lwkt_serialize_enter(ifp->if_serializer); - iwl2100_stop(sc); - lwkt_serialize_exit(ifp->if_serializer); - - return 0; -} - -static void -iwl2100_stop(struct iwl2100_softc *sc) -{ - struct iwlmsg msg; - - ASSERT_SERIALIZED(sc->sc_ic.ic_if.if_serializer); - - iwl2100_stop_callouts(sc); - - iwlmsg_init(&msg, &sc->sc_reply_port, iwl2100_stop_dispatch, sc); - lwkt_domsg(&sc->sc_thread_port, &msg.iwlm_nmsg.nm_lmsg, 0); -} - -static void -iwl2100_stop_dispatch(struct netmsg *nmsg) -{ - struct iwlmsg *msg = (struct iwlmsg *)nmsg; - struct iwl2100_softc *sc = msg->iwlm_softc; - - ASSERT_SERIALIZED(sc->sc_ic.ic_if.if_serializer); - - ieee80211_new_state(&sc->sc_ic, IEEE80211_S_INIT, -1); - iwl2100_hw_stop(sc); - lwkt_replymsg(&nmsg->nm_lmsg, 0); -} - -static void -iwl2100_hw_stop(struct iwl2100_softc *sc) -{ - struct ifnet *ifp = &sc->sc_ic.ic_if; - - ASSERT_SERIALIZED(ifp->if_serializer); - KKASSERT(curthread == &sc->sc_thread); - - callout_stop(&sc->sc_reinit); - - /* Disable interrupts */ - CSR_WRITE_4(sc, IWL2100_INTR_MASK, 0); - - /* - * HW and SW reset - */ - iwl2100_hw_reset(sc); - iwl2100_reset(sc); - - /* - * Free TX/RX rings - */ - iwl2100_free_tx_ring(sc); - iwl2100_free_rx_ring(sc); - - /* NOTE: MUST after iwl2100_free_tx_ring() */ - iwl2100_free_cmd(sc); - - ifp->if_timer = 0; - ifp->if_flags &= ~IFF_RUNNING; - ifq_clr_oactive(&ifp->if_snd); - - sc->sc_tx_timer = 0; - sc->sc_flags &= ~(IWL2100_F_WAITCMD | - IWL2100_F_INITED | - IWL2100_F_SCANNING | - IWL2100_F_RESTARTING | - IWL2100_F_IFSTART | - IWL2100_F_ERROR | - IWL2100_F_ZERO_CMD); -} - -static int -iwl2100_reset(struct iwl2100_softc *sc) -{ - int i; - - /* - * Software reset - */ -#define WAIT_MAX 1000 - - CSR_WRITE_4(sc, IWL2100_RESET, IWL2100_RESET_SW); - for (i = 0; i < WAIT_MAX; ++i) { - DELAY(10); - if (CSR_READ_4(sc, IWL2100_RESET) & IWL2100_RESET_DONE) - break; - } - if (i == WAIT_MAX) { - if_printf(&sc->sc_ic.ic_if, "sw reset timed out\n"); - return ETIMEDOUT; - } - -#undef WAIT_MAX - - /* - * Move to D0 state, wait clock to become stable - */ -#define WAIT_MAX 10000 - - CSR_WRITE_4(sc, IWL2100_CTRL, IWL2100_CTRL_INITDONE); - for (i = 0; i < WAIT_MAX; ++i) { - DELAY(200); - if (CSR_READ_4(sc, IWL2100_CTRL) & IWL2100_CTRL_CLKREADY) - break; - } - if (i == WAIT_MAX) { - if_printf(&sc->sc_ic.ic_if, "can't stablize clock\n"); - return ETIMEDOUT; - } - -#undef WAIT_MAX - - /* - * Move to D0 standby - */ - CSR_SETBITS_4(sc, IWL2100_CTRL, IWL2100_CTRL_STANDBY); - return 0; -} - -static int -iwl2100_dma_alloc(device_t dev) -{ - struct iwl2100_softc *sc = device_get_softc(dev); - struct iwl2100_tx_ring *tr = &sc->sc_txring; - struct iwl2100_rx_ring *rr = &sc->sc_rxring; - int error; - - /* - * Create top level DMA tag - */ - error = bus_dma_tag_create(NULL, 1, 0, - BUS_SPACE_MAXADDR_32BIT, - BUS_SPACE_MAXADDR, - NULL, NULL, - MAXBSIZE, - BUS_SPACE_UNRESTRICTED, - BUS_SPACE_MAXSIZE_32BIT, - 0, &sc->sc_dtag); - if (error) { - device_printf(dev, "can't create DMA tag\n"); - return error; - } - - /* - * Create DMA stuffs for TX desc ring - */ - error = iwl_dma_mem_create(dev, sc->sc_dtag, IWL2100_TXRING_SIZE, - &tr->tr_dtag, (void **)&tr->tr_desc, - &tr->tr_paddr, &tr->tr_dmap); - if (error) { - device_printf(dev, "can't create DMA memory for " - "TX desc ring\n"); - return error; - } - - /* - * Create DMA stuffs for RX desc ring - */ - error = iwl_dma_mem_create(dev, sc->sc_dtag, IWL2100_RXRING_SIZE, - &rr->rr_dtag, (void **)&rr->rr_desc, - &rr->rr_paddr, &rr->rr_dmap); - if (error) { - device_printf(dev, "can't create DMA memory for " - "RX desc ring\n"); - return error; - } - - /* - * Create DMA stuffs for RX status ring - */ - error = iwl_dma_mem_create(dev, sc->sc_dtag, IWL2100_RXSTATUS_SIZE, - &rr->rr_st_dtag, (void **)&rr->rr_status, - &rr->rr_st_paddr, &rr->rr_st_dmap); - if (error) { - device_printf(dev, "can't create DMA memory for " - "RX status ring\n"); - return error; - } - - /* - * Create mbuf DMA stuffs - */ - error = iwl2100_dma_mbuf_create(dev); - if (error) - return error; - - return 0; -} - -static void -iwl2100_dma_free(device_t dev) -{ - struct iwl2100_softc *sc = device_get_softc(dev); - struct iwl2100_tx_ring *tr = &sc->sc_txring; - struct iwl2100_rx_ring *rr = &sc->sc_rxring; - - /* Free DMA stuffs for TX desc ring */ - iwl_dma_mem_destroy(tr->tr_dtag, tr->tr_desc, tr->tr_dmap); - - /* Free DMA stuffs for RX desc ring */ - iwl_dma_mem_destroy(rr->rr_dtag, rr->rr_desc, rr->rr_dmap); - - /* Free DMA stuffs for RX status ring */ - iwl_dma_mem_destroy(rr->rr_st_dtag, rr->rr_status, rr->rr_st_dmap); - - /* Free DMA stuffs for mbufs */ - iwl2100_dma_mbuf_destroy(dev, IWL2100_TX_NDESC, IWL2100_RX_NDESC); - - /* Free top level DMA tag */ - if (sc->sc_dtag != NULL) - bus_dma_tag_destroy(sc->sc_dtag); -} - -static int -iwl2100_dma_mbuf_create(device_t dev) -{ - struct iwl2100_softc *sc = device_get_softc(dev); - struct iwl2100_tx_ring *tr = &sc->sc_txring; - struct iwl2100_rx_ring *rr = &sc->sc_rxring; - int i, error; - - /* - * Create mbuf DMA tag - */ - error = bus_dma_tag_create(sc->sc_dtag, 1, 0, - BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, - NULL, NULL, - MCLBYTES, IWL2100_NSEG_MAX, - BUS_SPACE_MAXSIZE_32BIT, - BUS_DMA_ALLOCNOW, &sc->sc_mbuf_dtag); - if (error) { - device_printf(dev, "can't create mbuf DMA tag\n"); - return error; - } - - /* - * Create spare DMA map for RX mbufs - */ - error = bus_dmamap_create(sc->sc_mbuf_dtag, 0, &rr->rr_tmp_dmap); - if (error) { - device_printf(dev, "can't create spare mbuf DMA map\n"); - bus_dma_tag_destroy(sc->sc_mbuf_dtag); - sc->sc_mbuf_dtag = NULL; - return error; - } - - /* - * Create DMA maps for RX mbufs - */ - for (i = 0; i < IWL2100_RX_NDESC; ++i) { - error = bus_dmamap_create(sc->sc_mbuf_dtag, 0, - &rr->rr_buf[i].rb_dmap); - if (error) { - device_printf(dev, "can't create %d RX mbuf " - "for RX ring\n", i); - iwl2100_dma_mbuf_destroy(dev, 0, i); - return error; - } - } - - /* - * Create DMA maps for TX mbufs - */ - for (i = 0; i < IWL2100_TX_NDESC; ++i) { - error = bus_dmamap_create(sc->sc_mbuf_dtag, 0, - &tr->tr_buf[i].tb_dmap); - if (error) { - device_printf(dev, "can't create %d TX mbuf " - "DMA map\n", i); - iwl2100_dma_mbuf_destroy(dev, i, IWL2100_RX_NDESC); - return error; - } - } - return 0; -} - -static void -iwl2100_dma_mbuf_destroy(device_t dev, int tx_done, int rx_done) -{ - struct iwl2100_softc *sc = device_get_softc(dev); - struct iwl2100_tx_ring *tr = &sc->sc_txring; - struct iwl2100_rx_ring *rr = &sc->sc_rxring; - int i; - - if (sc->sc_mbuf_dtag == NULL) - return; - - /* - * Destroy DMA maps for RX mbufs - */ - for (i = 0; i < rx_done; ++i) { - struct iwl2100_rxbuf *rb = &rr->rr_buf[i]; - - KASSERT(rb->rb_mbuf == NULL, ("RX mbuf is not freed yet")); - bus_dmamap_destroy(sc->sc_mbuf_dtag, rb->rb_dmap); - } - - /* - * Destroy DMA maps for TX mbufs - */ - for (i = 0; i < tx_done; ++i) { - struct iwl2100_txbuf *tb = &tr->tr_buf[i]; - - KASSERT(tb->tb_mbuf == NULL, ("TX mbuf is not freed yet")); - bus_dmamap_destroy(sc->sc_mbuf_dtag, tb->tb_dmap); - } - - /* - * Destroy spare mbuf DMA map - */ - bus_dmamap_destroy(sc->sc_mbuf_dtag, rr->rr_tmp_dmap); - - /* - * Destroy mbuf DMA tag - */ - bus_dma_tag_destroy(sc->sc_mbuf_dtag); - sc->sc_mbuf_dtag = NULL; -} - -static void -iwl2100_init(void *xsc) -{ - struct iwl2100_softc *sc = xsc; - struct iwlmsg msg; - - ASSERT_SERIALIZED(sc->sc_ic.ic_if.if_serializer); - - iwl2100_stop_callouts(sc); - - iwlmsg_init(&msg, &sc->sc_reply_port, iwl2100_init_dispatch, sc); - lwkt_domsg(&sc->sc_thread_port, &msg.iwlm_nmsg.nm_lmsg, 0); -} - -static void -iwl2100_init_dispatch(struct netmsg *nmsg) -{ - struct iwlmsg *msg = (struct iwlmsg *)nmsg; - struct iwl2100_softc *sc = msg->iwlm_softc; - struct ieee80211com *ic = &sc->sc_ic; - struct ifnet *ifp = &ic->ic_if; - int error = 0, flags; - - ASSERT_SERIALIZED(ifp->if_serializer); - - if (sc->sc_flags & IWL2100_F_DETACH) - goto back; - - ieee80211_new_state(ic, IEEE80211_S_INIT, -1); - - if (ic->ic_opmode != IEEE80211_M_MONITOR) { - /* - * XXX - * Workaround for dummy firmware: - * Don't enable hardware too early, since - * once it is enabled, it will start scanning. - */ - flags = 0; - } else { - flags = IWL2100_INIT_F_ENABLE; - } - - /* Always put the device into a known state */ - error = iwl2100_hw_init(sc, NULL, - ic->ic_des_essid, ic->ic_des_esslen, flags); - if (error) - goto back; - - if (sc->sc_flags & IWL2100_F_ZERO_CMD) { - if_printf(ifp, "zero cmd, reinit 1s later\n"); - iwl2100_hw_stop(sc); - - callout_reset(&sc->sc_reinit, hz, iwl2100_reinit_callout, sc); - goto back; - } - - if (ic->ic_opmode != IEEE80211_M_MONITOR) { - if (ic->ic_roaming != IEEE80211_ROAMING_MANUAL) - ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); - } else { - ieee80211_new_state(ic, IEEE80211_S_RUN, -1); - } -back: - if (error) - iwl2100_stop(sc); - lwkt_replymsg(&nmsg->nm_lmsg, error); -} - -static int -iwl2100_ioctl(struct ifnet *ifp, u_long cmd, caddr_t req, struct ucred *cr) -{ - struct iwl2100_softc *sc = ifp->if_softc; - int error = 0; - - ASSERT_SERIALIZED(ifp->if_serializer); - - if (sc->sc_flags & IWL2100_F_DETACH) - return 0; - - switch (cmd) { - case SIOCSIFFLAGS: - if (ifp->if_flags & IFF_UP) { - if ((ifp->if_flags & IFF_RUNNING) == 0) - iwl2100_init(sc); - } else { - if (ifp->if_flags & IFF_RUNNING) { - iwl2100_stop(sc); - } else { - /* - * Stop callouts explicitly, since - * if reinitialization is happening, - * IFF_RUNNING will not be turned on. - */ - iwl2100_stop_callouts(sc); - } - } - break; - default: - error = ieee80211_ioctl(&sc->sc_ic, cmd, req, cr); - break; - } - - if (error == ENETRESET) { - if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == - (IFF_UP | IFF_RUNNING)) - iwl2100_init(sc); - error = 0; - } - return error; -} - -static void -iwl2100_start(struct ifnet *ifp, struct ifaltq_subque *ifsq) -{ - struct iwl2100_softc *sc = ifp->if_softc; - struct ieee80211com *ic = &sc->sc_ic; - struct iwl2100_tx_ring *tr = &sc->sc_txring; - int trans = 0; - - ASSERT_ALTQ_SQ_DEFAULT(ifp, ifsq); - ASSERT_SERIALIZED(ifp->if_serializer); - - if (sc->sc_flags & IWL2100_F_DETACH) { - ieee80211_drain_mgtq(&ic->ic_mgtq); - ifq_purge(&ifp->if_snd); - return; - } - - if ((ifp->if_flags & IFF_RUNNING) == 0 || ifq_is_oactive(&ifp->if_snd)) - return; - - if ((sc->sc_flags & IWL2100_F_IFSTART) == 0) { - ifq_purge(&ifp->if_snd); - goto back; - } - - while (tr->tr_used < IWL2100_TX_USED_MAX) { - struct ieee80211_frame *wh; - struct ieee80211_node *ni; - struct ether_header *eh; - struct mbuf *m; - - m = ifq_dequeue(&ifp->if_snd); - if (m == NULL) - break; - - if (m->m_len < sizeof(*eh)) { - m = m_pullup(m, sizeof(*eh)); - if (m == NULL) { - IFNET_STAT_INC(ifp, oerrors, 1); - continue; - } - } - eh = mtod(m, struct ether_header *); - - ni = ieee80211_find_txnode(ic, eh->ether_dhost); - if (ni == NULL) { - m_freem(m); - IFNET_STAT_INC(ifp, oerrors, 1); - continue; - } - - /* TODO: PS */ - - BPF_MTAP(ifp, m); - - m = ieee80211_encap(ic, m, ni); - if (m == NULL) { - ieee80211_free_node(ni); - IFNET_STAT_INC(ifp, oerrors, 1); - continue; - } - - if (ic->ic_rawbpf != NULL) - bpf_mtap(ic->ic_rawbpf, m); - - wh = mtod(m, struct ieee80211_frame *); - if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { - if (ieee80211_crypto_encap(ic, ni, m) == NULL) { - ieee80211_free_node(ni); - m_freem(m); - IFNET_STAT_INC(ifp, oerrors, 1); - continue; - } - } - - /* - * TX radio tap - */ - if (sc->sc_drvbpf != NULL) { - if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) - sc->sc_tx_th.wt_flags = IEEE80211_RADIOTAP_F_WEP; - else - sc->sc_tx_th.wt_flags = 0; - bpf_ptap(sc->sc_drvbpf, m, &sc->sc_tx_th, - sc->sc_tx_th_len); - } - wh = NULL; /* Catch any invalid use */ - - ieee80211_free_node(ni); - - if (iwl2100_encap(sc, m)) { - IFNET_STAT_INC(ifp, oerrors, 1); - continue; - } - - IFNET_STAT_INC(ifp, opackets, 1); - trans = 1; - } - - if (tr->tr_used >= IWL2100_TX_USED_MAX) - ifq_set_oactive(&ifp->if_snd); - - if (trans) { - bus_dmamap_sync(tr->tr_dtag, tr->tr_dmap, BUS_DMASYNC_PREWRITE); - CSR_WRITE_4(sc, IWL2100_TXQ_WRITE_IDX, tr->tr_index); - sc->sc_tx_timer = 5; - } -back: - ieee80211_drain_mgtq(&ic->ic_mgtq); - ifp->if_timer = 1; -} - -static void -iwl2100_watchdog(struct ifnet *ifp) -{ - struct iwl2100_softc *sc = ifp->if_softc; - - ASSERT_SERIALIZED(ifp->if_serializer); - - if (sc->sc_flags & IWL2100_F_DETACH) - return; - - if (sc->sc_tx_timer) { - if (--sc->sc_tx_timer == 0) { - if_printf(ifp, "watchdog timeout!\n"); - IFNET_STAT_INC(ifp, oerrors, 1); - iwl2100_restart(sc); - return; - } else { - ifp->if_timer = 1; - } - } - ieee80211_watchdog(&sc->sc_ic); -} - -static int -iwl2100_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg) -{ - struct ifnet *ifp = &ic->ic_if; - struct iwl2100_softc *sc = ifp->if_softc; - struct iwlmsg msg; - - ASSERT_SERIALIZED(ifp->if_serializer); - - iwlmsg_init(&msg, &sc->sc_reply_port, iwl2100_newstate_dispatch, sc); - msg.iwlm_nstate = nstate; - msg.iwlm_arg = arg; - - return lwkt_domsg(&sc->sc_thread_port, &msg.iwlm_nmsg.nm_lmsg, 0); -} - -static void -iwl2100_newstate_dispatch(struct netmsg *nmsg) -{ - struct iwlmsg *msg = (struct iwlmsg *)nmsg; - struct iwl2100_softc *sc = msg->iwlm_softc; - struct ieee80211com *ic = &sc->sc_ic; -#ifdef INVARIANTS - struct ifnet *ifp = &ic->ic_if; -#endif - enum ieee80211_state nstate, ostate; - int arg = msg->iwlm_arg, error = 0; - - ASSERT_SERIALIZED(ifp->if_serializer); - - nstate = msg->iwlm_nstate; - ostate = ic->ic_state; - - sc->sc_flags &= ~IWL2100_F_IFSTART; - sc->sc_state_age++; - - iwl2100_chan_change(sc, ic->ic_curchan); - - callout_stop(&sc->sc_ibss); - iwl2100_restart_done(sc); - - if (nstate == IEEE80211_S_INIT) - goto back; - - if (sc->sc_flags & IWL2100_F_DETACH) { - /* - * Except for INIT, we skip rest of the - * state changes during detaching - */ - goto reply; - } - - if (ic->ic_opmode == IEEE80211_M_STA) { - if (nstate == IEEE80211_S_AUTH) - error = iwl2100_auth(sc); - else if (nstate == IEEE80211_S_RUN) - sc->sc_flags |= IWL2100_F_IFSTART; - } else if (ic->ic_opmode == IEEE80211_M_IBSS) { - if (nstate == IEEE80211_S_RUN) { - DPRINTF(sc, IWL2100_DBG_IBSS, "%s", - "start/join ibss\n"); - - /* - * IWL2100_F_IFSTART can't be turned on - * until BSSID generated by the firmware - * is extracted. - * - * XXX only if we started the IBSS - */ - error = iwl2100_ibss(sc); - } - } -back: - if (!error) - error = sc->sc_newstate(ic, nstate, arg); - - if (!error) { - if (ic->ic_opmode != IEEE80211_M_MONITOR) { - /* - * Don't use 'nstate' here, since for IBSS - * mode 802.11 layer may enter RUN state in - * a recursive manner, i.e. when we reach - * here, nstate != ic->ic_state - */ - if (ic->ic_state == IEEE80211_S_SCAN && - ic->ic_state != ostate) { - DPRINTF(sc, IWL2100_DBG_SCAN, "%s", - "start scan\n"); - error = iwl2100_scan(sc); - } - } - } -reply: - lwkt_replymsg(&nmsg->nm_lmsg, error); -} - -static int -iwl2100_media_change(struct ifnet *ifp) -{ - int error; - - ASSERT_SERIALIZED(ifp->if_serializer); - - error = ieee80211_media_change(ifp); - if (error != ENETRESET) - return error; - - if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING)) - iwl2100_init(ifp->if_softc); - return 0; -} - -static void -iwl2100_media_status(struct ifnet *ifp, struct ifmediareq *imr) -{ - struct iwl2100_softc *sc = ifp->if_softc; - - if (sc->sc_flags & IWL2100_F_IFSTART) { - struct ieee80211_node *ni = sc->sc_ic.ic_bss; - uint32_t txrate; - int i, nrates = 4; - - txrate = iwl2100_read_ord1(sc, IWL2100_ORD1_TXRATE) & 0xf; - if (ni->ni_rates.rs_nrates < 4) - nrates = ni->ni_rates.rs_nrates; - - for (i = 0; i < nrates; ++i) { - if ((1 << i) & txrate) - ni->ni_txrate = i; - } - } - ieee80211_media_status(ifp, imr); -} - -static void -iwl2100_intr(void *xsc) -{ - struct iwl2100_softc *sc = xsc; - struct ifnet *ifp = &sc->sc_ic.ic_if; - uint32_t intr_status; - - ASSERT_SERIALIZED(ifp->if_serializer); - - if ((sc->sc_flags & IWL2100_F_INITED) == 0) - return; - - intr_status = CSR_READ_4(sc, IWL2100_INTR_STATUS); - if (intr_status == 0xffffffff) /* not for us */ - return; - - if ((intr_status & IWL2100_INTRS) == 0) /* not interested */ - return; - - sc->sc_flags |= IWL2100_F_IN_INTR; - - /* Disable interrupts */ - CSR_WRITE_4(sc, IWL2100_INTR_MASK, 0); - - if (intr_status & IWL2100_INTR_EFATAL) { - uint32_t error_info; - - if_printf(ifp, "intr fatal error\n"); - CSR_WRITE_4(sc, IWL2100_INTR_STATUS, IWL2100_INTR_EFATAL); - - error_info = IND_READ_4(sc, IWL2100_IND_ERROR_INFO); - IND_READ_4(sc, error_info & IWL2100_IND_ERRORADDR_MASK); - - callout_stop(&sc->sc_reinit); - iwl2100_reinit(sc); - - /* Leave interrupts disabled */ - goto back; - } - - if (intr_status & IWL2100_INTR_EPARITY) { - if_printf(ifp, "intr parity error\n"); - CSR_WRITE_4(sc, IWL2100_INTR_STATUS, IWL2100_INTR_EPARITY); - } - - if (intr_status & IWL2100_INTR_RX) { - CSR_WRITE_4(sc, IWL2100_INTR_STATUS, IWL2100_INTR_RX); - iwl2100_rxeof(sc); - iwl2100_txeof(sc); - } - - if (intr_status & IWL2100_INTR_TX) { - CSR_WRITE_4(sc, IWL2100_INTR_STATUS, IWL2100_INTR_TX); - iwl2100_txeof(sc); - } - - if (intr_status & IWL2100_INTR_FW_INITED) - CSR_WRITE_4(sc, IWL2100_INTR_STATUS, IWL2100_INTR_FW_INITED); - if (intr_status & IWL2100_INTR_CMD_DONE) - CSR_WRITE_4(sc, IWL2100_INTR_STATUS, IWL2100_INTR_CMD_DONE); - - /* Enable interrupts */ - CSR_WRITE_4(sc, IWL2100_INTR_MASK, IWL2100_INTRS); -back: - sc->sc_flags &= ~IWL2100_F_IN_INTR; -} - -static int -iwl2100_hw_reset(struct iwl2100_softc *sc) -{ - int i; - - /* - * Initialize GPIO: - * - Enable GPIO3 - * - Make GPIO3 firmware writable - * - Enable GPIO1 - * - Turn off LED - */ - CSR_WRITE_4(sc, IWL2100_GPIO, - IWL2100_GPIO_3_EN | IWL2100_GPIO_3_FWWR | - IWL2100_GPIO_1_EN | IWL2100_GPIO_LEDOFF); - - /* - * Stop master - */ -#define WAIT_MAX 5 - - CSR_WRITE_4(sc, IWL2100_RESET, IWL2100_RESET_STOP_MASTER); - for (i = 0; i < WAIT_MAX; ++i) { - DELAY(10); - - if (CSR_READ_4(sc, IWL2100_RESET) & - IWL2100_RESET_MASTER_STOPPED) - break; - } - if (i == WAIT_MAX) { - if_printf(&sc->sc_ic.ic_if, "can't stop master\n"); - return ETIMEDOUT; - } - -#undef WAIT_MAX - - CSR_WRITE_4(sc, IWL2100_RESET, IWL2100_RESET_SW); - return 0; -} - -static int -iwl2100_alloc_firmware(struct iwl2100_softc *sc, enum ieee80211_opmode opmode) -{ - struct { - const char *suffix; - uint16_t mode; - enum ieee80211_opmode opmode; - struct iwl2100_firmware *fw; - } fw_arr[] = { - { "", IWL2100_FW_M_STA, IEEE80211_M_STA, - &sc->sc_fw_sta }, - { "-i", IWL2100_FW_M_IBSS, IEEE80211_M_IBSS, - &sc->sc_fw_ibss }, - { "-p", IWL2100_FW_M_MONITOR, IEEE80211_M_MONITOR, - &sc->sc_fw_monitor }, - { NULL, 0, 0, NULL } - }; - struct ifnet *ifp = &sc->sc_ic.ic_if; - const struct iwl2100_fwimg_hdr *hdr; - struct iwl2100_firmware *fw = NULL; - struct fw_image *image; - char filename[128]; - int i, error; - - for (i = 0; fw_arr[i].fw != NULL; ++i) { - fw = fw_arr[i].fw; - - if (fw_arr[i].opmode == opmode) { - if (fw->fw_image != NULL) - return 0; - else - break; - } - } - KASSERT(fw_arr[i].fw != NULL, ("unsupported opmode %u", opmode)); - - ksnprintf(filename, sizeof(filename), IWL2100_FW_PATH, - fw_arr[i].suffix); - - /* - * Release the serializer to avoid possible dead lock - */ - lwkt_serialize_exit(ifp->if_serializer); - image = firmware_image_load(filename, NULL); - lwkt_serialize_enter(ifp->if_serializer); - - if (image == NULL) - return ENOENT; - fw->fw_image = image; - - /* - * Verify the image - */ - error = EINVAL; - - hdr = (const struct iwl2100_fwimg_hdr *)image->fw_image; - if ((hdr->version & 0xff) != 1) { - if_printf(ifp, "%s unsupported firmware version %d", - image->fw_name, hdr->version & 0xff); - goto back; - } - - if (hdr->mode != fw_arr[i].mode) { - if_printf(ifp, "%s contains %d mode firmware, should be %d\n", - image->fw_name, hdr->mode, fw_arr[i].mode); - goto back; - } - - if (hdr->data_size + hdr->ucode_size + sizeof(*hdr) != - image->fw_imglen) { - if_printf(ifp, - "%s size mismatch, %zu/hdr %zu\n", - image->fw_name, fw->fw_image->fw_imglen, - hdr->data_size + hdr->ucode_size + sizeof(*hdr)); - goto back; - } - - fw->fw_data = (const uint8_t *)(hdr + 1); - fw->fw_data_size = hdr->data_size; - fw->fw_ucode = fw->fw_data + fw->fw_data_size; - fw->fw_ucode_size = hdr->ucode_size; - error = 0; -back: - if (error) { - firmware_image_unload(fw->fw_image); - bzero(fw, sizeof(*fw)); - } - return error; -} - -static void -iwl2100_free_firmware(struct iwl2100_softc *sc) -{ - struct iwl2100_firmware *fw_arr[] = - { &sc->sc_fw_sta, &sc->sc_fw_ibss, &sc->sc_fw_monitor, NULL }; - int i; - - for (i = 0; fw_arr[i] != NULL; ++i) { - struct iwl2100_firmware *fw = fw_arr[i]; - - if (fw->fw_image != NULL) { - firmware_image_unload(fw->fw_image); - bzero(fw, sizeof(*fw)); - } - } -} - -static int -iwl2100_load_firmware(struct iwl2100_softc *sc, enum ieee80211_opmode opmode) -{ - static const struct { - uint32_t addr; - int size; - } share_mem[] = { - { IWL2100_SHMEM0, IWL2100_SHMEM0_SIZE }, - { IWL2100_SHMEM1, IWL2100_SHMEM1_SIZE }, - { IWL2100_SHMEM2, IWL2100_SHMEM2_SIZE }, - { IWL2100_SHMEM3, IWL2100_SHMEM3_SIZE }, - { IWL2100_SHMEM_INTR, IWL2100_SHMEM_INTR_SIZE }, - { 0, 0 } - }; - const struct iwl2100_firmware *fw = NULL; - int i, error; - - /* - * Pick up the firmware image corresponding to - * the current operation mode - */ - switch (opmode) { - case IEEE80211_M_STA: - fw = &sc->sc_fw_sta; - break; - case IEEE80211_M_IBSS: - fw = &sc->sc_fw_ibss; - break; - case IEEE80211_M_MONITOR: - fw = &sc->sc_fw_monitor; - break; - default: - panic("unsupported opmode %d", opmode); - break; - } - KASSERT(fw->fw_image != NULL, - ("opmode %d firmware image is not allocated yet\n", opmode)); - - /* Load ucode */ - error = iwl2100_load_fw_ucode(sc, fw); - if (error) - return error; - - /* SW reset */ - error = iwl2100_reset(sc); - if (error) - return error; - - /* Load data */ - error = iwl2100_load_fw_data(sc, fw); - if (error) - return error; - - /* Clear shared memory */ - for (i = 0; share_mem[i].size != 0; ++i) { - uint32_t addr = share_mem[i].addr; - int j; - - for (j = 0; j < share_mem[i].size; j += 4) - IND_WRITE_4(sc, addr + j, 0); - } - - return 0; -} - -#define IND_WRITE_FLUSH_2(sc, reg, val) \ -do { \ - IND_WRITE_2((sc), (reg), (val)); \ - CSR_READ_4((sc), 0); \ -} while (0) - -#define IND_WRITE_FLUSH_1(sc, reg, val) \ -do { \ - IND_WRITE_1((sc), (reg), (val)); \ - CSR_READ_4((sc), 0); \ -} while (0) - -/* XXX need more comment */ -static int -iwl2100_load_fw_ucode(struct iwl2100_softc *sc, - const struct iwl2100_firmware *fw) -{ - struct iwl2100_ucode_resp resp; - const uint8_t *p; - int i; - - /* Hold ARC */ - IND_WRITE_4(sc, IWL2100_IND_HALT, IWL2100_IND_HALT_HOLD); - - /* Allow ARC to run */ - CSR_WRITE_4(sc, IWL2100_RESET, 0); - - IND_WRITE_FLUSH_2(sc, IWL2100_IND_CTRL, 0x703); - IND_WRITE_FLUSH_2(sc, IWL2100_IND_CTRL, 0x707); - - IND_WRITE_FLUSH_1(sc, 0x210014, 0x72); - IND_WRITE_FLUSH_1(sc, 0x210014, 0x72); - - IND_WRITE_FLUSH_1(sc, 0x210000, 0x40); - IND_WRITE_FLUSH_1(sc, 0x210000, 0); - IND_WRITE_FLUSH_1(sc, 0x210000, 0x40); - - p = fw->fw_ucode; - for (i = 0; i < fw->fw_ucode_size; ++i, ++p) - IND_WRITE_1(sc, 0x210010, *p); - - IND_WRITE_FLUSH_1(sc, 0x210000, 0); - IND_WRITE_FLUSH_1(sc, 0x210000, 0); - IND_WRITE_FLUSH_1(sc, 0x210000, 0x80); - - - IND_WRITE_FLUSH_2(sc, IWL2100_IND_CTRL, 0x703); - IND_WRITE_FLUSH_2(sc, IWL2100_IND_CTRL, 0x707); - - IND_WRITE_FLUSH_1(sc, 0x210014, 0x72); - IND_WRITE_FLUSH_1(sc, 0x210014, 0x72); - - IND_WRITE_FLUSH_1(sc, 0x210000, 0); - IND_WRITE_1(sc, 0x210000, 0x80); - -#define WAIT_MAX 10 - for (i = 0; i < WAIT_MAX; ++i) { - DELAY(10); - - if (IND_READ_1(sc, 0x210000) & 0x1) - break; - } - if (i == WAIT_MAX) { - if_printf(&sc->sc_ic.ic_if, - "wait ucode symbol init timed out\n"); - return ETIMEDOUT; - } -#undef WAIT_MAX - -#define WAIT_MAX 30 - for (i = 0; i < WAIT_MAX; ++i) { - uint16_t *r = (uint16_t *)&resp; - int j; - - for (j = 0; j < sizeof(resp) / 2; ++j, ++r) - *r = IND_READ_2(sc, 0x210004); - - if (resp.cmd_id == 1 && resp.ucode_valid == 1) - break; - DELAY(10); - } - if (i == WAIT_MAX) { - if_printf(&sc->sc_ic.ic_if, - "wait ucode response timed out\n"); - return ETIMEDOUT; - } -#undef WAIT_MAX - - /* Release ARC */ - IND_WRITE_4(sc, IWL2100_IND_HALT, 0); - - if (bootverbose) { - if_printf(&sc->sc_ic.ic_if, "ucode rev.%d date %d.%d.20%02d " - "time %02d:%02d\n", resp.ucode_rev, - resp.date_time[0], resp.date_time[1], - resp.date_time[2], resp.date_time[3], - resp.date_time[4]); - } - - return 0; -} - -#undef IND_WRITE_FLUSH_1 -#undef IND_WRITE_FLUSH_2 - -static int -iwl2100_load_fw_data(struct iwl2100_softc *sc, - const struct iwl2100_firmware *fw) -{ - const uint8_t *p = fw->fw_data; - int w = 0; - - while (w < fw->fw_data_size) { - const struct iwl2100_fwdata_hdr *h; - int hlen, i; - - h = (const struct iwl2100_fwdata_hdr *)p; - if (h->len > 32 || h->len == 0) { - if_printf(&sc->sc_ic.ic_if, - "firmware image data corrupted\n"); - return EINVAL; - } - if ((h->addr & 0x3) || (h->len & 0x3)) { - if_printf(&sc->sc_ic.ic_if, - "firmware image data with unaligned " - "address %#x or length %#x\n", - h->addr, h->len); - return EOPNOTSUPP; - } - - hlen = sizeof(*h) + h->len - 1; - if (w + hlen > fw->fw_data_size) { - if_printf(&sc->sc_ic.ic_if, - "firmware image data size mismatch\n"); - return EINVAL; - } - - CSR_WRITE_4(sc, IWL2100_AUTOINC_ADDR, h->addr); - for (i = 0; i < h->len; i += 4) { - CSR_WRITE_4(sc, IWL2100_AUTOINC_DATA, - *(const uint32_t *)&h->data[i]); - } - - p += hlen; - w += hlen; - } - KKASSERT(w == fw->fw_data_size); - - return 0; -} - -static void -iwl2100_free_tx_ring(struct iwl2100_softc *sc) -{ - struct iwl2100_tx_ring *tr = &sc->sc_txring; - int i; - - for (i = 0; i < IWL2100_TX_NDESC; ++i) { - struct iwl2100_txbuf *tb = &tr->tr_buf[i]; - - if (tb->tb_mbuf != NULL) { - bus_dmamap_unload(sc->sc_mbuf_dtag, tb->tb_dmap); - if (tb->tb_flags & IWL2100_TBF_CMDBUF) { - KKASSERT(tb->tb_mbuf == sc->sc_cmd); - tb->tb_flags &= ~IWL2100_TBF_CMDBUF; - } else { - m_freem(tb->tb_mbuf); - } - tb->tb_mbuf = NULL; - } - } - - bzero(tr->tr_desc, IWL2100_TXRING_SIZE); - bus_dmamap_sync(tr->tr_dtag, tr->tr_dmap, BUS_DMASYNC_PREWRITE); - - tr->tr_used = 0; - tr->tr_index = 0; - tr->tr_coll = 0; -} - -static void -iwl2100_free_rx_ring(struct iwl2100_softc *sc) -{ - struct iwl2100_rx_ring *rr = &sc->sc_rxring; - int i; - - for (i = 0; i < IWL2100_RX_NDESC; ++i) { - struct iwl2100_rxbuf *rb = &rr->rr_buf[i]; - - if (rb->rb_mbuf != NULL) { - bus_dmamap_unload(sc->sc_mbuf_dtag, rb->rb_dmap); - m_freem(rb->rb_mbuf); - rb->rb_mbuf = NULL; - } - } - - bzero(rr->rr_desc, IWL2100_RXRING_SIZE); - bus_dmamap_sync(rr->rr_dtag, rr->rr_dmap, BUS_DMASYNC_PREWRITE); - - bzero(rr->rr_status, IWL2100_RXSTATUS_SIZE); - bus_dmamap_sync(rr->rr_st_dtag, rr->rr_st_dmap, BUS_DMASYNC_PREWRITE); - - rr->rr_index = 0; -} - -static void -iwl2100_free_cmd(struct iwl2100_softc *sc) -{ - if (sc->sc_cmd != NULL) { - m_freem(sc->sc_cmd); - sc->sc_cmd = NULL; - } -} - -static int -iwl2100_init_tx_ring(struct iwl2100_softc *sc) -{ - struct iwl2100_tx_ring *tr = &sc->sc_txring; - - tr->tr_used = 0; - tr->tr_index = 0; - tr->tr_coll = 0; - - bzero(tr->tr_desc, IWL2100_TXRING_SIZE); - bus_dmamap_sync(tr->tr_dtag, tr->tr_dmap, BUS_DMASYNC_PREWRITE); - - CSR_WRITE_4(sc, IWL2100_TXQ_ADDR, tr->tr_paddr); - CSR_WRITE_4(sc, IWL2100_TXQ_SIZE, IWL2100_TX_NDESC); - CSR_WRITE_4(sc, IWL2100_TXQ_READ_IDX, 0); - CSR_WRITE_4(sc, IWL2100_TXQ_WRITE_IDX, tr->tr_index); - - return 0; -} - -static int -iwl2100_init_rx_ring(struct iwl2100_softc *sc) -{ - struct iwl2100_rx_ring *rr = &sc->sc_rxring; - int i, error; - - for (i = 0; i < IWL2100_RX_NDESC; ++i) { - error = iwl2100_newbuf(sc, i, 1); - if (error) - return error; - } - bus_dmamap_sync(rr->rr_st_dtag, rr->rr_st_dmap, BUS_DMASYNC_PREWRITE); - bus_dmamap_sync(rr->rr_dtag, rr->rr_dmap, BUS_DMASYNC_PREWRITE); - - rr->rr_index = IWL2100_RX_NDESC - 1; - - CSR_WRITE_4(sc, IWL2100_RXQ_ADDR, rr->rr_paddr); - CSR_WRITE_4(sc, IWL2100_RXQ_SIZE, IWL2100_RX_NDESC); - CSR_WRITE_4(sc, IWL2100_RXQ_READ_IDX, 0); - CSR_WRITE_4(sc, IWL2100_RXQ_WRITE_IDX, rr->rr_index); - - CSR_WRITE_4(sc, IWL2100_RX_STATUS_ADDR, rr->rr_st_paddr); - - return 0; -} - -static int -iwl2100_alloc_cmd(struct iwl2100_softc *sc) -{ - KKASSERT(sc->sc_cmd == NULL); - - sc->sc_cmd = m_getcl(M_WAITOK, MT_DATA, M_PKTHDR); - if (sc->sc_cmd == NULL) - return ENOBUFS; - return 0; -} - -static int -iwl2100_newbuf(struct iwl2100_softc *sc, int buf_idx, int init) -{ - struct iwl2100_rx_ring *rr = &sc->sc_rxring; - struct iwl2100_rxbuf *rb; - struct iwl_dmamap_ctx ctx; - bus_dma_segment_t seg; - bus_dmamap_t dmap; - struct mbuf *m; - int error; - - KKASSERT(buf_idx < IWL2100_RX_NDESC); - rb = &rr->rr_buf[buf_idx]; - - m = m_getcl(init ? M_WAITOK : M_NOWAIT, MT_DATA, M_PKTHDR); - if (m == NULL) { - error = ENOBUFS; - - if (init) { - if_printf(&sc->sc_ic.ic_if, "m_getcl failed\n"); - return error; - } else { - goto back; - } - } - m->m_len = m->m_pkthdr.len = MCLBYTES; - - /* - * Try load RX mbuf into temporary DMA map - */ - ctx.nsegs = 1; - ctx.segs = &seg; - error = bus_dmamap_load_mbuf(sc->sc_mbuf_dtag, rr->rr_tmp_dmap, m, - iwl_dma_buf_addr, &ctx, - init ? BUS_DMA_WAITOK : BUS_DMA_NOWAIT); - if (error || ctx.nsegs == 0) { - if (!error) { - bus_dmamap_unload(sc->sc_mbuf_dtag, rr->rr_tmp_dmap); - error = EFBIG; - if_printf(&sc->sc_ic.ic_if, "too many segments?!\n"); - } - m_freem(m); - - if (init) { - if_printf(&sc->sc_ic.ic_if, "can't load RX mbuf\n"); - return error; - } else { - goto back; - } - } - - if (!init) - bus_dmamap_unload(sc->sc_mbuf_dtag, rb->rb_dmap); - rb->rb_mbuf = m; - rb->rb_paddr = seg.ds_addr; - - /* - * Swap RX buf's DMA map with the loaded temporary one - */ - dmap = rb->rb_dmap; - rb->rb_dmap = rr->rr_tmp_dmap; - rr->rr_tmp_dmap = dmap; - - error = 0; -back: - iwl2100_rxdesc_setup(sc, buf_idx); - return error; -} - -static void -iwl2100_rxdesc_setup(struct iwl2100_softc *sc, int buf_idx) -{ - struct iwl2100_rx_ring *rr = &sc->sc_rxring; - struct iwl2100_rxbuf *rb; - struct iwl2100_desc *d; - struct iwl2100_rx_status *st; - - KKASSERT(buf_idx < IWL2100_RX_NDESC); - rb = &rr->rr_buf[buf_idx]; - - st = &rr->rr_status[buf_idx]; - bzero(st, sizeof(*st)); - - d = &rr->rr_desc[buf_idx]; - bzero(d, sizeof(*d)); - d->d_paddr = rb->rb_paddr; - d->d_len = MCLBYTES; -} - -static int -iwl2100_init_firmware(struct iwl2100_softc *sc) -{ -#ifdef INVARIANTS - struct ifnet *ifp = &sc->sc_ic.ic_if; -#endif - uint32_t intr; - int i; - - ASSERT_SERIALIZED(ifp->if_serializer); - - CSR_WRITE_4(sc, IWL2100_GPIO, - IWL2100_GPIO_3_EN | IWL2100_GPIO_3_FWWR | - IWL2100_GPIO_1_EN | IWL2100_GPIO_LEDOFF); - CSR_WRITE_4(sc, IWL2100_RESET, 0); - - /* - * Wait for firmware to be initialized - */ -#define WAIT_MAX 5000 - - for (i = 0; i < WAIT_MAX; ++i) { - DELAY(8000); - - intr = CSR_READ_4(sc, IWL2100_INTR_STATUS); - if (intr & IWL2100_INTR_FW_INITED) { - CSR_WRITE_4(sc, IWL2100_INTR_STATUS, - IWL2100_INTR_FW_INITED); - break; - } - if (intr & (IWL2100_INTR_EFATAL | IWL2100_INTR_EPARITY)) { - CSR_WRITE_4(sc, IWL2100_INTR_STATUS, - IWL2100_INTR_EFATAL | IWL2100_INTR_EPARITY); - } - } - - intr = CSR_READ_4(sc, IWL2100_INTR_STATUS) & IWL2100_INTRS; - if (intr & CSR_READ_4(sc, IWL2100_INTR_MASK)) - CSR_WRITE_4(sc, IWL2100_INTR_STATUS, intr); - - if (i == WAIT_MAX) { - if_printf(&sc->sc_ic.ic_if, - "firmware initialization timed out\n"); - return ETIMEDOUT; - } - -#undef WAIT_MAX - - /* Enable GPIO1/3 and allow firmware to write to them */ - CSR_SETBITS_4(sc, IWL2100_GPIO, - IWL2100_GPIO_1_EN | IWL2100_GPIO_1_FWWR | - IWL2100_GPIO_3_EN | IWL2100_GPIO_3_FWWR); - return 0; -} - -static int -iwl2100_read_ord2(struct iwl2100_softc *sc, uint32_t ofs, void *buf0, int buflen) -{ - uint8_t *buf = buf0; - uint32_t addr, info; - int i, len, ret; - -#define IND_ALIGN 4 -#define IND_ALIGN_MASK 0x3 - - addr = IND_READ_4(sc, sc->sc_ord2 + (ofs << 3)); - info = IND_READ_4(sc, sc->sc_ord2 + (ofs << 3) + sizeof(addr)); - - len = info & 0xffff; - i = info >> 16; - - if ((len * i) < buflen) - buflen = len * i; - ret = buflen; - - i = addr & IND_ALIGN_MASK; - addr &= ~IND_ALIGN_MASK; - if (i) { - int lim, r; - - KKASSERT(i < IND_ALIGN); - if (buflen + i < IND_ALIGN) - lim = buflen + i; - else - lim = IND_ALIGN; - r = lim - i; - - CSR_WRITE_4(sc, IWL2100_IND_ADDR, addr); - for (; i < lim; ++i, ++buf) - *buf = CSR_READ_1(sc, IWL2100_IND_DATA + i); - - KKASSERT(buflen >= r); - buflen -= r; - if (buflen == 0) - goto back; - - addr += IND_ALIGN; - } - - len = buflen & ~IND_ALIGN_MASK; - buflen &= IND_ALIGN_MASK; - - if (len) { - CSR_WRITE_4(sc, IWL2100_AUTOINC_ADDR, addr); - for (i = 0; i < len; i += 4, addr += 4, buf += 4) { - *((uint32_t *)buf) = - CSR_READ_4(sc, IWL2100_AUTOINC_DATA); - } - } - if (buflen) { - CSR_WRITE_4(sc, IWL2100_IND_ADDR, addr); - for (i = 0; i < buflen; ++i, ++buf) - *buf = CSR_READ_1(sc, IWL2100_IND_DATA + i); - } -back: - return ret; - -#undef IND_ALIGN -#undef IND_ALIGN_MASK -} - -static uint32_t -iwl2100_read_ord1(struct iwl2100_softc *sc, uint32_t ofs) -{ - uint32_t addr; - - addr = IND_READ_4(sc, sc->sc_ord1 + (ofs << 2)); - return IND_READ_4(sc, addr); -} - -static void -iwl2100_write_ord1(struct iwl2100_softc *sc, uint32_t ofs, uint32_t val) -{ - uint32_t addr; - - addr = IND_READ_4(sc, sc->sc_ord1 + (ofs << 2)); - IND_WRITE_4(sc, addr, val); -} - -static int -iwl2100_rfkilled(struct iwl2100_softc *sc) -{ - int i; - - if ((sc->sc_caps & IWL2100_C_RFKILL) == 0) - return 0; - -#define TEST_MAX 5 - - for (i = 0; i < TEST_MAX; ++i) { - DELAY(40); - - if (CSR_READ_4(sc, IWL2100_GPIO) & IWL2100_GPIO_RFKILLED) - break; - } - if (i != TEST_MAX) { - if_printf(&sc->sc_ic.ic_if, "RF killed\n"); - return 1; - } - -#undef TEST_MAX - - return 0; -} - -static int -iwl2100_set_addr(struct iwl2100_softc *sc, const uint8_t *eaddr) -{ - struct iwl2100_cmd *cmd; - int error; - - if (sc->sc_flags & IWL2100_F_WAITCMD) { - if_printf(&sc->sc_ic.ic_if, "there is command pending\n"); - return EEXIST; - } - - cmd = mtod(sc->sc_cmd, struct iwl2100_cmd *); - bzero(cmd, sizeof(*cmd)); - - cmd->c_cmd = IWL2100_CMD_SET_ADDR; - cmd->c_param_len = IEEE80211_ADDR_LEN; - IEEE80211_ADDR_COPY(cmd->c_param, eaddr); - - error = iwl2100_wait_cmd(sc); - if (error) { - if_printf(&sc->sc_ic.ic_if, "%s failed\n", __func__); - return error; - } - return 0; -} - -static int -iwl2100_set_opmode(struct iwl2100_softc *sc, enum ieee80211_opmode opmode) -{ - struct iwl2100_cmd *cmd; - int error; - - if (sc->sc_flags & IWL2100_F_WAITCMD) { - if_printf(&sc->sc_ic.ic_if, "there is command pending\n"); - return EEXIST; - } - - cmd = mtod(sc->sc_cmd, struct iwl2100_cmd *); - bzero(cmd, sizeof(*cmd)); - - cmd->c_cmd = IWL2100_CMD_SET_OPMODE; - cmd->c_param_len = sizeof(cmd->c_param[0]); - switch (opmode) { - case IEEE80211_M_STA: - cmd->c_param[0] = IWL2100_OPMODE_STA; - break; - case IEEE80211_M_IBSS: - cmd->c_param[0] = IWL2100_OPMODE_IBSS; - break; - case IEEE80211_M_MONITOR: - /* YYY ipw2100 leave this unset */ - cmd->c_param[0] = IWL2100_OPMODE_MONITOR; - break; - default: - panic("unsupported opmode %d", opmode); - break; - } - - error = iwl2100_wait_cmd(sc); - if (error) { - if_printf(&sc->sc_ic.ic_if, "%s failed\n", __func__); - return error; - } - return 0; -} - -static int -iwl2100_set_80211(struct iwl2100_softc *sc) -{ - struct ieee80211com *ic = &sc->sc_ic; - struct iwl2100_cmd *cmd; - int error; - - if (sc->sc_flags & IWL2100_F_WAITCMD) { - if_printf(&ic->ic_if, "there is command pending\n"); - return EEXIST; - } - - cmd = mtod(sc->sc_cmd, struct iwl2100_cmd *); - bzero(cmd, sizeof(*cmd)); - - cmd->c_cmd = IWL2100_CMD_SET_80211; - cmd->c_param_len = sizeof(cmd->c_param[0]) * 3; - cmd->c_param[0] = IWL2100_CFG_IBSS | IWL2100_CFG_STA | - IWL2100_CFG_8021X | IWL2100_CFG_AUTO_PREAMBLE; - if (ic->ic_opmode == IEEE80211_M_IBSS) - cmd->c_param[0] |= IWL2100_CFG_IBSS_AUTO_START; - else if (ic->ic_opmode == IEEE80211_M_MONITOR) /* YYY not ipw2100 */ - cmd->c_param[0] |= IWL2100_CFG_MONITOR; - cmd->c_param[1] = IWL2100_CFG_CHANMASK; /* XXX sc->sc_bss_chans */ - cmd->c_param[2] = IWL2100_CFG_CHANMASK; /* YYY sc->sc_ibss_chans */ - - error = iwl2100_wait_cmd(sc); - if (error) { - if_printf(&ic->ic_if, "%s failed\n", __func__); - return error; - } - return 0; -} - -static int -iwl2100_set_basicrates(struct iwl2100_softc *sc) -{ - struct iwl2100_cmd *cmd; - int error; - - if (sc->sc_flags & IWL2100_F_WAITCMD) { - if_printf(&sc->sc_ic.ic_if, "there is command pending\n"); - return EEXIST; - } - - cmd = mtod(sc->sc_cmd, struct iwl2100_cmd *); - bzero(cmd, sizeof(*cmd)); - - /* - * This configuration does not seem to have any effects - * on probe-req and assoc-req frames. - */ - cmd->c_cmd = IWL2100_CMD_SET_BASICRATES; - cmd->c_param_len = sizeof(cmd->c_param[0]); - cmd->c_param[0] = 0x3; /* 1Mbps and 2Mbps. XXX from caller */ - - error = iwl2100_wait_cmd(sc); - if (error) { - if_printf(&sc->sc_ic.ic_if, "%s failed\n", __func__); - return error; - } - return 0; -} - -static int -iwl2100_set_txrates(struct iwl2100_softc *sc) -{ - struct ieee80211com *ic = &sc->sc_ic; - struct iwl2100_cmd *cmd; - uint32_t rate_mask; - int error; - - if (sc->sc_flags & IWL2100_F_WAITCMD) { - if_printf(&ic->ic_if, "there is command pending\n"); - return EEXIST; - } - - /* Calculate TX rate mask. XXX let caller do this */ - if (ic->ic_fixed_rate != IEEE80211_FIXED_RATE_NONE) - rate_mask = 1 << ic->ic_fixed_rate; - else - rate_mask = 0xf; /* all 11b rates */ - KKASSERT((rate_mask & ~0xf) == 0); - - /* - * Set TX rates - */ - cmd = mtod(sc->sc_cmd, struct iwl2100_cmd *); - bzero(cmd, sizeof(*cmd)); - - cmd->c_cmd = IWL2100_CMD_SET_TXRATES; - cmd->c_param_len = sizeof(cmd->c_param[0]); - cmd->c_param[0] = rate_mask; - - error = iwl2100_wait_cmd(sc); - if (error) { - if_printf(&ic->ic_if, "%s failed\n", __func__); - return error; - } - - /* - * Set MSDU TX rates - */ - cmd = mtod(sc->sc_cmd, struct iwl2100_cmd *); - bzero(cmd, sizeof(*cmd)); - - cmd->c_cmd = IWL2100_CMD_SET_MSDU_TXRATES; - cmd->c_param_len = sizeof(cmd->c_param[0]); - cmd->c_param[0] = rate_mask; - - error = iwl2100_wait_cmd(sc); - if (error) { - if_printf(&ic->ic_if, "%s failed\n", __func__); - return error; - } - return 0; -} - -static int -iwl2100_set_powersave(struct iwl2100_softc *sc, int on) -{ - struct iwl2100_cmd *cmd; - int error; - - if (sc->sc_flags & IWL2100_F_WAITCMD) { - if_printf(&sc->sc_ic.ic_if, "there is command pending\n"); - return EEXIST; - } - - cmd = mtod(sc->sc_cmd, struct iwl2100_cmd *); - bzero(cmd, sizeof(*cmd)); - - cmd->c_cmd = IWL2100_CMD_SET_POWERSAVE; - cmd->c_param_len = sizeof(cmd->c_param[0]); - cmd->c_param[0] = on; /* XXX power level? */ - - error = iwl2100_wait_cmd(sc); - if (error) { - if_printf(&sc->sc_ic.ic_if, "%s failed\n", __func__); - return error; - } - return 0; -} - -static int -iwl2100_set_rtsthreshold(struct iwl2100_softc *sc, uint16_t rtsthreshold) -{ - struct iwl2100_cmd *cmd; - int error; - - if (sc->sc_flags & IWL2100_F_WAITCMD) { - if_printf(&sc->sc_ic.ic_if, "there is command pending\n"); - return EEXIST; - } - - cmd = mtod(sc->sc_cmd, struct iwl2100_cmd *); - bzero(cmd, sizeof(*cmd)); - - cmd->c_cmd = IWL2100_CMD_SET_RTSTHRESHOLD; - cmd->c_param_len = sizeof(cmd->c_param[0]); - if (rtsthreshold == IEEE80211_RTS_MAX) { - /* Disable RTS threshold */ - cmd->c_param[0] = IWL2100_RTS_MAX; - } else { - if (rtsthreshold >= IWL2100_RTS_MAX) - rtsthreshold = IWL2100_RTS_MAX - 1; - cmd->c_param[0] = rtsthreshold; - } - - error = iwl2100_wait_cmd(sc); - if (error) { - if_printf(&sc->sc_ic.ic_if, "%s failed\n", __func__); - return error; - } - return 0; -} - -static int -iwl2100_set_bssid(struct iwl2100_softc *sc, const uint8_t *bssid) -{ - struct iwl2100_cmd *cmd; - int error; - - if (sc->sc_flags & IWL2100_F_WAITCMD) { - if_printf(&sc->sc_ic.ic_if, "there is command pending\n"); - return EEXIST; - } - - cmd = mtod(sc->sc_cmd, struct iwl2100_cmd *); - bzero(cmd, sizeof(*cmd)); - - cmd->c_cmd = IWL2100_CMD_SET_BSSID; - if (bssid != NULL) { - cmd->c_param_len = IEEE80211_ADDR_LEN; - IEEE80211_ADDR_COPY(cmd->c_param, bssid); - } - - error = iwl2100_wait_cmd(sc); - if (error) { - if_printf(&sc->sc_ic.ic_if, "%s failed\n", __func__); - return error; - } - return 0; -} - -static int -iwl2100_set_essid(struct iwl2100_softc *sc, const uint8_t *essid, int essid_len) -{ - struct iwl2100_cmd *cmd; - int error; - - if (sc->sc_flags & IWL2100_F_WAITCMD) { - if_printf(&sc->sc_ic.ic_if, "there is command pending\n"); - return EEXIST; - } - - cmd = mtod(sc->sc_cmd, struct iwl2100_cmd *); - bzero(cmd, sizeof(*cmd)); - - cmd->c_cmd = IWL2100_CMD_SET_ESSID; - if (essid != NULL) { - KKASSERT(essid_len <= sizeof(cmd->c_param)); - cmd->c_param_len = essid_len; - if (essid_len != 0) - bcopy(essid, cmd->c_param, essid_len); - } - - error = iwl2100_wait_cmd(sc); - if (error) { - if_printf(&sc->sc_ic.ic_if, "%s failed\n", __func__); - return error; - } - return 0; -} - -static int -iwl2100_set_auth_ciphers(struct iwl2100_softc *sc, - enum ieee80211_authmode authmode) -{ - struct iwl2100_cmdparam_sec *sec; - struct iwl2100_cmd *cmd; - int error; - - if (sc->sc_flags & IWL2100_F_WAITCMD) { - if_printf(&sc->sc_ic.ic_if, "there is command pending\n"); - return EEXIST; - } - - cmd = mtod(sc->sc_cmd, struct iwl2100_cmd *); - bzero(cmd, sizeof(*cmd)); - - cmd->c_cmd = IWL2100_CMD_SET_SECURITY; - cmd->c_param_len = sizeof(*sec); - sec = (struct iwl2100_cmdparam_sec *)cmd->c_param; - - sec->sec_cipher_mask = IWL2100_CIPHER_NONE | - IWL2100_CIPHER_WEP40 | - IWL2100_CIPHER_TKIP | - IWL2100_CIPHER_CCMP | - IWL2100_CIPHER_WEP104; - if (authmode == IEEE80211_AUTH_SHARED) - sec->sec_authmode = IWL2100_AUTH_SHARED; - else - sec->sec_authmode = IWL2100_AUTH_OPEN; - - error = iwl2100_wait_cmd(sc); - if (error) { - if_printf(&sc->sc_ic.ic_if, "%s failed\n", __func__); - return error; - } - return 0; -} - -static int -iwl2100_set_wepkey(struct iwl2100_softc *sc, const struct ieee80211_key *k) -{ - struct iwl2100_cmdparam_wepkey *key; - struct iwl2100_cmd *cmd; - int error; - - if (k->wk_keylen > IWL2100_KEYDATA_SIZE) - return E2BIG; - - if (sc->sc_flags & IWL2100_F_WAITCMD) { - if_printf(&sc->sc_ic.ic_if, "there is command pending\n"); - return EEXIST; - } - - cmd = mtod(sc->sc_cmd, struct iwl2100_cmd *); - bzero(cmd, sizeof(*cmd)); - - cmd->c_cmd = IWL2100_CMD_SET_WEPKEY; - cmd->c_param_len = sizeof(*key); - key = (struct iwl2100_cmdparam_wepkey *)cmd->c_param; - key->key_index = k->wk_keyix; - key->key_len = k->wk_keylen; - bcopy(k->wk_key, key->key_data, key->key_len); - - error = iwl2100_wait_cmd(sc); - if (error) { - if_printf(&sc->sc_ic.ic_if, "%s failed\n", __func__); - return error; - } - return 0; -} - -static int -iwl2100_set_weptxkey(struct iwl2100_softc *sc, ieee80211_keyix txkey) -{ - struct iwl2100_cmd *cmd; - int error; - - if (sc->sc_flags & IWL2100_F_WAITCMD) { - if_printf(&sc->sc_ic.ic_if, "there is command pending\n"); - return EEXIST; - } - - cmd = mtod(sc->sc_cmd, struct iwl2100_cmd *); - bzero(cmd, sizeof(*cmd)); - - cmd->c_cmd = IWL2100_CMD_SET_WEPTXKEY; - cmd->c_param_len = sizeof(cmd->c_param[0]); - cmd->c_param[0] = txkey; - - error = iwl2100_wait_cmd(sc); - if (error) { - if_printf(&sc->sc_ic.ic_if, "%s failed\n", __func__); - return error; - } - return 0; -} - -static int -iwl2100_set_privacy(struct iwl2100_softc *sc, int on) -{ - struct iwl2100_cmd *cmd; - int error; - - if (sc->sc_flags & IWL2100_F_WAITCMD) { - if_printf(&sc->sc_ic.ic_if, "there is command pending\n"); - return EEXIST; - } - - cmd = mtod(sc->sc_cmd, struct iwl2100_cmd *); - bzero(cmd, sizeof(*cmd)); - - cmd->c_cmd = IWL2100_CMD_SET_PRIVACY; - cmd->c_param_len = sizeof(cmd->c_param[0]); - cmd->c_param[0] = on ? IWL2100_PRIVACY_ENABLE : 0; - - error = iwl2100_wait_cmd(sc); - if (error) { - if_printf(&sc->sc_ic.ic_if, "%s failed\n", __func__); - return error; - } - return 0; -} - -static int -iwl2100_wait_cmd(struct iwl2100_softc *sc) -{ - struct ifnet *ifp = &sc->sc_ic.ic_if; - struct iwl2100_tx_ring *tr = &sc->sc_txring; - struct mbuf *m = sc->sc_cmd; - struct iwl_dmamap_ctx ctx; - bus_dma_segment_t seg; - struct iwl2100_desc *d; - struct iwl2100_txbuf *tb; - int error; - - ASSERT_SERIALIZED(ifp->if_serializer); - - KKASSERT(tr->tr_index < IWL2100_TX_NDESC); - tb = &tr->tr_buf[tr->tr_index]; - - ctx.nsegs = 1; - ctx.segs = &seg; - error = bus_dmamap_load_mbuf(sc->sc_mbuf_dtag, tb->tb_dmap, m, - iwl_dma_buf_addr, &ctx, BUS_DMA_WAITOK); - if (error || ctx.nsegs == 0) { - if (!error) { - bus_dmamap_unload(sc->sc_mbuf_dtag, tb->tb_dmap); - error = EFBIG; - if_printf(ifp, "too many segments?!\n"); - } - - if_printf(ifp, "can't load RX mbuf\n"); - return error; - } - tb->tb_mbuf = sc->sc_cmd; - tb->tb_flags |= IWL2100_TBF_CMDBUF; - - d = &tr->tr_desc[tr->tr_index]; - d->d_paddr = seg.ds_addr; - d->d_len = sizeof(struct iwl2100_cmd); - d->d_nfrag = 1; - d->d_flags = IWL2100_TXD_F_INTR | IWL2100_TXD_F_CMD; - - KKASSERT(tr->tr_used < IWL2100_TX_NDESC); - ++tr->tr_used; - tr->tr_index = (tr->tr_index + 1) % IWL2100_TX_NDESC; - - bus_dmamap_sync(tr->tr_dtag, tr->tr_dmap, BUS_DMASYNC_PREWRITE); - - CSR_WRITE_4(sc, IWL2100_TXQ_WRITE_IDX, tr->tr_index); - - if (sc->sc_flags & IWL2100_F_IN_INTR) - panic("sleep in interrupt thread"); - - sc->sc_flags |= IWL2100_F_WAITCMD; - error = zsleep(sc, ifp->if_serializer, 0, "iwlcmd", 2 * hz); - if (!error) { - sc->sc_flags &= ~IWL2100_F_WAITCMD; - if (sc->sc_flags & IWL2100_F_ERROR) { - if_printf(ifp, "error happened when waiting " - "command to be done\n"); - error = EIO; - } - } - return error; -} - -static void -iwl2100_rxeof(struct iwl2100_softc *sc) -{ - struct iwl2100_rx_ring *rr = &sc->sc_rxring; - struct ifnet *ifp = &sc->sc_ic.ic_if; - int hwidx, i; - - hwidx = CSR_READ_4(sc, IWL2100_RXQ_READ_IDX); - CSR_READ_4(sc, IWL2100_RXQ_WRITE_IDX); - - if (hwidx >= IWL2100_RX_NDESC) { - if_printf(ifp, "invalid hardware RX index %d\n", hwidx); - return; - } - - KKASSERT(rr->rr_index < IWL2100_RX_NDESC); - i = (rr->rr_index + 1) % IWL2100_RX_NDESC; - while (hwidx != i) { - struct iwl2100_rx_status *st = &rr->rr_status[i]; - struct iwl2100_rxbuf *rb = &rr->rr_buf[i]; - int frame_type; - - bus_dmamap_sync(rr->rr_st_dtag, rr->rr_st_dmap, - BUS_DMASYNC_POSTREAD); - frame_type = st->r_status & IWL2100_RXS_TYPE_MASK; - - bus_dmamap_sync(sc->sc_mbuf_dtag, rb->rb_dmap, - BUS_DMASYNC_POSTREAD); - switch (frame_type) { - case IWL2100_RXS_TYPE_CMD: - iwl2100_rxeof_cmd(sc, i); - break; - - case IWL2100_RXS_TYPE_STATUS: - iwl2100_rxeof_status(sc, i); - break; - - case IWL2100_RXS_TYPE_NOTE: - iwl2100_rxeof_note(sc, i); - break; - - case IWL2100_RXS_TYPE_DATA: - case IWL2100_RXS_TYPE_DATA1: - iwl2100_rxeof_data(sc, i); - break; - - default: - if_printf(ifp, "unknown frame type: %d\n", frame_type); - iwl2100_rxdesc_setup(sc, i); - break; - } - i = (i + 1) % IWL2100_RX_NDESC; - } - bus_dmamap_sync(rr->rr_st_dtag, rr->rr_st_dmap, BUS_DMASYNC_POSTREAD); - bus_dmamap_sync(rr->rr_dtag, rr->rr_dmap, BUS_DMASYNC_POSTREAD); - - if (i == 0) - rr->rr_index = IWL2100_RX_NDESC - 1; - else - rr->rr_index = i - 1; - CSR_WRITE_4(sc, IWL2100_RXQ_WRITE_IDX, rr->rr_index); -} - -static void -iwl2100_txeof(struct iwl2100_softc *sc) -{ - struct iwl2100_tx_ring *tr = &sc->sc_txring; - struct ifnet *ifp = &sc->sc_ic.ic_if; - int hwidx; - - hwidx = CSR_READ_4(sc, IWL2100_TXQ_READ_IDX); - CSR_READ_4(sc, IWL2100_TXQ_WRITE_IDX); - if (hwidx >= IWL2100_TX_NDESC) { - if_printf(ifp, "invalid hardware TX index %d\n", hwidx); - return; - } - - KKASSERT(tr->tr_coll < IWL2100_TX_NDESC); - while (tr->tr_used) { - struct iwl2100_txbuf *tb; - - if (tr->tr_coll == hwidx) - break; - - tb = &tr->tr_buf[tr->tr_coll]; - if (tb->tb_mbuf == NULL) - goto next; - - bus_dmamap_unload(sc->sc_mbuf_dtag, tb->tb_dmap); - if (tb->tb_flags & IWL2100_TBF_CMDBUF) { - tb->tb_flags &= ~IWL2100_TBF_CMDBUF; - KKASSERT(tb->tb_mbuf == sc->sc_cmd); - } else { - m_freem(tb->tb_mbuf); - } - tb->tb_mbuf = NULL; -next: - tr->tr_coll = (tr->tr_coll + 1) % IWL2100_TX_NDESC; - - KKASSERT(tr->tr_used > 0); - --tr->tr_used; - } - - if (tr->tr_used < IWL2100_TX_USED_MAX) { - if (tr->tr_used == 0) { - KKASSERT(tr->tr_coll == tr->tr_index); - sc->sc_tx_timer = 0; - } - - ifq_clr_oactive(&ifp->if_snd); - if_devstart(ifp); - } -} - -static int -iwl2100_config(struct iwl2100_softc *sc, const uint8_t *bssid, - const uint8_t *essid, uint8_t esslen, int ibss_chan) -{ - struct ieee80211com *ic = &sc->sc_ic; - struct ifnet *ifp = &ic->ic_if; - int error; - - if (ic->ic_opmode == IEEE80211_M_MONITOR) { - error = iwl2100_set_chan(sc, ic->ic_curchan); - if (error) { - if_printf(ifp, "can't set mon channel\n"); - return error; - } - } - - IEEE80211_ADDR_COPY(ic->ic_myaddr, IF_LLADDR(ifp)); - error = iwl2100_set_addr(sc, ic->ic_myaddr); - if (error) { - if_printf(ifp, "can't set MAC address\n"); - return error; - } - - error = iwl2100_set_opmode(sc, ic->ic_opmode); - if (error) { - if_printf(ifp, "can't set opmode\n"); - return error; - } - - if (ibss_chan) { - KKASSERT(ic->ic_opmode == IEEE80211_M_IBSS); - error = iwl2100_set_chan(sc, ic->ic_curchan); - if (error) { - if_printf(ifp, "can't set ibss channel\n"); - return error; - } - } - - error = iwl2100_set_80211(sc); - if (error) { - if_printf(ifp, "can't set 802.11 config\n"); - return error; - } - - error = iwl2100_set_basicrates(sc); - if (error) { - if_printf(ifp, "can't set basicrates\n"); - return error; - } - - error = iwl2100_set_txrates(sc); - if (error) { - if_printf(ifp, "can't set TX rates\n"); - return error; - } - - error = iwl2100_set_powersave(sc, ic->ic_flags & IEEE80211_F_PMGTON); - if (error) { - if_printf(ifp, "can't turn off powersave\n"); - return error; - } - - error = iwl2100_set_rtsthreshold(sc, ic->ic_rtsthreshold); - if (error) { - if_printf(ifp, "can't set RTS threshold\n"); - return error; - } - - error = iwl2100_set_bssid(sc, bssid); - if (error) { - if_printf(ifp, "can't set bssid\n"); - return error; - } - - error = iwl2100_set_essid(sc, essid, esslen); - if (error) { - if_printf(ifp, "can't set essid\n"); - return error; - } - - error = iwl2100_set_auth_ciphers(sc, ic->ic_bss->ni_authmode); - if (error) { - if_printf(ifp, "can't set authmode and ciphers\n"); - return error; - } - - if (ic->ic_flags & IEEE80211_F_PRIVACY) { - ieee80211_keyix txkey = IEEE80211_KEYIX_NONE; - int i; - - for (i = 0; i < IEEE80211_WEP_NKID; ++i) { - const struct ieee80211_key *k = &ic->ic_nw_keys[i]; - - if (k->wk_keyix == IEEE80211_KEYIX_NONE) - continue; - - error = iwl2100_set_wepkey(sc, k); - if (error == E2BIG) { - continue; - } else if (error) { - if_printf(ifp, "can't set wepkey\n"); - return error; - } - txkey = k->wk_keyix; - } - - if (txkey != IEEE80211_KEYIX_NONE) { - /* - * Found some valid WEP keys. - * - * If WEP TX key index from 802.11 layer is not - * set, then use the first valid WEP key as TX - * key. - */ - if (ic->ic_def_txkey != IEEE80211_KEYIX_NONE) - txkey = ic->ic_def_txkey; - - error = iwl2100_set_weptxkey(sc, txkey); - if (error) { - if_printf(ifp, "can't set weptxkey\n"); - return error; - } - } - } - - error = iwl2100_set_privacy(sc, ic->ic_flags & IEEE80211_F_PRIVACY); - if (error) { - if_printf(ifp, "can't set privacy\n"); - return error; - } - - error = iwl2100_set_optie(sc, ic->ic_opt_ie, ic->ic_opt_ie_len); - if (error) { - if (error != E2BIG) { - if_printf(ifp, "can't set opt ie\n"); - return error; - } - } - - if (ic->ic_opmode == IEEE80211_M_IBSS) { - error = iwl2100_set_bintval(sc, ic->ic_bss->ni_intval); - if (error) { - if_printf(ifp, "can't set bintval\n"); - return error; - } - - error = iwl2100_set_txpower(sc, 32 /* XXX */); - if (error) { - if_printf(ifp, "can't set txpwr\n"); - return error; - } - } - return 0; -} - -static int -iwl2100_config_op(struct iwl2100_softc *sc, uint32_t op) -{ - struct iwl2100_cmd *cmd; - int error; - - KASSERT(op == IWL2100_CMD_CONF_DONE || op == IWL2100_CMD_CONF_START, - ("unknown config_op %u", op)); - - if (sc->sc_flags & IWL2100_F_WAITCMD) { - if_printf(&sc->sc_ic.ic_if, "there is command pending\n"); - return EEXIST; - } - - cmd = mtod(sc->sc_cmd, struct iwl2100_cmd *); - bzero(cmd, sizeof(*cmd)); - cmd->c_cmd = op; - - error = iwl2100_wait_cmd(sc); - if (error) { - if_printf(&sc->sc_ic.ic_if, "%s(%u) failed\n", __func__, op); - return error; - } - - iwl2100_read_ord1(sc, IWL2100_ORD1_CONF_START); /* dummy read */ - return 0; -} - -static int -iwl2100_set_chan(struct iwl2100_softc *sc, const struct ieee80211_channel *c) -{ - struct ieee80211com *ic = &sc->sc_ic; - struct iwl2100_cmd *cmd; - u_int chan; - int error; - - KKASSERT(ic->ic_opmode != IEEE80211_M_STA); - - chan = ieee80211_chan2ieee(ic, c); - if (chan == IEEE80211_CHAN_ANY) { - if_printf(&ic->ic_if, "invalid channel!\n"); - return EINVAL; - } - - if (sc->sc_flags & IWL2100_F_WAITCMD) { - if_printf(&ic->ic_if, "there is command pending\n"); - return EEXIST; - } - - cmd = mtod(sc->sc_cmd, struct iwl2100_cmd *); - bzero(cmd, sizeof(*cmd)); - - cmd->c_cmd = IWL2100_CMD_SET_CHAN; - cmd->c_param_len = sizeof(cmd->c_param[0]); - cmd->c_param[0] = chan; - - error = iwl2100_wait_cmd(sc); - if (error) { - if_printf(&ic->ic_if, "%s failed\n", __func__); - return error; - } - return 0; -} - -static int -iwl2100_set_scanopt(struct iwl2100_softc *sc, uint32_t chans, uint32_t flags) -{ - struct ieee80211com *ic = &sc->sc_ic; - struct iwl2100_cmd *cmd; - int error; - - KKASSERT(ic->ic_opmode != IEEE80211_M_MONITOR); - - if (sc->sc_flags & IWL2100_F_WAITCMD) { - if_printf(&ic->ic_if, "there is command pending\n"); - return EEXIST; - } - - cmd = mtod(sc->sc_cmd, struct iwl2100_cmd *); - bzero(cmd, sizeof(*cmd)); - - /* - * NOTE: - * 1) IWL2100_SCANOPT_NOASSOC is ignored by firmware, but same - * function could be achieved by clearing bssid. - * 2) Channel mask is ignored by firmware, if NIC is in STA opmode. - * - * We leave the correct configuration here just with the hope - * that one day firmware could do better. - */ - cmd->c_cmd = IWL2100_CMD_SET_SCANOPT; - cmd->c_param_len = sizeof(cmd->c_param[0]) * 2; - cmd->c_param[0] = flags | IWL2100_SCANOPT_MIXED; - cmd->c_param[1] = chans; - - error = iwl2100_wait_cmd(sc); - if (error) { - if_printf(&ic->ic_if, "%s failed\n", __func__); - return error; - } - return 0; -} - -static int -iwl2100_set_scan(struct iwl2100_softc *sc) -{ - struct ieee80211com *ic = &sc->sc_ic; - struct iwl2100_cmd *cmd; - int error; - - KKASSERT(ic->ic_opmode != IEEE80211_M_MONITOR); - - if (sc->sc_flags & IWL2100_F_WAITCMD) { - if_printf(&ic->ic_if, "there is command pending\n"); - return EEXIST; - } - - cmd = mtod(sc->sc_cmd, struct iwl2100_cmd *); - bzero(cmd, sizeof(*cmd)); - - cmd->c_cmd = IWL2100_CMD_SCAN; - cmd->c_param_len = sizeof(cmd->c_param[0]); - - error = iwl2100_wait_cmd(sc); - if (error) { - if_printf(&ic->ic_if, "%s failed\n", __func__); - return error; - } - return 0; -} - -static int -iwl2100_set_optie(struct iwl2100_softc *sc, void *optie, uint16_t optie_len) -{ - struct iwl2100_cmd *cmd; - struct iwl2100_cmdparam_ie *ie; - int error; - - if (sc->sc_flags & IWL2100_F_WAITCMD) { - if_printf(&sc->sc_ic.ic_if, "there is command pending\n"); - return EEXIST; - } - - if (optie_len > IWL2100_OPTIE_MAX) { - if_printf(&sc->sc_ic.ic_if, "optie too long\n"); - return E2BIG; - } - - if (optie == NULL || optie_len == 0) - return 0; - - cmd = mtod(sc->sc_cmd, struct iwl2100_cmd *); - bzero(cmd, sizeof(*cmd)); - - cmd->c_cmd = IWL2100_CMD_SET_IE; - cmd->c_param_len = sizeof(*ie); - ie = (struct iwl2100_cmdparam_ie *)cmd->c_param; - ie->ie_optlen = optie_len; - bcopy(optie, ie->ie_opt, optie_len); - - error = iwl2100_wait_cmd(sc); - if (error) { - if_printf(&sc->sc_ic.ic_if, "%s failed\n", __func__); - return error; - } - return 0; -} - -static int -iwl2100_set_bintval(struct iwl2100_softc *sc, uint16_t bintval) -{ - struct iwl2100_cmd *cmd; - int error; - - if (sc->sc_flags & IWL2100_F_WAITCMD) { - if_printf(&sc->sc_ic.ic_if, "there is command pending\n"); - return EEXIST; - } - - cmd = mtod(sc->sc_cmd, struct iwl2100_cmd *); - bzero(cmd, sizeof(*cmd)); - - cmd->c_cmd = IWL2100_CMD_SET_BINTVAL; - cmd->c_param_len = sizeof(cmd->c_param[0]); - cmd->c_param[0] = bintval; - - error = iwl2100_wait_cmd(sc); - if (error) { - if_printf(&sc->sc_ic.ic_if, "%s failed\n", __func__); - return error; - } - return 0; -} - -static int -iwl2100_set_txpower(struct iwl2100_softc *sc, uint16_t txpower) -{ - struct iwl2100_cmd *cmd; - int error; - - if (sc->sc_flags & IWL2100_F_WAITCMD) { - if_printf(&sc->sc_ic.ic_if, "there is command pending\n"); - return EEXIST; - } - - cmd = mtod(sc->sc_cmd, struct iwl2100_cmd *); - bzero(cmd, sizeof(*cmd)); - - cmd->c_cmd = IWL2100_CMD_SET_TXPOWER; - cmd->c_param_len = sizeof(cmd->c_param[0]); - cmd->c_param[0] = txpower; - - error = iwl2100_wait_cmd(sc); - if (error) { - if_printf(&sc->sc_ic.ic_if, "%s failed\n", __func__); - return error; - } - return 0; -} - -static void -iwl2100_rxeof_status(struct iwl2100_softc *sc, int i) -{ - struct ieee80211com *ic = &sc->sc_ic; - struct ifnet *ifp = &ic->ic_if; - struct iwl2100_rx_ring *rr = &sc->sc_rxring; - struct iwl2100_rx_status *st = &rr->rr_status[i]; - struct iwl2100_rxbuf *rb = &rr->rr_buf[i]; - struct mbuf *m = rb->rb_mbuf; - uint32_t status; - - if (st->r_len != sizeof(status)) { - if_printf(ifp, "invalid status frame len %u\n", st->r_len); - goto back; - } - - if (ic->ic_opmode == IEEE80211_M_MONITOR) - goto back; - - if ((ic->ic_flags & IEEE80211_F_SCAN) == 0) - sc->sc_flags &= ~IWL2100_F_SCANNING; - - status = *mtod(m, uint32_t *); - DPRINTF(sc, IWL2100_DBG_STATUS, "status 0x%08x\n", status); - - switch (status) { - case IWL2100_STATUS_SCANDONE: - if (ic->ic_flags & IEEE80211_F_SCAN) { - /* - * To make sure that firmware has iterated all - * of the channels, we wait for the second scan - * done status change. - */ - if (sc->sc_flags & IWL2100_F_SCANNING) { - iwlmsg_send(&sc->sc_scanend_msg, - &sc->sc_thread_port); - } else { - sc->sc_flags |= IWL2100_F_SCANNING; - } - } - break; - - case IWL2100_STATUS_RUNNING: - iwl2100_restart_done(sc); - if (ic->ic_state == IEEE80211_S_ASSOC) { - KKASSERT(ic->ic_opmode == IEEE80211_M_STA); - iwlmsg_send(&sc->sc_run_msg, &sc->sc_thread_port); - } else if (ic->ic_state == IEEE80211_S_RUN) { - if (ic->ic_opmode == IEEE80211_M_STA) { - DPRINTF(sc, IWL2100_DBG_RESTART, "%s", - "restart done\n"); - sc->sc_flags |= IWL2100_F_IFSTART; - if_devstart(ifp); - } else { - KKASSERT(ic->ic_opmode == IEEE80211_M_IBSS); - callout_reset(&sc->sc_ibss, (100 * hz) / 1000, - iwl2100_ibss_bssid, sc); - } - } - break; - - case IWL2100_STATUS_BMISS: - if (ic->ic_opmode == IEEE80211_M_STA) { - DPRINTF(sc, IWL2100_DBG_SCAN, "%s", "bmiss\n"); - iwlmsg_send(&sc->sc_bmiss_msg, &sc->sc_thread_port); - } - break; - - case IWL2100_STATUS_SCANNING: - if (ic->ic_opmode == IEEE80211_M_STA && - ic->ic_state == IEEE80211_S_RUN) { - /* Firmware error happens */ - iwl2100_restart(sc); - } - break; - } -back: - iwl2100_rxdesc_setup(sc, i); -} - -static void -iwl2100_rxeof_note(struct iwl2100_softc *sc, int i) -{ - struct iwl2100_rx_ring *rr = &sc->sc_rxring; - struct iwl2100_rx_status *st = &rr->rr_status[i]; - struct iwl2100_rxbuf *rb = &rr->rr_buf[i]; - struct mbuf *m = rb->rb_mbuf; - struct ieee80211com *ic = &sc->sc_ic; - struct iwl2100_note *note; - - if (st->r_len < sizeof(*note)) { - if_printf(&ic->ic_if, "invalid note frame len %u\n", st->r_len); - goto back; - } - - if (ic->ic_opmode == IEEE80211_M_MONITOR) - goto back; - - note = mtod(m, struct iwl2100_note *); - DPRINTF(sc, IWL2100_DBG_NOTE, "note subtype %u, size %u\n", - note->nt_subtype, note->nt_size); - - if (note->nt_subtype == 19 /* XXX */ && - ic->ic_state == IEEE80211_S_AUTH) { - KKASSERT(ic->ic_opmode == IEEE80211_M_STA); - iwlmsg_send(&sc->sc_assoc_msg, &sc->sc_thread_port); - } -back: - iwl2100_rxdesc_setup(sc, i); -} - -static void -iwl2100_rxeof_cmd(struct iwl2100_softc *sc, int i) -{ - struct iwl2100_rx_ring *rr = &sc->sc_rxring; - struct iwl2100_rx_status *st = &rr->rr_status[i]; - struct iwl2100_rxbuf *rb = &rr->rr_buf[i]; - struct mbuf *m = rb->rb_mbuf; - struct iwl2100_cmd *cmd; - - if (st->r_len != sizeof(*cmd)) { - if_printf(&sc->sc_ic.ic_if, - "invalid cmd done frame len %u\n", st->r_len); - goto back; - } - - cmd = mtod(m, struct iwl2100_cmd *); - DPRINTF(sc, IWL2100_DBG_CMD, "cmd %u\n", cmd->c_cmd); - if (cmd->c_cmd == 0) - sc->sc_flags |= IWL2100_F_ZERO_CMD; - wakeup(sc); -back: - iwl2100_rxdesc_setup(sc, i); -} - -static void -iwl2100_rxeof_data(struct iwl2100_softc *sc, int i) -{ - struct ieee80211com *ic = &sc->sc_ic; - struct ifnet *ifp = &ic->ic_if; - struct iwl2100_rx_ring *rr = &sc->sc_rxring; - struct iwl2100_rx_status *st = &rr->rr_status[i]; - struct iwl2100_rxbuf *rb = &rr->rr_buf[i]; - struct mbuf *m = rb->rb_mbuf; - struct ieee80211_frame_min *wh; - struct ieee80211_node *ni; - int frame_len, rssi; - const struct ieee80211_channel *c; - - /* - * Gather all necessary information from status ring _here_, - * since the following iwl2100_newbuf() will clear them out. - */ - rssi = st->r_rssi; - frame_len = st->r_len; - - if (iwl2100_newbuf(sc, i, 0)) { - IFNET_STAT_INC(ifp, ierrors, 1); - return; - } - - c = ic->ic_curchan; - - m->m_pkthdr.rcvif = ifp; - m->m_len = m->m_pkthdr.len = frame_len; - - wh = mtod(m, struct ieee80211_frame_min *); - ni = ieee80211_find_rxnode(ic, wh); - - /* - * RX radio tap - */ - if (sc->sc_drvbpf != NULL) { - if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) - sc->sc_rx_th.wr_flags = IEEE80211_RADIOTAP_F_WEP; - else - sc->sc_rx_th.wr_flags = 0; - - sc->sc_rx_th.wr_antsignal = rssi + IWL2100_NOISE_FLOOR; - sc->sc_rx_th.wr_antnoise = IWL2100_NOISE_FLOOR; - - bpf_ptap(sc->sc_drvbpf, m, &sc->sc_rx_th, sc->sc_rx_th_len); - } - - ieee80211_input(ic, m, ni, rssi, 0); - ieee80211_free_node(ni); - - if (c != ic->ic_curchan) /* Happen during scanning */ - iwl2100_chan_change(sc, ic->ic_curchan); -} - -static void -iwl2100_scanend_dispatch(struct netmsg *nmsg) -{ - struct iwlmsg *msg = (struct iwlmsg *)nmsg; - struct iwl2100_softc *sc = msg->iwlm_softc; - struct ieee80211com *ic = &sc->sc_ic; - struct ifnet *ifp = &ic->ic_if; - - ASSERT_SERIALIZED(ifp->if_serializer); - - if (sc->sc_flags & IWL2100_F_DETACH) - goto reply; - - if (ifp->if_flags & IFF_RUNNING) { - ieee80211_end_scan(ic); - sc->sc_flags &= ~IWL2100_F_SCANNING; - } -reply: - lwkt_replymsg(&nmsg->nm_lmsg, 0); -} - -static int -iwl2100_hw_init(struct iwl2100_softc *sc, const uint8_t *bssid, - const uint8_t *essid, uint8_t esslen, uint32_t flags) -{ - struct ieee80211com *ic = &sc->sc_ic; - struct ifnet *ifp = &ic->ic_if; - uint32_t db_addr; - int error; - - ASSERT_SERIALIZED(ifp->if_serializer); - KKASSERT(curthread == &sc->sc_thread); - - iwl2100_hw_stop(sc); - - error = iwl2100_alloc_firmware(sc, ic->ic_opmode); - if (error) { - if_printf(ifp, "can't allocate firmware\n"); - goto back; - } - - error = iwl2100_load_firmware(sc, ic->ic_opmode); - if (error) { - if_printf(ifp, "can't load firmware\n"); - goto back; - } - - error = iwl2100_alloc_cmd(sc); - if (error) { - if_printf(ifp, "can't allocate cmd\n"); - goto back; - } - - error = iwl2100_init_tx_ring(sc); - if (error) { - if_printf(ifp, "can't init TX ring\n"); - goto back; - } - - error = iwl2100_init_rx_ring(sc); - if (error) { - if_printf(ifp, "can't init RX ring\n"); - goto back; - } - - error = iwl2100_init_firmware(sc); - if (error) { - if_printf(ifp, "can't initialize firmware\n"); - goto back; - } - - sc->sc_ord1 = CSR_READ_4(sc, IWL2100_ORD1_ADDR); - sc->sc_ord2 = CSR_READ_4(sc, IWL2100_ORD2_ADDR); - - db_addr = iwl2100_read_ord1(sc, IWL2100_ORD1_DBADDR); - if ((IND_READ_4(sc, db_addr + 0x20) >> 24) & 0x1) - sc->sc_caps &= ~IWL2100_C_RFKILL; - else - sc->sc_caps |= IWL2100_C_RFKILL; - - /* Unlock firmware */ - iwl2100_write_ord1(sc, IWL2100_ORD1_FWLOCK, 0); - - if (iwl2100_rfkilled(sc)) { - error = ENXIO; - goto back; - } - - /* Let interrupt handler run */ - sc->sc_flags |= IWL2100_F_INITED; - - /* Enable interrupts */ - CSR_WRITE_4(sc, IWL2100_INTR_MASK, IWL2100_INTRS); - - error = iwl2100_config(sc, bssid, essid, esslen, - flags & IWL2100_INIT_F_IBSSCHAN); - if (error) - goto back; - - if (flags & IWL2100_INIT_F_ENABLE) { - error = iwl2100_config_done(sc); - if (error) { - if_printf(ifp, "can't complete config\n"); - goto back; - } - } - - ifq_clr_oactive(&ifp->if_snd); - ifp->if_flags |= IFF_RUNNING; -back: - if (error) - iwl2100_stop(sc); - return error; -} - -static int -iwl2100_start_scan(struct iwl2100_softc *sc, uint32_t chans, uint32_t flags) -{ - int error; - - /* - * XXX - * Firmware always starts scanning once config is done - */ - error = iwl2100_set_scanopt(sc, chans, flags); - if (error) { - if_printf(&sc->sc_ic.ic_if, "can't set scan opt\n"); - return error; - } - - error = iwl2100_set_scan(sc); - if (error) { - if_printf(&sc->sc_ic.ic_if, "can't set bcast scanning\n"); - return error; - } - return 0; -} - -static int -iwl2100_scan(struct iwl2100_softc *sc) -{ - struct ieee80211com *ic = &sc->sc_ic; - uint32_t chans, flags; - int error; - - KKASSERT(ic->ic_opmode != IEEE80211_M_MONITOR); - - error = iwl2100_hw_init(sc, NULL, - ic->ic_des_essid, ic->ic_des_esslen, IWL2100_INIT_F_ENABLE); - if (error) - return error; - - if (ic->ic_opmode == IEEE80211_M_STA) { - chans = sc->sc_bss_chans; - flags = IWL2100_SCANOPT_NOASSOC; - } else { - /* - * Normally # of IBSS channels is less than BSS's - * but it seems IBSS mode works on all BSS channels - */ -#if 0 - chans = sc->sc_ibss_chans; -#else - chans = sc->sc_bss_chans; -#endif - /* - * Don't set NOASSOC scan option, it seems that - * firmware will disable itself after scanning - * if this flag is set. After all, we are in - * IBSS mode, which does not have concept of - * association. - */ - flags = 0; - } - - /* See NOTE in iwl2100_set_scanopt() */ - error = iwl2100_start_scan(sc, chans, flags); - if (error) - return error; - return 0; -} - -static int -iwl2100_auth(struct iwl2100_softc *sc) -{ - struct ieee80211com *ic = &sc->sc_ic; - struct ieee80211_node *ni = ic->ic_bss; - u_int chan; - int error; - - KKASSERT(ic->ic_opmode == IEEE80211_M_STA); - - chan = ieee80211_chan2ieee(ic, ic->ic_curchan); - if (chan == IEEE80211_CHAN_ANY) { - if_printf(&ic->ic_if, "invalid curchan\n"); - return EINVAL; - } - - error = iwl2100_hw_init(sc, ni->ni_bssid, - ni->ni_essid, ni->ni_esslen, IWL2100_INIT_F_ENABLE); - if (error) - return error; - - /* See NOTE in iwl2100_set_scanopt() */ - error = iwl2100_start_scan(sc, 1 << (chan - 1), 0); - if (error) - return error; - return 0; -} - -static int -iwl2100_ibss(struct iwl2100_softc *sc) -{ - struct ieee80211com *ic = &sc->sc_ic; - struct ieee80211_node *ni = ic->ic_bss; - - return iwl2100_hw_init(sc, ni->ni_bssid, - ni->ni_essid, ni->ni_esslen, - IWL2100_INIT_F_ENABLE | IWL2100_INIT_F_IBSSCHAN); -} - -static int -iwl2100_encap(struct iwl2100_softc *sc, struct mbuf *m) -{ - struct iwl2100_tx_ring *tr = &sc->sc_txring; - struct iwl2100_tx_hdr *th; - struct ieee80211_frame *wh; - struct iwl_dmamap_ctx ctx; - bus_dma_segment_t segs[IWL2100_NSEG_MAX]; - uint8_t src[IEEE80211_ADDR_LEN], dst[IEEE80211_ADDR_LEN]; - bus_dmamap_t dmap; - int maxsegs, i, first_idx, last_idx, error, host_enc; - - /* - * Save necessary information and strip 802.11 header - */ - wh = mtod(m, struct ieee80211_frame *); - IEEE80211_ADDR_COPY(src, wh->i_addr2); - if (sc->sc_ic.ic_opmode == IEEE80211_M_STA) - IEEE80211_ADDR_COPY(dst, wh->i_addr3); - else - IEEE80211_ADDR_COPY(dst, wh->i_addr1); - if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) - host_enc = 1; - else - host_enc = 0; - m_adj(m, sizeof(*wh)); - - /* - * Prepend and setup hardware TX header - */ - M_PREPEND(m, sizeof(*th), M_NOWAIT); - if (m == NULL) { - if_printf(&sc->sc_ic.ic_if, "prepend TX header failed\n"); - return ENOBUFS; - } - th = mtod(m, struct iwl2100_tx_hdr *); - - bzero(th, sizeof(*th)); - th->th_cmd = IWL2100_CMD_TX_DATA; - th->th_host_enc = host_enc; - IEEE80211_ADDR_COPY(th->th_src, src); - IEEE80211_ADDR_COPY(th->th_dst, dst); - - /* - * Load mbuf into DMA map - */ - maxsegs = IWL2100_TX_USED_MAX - tr->tr_used; - if (maxsegs > IWL2100_NSEG_MAX) - maxsegs = IWL2100_NSEG_MAX; - - KKASSERT(tr->tr_index < IWL2100_TX_NDESC); - first_idx = tr->tr_index; - dmap = tr->tr_buf[first_idx].tb_dmap; - - ctx.nsegs = maxsegs; - ctx.segs = segs; - error = bus_dmamap_load_mbuf(sc->sc_mbuf_dtag, dmap, m, - iwl_dma_buf_addr, &ctx, BUS_DMA_NOWAIT); - if (!error && ctx.nsegs == 0) { - bus_dmamap_unload(sc->sc_mbuf_dtag, dmap); - error = EFBIG; - } - if (error && error != EFBIG) { - if_printf(&sc->sc_ic.ic_if, "can't load TX mbuf, error %d\n", - error); - goto back; - } - if (error) { /* error == EFBIG */ - struct mbuf *m_new; - - m_new = m_defrag(m, M_NOWAIT); - if (m_new == NULL) { - if_printf(&sc->sc_ic.ic_if, "can't defrag TX mbuf\n"); - error = ENOBUFS; - goto back; - } else { - m = m_new; - } - - ctx.nsegs = maxsegs; - ctx.segs = segs; - error = bus_dmamap_load_mbuf(sc->sc_mbuf_dtag, dmap, m, - iwl_dma_buf_addr, &ctx, - BUS_DMA_NOWAIT); - if (error || ctx.nsegs == 0) { - if (ctx.nsegs == 0) { - bus_dmamap_unload(sc->sc_mbuf_dtag, dmap); - error = EFBIG; - } - if_printf(&sc->sc_ic.ic_if, - "can't load defraged TX mbuf\n"); - goto back; - } - } - bus_dmamap_sync(sc->sc_mbuf_dtag, dmap, BUS_DMASYNC_PREWRITE); - - /* - * Fill TX desc ring - */ - last_idx = -1; - for (i = 0; i < ctx.nsegs; ++i) { - struct iwl2100_desc *d = &tr->tr_desc[tr->tr_index]; - - d->d_paddr = segs[i].ds_addr; - d->d_len = segs[i].ds_len; - if (i != 0) - d->d_nfrag = 0; - else - d->d_nfrag = ctx.nsegs; - - if (i == ctx.nsegs - 1) { - d->d_flags = IWL2100_TXD_F_INTR; - last_idx = tr->tr_index; - } else { - d->d_flags = IWL2100_TXD_F_NOTLAST; - } - - tr->tr_index = (tr->tr_index + 1) % IWL2100_TX_NDESC; - } - KKASSERT(last_idx >= 0); - - tr->tr_buf[first_idx].tb_dmap = tr->tr_buf[last_idx].tb_dmap; - tr->tr_buf[last_idx].tb_dmap = dmap; - tr->tr_buf[last_idx].tb_mbuf = m; - - tr->tr_used += ctx.nsegs; - KKASSERT(tr->tr_used <= IWL2100_TX_USED_MAX); - - error = 0; -back: - if (error) - m_freem(m); - return error; -} - -static void -iwl2100_restart_dispatch(struct netmsg *nmsg) -{ - struct iwlmsg *msg = (struct iwlmsg *)nmsg; - struct iwl2100_softc *sc = msg->iwlm_softc; - struct ieee80211com *ic = &sc->sc_ic; - struct ifnet *ifp = &ic->ic_if; - int error = 0; - - ASSERT_SERIALIZED(ifp->if_serializer); - - if (sc->sc_flags & IWL2100_F_DETACH) - goto reply; - - if ((ifp->if_flags & IFF_RUNNING) == 0) - goto reply; - - if (msg->iwlm_arg != sc->sc_state_age) { - /* - * Restarting was triggered in old 802.11 state - * Don't do anything, this is a staled restarting. - */ - goto reply; - } - - if (ic->ic_state != IEEE80211_S_RUN) { - if_printf(ifp, "restart happened when not in RUN state\n"); - goto reply; - } - - /* - * iwl2100_auth() may release slizer, so stop all - * callouts to prevent them from misfiring. - */ - callout_stop(&sc->sc_restart_bmiss); - callout_stop(&sc->sc_ibss); - - if (ic->ic_opmode == IEEE80211_M_STA) { - error = iwl2100_auth(sc); - if (error) - goto reply; - - /* - * Start software beacon missing to handle missing - * firmware bmiss status change when we restarting - */ - callout_reset(&sc->sc_restart_bmiss, IEEE80211_TU_TO_TICKS( - 2 * ic->ic_bmissthreshold * ic->ic_bss->ni_intval), - iwl2100_restart_bmiss, sc); - } else if (ic->ic_opmode == IEEE80211_M_IBSS) { - error = iwl2100_ibss(sc); - if (error) - goto reply; - } - - /* Turn on restarting flag before reply this message */ - sc->sc_flags |= IWL2100_F_RESTARTING; -reply: - lwkt_replymsg(&nmsg->nm_lmsg, error); -} - -static void -iwl2100_restart(struct iwl2100_softc *sc) -{ - if ((sc->sc_flags & (IWL2100_F_RESTARTING | IWL2100_F_DETACH)) == 0) { - struct iwlmsg *msg = &sc->sc_restart_msg; - struct lwkt_msg *lmsg = &msg->iwlm_nmsg.nm_lmsg; - - DPRINTF(sc, IWL2100_DBG_RESTART, "%s", "restart\n"); - if (lmsg->ms_flags & MSGF_DONE) { - sc->sc_flags &= ~IWL2100_F_IFSTART; - msg->iwlm_arg = sc->sc_state_age; - lwkt_sendmsg(&sc->sc_thread_port, lmsg); - } - } -} - -static void -iwl2100_bmiss_dispatch(struct netmsg *nmsg) -{ - struct iwlmsg *msg = (struct iwlmsg *)nmsg; - struct iwl2100_softc *sc = msg->iwlm_softc; - struct ieee80211com *ic = &sc->sc_ic; - struct ifnet *ifp = &ic->ic_if; - - ASSERT_SERIALIZED(ifp->if_serializer); - - if (sc->sc_flags & IWL2100_F_DETACH) - goto reply; - - if (ifp->if_flags & IFF_RUNNING) { - /* - * Fake a ic_bmiss_count to make sure that - * ieee80211_beacon_miss() will do its job - */ - ic->ic_bmiss_count = ic->ic_bmiss_max; - ieee80211_beacon_miss(ic); - } -reply: - lwkt_replymsg(&nmsg->nm_lmsg, 0); -} - -static void -iwl2100_restart_bmiss(void *xsc) -{ - struct iwl2100_softc *sc = xsc; - struct ifnet *ifp = &sc->sc_ic.ic_if; - - lwkt_serialize_enter(ifp->if_serializer); - - if (sc->sc_flags & IWL2100_F_DETACH) - goto back; - - if ((ifp->if_flags & IFF_RUNNING) == 0) - goto back; - - if (sc->sc_flags & IWL2100_F_RESTARTING) { - DPRINTF(sc, IWL2100_DBG_SCAN | IWL2100_DBG_RESTART, "%s", - "restart bmiss\n"); - iwlmsg_send(&sc->sc_bmiss_msg, &sc->sc_thread_port); - } -back: - lwkt_serialize_exit(ifp->if_serializer); -} - -static void -iwl2100_ibss_bssid(void *xsc) -{ - struct iwl2100_softc *sc = xsc; - struct ieee80211com *ic = &sc->sc_ic; - struct ifnet *ifp = &ic->ic_if; - char ethstr[ETHER_ADDRSTRLEN + 1]; - - lwkt_serialize_enter(ifp->if_serializer); - - if (sc->sc_flags & IWL2100_F_DETACH) - goto back; - - if ((ifp->if_flags & IFF_RUNNING) == 0) - goto back; - - if (ic->ic_state == IEEE80211_S_RUN && - ic->ic_opmode == IEEE80211_M_IBSS) { - uint8_t bssid[IEEE80211_ADDR_LEN]; - int len; - - len = iwl2100_read_ord2(sc, IWL2100_ORD2_BSSID, - bssid, sizeof(bssid)); - if (len < (int)sizeof(bssid)) { - if_printf(ifp, "can't get IBSS bssid\n"); - } else { - DPRINTF(sc, IWL2100_DBG_IBSS, "IBSS bssid: %s\n", - kether_ntoa(bssid, ethstr)); - IEEE80211_ADDR_COPY(ic->ic_bss->ni_bssid, bssid); - - sc->sc_flags |= IWL2100_F_IFSTART; - if_devstart(ifp); - } - } -back: - lwkt_serialize_exit(ifp->if_serializer); -} - -static void -iwl2100_reinit(struct iwl2100_softc *sc) -{ - struct ifnet *ifp = &sc->sc_ic.ic_if; - - callout_stop(&sc->sc_restart_bmiss); - callout_stop(&sc->sc_ibss); - - ifp->if_flags &= ~IFF_RUNNING; - ifp->if_timer = 0; - - sc->sc_flags &= ~IWL2100_F_INITED; - sc->sc_tx_timer = 0; - - /* Mark error happened, and wake up the pending command */ - sc->sc_flags |= IWL2100_F_ERROR; - wakeup(sc); - - if ((sc->sc_flags & IWL2100_F_DETACH) == 0) { - /* - * Schedule complete initialization, - * i.e. blow away current state - */ - iwlmsg_send(&sc->sc_reinit_msg, &sc->sc_thread_port); - } -} - -static void -iwl2100_reinit_dispatch(struct netmsg *nmsg) -{ - struct iwlmsg *msg = (struct iwlmsg *)nmsg; - struct iwl2100_softc *sc = msg->iwlm_softc; - struct ifnet *ifp = &sc->sc_ic.ic_if; - - ASSERT_SERIALIZED(ifp->if_serializer); - - /* - * NOTE: Reply ASAP, so reinit msg could be used if error intr - * happened again during following iwl2100_init() - */ - lwkt_replymsg(&nmsg->nm_lmsg, 0); - - if (sc->sc_flags & IWL2100_F_DETACH) - return; - - if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == IFF_UP) - iwl2100_init(sc); -} - -static void -iwl2100_reinit_callout(void *xsc) -{ - struct iwl2100_softc *sc = xsc; - struct ifnet *ifp = &sc->sc_ic.ic_if; - - lwkt_serialize_enter(ifp->if_serializer); - if ((sc->sc_flags & IWL2100_F_DETACH) == 0) - iwl2100_reinit(sc); - lwkt_serialize_exit(ifp->if_serializer); -} - -static void -iwl2100_chan_change(struct iwl2100_softc *sc, const struct ieee80211_channel *c) -{ - sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq = - htole16(c->ic_freq); -} - -static void -iwl2100_stop_callouts(struct iwl2100_softc *sc) -{ - callout_stop(&sc->sc_restart_bmiss); - callout_stop(&sc->sc_ibss); - callout_stop(&sc->sc_reinit); -} diff --git a/sys/dev/netif/iwl/iwl2100reg.h b/sys/dev/netif/iwl/iwl2100reg.h deleted file mode 100644 index 5895fbf5c0..0000000000 --- a/sys/dev/netif/iwl/iwl2100reg.h +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Copyright (c) 2008 The DragonFly Project. All rights reserved. - * - * This code is derived from software contributed to The DragonFly Project - * by Sepherosa Ziehau - * - * 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. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * 3. Neither the name of The DragonFly Project nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific, prior written permission. - * - * 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 MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, 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 DAMAGE. - * - * $DragonFly: src/sys/dev/netif/iwl/iwl2100reg.h,v 1.1 2008/03/05 14:10:39 sephe Exp $ - */ - -#ifndef _IWL2100REG_H -#define _IWL2100REG_H - -#include "if_iwlreg.h" - -#define IWL2100_NOISE_FLOOR -98 - -#define IWL2100_RTS_MAX 2304 - -/* - * PCI configuration registers - */ -#define IWL2100_PCIR_RETRY_TIMEOUT 0x41 - -/* - * EEPROM offsets - */ -#define IWL2100_EEPROM_MAC 0x21 -#define IWL2100_EEPROM_IBSS_CHANS 0x25 -#define IWL2100_EEPROM_CHANS 0x37 - -/* - * Registers and values - */ -#define IWL2100_INTR_STATUS 0x08 -#define IWL2100_INTR_MASK 0x0c -#define IWL2100_INTR_TX 0x00000001 -#define IWL2100_INTR_RX 0x00000002 -#define IWL2100_INTR_STATE_CHG 0x00000010 -#define IWL2100_INTR_CMD_DONE 0x00010000 -#define IWL2100_INTR_FW_INITED 0x01000000 -#define IWL2100_INTR_EFATAL 0x40000000 -#define IWL2100_INTR_EPARITY 0x80000000 -#define IWL2100_INTRS \ - (IWL2100_INTR_TX | \ - IWL2100_INTR_RX | \ - IWL2100_INTR_STATE_CHG | \ - IWL2100_INTR_CMD_DONE | \ - IWL2100_INTR_FW_INITED | \ - IWL2100_INTR_EFATAL | \ - IWL2100_INTR_EPARITY) - -#define IWL2100_IND_ADDR IWL_IND_ADDR -#define IWL2100_IND_DATA IWL_IND_DATA - -#define IWL2100_AUTOINC_ADDR 0x18 -#define IWL2100_AUTOINC_DATA 0x1c - -#define IWL2100_RESET 0x20 -#define IWL2100_RESET_DONE 0x001 -#define IWL2100_RESET_SW 0x080 -#define IWL2100_RESET_MASTER_STOPPED 0x100 -#define IWL2100_RESET_STOP_MASTER 0x200 - -#define IWL2100_CTRL 0x24 -#define IWL2100_CTRL_INITDONE 0x04 -#define IWL2100_CTRL_STANDBY 0x02 -#define IWL2100_CTRL_CLKREADY 0x01 - -#define IWL2100_GPIO 0x30 -#define IWL2100_GPIO_1_FWWR 0x00004 -#define IWL2100_GPIO_1_EN 0x00008 -#define IWL2100_GPIO_3_FWWR 0x00040 -#define IWL2100_GPIO_3_EN 0x00080 -#define IWL2100_GPIO_LEDOFF 0x02000 -#define IWL2100_GPIO_RFKILLED 0x10000 - -#define IWL2100_TXQ_ADDR 0x200 -#define IWL2100_TXQ_SIZE 0x204 -#define IWL2100_TXQ_READ_IDX 0x280 -#define IWL2100_TXQ_WRITE_IDX 0xf80 - -#define IWL2100_RXQ_ADDR 0x240 -#define IWL2100_RX_STATUS_ADDR 0x244 -#define IWL2100_RXQ_SIZE 0x248 -#define IWL2100_RXQ_READ_IDX 0x2a0 -#define IWL2100_RXQ_WRITE_IDX 0xfa0 - -#define IWL2100_ORD1_ADDR 0x380 -#define IWL2100_ORD2_ADDR 0x384 - -/* - * Indirect registers and values - */ -#define IWL2100_IND_CTRL 0x220000 - -#define IWL2100_IND_ERROR_INFO 0x2a7f0 -#define IWL2100_IND_ERRORADDR_MASK 0x3ffff - -#define IWL2100_IND_HALT 0x3000e0 -#define IWL2100_IND_HALT_HOLD 0x80000000 - -/* - * Shared memory - */ -#define IWL2100_SHMEM0 0x2f200 -#define IWL2100_SHMEM0_SIZE 0x310 - -#define IWL2100_SHMEM1 0x2f610 -#define IWL2100_SHMEM1_SIZE 0x20 - -#define IWL2100_SHMEM2 0x2fa00 -#define IWL2100_SHMEM2_SIZE 0x20 - -#define IWL2100_SHMEM3 0x2fc00 -#define IWL2100_SHMEM3_SIZE 0x10 - -#define IWL2100_SHMEM_INTR 0x2ff80 -#define IWL2100_SHMEM_INTR_SIZE 0x80 - -/* - * Offsets within ORDINAL1 - */ -#define IWL2100_ORD1_FWLOCK 120 -#define IWL2100_ORD1_CONF_START 157 -#define IWL2100_ORD1_TXRATE 192 -#define IWL2100_ORD1_DBADDR 204 - -/* - * Offsets within ORDINAL2 - */ -#define IWL2100_ORD2_BSSID 14 - -/* - * Firmware commands - */ -#define IWL2100_CMD_CONF_DONE 2 -#define IWL2100_CMD_SET_80211 6 -#define IWL2100_CFG_MONITOR 0x00004 -#define IWL2100_CFG_AUTO_PREAMBLE 0x00010 -#define IWL2100_CFG_IBSS_AUTO_START 0x00020 -#define IWL2100_CFG_ANS_BCAST_PROBE 0x00800 -#define IWL2100_CFG_8021X 0x04000 -#define IWL2100_CFG_STA 0x08000 -#define IWL2100_CFG_IBSS 0x10000 -#define IWL2100_CFG_CHANMASK 0x3fff -#define IWL2100_CMD_SET_ESSID 8 -#define IWL2100_CMD_SET_BSSID 9 -#define IWL2100_CMD_SET_ADDR 11 -#define IWL2100_CMD_SET_OPMODE 12 -#define IWL2100_OPMODE_STA 1 -#define IWL2100_OPMODE_MONITOR 2 -#define IWL2100_OPMODE_IBSS 3 -#define IWL2100_CMD_SET_CHAN 14 -#define IWL2100_CMD_SET_RTSTHRESHOLD 15 -#define IWL2100_CMD_SET_POWERSAVE 17 -#define IWL2100_CMD_SET_TXRATES 18 -#define IWL2100_CMD_SET_BASICRATES 19 -#define IWL2100_CMD_SET_WEPKEY 20 -#define IWL2100_CMD_SET_WEPTXKEY 25 -#define IWL2100_CMD_SET_PRIVACY 26 -#define IWL2100_PRIVACY_ENABLE 0x8 -#define IWL2100_CMD_SET_BINTVAL 29 -#define IWL2100_CMD_TX_DATA 33 -#define IWL2100_CMD_SET_TXPOWER 36 -#define IWL2100_CMD_SCAN 43 -#define IWL2100_CMD_CONF_START 44 -#define IWL2100_CMD_SET_SCANOPT 46 -#define IWL2100_SCANOPT_NOASSOC (1 << 0) -#define IWL2100_SCANOPT_MIXED (1 << 1) -#define IWL2100_SCANOPT_PASSIVE (1 << 3) -#define IWL2100_CMD_SET_MSDU_TXRATES 62 -#define IWL2100_CMD_SET_SECURITY 67 -#define IWL2100_CMD_SET_IE 69 - -#endif /* !_IWL2100REG_H */ diff --git a/sys/dev/netif/iwl/iwl2100var.h b/sys/dev/netif/iwl/iwl2100var.h deleted file mode 100644 index 433bf21eb8..0000000000 --- a/sys/dev/netif/iwl/iwl2100var.h +++ /dev/null @@ -1,363 +0,0 @@ -/* - * Copyright (c) 2008 The DragonFly Project. All rights reserved. - * - * This code is derived from software contributed to The DragonFly Project - * by Sepherosa Ziehau - * - * 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. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * 3. Neither the name of The DragonFly Project nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific, prior written permission. - * - * 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 MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, 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 DAMAGE. - * - * $DragonFly: src/sys/dev/netif/iwl/iwl2100var.h,v 1.2 2008/03/08 06:43:52 sephe Exp $ - */ - -#ifndef _IWL2100VAR_H -#define _IWL2100VAR_H - -#define IWL2100_DEBUG - -#define IWL2100_NSEG_MAX 6 -#define IWL2100_TX_NDESC 256 -#define IWL2100_RX_NDESC 256 - -#define IWL2100_SPARE_NDESC 6 -#define IWL2100_TX_USED_MAX (IWL2100_TX_NDESC - IWL2100_SPARE_NDESC) - -#define IWL2100_TXRING_SIZE (IWL2100_TX_NDESC * sizeof(struct iwl2100_desc)) -#define IWL2100_RXRING_SIZE (IWL2100_RX_NDESC * sizeof(struct iwl2100_desc)) -#define IWL2100_RXSTATUS_SIZE \ - (IWL2100_RX_NDESC * sizeof(struct iwl2100_rx_status)) - -#ifndef IWL2100_DEBUG -#define DPRINTF(sc, flags, fmt, ...) ((void)0) -#else -#define DPRINTF(sc, flags, fmt, ...) \ -do { \ - if ((sc)->sc_debug & (flags)) \ - if_printf(&(sc)->sc_ic.ic_if, fmt, __VA_ARGS__); \ -} while (0) -#endif /* !IWL2100_DEBUG */ - -struct iwl2100_desc { - uint32_t d_paddr; - uint32_t d_len; - uint8_t d_flags; /* IWL2100_TXD_F_ */ - uint8_t d_nfrag; - uint8_t d_reserved[6]; -} __packed; - -#define IWL2100_TXD_F_NOTLAST 0x1 -#define IWL2100_TXD_F_CMD 0x2 -#define IWL2100_TXD_F_INTR 0x8 - -struct iwl2100_tx_hdr { - uint32_t th_cmd; - uint32_t th_cmd1; - uint8_t th_host_enc; - uint8_t th_enc; - uint8_t th_keyidx; - uint8_t th_keysz; - uint8_t th_key[IEEE80211_KEYBUF_SIZE]; - uint8_t th_reserved[10]; - uint8_t th_src[IEEE80211_ADDR_LEN]; - uint8_t th_dst[IEEE80211_ADDR_LEN]; - uint16_t th_frag_size; -} __packed; - -struct iwl2100_rx_status { - uint32_t r_len; - uint16_t r_status; /* IWL2100_RXS_ */ - uint8_t r_flags; - uint8_t r_rssi; -} __packed; - -#define IWL2100_RXS_TYPE_MASK 0xf -#define IWL2100_RXS_TYPE_CMD 0 -#define IWL2100_RXS_TYPE_STATUS 1 -#define IWL2100_RXS_TYPE_DATA 2 -#define IWL2100_RXS_TYPE_DATA1 3 -#define IWL2100_RXS_TYPE_NOTE 4 - -#define IWL2100_STATUS_RUNNING (1 << 2) -#define IWL2100_STATUS_BMISS (1 << 3) -#define IWL2100_STATUS_SCANDONE (1 << 5) -#define IWL2100_STATUS_SCANNING (1 << 11) - -struct iwl2100_note { - uint32_t nt_subtype; - uint32_t nt_size; -} __packed; - -#define IWL2100_CMD_PARAMSZ 100 - -struct iwl2100_cmd { - uint32_t c_cmd; - uint32_t c_cmd1; - uint32_t c_seq; - uint32_t c_param_len; - uint32_t c_param[IWL2100_CMD_PARAMSZ]; - uint32_t c_status; - uint32_t c_unused[17]; -} __packed; - -struct iwl2100_cmdparam_sec { - uint32_t sec_cipher_mask; /* IWL2100_CIPHER_ */ - uint16_t sec_ver; - uint8_t sec_authmode; /* IWL2100_AUTH_ */ - uint8_t sec_replay_counter; - uint8_t sec_unused; -} __packed; - -#define IWL2100_CIPHER_NONE (1 << 0) -#define IWL2100_CIPHER_WEP40 (1 << 1) -#define IWL2100_CIPHER_TKIP (1 << 2) -#define IWL2100_CIPHER_CCMP (1 << 4) -#define IWL2100_CIPHER_WEP104 (1 << 5) - -#define IWL2100_AUTH_OPEN 0 -#define IWL2100_AUTH_SHARED 1 - -#define IWL2100_KEYDATA_SIZE 13 - -struct iwl2100_cmdparam_wepkey { - uint8_t key_index; - uint8_t key_len; - uint8_t key_data[IWL2100_KEYDATA_SIZE]; -} __packed; - -/* 16: ie_fixed_mask + ie_fixed + ie_optlen */ -#define IWL2100_OPTIE_MAX ((IWL2100_CMD_PARAMSZ * sizeof(uint32_t)) - 16) - -struct iwl2100_cmdparam_ie { - uint16_t ie_fixed_mask; - struct { - uint16_t cap_info; - uint16_t lintval; - uint8_t bssid[IEEE80211_ADDR_LEN]; - } ie_fixed; - uint32_t ie_optlen; - uint8_t ie_opt[IWL2100_OPTIE_MAX]; -} __packed; - -struct iwl2100_ucode_resp { - uint8_t cmd_id; - uint8_t seq_no; - uint8_t ucode_rev; - uint8_t eeprom_valid; - uint16_t valid_flags; - uint8_t addr[6]; - uint16_t flags; - uint16_t pcb_rev; - uint16_t clk_settle_time; - uint16_t pwr_settle_time; - uint16_t hop_settle_time; - uint8_t date_time[5]; - uint8_t ucode_valid; -} __packed; - -struct iwl2100_fwdata_hdr { - uint32_t addr; - uint16_t len; - uint8_t data[1]; -} __packed; - -struct iwl2100_fwimg_hdr { - uint16_t version; - uint16_t mode; /* IWL2100_FW_M_ */ - uint32_t data_size; - uint32_t ucode_size; -} __packed; - -#define IWL2100_FW_M_STA 0 -#define IWL2100_FW_M_IBSS 1 -#define IWL2100_FW_M_MONITOR 2 - -struct iwl2100_txbuf { - struct mbuf *tb_mbuf; - bus_dmamap_t tb_dmap; - uint32_t tb_flags; /* IWL2100_TBF_ */ -}; - -#define IWL2100_TBF_CMDBUF 0x1 - -struct iwl2100_rxbuf { - struct mbuf *rb_mbuf; - bus_dmamap_t rb_dmap; - bus_addr_t rb_paddr; -}; - -struct iwl2100_tx_ring { - bus_dma_tag_t tr_dtag; - bus_dmamap_t tr_dmap; - bus_addr_t tr_paddr; - struct iwl2100_desc *tr_desc; - - int tr_used; - int tr_index; - int tr_coll; - - struct iwl2100_txbuf tr_buf[IWL2100_TX_NDESC]; -}; - -struct iwl2100_rx_ring { - bus_dma_tag_t rr_dtag; - bus_dmamap_t rr_dmap; - bus_addr_t rr_paddr; - struct iwl2100_desc *rr_desc; - - bus_dma_tag_t rr_st_dtag; - bus_dmamap_t rr_st_dmap; - bus_addr_t rr_st_paddr; - struct iwl2100_rx_status *rr_status; - - int rr_index; - - bus_dmamap_t rr_tmp_dmap; - struct iwl2100_rxbuf rr_buf[IWL2100_RX_NDESC]; -}; - -struct fw_image; - -struct iwl2100_firmware { - struct fw_image *fw_image; - const uint8_t *fw_data; - int fw_data_size; - const uint8_t *fw_ucode; - int fw_ucode_size; -}; - -#define IWL2100_TX_RADIOTAP_PRESENT \ - ((1 << IEEE80211_RADIOTAP_FLAGS) | \ - (1 << IEEE80211_RADIOTAP_CHANNEL)) - -struct iwl2100_tx_radiotap_hdr { - struct ieee80211_radiotap_header wt_ihdr; - uint8_t wt_flags; - uint16_t wt_chan_freq; - uint16_t wt_chan_flags; -}; - -#define IWL2100_RX_RADIOTAP_PRESENT \ - ((1 << IEEE80211_RADIOTAP_FLAGS) | \ - (1 << IEEE80211_RADIOTAP_CHANNEL) | \ - (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | \ - (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE)) - -struct iwl2100_rx_radiotap_hdr { - struct ieee80211_radiotap_header wr_ihdr; - uint8_t wr_flags; - uint16_t wr_chan_freq; - uint16_t wr_chan_flags; - int8_t wr_antsignal; - int8_t wr_antnoise; -}; - -struct iwl2100_softc { - struct iwlcom iwlcom; - - uint32_t sc_ord1; - uint32_t sc_ord2; - uint32_t sc_caps; /* IWL2100_C_ */ - uint32_t sc_flags; /* IWL2100_F_ */ - int sc_state_age; - - uint16_t sc_ibss_chans; - uint16_t sc_bss_chans; - - bus_dma_tag_t sc_dtag; - bus_dma_tag_t sc_mbuf_dtag; - struct iwl2100_tx_ring sc_txring; - struct iwl2100_rx_ring sc_rxring; - - struct iwl2100_firmware sc_fw_sta; - struct iwl2100_firmware sc_fw_ibss; - struct iwl2100_firmware sc_fw_monitor; - - struct mbuf *sc_cmd; - - struct callout sc_restart_bmiss; - struct callout sc_ibss; - struct callout sc_reinit; - - struct iwlmsg sc_scanend_msg; - struct iwlmsg sc_assoc_msg; - struct iwlmsg sc_run_msg; - struct iwlmsg sc_restart_msg; - struct iwlmsg sc_bmiss_msg; - struct iwlmsg sc_reinit_msg; - - struct bpf_if *sc_drvbpf; - - union { - struct iwl2100_tx_radiotap_hdr u_tx_th; - uint8_t u_pad[IEEE80211_RADIOTAP_HDRLEN]; - } sc_u_tx_th; - int sc_tx_th_len; - - union { - struct iwl2100_rx_radiotap_hdr u_rx_th; - uint8_t u_pad[IEEE80211_RADIOTAP_HDRLEN]; - } sc_u_rx_th; - int sc_rx_th_len; - - int (*sc_newstate) - (struct ieee80211com *, - enum ieee80211_state, int); - - /* - * Sysctl variables - */ - uint32_t sc_debug; /* IWL2100_DBG_ */ -}; - -#define IWL2100_C_RFKILL 0x1 - -#define IWL2100_F_WAITCMD 0x1 -#define IWL2100_F_INITED 0x2 -#define IWL2100_F_IN_INTR 0x4 /* for sanity check */ -#define IWL2100_F_SCANNING 0x8 -#define IWL2100_F_RESTARTING 0x10 -#define IWL2100_F_IFSTART 0x20 /* if_start could run */ -#define IWL2100_F_ERROR 0x40 -#define IWL2100_F_ZERO_CMD 0x80 -#define IWL2100_F_DETACH 0x100 /* detaching */ - -#define IWL2100_DBG_IBSS 0x01 -#define IWL2100_DBG_SCAN 0x02 -#define IWL2100_DBG_STATUS 0x04 -#define IWL2100_DBG_RESTART 0x08 -#define IWL2100_DBG_NOTE 0x10 -#define IWL2100_DBG_CMD 0x20 - -#define IWL2100_PCIR_BAR PCIR_BAR(0) -#define IWL2100_DESC "Intel PRO/Wireless LAN 2100" -#define IWL2100_FW_PATH IWL_FW_PATH "2100/1.3/ipw2100-1.3%s.fw" - -int iwl2100_attach(device_t); -void iwl2100_detach(device_t); -int iwl2100_shutdown(device_t); - -#endif /* _IWL2100VAR_H */ diff --git a/sys/dev/netif/rtw/Makefile b/sys/dev/netif/rtw/Makefile deleted file mode 100644 index db0c929d1b..0000000000 --- a/sys/dev/netif/rtw/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -KMOD = if_rtw - -SRCS = if_rtw_pci.c smc93cx6.c rtwphyio.c rtwphy.c rtw.c -SRCS += device_if.h bus_if.h pci_if.h pcidevs.h opt_aic7xxx.h - -.if !defined(BUILDING_WITH_KERNEL) -opt_aic7xxx.h: - echo "" > ${.TARGET} -.endif - -.include diff --git a/sys/dev/netif/rtw/if_rtw_pci.c b/sys/dev/netif/rtw/if_rtw_pci.c deleted file mode 100644 index 5ef611736c..0000000000 --- a/sys/dev/netif/rtw/if_rtw_pci.c +++ /dev/null @@ -1,261 +0,0 @@ -/* - * Copyright (c) 2006 The DragonFly Project. All rights reserved. - * - * This code is derived from software contributed to The DragonFly Project - * by Sepherosa Ziehau - * - * 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. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * 3. Neither the name of The DragonFly Project nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific, prior written permission. - * - * 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 MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, 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 DAMAGE. - * - * $NetBSD: if_rtw_pci.c,v 1.4 2005/12/04 17:44:02 christos Exp $ - */ - -/* - * Copyright (c) 1998, 1999, 2000, 2002 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, - * NASA Ames Research Center; Charles M. Hannum; and David Young. - * - * 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. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 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 DAMAGE. - */ - -/* - * PCI bus front-end for the Realtek RTL8180 802.11 MAC/BBP chip. - */ - -#include -#include -#include -#include -#include - -#include -#include -#include "pcidevs.h" - -#include -#include -#include - -#include -#include -#include - -#include -#include -#include - -/* - * PCI configuration space registers - */ -#define RTW_PCI_IOBA 0x10 /* i/o mapped base */ -#define RTW_PCI_MMBA 0x14 /* memory mapped base */ - -static const struct rtw_pci_reg { - int reg_type; - int reg_rid; -} rtw_pci_regs[] = { - /* Prefer IO memory over IO port */ - { SYS_RES_MEMORY, RTW_PCI_MMBA }, - { SYS_RES_IOPORT, RTW_PCI_IOBA } -}; - -static const struct rtw_pci_product { - uint16_t app_vendor; /* PCI vendor ID */ - uint16_t app_product; /* PCI product ID */ - const char *app_product_name; -} rtw_pci_products[] = { - { PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8180, - "Realtek RTL8180 802.11 MAC/BBP" }, - { PCI_VENDOR_BELKIN, PCI_PRODUCT_BELKIN_F5D6001, - "Belkin F5D6001" }, - - { 0, 0, NULL } -}; - -static int rtw_pci_probe(device_t); -static int rtw_pci_attach(device_t); -static int rtw_pci_detach(device_t); -static int rtw_pci_shutdown(device_t); - -static device_method_t rtw_pci_methods[] = { - DEVMETHOD(device_probe, rtw_pci_probe), - DEVMETHOD(device_attach, rtw_pci_attach), - DEVMETHOD(device_detach, rtw_pci_detach), - DEVMETHOD(device_shutdown, rtw_pci_shutdown), -#if 0 - DEVMETHOD(device_suspend, rtw_pci_suspend), - DEVMETHOD(device_resume, rtw_pci_resume), -#endif - DEVMETHOD_END -}; - -static driver_t rtw_pci_driver = { - "rtw", - rtw_pci_methods, - sizeof(struct rtw_softc) -}; - -DRIVER_MODULE(rtw, pci, rtw_pci_driver, rtw_devclass, NULL, NULL); -DRIVER_MODULE(rtw, cardbus, rtw_pci_driver, rtw_devclass, NULL, NULL); - -MODULE_DEPEND(rtw, wlan, 1, 1, 1); -MODULE_DEPEND(rtw, wlan_ratectl_onoe, 1, 1, 1); -MODULE_DEPEND(rtw, pci, 1, 1, 1); -MODULE_DEPEND(rtw, cardbus, 1, 1, 1); - -static int -rtw_pci_probe(device_t dev) -{ - const struct rtw_pci_product *app; - uint16_t vid, did; - - vid = pci_get_vendor(dev); - did = pci_get_device(dev); - for (app = rtw_pci_products; app->app_product_name != NULL; app++) { - if (vid == app->app_vendor && did == app->app_product) { - device_set_desc(dev, app->app_product_name); - return 0; - } - } - return ENXIO; -} - -static int -rtw_pci_attach(device_t dev) -{ - struct rtw_softc *sc = device_get_softc(dev); - struct rtw_regs *regs = &sc->sc_regs; - int i, error; - - /* - * No power management hooks. - * XXX Maybe we should add some! - */ - sc->sc_flags |= RTW_F_ENABLED; - - sc->sc_rev = pci_get_revid(dev); - -#ifndef BURN_BRIDGES - if (pci_get_powerstate(dev) != PCI_POWERSTATE_D0) { - uint32_t mem, port, irq; - - mem = pci_read_config(dev, RTW_PCI_MMBA, 4); - port = pci_read_config(dev, RTW_PCI_IOBA, 4); - irq = pci_read_config(dev, PCIR_INTLINE, 4); - - device_printf(dev, "chip is in D%d power mode " - "-- setting to D0\n", pci_get_powerstate(dev)); - - pci_set_powerstate(dev, PCI_POWERSTATE_D0); - - pci_write_config(dev, RTW_PCI_MMBA, mem, 4); - pci_write_config(dev, RTW_PCI_IOBA, port, 4); - pci_write_config(dev, PCIR_INTLINE, irq, 4); - } -#endif /* !BURN_BRIDGES */ - - /* Enable PCI bus master */ - pci_enable_busmaster(dev); - - /* Allocate IO memory/port */ - for (i = 0; i < NELEM(rtw_pci_regs); ++i) { - regs->r_rid = rtw_pci_regs[i].reg_rid; - regs->r_type = rtw_pci_regs[i].reg_type; - regs->r_res = bus_alloc_resource_any(dev, regs->r_type, - ®s->r_rid, RF_ACTIVE); - if (regs->r_res != NULL) - break; - } - if (regs->r_res == NULL) { - device_printf(dev, "can't allocate IO mem/port\n"); - return ENXIO; - } - regs->r_bh = rman_get_bushandle(regs->r_res); - regs->r_bt = rman_get_bustag(regs->r_res); - - error = rtw_attach(dev); - if (error) - rtw_pci_detach(dev); - return error; -} - -static int -rtw_pci_detach(device_t dev) -{ - struct rtw_softc *sc = device_get_softc(dev); - struct rtw_regs *regs = &sc->sc_regs; - - if (device_is_attached(dev)) - rtw_detach(dev); - - if (regs->r_res != NULL) { - bus_release_resource(dev, regs->r_type, regs->r_rid, - regs->r_res); - } - return 0; -} - -static int -rtw_pci_shutdown(device_t dev) -{ - struct rtw_softc *sc = device_get_softc(dev); - struct ifnet *ifp = &sc->sc_ic.ic_if; - - lwkt_serialize_enter(ifp->if_serializer); - rtw_stop(sc, 1); - lwkt_serialize_exit(ifp->if_serializer); - return 0; -} diff --git a/sys/dev/netif/rtw/max2820reg.h b/sys/dev/netif/rtw/max2820reg.h deleted file mode 100644 index 79bdaaf9d3..0000000000 --- a/sys/dev/netif/rtw/max2820reg.h +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright (c) 2004 David Young. All rights reserved. - * - * This code was written by David Young. - * - * 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. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY David Young ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL David - * Young BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 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 DAMAGE. - * - * $NetBSD: max2820reg.h,v 1.5 2006/03/08 08:26:50 dyoung Exp $ - * $DragonFly: src/sys/dev/netif/rtw/max2820reg.h,v 1.2 2007/10/14 04:15:17 sephe Exp $ - */ - -#ifndef _DEV_IC_MAX2820REG_H_ -#define _DEV_IC_MAX2820REG_H_ - -/* - * Serial bus format for Maxim MAX2820/MAX2820A/MAX2821/MAX2821A - * 2.4GHz 802.11b Zero-IF Transceivers - */ -#define MAX2820_TWI_ADDR_MASK __BITS(15,12) -#define MAX2820_TWI_DATA_MASK __BITS(11,0) - -/* - * Registers for Maxim MAX2820/MAX2820A/MAX2821/MAX2821A 2.4GHz - * 802.11b Zero-IF Transceivers - */ -#define MAX2820_TEST 0 /* Test Register */ -#define MAX2820_TEST_DEFAULT __BITS(2,0) /* Always set to this value. */ - -#define MAX2820_ENABLE 1 /* Block-Enable Register */ -#define MAX2820_ENABLE_RSVD1 __BIT(11) /* reserved */ -#define MAX2820_ENABLE_PAB __BIT(10) /* Transmit Baseband Filters - * Enable - * PAB_EN = SHDNB && - * (MAX2820_ENABLE_PAB || - * TX_ON) - */ -#define MAX2820_ENABLE_TXFLT __BIT(9) /* Transmit Baseband Filters - * Enable - * TXFLT_EN = SHDNB && - * (MAX2820_ENABLE_TXFLT || - * TX_ON) - */ -#define MAX2820_ENABLE_TXUVD __BIT(8) /* Tx Upconverter, VGA, and - * Driver Amp Enable - * TXUVD_EN = SHDNB && - * (MAX2820_ENABLE_TXUVD || - * TX_ON) - */ -#define MAX2820_ENABLE_DET __BIT(7) /* Receive Detector Enable - * DET_EN = SHDNB && - * (MAX2820_ENABLE_DET || - * RX_ON) - */ -#define MAX2820_ENABLE_RXDFA __BIT(6) /* Rx Downconverter, Filters, - * and AGC Amps Enable - * RXDFA_EN = SHDNB && - * (MAX2820_ENABLE_RXDFA || - * RX_ON) - */ -#define MAX2820_ENABLE_RXLNA __BIT(5) /* Receive LNA Enable - * AT_EN = SHDNB && - * (MAX2820_ENABLE_RXLNA || - * RX_ON) - */ -#define MAX2820_ENABLE_AT __BIT(4) /* Auto-tuner Enable - * AT_EN = SHDNB && - * (MAX2820_ENABLE_AT || - * RX_ON || TX_ON) - */ -#define MAX2820_ENABLE_CP __BIT(3) /* PLL Charge-Pump Enable - * CP_EN = SHDNB - * && MAX2820_ENABLE_CP - */ -#define MAX2820_ENABLE_PLL __BIT(2) /* PLL Enable - * PLL_EN = SHDNB - * && MAX2820_ENABLE_PLL - */ -#define MAX2820_ENABLE_VCO __BIT(1) /* VCO Enable - * VCO_EN = SHDNB - * && MAX2820_ENABLE_VCO - */ -#define MAX2820_ENABLE_RSVD0 __BIT(0) /* reserved */ -#define MAX2820_ENABLE_DEFAULT (MAX2820_ENABLE_AT|MAX2820_ENABLE_CP|\ - MAX2820_ENABLE_PLL|MAX2820_ENABLE_VCO) - -#define MAX2820_SYNTH 2 /* Synthesizer Register */ -#define MAX2820_SYNTH_RSVD0 __BITS(11,7) /* reserved */ -#define MAX2820_SYNTH_ICP __BIT(6) /* Charge-Pump Current Select - * 0 = +/-1mA - * 1 = +/-2mA - */ -#define MAX2820_SYNTH_R_MASK __BITS(5,0) /* Reference Frequency Divider - * 0 = 22MHz - * 1 = 44MHz - */ -#define MAX2820_SYNTH_R_22MHZ __SHIFTIN(0, MAX2820_SYNTH_R_MASK) -#define MAX2820_SYNTH_R_44MHZ __SHIFTIN(1, MAX2820_SYNTH_R_MASK) -#define MAX2820_SYNTH_ICP_DEFAULT MAX2820_SYNTH_ICP -#define MAX2820_SYNTH_R_DEFAULT __SHIFTIN(0, MAX2820_SYNTH_R_MASK) - -#define MAX2820_CHANNEL 3 /* Channel Frequency Register */ -#define MAX2820_CHANNEL_RSVD __BITS(11,7) /* reserved */ -#define MAX2820_CHANNEL_CF_MASK __BITS(6,0) /* Channel Frequency Select - * fLO = 2400MHz + CF * 1MHz - */ -#define MAX2820_CHANNEL_RSVD_DEFAULT __SHIFTIN(0, MAX2820_CHANNEL_RSVD) -#define MAX2820_CHANNEL_CF_DEFAULT __SHIFTIN(37, MAX2820_CHANNEL_CF_MASK) - -#define MAX2820_RECEIVE 4 /* Receiver Settings Register - * MAX2820/MAX2821 - */ -#define MAX2820_RECEIVE_2C_MASK __BITS(11,9) /* VGA DC Offset Nulling - * Parameter 2 - */ -#define MAX2820_RECEIVE_1C_MASK __BITS(8,6) /* VGA DC Offset Nulling - * Parameter 1 - */ -#define MAX2820_RECEIVE_DL_MASK __BITS(5,4) /* Rx Level Detector Midpoint - * Select - * 11, 01 = 50.2mVp - * 10 = 70.9mVp - * 00 = 35.5mVp - */ -#define MAX2820_RECEIVE_SF __BIT(3) /* Special Function Select - * 0 = OFF - * 1 = ON - */ -#define MAX2820_RECEIVE_BW_MASK __BITS(2,0) /* Receive Filter -3dB Frequency - * Select (all frequencies are - * approximate) - */ -/* 8.5MHz */ -#define MAX2820_RECEIVE_BW_8_5MHZ __SHIFTIN(0, MAX2820_RECEIVE_BW_MASK) -#define MAX2820_RECEIVE_BW_8MHZ __SHIFTIN(1, MAX2820_RECEIVE_BW_MASK) -#define MAX2820_RECEIVE_BW_7_5MHZ __SHIFTIN(2, MAX2820_RECEIVE_BW_MASK) -#define MAX2820_RECEIVE_BW_7MHZ __SHIFTIN(3, MAX2820_RECEIVE_BW_MASK) -#define MAX2820_RECEIVE_BW_6_5MHZ __SHIFTIN(4, MAX2820_RECEIVE_BW_MASK) -#define MAX2820_RECEIVE_BW_6MHZ __SHIFTIN(5, MAX2820_RECEIVE_BW_MASK) -#define MAX2820_RECEIVE_2C_DEFAULT __SHIFTIN(7, MAX2820_RECEIVE_2C_MASK) -#define MAX2820_RECEIVE_1C_DEFAULT __SHIFTIN(7, MAX2820_RECEIVE_1C_MASK) -#define MAX2820_RECEIVE_DL_DEFAULT __SHIFTIN(1, MAX2820_RECEIVE_DL_MASK) -#define MAX2820_RECEIVE_SF_DEFAULT __SHIFTIN(0, MAX2820_RECEIVE_SF) -#define MAX2820_RECEIVE_BW_DEFAULT MAX2820_RECEIVE_BW_7_5MHZ - -#define MAX2820A_RECEIVE 4 /* Receiver Settings Register, - * MAX2820A/MAX2821A - */ -/* VGA DC Offset Nulling Parameter 2 */ -#define MAX2820A_RECEIVE_2C_MASK __BITS(11,9) -#define MAX2820A_RECEIVE_2C_DEFAULT __SHIFTIN(7, MAX2820A_RECEIVE_2C_MASK) -/* VGA DC Offset Nulling Parameter 1 */ -#define MAX2820A_RECEIVE_1C_MASK __BITS(8,6) -#define MAX2820A_RECEIVE_1C_DEFAULT __SHIFTIN(7, MAX2820A_RECEIVE_1C_MASK) -#define MAX2820A_RECEIVE_RSVD0_MASK __BITS(5,3) -#define MAX2820A_RECEIVE_RSVD0_DEFAULT __SHIFTIN(2, MAX2820A_RECEIVE_RSVD0_MASK) -#define MAX2820A_RECEIVE_RSVD1_MASK __BITS(2,0) -#define MAX2820A_RECEIVE_RSVD1_DEFAULT __SHIFTIN(2,MAX2820_RECEIVE_RSVD1_MASK) - -#define MAX2820_TRANSMIT 5 /* Transmitter Settings Reg. */ -#define MAX2820_TRANSMIT_RSVD_MASK __BITS(11,4) /* reserved */ -#define MAX2820_TRANSMIT_PA_MASK __BITS(3,0) /* PA Bias Select - * 15 = Highest - * 0 = Lowest - */ -#define MAX2820_TRANSMIT_PA_DEFAULT __SHIFTIN(0, MAX2820_TRANSMIT_PA_MASK) - -#endif /* _DEV_IC_MAX2820REG_H_ */ diff --git a/sys/dev/netif/rtw/rtw.c b/sys/dev/netif/rtw/rtw.c deleted file mode 100644 index 297dd1094e..0000000000 --- a/sys/dev/netif/rtw/rtw.c +++ /dev/null @@ -1,4545 +0,0 @@ -/* - * Copyright (c) 2006 The DragonFly Project. All rights reserved. - * - * This code is derived from software contributed to The DragonFly Project - * by Sepherosa Ziehau - * - * 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. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * 3. Neither the name of The DragonFly Project nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific, prior written permission. - * - * 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 MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, 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 DAMAGE. - * - * $NetBSD: rtw.c,v 1.72 2006/03/28 00:48:10 dyoung Exp $ - */ - -/* - * Copyright (c) 2004, 2005 David Young. All rights reserved. - * - * Programmed for NetBSD by David Young. - * - * 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. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of David Young may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY David Young ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL David - * Young BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 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 DAMAGE. - */ - -/* - * Device driver for the Realtek RTL8180 802.11 MAC/BBP. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -/* XXX */ -#define IEEE80211_DUR_DS_LONG_PREAMBLE 144 -#define IEEE80211_DUR_DS_SHORT_PREAMBLE 72 -#define IEEE80211_DUR_DS_SLOW_PLCPHDR 48 -#define IEEE80211_DUR_DS_FAST_PLCPHDR 24 -#define IEEE80211_DUR_DS_SLOW_ACK 112 -#define IEEE80211_DUR_DS_SLOW_CTS 112 -#define IEEE80211_DUR_DS_SIFS 10 - -struct rtw_txsegs { - int nseg; - bus_dma_segment_t segs[RTW_MAXPKTSEGS]; -}; - -devclass_t rtw_devclass; - -static const struct ieee80211_rateset rtw_rates_11b = { 4, { 2, 4, 11, 22 } }; - -SYSCTL_NODE(_hw, OID_AUTO, rtw, CTLFLAG_RD, 0, - "Realtek RTL818x 802.11 controls"); - -/* [0, __SHIFTOUT(RTW_CONFIG4_RFTYPE_MASK, RTW_CONFIG4_RFTYPE_MASK)] */ -static int rtw_rfprog_fallback = 0; -SYSCTL_INT(_hw_rtw, OID_AUTO, rfprog_fallback, CTLFLAG_RW, - &rtw_rfprog_fallback, 0, "fallback RF programming method"); - -static int rtw_host_rfio = 0; /* 0/1 */ -SYSCTL_INT(_hw_rtw, OID_AUTO, host_rfio, CTLFLAG_RW, - &rtw_host_rfio, 0, "enable host control of RF I/O"); - -#ifdef RTW_DEBUG -int rtw_debug = 0; /* [0, RTW_DEBUG_MAX] */ -SYSCTL_INT(_hw_rtw, OID_AUTO, debug, CTLFLAG_RW, &rtw_debug, 0, "debug level"); - -static int rtw_rxbufs_limit = RTW_RXQLEN; /* [0, RTW_RXQLEN] */ -SYSCTL_INT(_hw_rtw, OID_AUTO, rxbufs_limit, CTLFLAG_RW, &rtw_rxbufs_limit, 0, - "rx buffers limit"); -#endif /* RTW_DEBUG */ - -#if 0 -static int rtw_xmtr_restart = 0; -SYSCTL_INT(_hw_rtw, OID_AUTO, xmtr_restart, CTLFLAG_RW, &rtw_xmtr_restart, 0, - "gratuitously reset xmtr on rcvr error"); - -static int rtw_ring_reset = 0; -SYSCTL_INT(_hw_rtw, OID_AUTO, ring_reset, CTLFLAG_RW, &rtw_ring_reset, 0, - "reset ring pointers on rcvr error"); -#endif - -static int rtw_do_chip_reset = 0; -SYSCTL_INT(_hw_rtw, OID_AUTO, chip_reset, CTLFLAG_RW, &rtw_do_chip_reset, 0, - "gratuitously reset chip on rcvr error"); - -int rtw_dwelltime = 200; /* milliseconds */ - -/* XXX */ -static struct ieee80211_cipher rtw_cipher_wep; - -static void rtw_led_init(struct rtw_softc *); -static void rtw_led_newstate(struct rtw_softc *, enum ieee80211_state); -static void rtw_led_slowblink(void *); -static void rtw_led_fastblink(void *); -static void rtw_led_set(struct rtw_softc *); - -static void rtw_init(void *); -static void rtw_start(struct ifnet *, struct ifaltq_subque *); -static int rtw_ioctl(struct ifnet *, u_long, caddr_t, struct ucred *); -static void rtw_watchdog(struct ifnet *); -static void rtw_intr(void *); - -static void rtw_intr_rx(struct rtw_softc *, uint16_t); -static void rtw_intr_tx(struct rtw_softc *, uint16_t); -static void rtw_intr_beacon(struct rtw_softc *, uint16_t); -static void rtw_intr_atim(struct rtw_softc *); -static void rtw_intr_ioerror(struct rtw_softc *, uint16_t); -static void rtw_intr_timeout(struct rtw_softc *); - -static int rtw_dequeue(struct ifnet *, struct rtw_txsoft_blk **, - struct rtw_txdesc_blk **, struct mbuf **, - struct ieee80211_node **); -static struct mbuf *rtw_load_txbuf(struct rtw_softc *, struct rtw_txsoft *, - struct rtw_txsegs *, int, struct mbuf *); - -static void rtw_idle(struct rtw_softc *); -static void rtw_txring_fixup(struct rtw_softc *); -static void rtw_rxring_fixup(struct rtw_softc *); -static int rtw_txring_next(struct rtw_regs *, struct rtw_txdesc_blk *); -static void rtw_reset_oactive(struct rtw_softc *); - -static int rtw_enable(struct rtw_softc *); -static void rtw_disable(struct rtw_softc *); -static void rtw_io_enable(struct rtw_softc *, uint8_t, int); -static int rtw_pwrstate(struct rtw_softc *, enum rtw_pwrstate); -static void rtw_set_access(struct rtw_softc *, enum rtw_access); - -static void rtw_continuous_tx_enable(struct rtw_softc *, int); -static void rtw_txdac_enable(struct rtw_softc *, int); -static void rtw_anaparm_enable(struct rtw_regs *, int); -static void rtw_config0123_enable(struct rtw_regs *, int); - -static void rtw_transmit_config(struct rtw_regs *); -static void rtw_set_rfprog(struct rtw_softc *); -static void rtw_enable_interrupts(struct rtw_softc *); -static void rtw_pktfilt_load(struct rtw_softc *); -static void rtw_wep_setkeys(struct rtw_softc *); -static void rtw_resume_ticks(struct rtw_softc *); -static void rtw_set_nettype(struct rtw_softc *, enum ieee80211_opmode); - -static int rtw_reset(struct rtw_softc *); -static int rtw_chip_reset(struct rtw_softc *); -static int rtw_recall_eeprom(struct rtw_softc *); -static int rtw_srom_read(struct rtw_softc *); -static int rtw_srom_parse(struct rtw_softc *); -static struct rtw_rf *rtw_rf_attach(struct rtw_softc *, enum rtw_rfchipid, int); - -static uint8_t rtw_check_phydelay(struct rtw_regs *, uint32_t); -static void rtw_identify_country(struct rtw_softc *); -static int rtw_identify_sta(struct rtw_softc *); - -static int rtw_swring_setup(struct rtw_softc *); -static void rtw_hwring_setup(struct rtw_softc *); - -static int rtw_desc_blk_alloc(struct rtw_softc *); -static void rtw_desc_blk_free(struct rtw_softc *); -static int rtw_soft_blk_alloc(struct rtw_softc *); -static void rtw_soft_blk_free(struct rtw_softc *); - -static void rtw_txdesc_blk_init_all(struct rtw_softc *); -static void rtw_txsoft_blk_init_all(struct rtw_softc *); -static void rtw_rxdesc_blk_init_all(struct rtw_softc *); -static int rtw_rxsoft_blk_init_all(struct rtw_softc *); - -static void rtw_txdesc_blk_reset_all(struct rtw_softc *); - -static int rtw_rxsoft_alloc(struct rtw_softc *, struct rtw_rxsoft *, int); -static void rtw_rxdesc_init(struct rtw_softc *, int idx, int); - -#ifdef RTW_DEBUG -static void rtw_print_txdesc(struct rtw_softc *, const char *, - struct rtw_txsoft *, struct rtw_txdesc_blk *, - int); -#endif /* RTW_DEBUG */ - -static int rtw_newstate(struct ieee80211com *, enum ieee80211_state, int); -static void rtw_next_scan(void *); - -static int rtw_key_delete(struct ieee80211com *, - const struct ieee80211_key *); -static int rtw_key_set(struct ieee80211com *, - const struct ieee80211_key *, - const u_int8_t[IEEE80211_ADDR_LEN]); -static void rtw_key_update_end(struct ieee80211com *); -static void rtw_key_update_begin(struct ieee80211com *); -static int rtw_wep_decap(struct ieee80211_key *, struct mbuf *, int); - -static int rtw_compute_duration1(int, int, uint32_t, int, - struct rtw_duration *); -static int rtw_compute_duration(const struct ieee80211_frame_min *, - const struct ieee80211_key *, int, - uint32_t, int, int, - struct rtw_duration *, - struct rtw_duration *, int *, int); - -static int rtw_get_rssi(struct rtw_softc *, uint8_t, uint8_t); -static int rtw_maxim_getrssi(uint8_t, uint8_t); -static int rtw_gct_getrssi(uint8_t, uint8_t); -static int rtw_philips_getrssi(uint8_t, uint8_t); - -static void *rtw_ratectl_attach(struct ieee80211com *, u_int); - -#ifdef RTW_DEBUG -static void -rtw_print_regs(struct rtw_regs *regs, const char *dvname, const char *where) -{ -#define PRINTREG32(sc, reg) \ - RTW_DPRINTF(RTW_DEBUG_REGDUMP, \ - ("%s: reg[ " #reg " / %03x ] = %08x\n", \ - dvname, reg, RTW_READ(regs, reg))) - -#define PRINTREG16(sc, reg) \ - RTW_DPRINTF(RTW_DEBUG_REGDUMP, \ - ("%s: reg[ " #reg " / %03x ] = %04x\n", \ - dvname, reg, RTW_READ16(regs, reg))) - -#define PRINTREG8(sc, reg) \ - RTW_DPRINTF(RTW_DEBUG_REGDUMP, \ - ("%s: reg[ " #reg " / %03x ] = %02x\n", \ - dvname, reg, RTW_READ8(regs, reg))) - - RTW_DPRINTF(RTW_DEBUG_REGDUMP, ("%s: %s\n", dvname, where)); - - PRINTREG32(regs, RTW_IDR0); - PRINTREG32(regs, RTW_IDR1); - PRINTREG32(regs, RTW_MAR0); - PRINTREG32(regs, RTW_MAR1); - PRINTREG32(regs, RTW_TSFTRL); - PRINTREG32(regs, RTW_TSFTRH); - PRINTREG32(regs, RTW_TLPDA); - PRINTREG32(regs, RTW_TNPDA); - PRINTREG32(regs, RTW_THPDA); - PRINTREG32(regs, RTW_TCR); - PRINTREG32(regs, RTW_RCR); - PRINTREG32(regs, RTW_TINT); - PRINTREG32(regs, RTW_TBDA); - PRINTREG32(regs, RTW_ANAPARM); - PRINTREG32(regs, RTW_BB); - PRINTREG32(regs, RTW_PHYCFG); - PRINTREG32(regs, RTW_WAKEUP0L); - PRINTREG32(regs, RTW_WAKEUP0H); - PRINTREG32(regs, RTW_WAKEUP1L); - PRINTREG32(regs, RTW_WAKEUP1H); - PRINTREG32(regs, RTW_WAKEUP2LL); - PRINTREG32(regs, RTW_WAKEUP2LH); - PRINTREG32(regs, RTW_WAKEUP2HL); - PRINTREG32(regs, RTW_WAKEUP2HH); - PRINTREG32(regs, RTW_WAKEUP3LL); - PRINTREG32(regs, RTW_WAKEUP3LH); - PRINTREG32(regs, RTW_WAKEUP3HL); - PRINTREG32(regs, RTW_WAKEUP3HH); - PRINTREG32(regs, RTW_WAKEUP4LL); - PRINTREG32(regs, RTW_WAKEUP4LH); - PRINTREG32(regs, RTW_WAKEUP4HL); - PRINTREG32(regs, RTW_WAKEUP4HH); - PRINTREG32(regs, RTW_DK0); - PRINTREG32(regs, RTW_DK1); - PRINTREG32(regs, RTW_DK2); - PRINTREG32(regs, RTW_DK3); - PRINTREG32(regs, RTW_RETRYCTR); - PRINTREG32(regs, RTW_RDSAR); - PRINTREG32(regs, RTW_FER); - PRINTREG32(regs, RTW_FEMR); - PRINTREG32(regs, RTW_FPSR); - PRINTREG32(regs, RTW_FFER); - - /* 16-bit registers */ - PRINTREG16(regs, RTW_BRSR); - PRINTREG16(regs, RTW_IMR); - PRINTREG16(regs, RTW_ISR); - PRINTREG16(regs, RTW_BCNITV); - PRINTREG16(regs, RTW_ATIMWND); - PRINTREG16(regs, RTW_BINTRITV); - PRINTREG16(regs, RTW_ATIMTRITV); - PRINTREG16(regs, RTW_CRC16ERR); - PRINTREG16(regs, RTW_CRC0); - PRINTREG16(regs, RTW_CRC1); - PRINTREG16(regs, RTW_CRC2); - PRINTREG16(regs, RTW_CRC3); - PRINTREG16(regs, RTW_CRC4); - PRINTREG16(regs, RTW_CWR); - - /* 8-bit registers */ - PRINTREG8(regs, RTW_CR); - PRINTREG8(regs, RTW_9346CR); - PRINTREG8(regs, RTW_CONFIG0); - PRINTREG8(regs, RTW_CONFIG1); - PRINTREG8(regs, RTW_CONFIG2); - PRINTREG8(regs, RTW_MSR); - PRINTREG8(regs, RTW_CONFIG3); - PRINTREG8(regs, RTW_CONFIG4); - PRINTREG8(regs, RTW_TESTR); - PRINTREG8(regs, RTW_PSR); - PRINTREG8(regs, RTW_SCR); - PRINTREG8(regs, RTW_PHYDELAY); - PRINTREG8(regs, RTW_CRCOUNT); - PRINTREG8(regs, RTW_PHYADDR); - PRINTREG8(regs, RTW_PHYDATAW); - PRINTREG8(regs, RTW_PHYDATAR); - PRINTREG8(regs, RTW_CONFIG5); - PRINTREG8(regs, RTW_TPPOLL); - - PRINTREG16(regs, RTW_BSSID16); - PRINTREG32(regs, RTW_BSSID32); -#undef PRINTREG32 -#undef PRINTREG16 -#undef PRINTREG8 -} -#endif /* RTW_DEBUG */ - -static void -rtw_continuous_tx_enable(struct rtw_softc *sc, int enable) -{ - struct rtw_regs *regs = &sc->sc_regs; - uint32_t tcr; - - tcr = RTW_READ(regs, RTW_TCR); - tcr &= ~RTW_TCR_LBK_MASK; - if (enable) - tcr |= RTW_TCR_LBK_CONT; - else - tcr |= RTW_TCR_LBK_NORMAL; - RTW_WRITE(regs, RTW_TCR, tcr); - RTW_SYNC(regs, RTW_TCR, RTW_TCR); - rtw_set_access(sc, RTW_ACCESS_ANAPARM); - rtw_txdac_enable(sc, !enable); - rtw_set_access(sc, RTW_ACCESS_ANAPARM);/* XXX Voodoo from Linux. */ - rtw_set_access(sc, RTW_ACCESS_NONE); -} - -#ifdef RTW_DEBUG -static const char * -rtw_access_string(enum rtw_access access) -{ - switch (access) { - case RTW_ACCESS_NONE: - return "none"; - case RTW_ACCESS_CONFIG: - return "config"; - case RTW_ACCESS_ANAPARM: - return "anaparm"; - default: - return "unknown"; - } -} -#endif /* RTW_DEBUG */ - -static void -rtw_set_access1(struct rtw_regs *regs, enum rtw_access naccess) -{ - KKASSERT(naccess >= RTW_ACCESS_NONE && naccess <= RTW_ACCESS_ANAPARM); - KKASSERT(regs->r_access >= RTW_ACCESS_NONE && - regs->r_access <= RTW_ACCESS_ANAPARM); - - if (naccess == regs->r_access) - return; - - switch (naccess) { - case RTW_ACCESS_NONE: - switch (regs->r_access) { - case RTW_ACCESS_ANAPARM: - rtw_anaparm_enable(regs, 0); - /*FALLTHROUGH*/ - case RTW_ACCESS_CONFIG: - rtw_config0123_enable(regs, 0); - /*FALLTHROUGH*/ - case RTW_ACCESS_NONE: - break; - } - break; - case RTW_ACCESS_CONFIG: - switch (regs->r_access) { - case RTW_ACCESS_NONE: - rtw_config0123_enable(regs, 1); - /*FALLTHROUGH*/ - case RTW_ACCESS_CONFIG: - break; - case RTW_ACCESS_ANAPARM: - rtw_anaparm_enable(regs, 0); - break; - } - break; - case RTW_ACCESS_ANAPARM: - switch (regs->r_access) { - case RTW_ACCESS_NONE: - rtw_config0123_enable(regs, 1); - /*FALLTHROUGH*/ - case RTW_ACCESS_CONFIG: - rtw_anaparm_enable(regs, 1); - /*FALLTHROUGH*/ - case RTW_ACCESS_ANAPARM: - break; - } - break; - } -} - -static void -rtw_set_access(struct rtw_softc *sc, enum rtw_access access) -{ - struct rtw_regs *regs = &sc->sc_regs; - - rtw_set_access1(regs, access); - RTW_DPRINTF(RTW_DEBUG_ACCESS, - ("%s: access %s -> %s\n", sc->sc_ic.ic_if.if_xname, - rtw_access_string(regs->r_access), - rtw_access_string(access))); - regs->r_access = access; -} - -/* - * Enable registers, switch register banks. - */ -static void -rtw_config0123_enable(struct rtw_regs *regs, int enable) -{ - uint8_t ecr; - - ecr = RTW_READ8(regs, RTW_9346CR); - ecr &= ~(RTW_9346CR_EEM_MASK | RTW_9346CR_EECS | RTW_9346CR_EESK); - if (enable) { - ecr |= RTW_9346CR_EEM_CONFIG; - } else { - RTW_WBW(regs, RTW_9346CR, MAX(RTW_CONFIG0, RTW_CONFIG3)); - ecr |= RTW_9346CR_EEM_NORMAL; - } - RTW_WRITE8(regs, RTW_9346CR, ecr); - RTW_SYNC(regs, RTW_9346CR, RTW_9346CR); -} - -/* requires rtw_config0123_enable(, 1) */ -static void -rtw_anaparm_enable(struct rtw_regs *regs, int enable) -{ - uint8_t cfg3; - - cfg3 = RTW_READ8(regs, RTW_CONFIG3); - cfg3 |= RTW_CONFIG3_CLKRUNEN; - if (enable) - cfg3 |= RTW_CONFIG3_PARMEN; - else - cfg3 &= ~RTW_CONFIG3_PARMEN; - RTW_WRITE8(regs, RTW_CONFIG3, cfg3); - RTW_SYNC(regs, RTW_CONFIG3, RTW_CONFIG3); -} - -/* requires rtw_anaparm_enable(, 1) */ -static void -rtw_txdac_enable(struct rtw_softc *sc, int enable) -{ - uint32_t anaparm; - struct rtw_regs *regs = &sc->sc_regs; - - anaparm = RTW_READ(regs, RTW_ANAPARM); - if (enable) - anaparm &= ~RTW_ANAPARM_TXDACOFF; - else - anaparm |= RTW_ANAPARM_TXDACOFF; - RTW_WRITE(regs, RTW_ANAPARM, anaparm); - RTW_SYNC(regs, RTW_ANAPARM, RTW_ANAPARM); -} - -static int -rtw_chip_reset1(struct rtw_softc *sc) -{ - struct rtw_regs *regs = &sc->sc_regs; - uint8_t cr; - int i; - - RTW_WRITE8(regs, RTW_CR, RTW_CR_RST); - - RTW_WBR(regs, RTW_CR, RTW_CR); - - for (i = 0; i < 1000; i++) { - if ((cr = RTW_READ8(regs, RTW_CR) & RTW_CR_RST) == 0) { - RTW_DPRINTF(RTW_DEBUG_RESET, - ("%s: reset in %dus\n", - sc->sc_ic.ic_if.if_xname, i)); - return 0; - } - RTW_RBR(regs, RTW_CR, RTW_CR); - DELAY(10); /* 10us */ - } - - if_printf(&sc->sc_ic.ic_if, "reset failed\n"); - return ETIMEDOUT; -} - -static int -rtw_chip_reset(struct rtw_softc *sc) -{ - struct rtw_regs *regs = &sc->sc_regs; - uint32_t tcr; - - /* from Linux driver */ - tcr = RTW_TCR_CWMIN | RTW_TCR_MXDMA_2048 | - __SHIFTIN(7, RTW_TCR_SRL_MASK) | __SHIFTIN(7, RTW_TCR_LRL_MASK); - - RTW_WRITE(regs, RTW_TCR, tcr); - - RTW_WBW(regs, RTW_CR, RTW_TCR); - - return rtw_chip_reset1(sc); -} - -static int -rtw_wep_decap(struct ieee80211_key *k, struct mbuf *m, int hdrlen) -{ - struct ieee80211_key keycopy; - const struct ieee80211_cipher *wep_cipher; - - RTW_DPRINTF(RTW_DEBUG_KEY, ("%s:\n", __func__)); - - keycopy = *k; - keycopy.wk_flags &= ~IEEE80211_KEY_SWCRYPT; - - wep_cipher = ieee80211_crypto_cipher(IEEE80211_CIPHER_WEP); - KKASSERT(wep_cipher != NULL); - - return wep_cipher->ic_decap(&keycopy, m, hdrlen); -} - -static int -rtw_key_delete(struct ieee80211com *ic, const struct ieee80211_key *k) -{ - struct rtw_softc *sc = ic->ic_ifp->if_softc; - u_int keyix = k->wk_keyix; - - DPRINTF(sc, RTW_DEBUG_KEY, ("%s: delete key %u\n", __func__, keyix)); - - if (keyix >= IEEE80211_WEP_NKID) - return 0; - if (k->wk_keylen != 0) - sc->sc_flags &= ~RTW_F_DK_VALID; - return 1; -} - -static int -rtw_key_set(struct ieee80211com *ic, const struct ieee80211_key *k, - const u_int8_t mac[IEEE80211_ADDR_LEN]) -{ - struct rtw_softc *sc = ic->ic_ifp->if_softc; - - DPRINTF(sc, RTW_DEBUG_KEY, ("%s: set key %u\n", __func__, k->wk_keyix)); - - if (k->wk_keyix >= IEEE80211_WEP_NKID) - return 0; - - sc->sc_flags &= ~RTW_F_DK_VALID; - return 1; -} - -static void -rtw_key_update_begin(struct ieee80211com *ic) -{ -#ifdef RTW_DEBUG - struct ifnet *ifp = ic->ic_ifp; - struct rtw_softc *sc = ifp->if_softc; -#endif - - DPRINTF(sc, RTW_DEBUG_KEY, ("%s:\n", __func__)); -} - -static void -rtw_key_update_end(struct ieee80211com *ic) -{ - struct ifnet *ifp = ic->ic_ifp; - struct rtw_softc *sc = ifp->if_softc; - - DPRINTF(sc, RTW_DEBUG_KEY, ("%s:\n", __func__)); - - if ((sc->sc_flags & RTW_F_DK_VALID) != 0 || - (sc->sc_flags & RTW_F_ENABLED) == 0 || - (sc->sc_flags & RTW_F_INVALID) != 0) - return; - - rtw_io_enable(sc, RTW_CR_RE | RTW_CR_TE, 0); - rtw_wep_setkeys(sc); - rtw_io_enable(sc, RTW_CR_RE | RTW_CR_TE, - (ifp->if_flags & IFF_RUNNING) != 0); -} - -static __inline int -rtw_key_hwsupp(uint32_t flags, const struct ieee80211_key *k) -{ - if (k->wk_cipher->ic_cipher != IEEE80211_CIPHER_WEP) - return 0; - - return ((flags & RTW_C_RXWEP_40) != 0 && k->wk_keylen == 5) || - ((flags & RTW_C_RXWEP_104) != 0 && k->wk_keylen == 13); -} - -static void -rtw_wep_setkeys(struct rtw_softc *sc) -{ - struct ieee80211com *ic = &sc->sc_ic; - struct ieee80211_key *wk = ic->ic_nw_keys; - const struct ieee80211_cipher *wep_cipher; - struct rtw_regs *regs = &sc->sc_regs; - union rtw_keys *rk = &sc->sc_keys; - uint8_t psr, scr; - int i, keylen; - - memset(rk->rk_keys, 0, sizeof(rk->rk_keys)); - - wep_cipher = ieee80211_crypto_cipher(IEEE80211_CIPHER_WEP); - KKASSERT(wep_cipher != NULL); - - /* Temporarily use software crypto for all keys. */ - for (i = 0; i < IEEE80211_WEP_NKID; i++) { - if (wk[i].wk_cipher == &rtw_cipher_wep) - wk[i].wk_cipher = wep_cipher; - } - - rtw_set_access(sc, RTW_ACCESS_CONFIG); - - psr = RTW_READ8(regs, RTW_PSR); - scr = RTW_READ8(regs, RTW_SCR); - scr &= ~(RTW_SCR_KM_MASK | RTW_SCR_TXSECON | RTW_SCR_RXSECON); - - if ((sc->sc_ic.ic_flags & IEEE80211_F_PRIVACY) == 0) - goto out; - - for (keylen = i = 0; i < IEEE80211_WEP_NKID; i++) { - if (!rtw_key_hwsupp(sc->sc_flags, &wk[i])) - continue; - if (i == ic->ic_def_txkey) { - keylen = wk[i].wk_keylen; - break; - } - keylen = MAX(keylen, wk[i].wk_keylen); - } - - if (keylen == 5) - scr |= RTW_SCR_KM_WEP40 | RTW_SCR_RXSECON; - else if (keylen == 13) - scr |= RTW_SCR_KM_WEP104 | RTW_SCR_RXSECON; - - for (i = 0; i < IEEE80211_WEP_NKID; i++) { - if (wk[i].wk_keylen != keylen || - wk[i].wk_cipher->ic_cipher != IEEE80211_CIPHER_WEP) - continue; - /* h/w will decrypt, s/w still strips headers */ - wk[i].wk_cipher = &rtw_cipher_wep; - memcpy(rk->rk_keys[i], wk[i].wk_key, wk[i].wk_keylen); - } -out: - RTW_WRITE8(regs, RTW_PSR, psr & ~RTW_PSR_PSEN); - - bus_space_write_region_4(regs->r_bt, regs->r_bh, RTW_DK0, rk->rk_words, - NELEM(rk->rk_words)); - - RTW_WBW(regs, RTW_DK0, RTW_PSR); - RTW_WRITE8(regs, RTW_PSR, psr); - RTW_WBW(regs, RTW_PSR, RTW_SCR); - RTW_WRITE8(regs, RTW_SCR, scr); - RTW_SYNC(regs, RTW_SCR, RTW_SCR); - rtw_set_access(sc, RTW_ACCESS_NONE); - sc->sc_flags |= RTW_F_DK_VALID; -} - -static int -rtw_recall_eeprom(struct rtw_softc *sc) -{ - struct rtw_regs *regs = &sc->sc_regs; - int i; - uint8_t ecr; - - ecr = RTW_READ8(regs, RTW_9346CR); - ecr = (ecr & ~RTW_9346CR_EEM_MASK) | RTW_9346CR_EEM_AUTOLOAD; - RTW_WRITE8(regs, RTW_9346CR, ecr); - - RTW_WBR(regs, RTW_9346CR, RTW_9346CR); - - /* wait 25ms for completion */ - for (i = 0; i < 250; i++) { - ecr = RTW_READ8(regs, RTW_9346CR); - if ((ecr & RTW_9346CR_EEM_MASK) == RTW_9346CR_EEM_NORMAL) { - RTW_DPRINTF(RTW_DEBUG_RESET, - ("%s: recall EEPROM in %dus\n", - sc->sc_ic.ic_if.if_xname, i * 100)); - return 0; - } - RTW_RBR(regs, RTW_9346CR, RTW_9346CR); - DELAY(100); - } - if_printf(&sc->sc_ic.ic_if, "recall EEPROM failed\n"); - return ETIMEDOUT; -} - -static int -rtw_reset(struct rtw_softc *sc) -{ - struct rtw_regs *regs = &sc->sc_regs; - uint8_t config1; - int rc; - - sc->sc_flags &= ~RTW_F_DK_VALID; - - rc = rtw_chip_reset(sc); - if (rc) - return rc; - - rtw_recall_eeprom(sc); /* ignore err */ - - config1 = RTW_READ8(regs, RTW_CONFIG1); - RTW_WRITE8(regs, RTW_CONFIG1, config1 & ~RTW_CONFIG1_PMEN); - /* TBD turn off maximum power saving? */ - return 0; -} - -static int -rtw_srom_parse(struct rtw_softc *sc) -{ - struct rtw_srom *sr = &sc->sc_srom; - char scratch[sizeof("unknown 0xXX")]; - uint8_t mac[IEEE80211_ADDR_LEN]; - const char *rfname, *paname; - uint16_t srom_version; - char ethstr[ETHER_ADDRSTRLEN + 1]; - int i; - - sc->sc_flags &= ~(RTW_F_DIGPHY | RTW_F_DFLANTB | RTW_F_ANTDIV); - sc->sc_rcr &= ~(RTW_RCR_ENCS1 | RTW_RCR_ENCS2); - - srom_version = RTW_SR_GET16(sr, RTW_SR_VERSION); - if_printf(&sc->sc_ic.ic_if, "SROM version %d.%d", - srom_version >> 8, srom_version & 0xff); - - if (srom_version <= 0x0101) { - kprintf(" is not understood, limping along with defaults\n"); - - /* Default values */ - sc->sc_flags |= (RTW_F_DIGPHY | RTW_F_ANTDIV); - sc->sc_csthr = RTW_SR_ENERGYDETTHR_DEFAULT; - sc->sc_rcr |= RTW_RCR_ENCS1; - sc->sc_rfchipid = RTW_RFCHIPID_PHILIPS; - return 0; - } - kprintf("\n"); - - for (i = 0; i < IEEE80211_ADDR_LEN; i++) - mac[i] = RTW_SR_GET(sr, RTW_SR_MAC + i); - - RTW_DPRINTF(RTW_DEBUG_ATTACH, - ("%s: EEPROM MAC %s\n", sc->sc_ic.ic_if.if_xname, kether_addr(mac, ethstr))); - - sc->sc_csthr = RTW_SR_GET(sr, RTW_SR_ENERGYDETTHR); - - if ((RTW_SR_GET(sr, RTW_SR_CONFIG2) & RTW_CONFIG2_ANT) != 0) - sc->sc_flags |= RTW_F_ANTDIV; - - /* - * Note well: the sense of the RTW_SR_RFPARM_DIGPHY bit seems - * to be reversed. - */ - if ((RTW_SR_GET(sr, RTW_SR_RFPARM) & RTW_SR_RFPARM_DIGPHY) == 0) - sc->sc_flags |= RTW_F_DIGPHY; - if ((RTW_SR_GET(sr, RTW_SR_RFPARM) & RTW_SR_RFPARM_DFLANTB) != 0) - sc->sc_flags |= RTW_F_DFLANTB; - - sc->sc_rcr |= __SHIFTIN(__SHIFTOUT(RTW_SR_GET(sr, RTW_SR_RFPARM), - RTW_SR_RFPARM_CS_MASK), RTW_RCR_ENCS1); - - if ((RTW_SR_GET(sr, RTW_SR_CONFIG0) & RTW_CONFIG0_WEP104) != 0) - sc->sc_flags |= RTW_C_RXWEP_104; - - sc->sc_flags |= RTW_C_RXWEP_40; /* XXX */ - - sc->sc_rfchipid = RTW_SR_GET(sr, RTW_SR_RFCHIPID); - switch (sc->sc_rfchipid) { - case RTW_RFCHIPID_GCT: /* this combo seen in the wild */ - rfname = "GCT GRF5101"; - paname = "Winspring WS9901"; - break; - case RTW_RFCHIPID_MAXIM: - rfname = "Maxim MAX2820"; /* guess */ - paname = "Maxim MAX2422"; /* guess */ - break; - case RTW_RFCHIPID_INTERSIL: - rfname = "Intersil HFA3873"; /* guess */ - paname = "Intersil "; - break; - case RTW_RFCHIPID_PHILIPS: /* this combo seen in the wild */ - rfname = "Philips SA2400A"; - paname = "Philips SA2411"; - break; - case RTW_RFCHIPID_RFMD: - /* this is the same front-end as an atw(4)! */ - rfname = "RFMD RF2948B, " /* mentioned in Realtek docs */ - "LNA: RFMD RF2494, " /* mentioned in Realtek docs */ - "SYN: Silicon Labs Si4126"; /* inferred from - * reference driver - */ - paname = "RFMD RF2189"; /* mentioned in Realtek docs */ - break; - case RTW_RFCHIPID_RESERVED: - rfname = paname = "reserved"; - break; - default: - ksnprintf(scratch, sizeof(scratch), "unknown 0x%02x", - sc->sc_rfchipid); - rfname = paname = scratch; - } - if_printf(&sc->sc_ic.ic_if, "RF: %s, PA: %s\n", rfname, paname); - - switch (RTW_SR_GET(sr, RTW_SR_CONFIG0) & RTW_CONFIG0_GL_MASK) { - case RTW_CONFIG0_GL_USA: - case _RTW_CONFIG0_GL_USA: - sc->sc_locale = RTW_LOCALE_USA; - break; - case RTW_CONFIG0_GL_EUROPE: - sc->sc_locale = RTW_LOCALE_EUROPE; - break; - case RTW_CONFIG0_GL_JAPAN: - sc->sc_locale = RTW_LOCALE_JAPAN; - break; - default: - sc->sc_locale = RTW_LOCALE_UNKNOWN; - break; - } - return 0; -} - -static int -rtw_srom_read(struct rtw_softc *sc) -{ - struct rtw_regs *regs = &sc->sc_regs; - struct rtw_srom *sr = &sc->sc_srom; - struct seeprom_descriptor sd; - uint8_t ecr; - int rc; - - memset(&sd, 0, sizeof(sd)); - - ecr = RTW_READ8(regs, RTW_9346CR); - - if ((sc->sc_flags & RTW_F_9356SROM) != 0) { - RTW_DPRINTF(RTW_DEBUG_ATTACH, - ("%s: 93c56 SROM\n", sc->sc_ic.ic_if.if_xname)); - sr->sr_size = 256; - sd.sd_chip = C56_66; - } else { - RTW_DPRINTF(RTW_DEBUG_ATTACH, - ("%s: 93c46 SROM\n", sc->sc_ic.ic_if.if_xname)); - sr->sr_size = 128; - sd.sd_chip = C46; - } - - ecr &= ~(RTW_9346CR_EEDI | RTW_9346CR_EEDO | RTW_9346CR_EESK | - RTW_9346CR_EEM_MASK | RTW_9346CR_EECS); - ecr |= RTW_9346CR_EEM_PROGRAM; - - RTW_WRITE8(regs, RTW_9346CR, ecr); - - sr->sr_content = kmalloc(sr->sr_size, M_DEVBUF, M_WAITOK | M_ZERO); - - /* - * RTL8180 has a single 8-bit register for controlling the - * 93cx6 SROM. There is no "ready" bit. The RTL8180 - * input/output sense is the reverse of read_seeprom's. - */ - sd.sd_tag = regs->r_bt; - sd.sd_bsh = regs->r_bh; - sd.sd_regsize = 1; - sd.sd_control_offset = RTW_9346CR; - sd.sd_status_offset = RTW_9346CR; - sd.sd_dataout_offset = RTW_9346CR; - sd.sd_CK = RTW_9346CR_EESK; - sd.sd_CS = RTW_9346CR_EECS; - sd.sd_DI = RTW_9346CR_EEDO; - sd.sd_DO = RTW_9346CR_EEDI; - /* make read_seeprom enter EEPROM read/write mode */ - sd.sd_MS = ecr; - sd.sd_RDY = 0; - - /* TBD bus barriers */ - if (!read_seeprom(&sd, sr->sr_content, 0, sr->sr_size / 2)) { - if_printf(&sc->sc_ic.ic_if, "could not read SROM\n"); - kfree(sr->sr_content, M_DEVBUF); - sr->sr_content = NULL; - return EIO; /* XXX */ - } - - /* end EEPROM read/write mode */ - RTW_WRITE8(regs, RTW_9346CR, - (ecr & ~RTW_9346CR_EEM_MASK) | RTW_9346CR_EEM_NORMAL); - RTW_WBRW(regs, RTW_9346CR, RTW_9346CR); - - rc = rtw_recall_eeprom(sc); - if (rc) - return rc; - -#ifdef RTW_DEBUG - { - int i; - RTW_DPRINTF(RTW_DEBUG_ATTACH, - ("\n%s: serial ROM:\n\t", sc->sc_ic.ic_if.if_xname)); - for (i = 0; i < sr->sr_size/2; i++) { - if (((i % 8) == 0) && (i != 0)) - RTW_DPRINTF(RTW_DEBUG_ATTACH, ("\n\t")); - RTW_DPRINTF(RTW_DEBUG_ATTACH, - (" %04x", sr->sr_content[i])); - } - RTW_DPRINTF(RTW_DEBUG_ATTACH, ("\n")); - } -#endif /* RTW_DEBUG */ - return 0; -} - -static void -rtw_set_rfprog(struct rtw_softc *sc) -{ - struct rtw_regs *regs = &sc->sc_regs; - const char *method; - uint8_t cfg4; - - cfg4 = RTW_READ8(regs, RTW_CONFIG4) & ~RTW_CONFIG4_RFTYPE_MASK; - - switch (sc->sc_rfchipid) { - default: - cfg4 |= __SHIFTIN(rtw_rfprog_fallback, RTW_CONFIG4_RFTYPE_MASK); - method = "fallback"; - break; - case RTW_RFCHIPID_INTERSIL: - cfg4 |= RTW_CONFIG4_RFTYPE_INTERSIL; - method = "Intersil"; - break; - case RTW_RFCHIPID_PHILIPS: - cfg4 |= RTW_CONFIG4_RFTYPE_PHILIPS; - method = "Philips"; - break; - case RTW_RFCHIPID_GCT: /* XXX a guess */ - case RTW_RFCHIPID_RFMD: - cfg4 |= RTW_CONFIG4_RFTYPE_RFMD; - method = "RFMD"; - break; - } - - RTW_WRITE8(regs, RTW_CONFIG4, cfg4); - - RTW_WBR(regs, RTW_CONFIG4, RTW_CONFIG4); - - RTW_DPRINTF(RTW_DEBUG_INIT, - ("%s: %s RF programming method, %#02x\n", - sc->sc_ic.ic_if.if_xname, method, - RTW_READ8(regs, RTW_CONFIG4))); -} - -static __inline void -rtw_init_channels(struct rtw_softc *sc) -{ - const char *name = NULL; - struct ieee80211_channel *chans = sc->sc_ic.ic_channels; - int i; -#define ADD_CHANNEL(_chans, _chan) do { \ - _chans[_chan].ic_flags = IEEE80211_CHAN_B; \ - _chans[_chan].ic_freq = \ - ieee80211_ieee2mhz(_chan, _chans[_chan].ic_flags); \ -} while (0) - - switch (sc->sc_locale) { - case RTW_LOCALE_USA: /* 1-11 */ - name = "USA"; - for (i = 1; i <= 11; i++) - ADD_CHANNEL(chans, i); - break; - case RTW_LOCALE_JAPAN: /* 1-14 */ - name = "Japan"; - ADD_CHANNEL(chans, 14); - for (i = 1; i <= 14; i++) - ADD_CHANNEL(chans, i); - break; - case RTW_LOCALE_EUROPE: /* 1-13 */ - name = "Europe"; - for (i = 1; i <= 13; i++) - ADD_CHANNEL(chans, i); - break; - default: /* 10-11 allowed by most countries */ - name = ""; - for (i = 10; i <= 11; i++) - ADD_CHANNEL(chans, i); - break; - } - if_printf(&sc->sc_ic.ic_if, "Geographic Location %s\n", name); -#undef ADD_CHANNEL -} - - -static void -rtw_identify_country(struct rtw_softc *sc) -{ - uint8_t cfg0; - - cfg0 = RTW_READ8(&sc->sc_regs, RTW_CONFIG0); - switch (cfg0 & RTW_CONFIG0_GL_MASK) { - case RTW_CONFIG0_GL_USA: - case _RTW_CONFIG0_GL_USA: - sc->sc_locale = RTW_LOCALE_USA; - break; - case RTW_CONFIG0_GL_JAPAN: - sc->sc_locale = RTW_LOCALE_JAPAN; - break; - case RTW_CONFIG0_GL_EUROPE: - sc->sc_locale = RTW_LOCALE_EUROPE; - break; - default: - sc->sc_locale = RTW_LOCALE_UNKNOWN; - break; - } -} - -static int -rtw_identify_sta(struct rtw_softc *sc) -{ - static const uint8_t empty_macaddr[IEEE80211_ADDR_LEN] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - struct rtw_regs *regs = &sc->sc_regs; - uint8_t *addr = sc->sc_ic.ic_myaddr; - uint32_t idr0, idr1; - - idr0 = RTW_READ(regs, RTW_IDR0); - idr1 = RTW_READ(regs, RTW_IDR1); - - addr[0] = __SHIFTOUT(idr0, __BITS(0, 7)); - addr[1] = __SHIFTOUT(idr0, __BITS(8, 15)); - addr[2] = __SHIFTOUT(idr0, __BITS(16, 23)); - addr[3] = __SHIFTOUT(idr0, __BITS(24 ,31)); - - addr[4] = __SHIFTOUT(idr1, __BITS(0, 7)); - addr[5] = __SHIFTOUT(idr1, __BITS(8, 15)); - - if (IEEE80211_ADDR_EQ(addr, empty_macaddr)) { - if_printf(&sc->sc_ic.ic_if, "could not get mac address\n"); - return ENXIO; - } - return 0; -} - -static uint8_t -rtw_chan2txpower(struct rtw_srom *sr, struct ieee80211com *ic, - struct ieee80211_channel *chan) -{ - u_int idx = RTW_SR_TXPOWER1 + ieee80211_chan2ieee(ic, chan) - 1; - - KASSERT(idx >= RTW_SR_TXPOWER1 && idx <= RTW_SR_TXPOWER14, - ("%s: channel %d out of range", __func__, - idx - RTW_SR_TXPOWER1 + 1)); - return RTW_SR_GET(sr, idx); -} - -static void -rtw_txdesc_blk_init_all(struct rtw_softc *sc) -{ - /* nfree: the number of free descriptors in each ring. - * The beacon ring is a special case: I do not let the - * driver use all of the descriptors on the beacon ring. - * The reasons are two-fold: - * - * (1) A BEACON descriptor's OWN bit is (apparently) not - * updated, so the driver cannot easily know if the descriptor - * belongs to it, or if it is racing the NIC. If the NIC - * does not OWN every descriptor, then the driver can safely - * update the descriptors when RTW_TBDA points at tdb_next. - * - * (2) I hope that the NIC will process more than one BEACON - * descriptor in a single beacon interval, since that will - * enable multiple-BSS support. Since the NIC does not - * clear the OWN bit, there is no natural place for it to - * stop processing BEACON desciptors. Maybe it will *not* - * stop processing them! I do not want to chance the NIC - * looping around and around a saturated beacon ring, so - * I will leave one descriptor unOWNed at all times. - */ - int nfree[RTW_NTXPRI] = { - RTW_NTXDESCLO, - RTW_NTXDESCMD, - RTW_NTXDESCHI, - RTW_NTXDESCBCN - 1 - }; - struct rtw_txdesc_blk *tdb; - int pri; - - for (tdb = sc->sc_txdesc_blk, pri = 0; pri < RTW_NTXPRI; tdb++, pri++) { - tdb->tdb_nfree = nfree[pri]; - tdb->tdb_next = 0; - - bus_dmamap_sync(tdb->tdb_dmat, tdb->tdb_dmamap, - BUS_DMASYNC_PREWRITE); - } -} - -static void -rtw_txsoft_blk_init_all(struct rtw_softc *sc) -{ - struct rtw_txsoft_blk *tsb; - int pri; - - for (tsb = sc->sc_txsoft_blk, pri = 0; pri < RTW_NTXPRI; tsb++, pri++) { - int i; - - STAILQ_INIT(&tsb->tsb_dirtyq); - STAILQ_INIT(&tsb->tsb_freeq); - for (i = 0; i < tsb->tsb_ndesc; i++) { - struct rtw_txsoft *ts; - - ts = &tsb->tsb_desc[i]; - ts->ts_mbuf = NULL; - STAILQ_INSERT_TAIL(&tsb->tsb_freeq, ts, ts_q); - } - tsb->tsb_tx_timer = 0; - } -} - -static void -rtw_rxbuf_dma_map(void *arg, bus_dma_segment_t *seg, int nseg, - bus_size_t mapsize, int error) -{ - if (error) - return; - - KASSERT(nseg == 1, ("too many rx mbuf seg")); - - *((bus_addr_t *)arg) = seg->ds_addr; -} - -static int -rtw_rxsoft_alloc(struct rtw_softc *sc, struct rtw_rxsoft *rs, int waitok) -{ - bus_addr_t paddr; - bus_dmamap_t map; - struct mbuf *m; - int rc; - - m = m_getcl(waitok ? M_WAITOK : M_NOWAIT, MT_DATA, M_PKTHDR); - if (m == NULL) - return ENOBUFS; - - m->m_pkthdr.len = m->m_len = MCLBYTES; - - rc = bus_dmamap_load_mbuf(sc->sc_rxsoft_dmat, sc->sc_rxsoft_dmamap, m, - rtw_rxbuf_dma_map, &paddr, - waitok ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK); - if (rc) { - if_printf(&sc->sc_ic.ic_if, "can't load rx mbuf\n"); - m_freem(m); - return rc; - } - - if (rs->rs_mbuf != NULL) - bus_dmamap_unload(sc->sc_rxsoft_dmat, rs->rs_dmamap); - - /* Swap DMA map */ - map = rs->rs_dmamap; - rs->rs_dmamap = sc->sc_rxsoft_dmamap; - sc->sc_rxsoft_dmamap = map; - - rs->rs_mbuf = m; - rs->rs_phyaddr = paddr; - - bus_dmamap_sync(sc->sc_rxsoft_dmat, rs->rs_dmamap, BUS_DMASYNC_PREREAD); - return 0; -} - -static int -rtw_rxsoft_blk_init_all(struct rtw_softc *sc) -{ - int i, rc = 0; - - for (i = 0; i < RTW_RXQLEN; i++) { - struct rtw_rxsoft *rs; - - rs = &sc->sc_rxsoft[i]; - /* we're in rtw_init, so there should be no mbufs allocated */ - KKASSERT(rs->rs_mbuf == NULL); -#ifdef RTW_DEBUG - if (i == rtw_rxbufs_limit) { - if_printf(&sc->sc_ic.ic_if, - "TEST hit %d-buffer limit\n", i); - rc = ENOBUFS; - break; - } -#endif /* RTW_DEBUG */ - rc = rtw_rxsoft_alloc(sc, rs, 1); - if (rc) - break; - } - return rc; -} - -static void -rtw_rxdesc_init(struct rtw_softc *sc, int idx, int kick) -{ - struct rtw_rxdesc_blk *rdb = &sc->sc_rxdesc_blk; - struct rtw_rxdesc *rd = &rdb->rdb_desc[idx]; - struct rtw_rxsoft *rs = &sc->sc_rxsoft[idx]; - uint32_t ctl; - -#ifdef RTW_DEBUG - uint32_t octl, obuf; - - obuf = rd->rd_buf; - octl = rd->rd_ctl; -#endif /* RTW_DEBUG */ - - rd->rd_buf = htole32(rs->rs_phyaddr); - - ctl = __SHIFTIN(rs->rs_mbuf->m_len, RTW_RXCTL_LENGTH_MASK) | - RTW_RXCTL_OWN | RTW_RXCTL_FS | RTW_RXCTL_LS; - - if (idx == rdb->rdb_ndesc - 1) - ctl |= RTW_RXCTL_EOR; - - rd->rd_ctl = htole32(ctl); - - RTW_DPRINTF(kick ? (RTW_DEBUG_RECV_DESC | RTW_DEBUG_IO_KICK) - : RTW_DEBUG_RECV_DESC, - ("%s: rd %p buf %08x -> %08x ctl %08x -> %08x\n", - sc->sc_ic.ic_if.if_xname, rd, le32toh(obuf), - le32toh(rd->rd_buf), le32toh(octl), le32toh(rd->rd_ctl))); -} - -static void -rtw_rxdesc_blk_init_all(struct rtw_softc *sc) -{ - struct rtw_rxdesc_blk *rdb = &sc->sc_rxdesc_blk; - int i; - - for (i = 0; i < rdb->rdb_ndesc; i++) - rtw_rxdesc_init(sc, i, 1); - - bus_dmamap_sync(rdb->rdb_dmat, rdb->rdb_dmamap, BUS_DMASYNC_PREWRITE); -} - -static void -rtw_io_enable(struct rtw_softc *sc, uint8_t flags, int enable) -{ - struct rtw_regs *regs = &sc->sc_regs; - uint8_t cr; - - RTW_DPRINTF(RTW_DEBUG_IOSTATE, - ("%s: %s 0x%02x\n", sc->sc_ic.ic_if.if_xname, - enable ? "enable" : "disable", flags)); - - cr = RTW_READ8(regs, RTW_CR); - - /* XXX reference source does not enable MULRW */ -#if 0 - /* enable PCI Read/Write Multiple */ - cr |= RTW_CR_MULRW; -#endif - - RTW_RBW(regs, RTW_CR, RTW_CR); /* XXX paranoia? */ - if (enable) - cr |= flags; - else - cr &= ~flags; - RTW_WRITE8(regs, RTW_CR, cr); - RTW_SYNC(regs, RTW_CR, RTW_CR); -} - -static void -rtw_intr_rx(struct rtw_softc *sc, uint16_t isr) -{ -#define IS_BEACON(__fc0) \ - ((__fc0 & (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) ==\ - (IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_BEACON)) - - /* - * convert rates: - * hardware -> net80211 - */ - static const int ratetbl[4] = { 2, 4, 11, 22 }; - struct ifnet *ifp = &sc->sc_if; - struct rtw_rxdesc_blk *rdb = &sc->sc_rxdesc_blk; - int next, nproc = 0, sync = 0; - - KKASSERT(rdb->rdb_next < rdb->rdb_ndesc); - - bus_dmamap_sync(rdb->rdb_dmat, rdb->rdb_dmamap, BUS_DMASYNC_POSTREAD); - - for (next = rdb->rdb_next; ; next = (next + 1) % rdb->rdb_ndesc) { - struct ieee80211_node *ni; - struct ieee80211_frame_min *wh; - struct rtw_rxdesc *rd; - struct rtw_rxsoft *rs; - struct mbuf *m; - int hwrate, len, rate, rssi, sq, error; - uint32_t hrssi, hstat, htsfth, htsftl; - - rd = &rdb->rdb_desc[next]; - rs = &sc->sc_rxsoft[next]; - - hstat = le32toh(rd->rd_stat); - hrssi = le32toh(rd->rd_rssi); - htsfth = le32toh(rd->rd_tsfth); - htsftl = le32toh(rd->rd_tsftl); - - RTW_DPRINTF(RTW_DEBUG_RECV_DESC, - ("%s: rxdesc[%d] hstat %08x hrssi %08x " - "htsft %08x%08x\n", ifp->if_xname, - next, hstat, hrssi, htsfth, htsftl)); - - ++nproc; - - /* still belongs to NIC */ - if (hstat & RTW_RXSTAT_OWN) { - if (nproc > 1) - break; - - /* sometimes the NIC skips to the 0th descriptor */ - rd = &rdb->rdb_desc[0]; - if (rd->rd_stat & htole32(RTW_RXSTAT_OWN)) - break; - RTW_DPRINTF(RTW_DEBUG_BUGS, - ("%s: NIC skipped from rxdesc[%u] " - "to rxdesc[0]\n", ifp->if_xname, next)); - next = rdb->rdb_ndesc - 1; - continue; - } - -#ifdef RTW_DEBUG -#define PRINTSTAT(flag) do { \ - if ((hstat & flag) != 0) { \ - kprintf("%s" #flag, delim); \ - delim = ","; \ - } \ -} while (0) - if (rtw_debug & RTW_DEBUG_RECV_DESC) { - const char *delim = "<"; - - if_printf(ifp, "%s", ""); - if ((hstat & RTW_RXSTAT_DEBUG) != 0) { - kprintf("status %08x", hstat); - PRINTSTAT(RTW_RXSTAT_SPLCP); - PRINTSTAT(RTW_RXSTAT_MAR); - PRINTSTAT(RTW_RXSTAT_PAR); - PRINTSTAT(RTW_RXSTAT_BAR); - PRINTSTAT(RTW_RXSTAT_PWRMGT); - PRINTSTAT(RTW_RXSTAT_CRC32); - PRINTSTAT(RTW_RXSTAT_ICV); - kprintf(">, "); - } - } -#endif /* RTW_DEBUG */ - - if (hstat & RTW_RXSTAT_IOERROR) { - if_printf(ifp, "DMA error/FIFO overflow %08x, " - "rx descriptor %d\n", - hstat & RTW_RXSTAT_IOERROR, next); - IFNET_STAT_INC(ifp, ierrors, 1); - goto next; - } - - len = __SHIFTOUT(hstat, RTW_RXSTAT_LENGTH_MASK); - if (len < IEEE80211_MIN_LEN) { - sc->sc_ic.ic_stats.is_rx_tooshort++; - goto next; - } - - /* CRC is included with the packet; trim it off. */ - len -= IEEE80211_CRC_LEN; - - hwrate = __SHIFTOUT(hstat, RTW_RXSTAT_RATE_MASK); - if (hwrate >= NELEM(ratetbl)) { - if_printf(ifp, "unknown rate #%d\n", - __SHIFTOUT(hstat, RTW_RXSTAT_RATE_MASK)); - IFNET_STAT_INC(ifp, ierrors, 1); - goto next; - } - rate = ratetbl[hwrate]; - -#ifdef RTW_DEBUG - RTW_DPRINTF(RTW_DEBUG_RECV_DESC, - ("%s rate %d.%d Mb/s, time %08x%08x\n", - ifp->if_xname, (rate * 5) / 10, - (rate * 5) % 10, htsfth, htsftl)); -#endif /* RTW_DEBUG */ - - if ((hstat & RTW_RXSTAT_RES) && - sc->sc_ic.ic_opmode != IEEE80211_M_MONITOR) - goto next; - - /* if bad flags, skip descriptor */ - if ((hstat & RTW_RXSTAT_ONESEG) != RTW_RXSTAT_ONESEG) { - if_printf(ifp, "too many rx segments\n"); - goto next; - } - - bus_dmamap_sync(sc->sc_rxsoft_dmat, rs->rs_dmamap, - BUS_DMASYNC_POSTREAD); - - m = rs->rs_mbuf; - - /* if temporarily out of memory, re-use mbuf */ - error = rtw_rxsoft_alloc(sc, rs, 0); - if (error) { - if_printf(ifp, "%s: rtw_rxsoft_alloc(, %d) failed, " - "dropping packet\n", ifp->if_xname, next); - goto next; - } - - rssi = __SHIFTOUT(hrssi, RTW_RXRSSI_RSSI); - sq = __SHIFTOUT(hrssi, RTW_RXRSSI_SQ); - - rssi = rtw_get_rssi(sc, rssi, sq); - - /* - * Note well: now we cannot recycle the rs_mbuf unless - * we restore its original length. - */ - m->m_pkthdr.rcvif = ifp; - m->m_pkthdr.len = m->m_len = len; - - wh = mtod(m, struct ieee80211_frame_min *); - - if (!IS_BEACON(wh->i_fc[0])) - sc->sc_led_state.ls_event |= RTW_LED_S_RX; - - /* TBD use _MAR, _BAR, _PAR flags as hints to _find_rxnode? */ - ni = ieee80211_find_rxnode(&sc->sc_ic, wh); - - sc->sc_tsfth = htsfth; - -#ifdef RTW_DEBUG - if ((ifp->if_flags & (IFF_DEBUG | IFF_LINK2)) == - (IFF_DEBUG | IFF_LINK2)) { - ieee80211_dump_pkt(mtod(m, uint8_t *), m->m_pkthdr.len, - rate, rssi); - } -#endif /* RTW_DEBUG */ - - if (sc->sc_radiobpf != NULL) { - struct rtw_rx_radiotap_header *rr = &sc->sc_rxtap; - - rr->rr_tsft = - htole64(((uint64_t)htsfth << 32) | htsftl); - - if ((hstat & RTW_RXSTAT_SPLCP) != 0) - rr->rr_flags = IEEE80211_RADIOTAP_F_SHORTPRE; - - rr->rr_flags = 0; - rr->rr_rate = rate; - rr->rr_antsignal = rssi; - rr->rr_barker_lock = htole16(sq); - - bpf_ptap(sc->sc_radiobpf, m, rr, sizeof(sc->sc_rxtapu)); - } - - ieee80211_input(&sc->sc_ic, m, ni, rssi, htsftl); - ieee80211_free_node(ni); -next: - rtw_rxdesc_init(sc, next, 0); - sync = 1; - } - - if (sync) { - bus_dmamap_sync(rdb->rdb_dmat, rdb->rdb_dmamap, - BUS_DMASYNC_PREWRITE); - } - - rdb->rdb_next = next; - KKASSERT(rdb->rdb_next < rdb->rdb_ndesc); -#undef IS_BEACON -} - -static __inline void -rtw_txsoft_release(bus_dma_tag_t dmat, struct rtw_txsoft *ts, - int data_retry, int rts_retry, int error, int ratectl) -{ - struct mbuf *m; - struct ieee80211_node *ni; - - if (!ts->ts_ratectl) - ratectl = 0; - - m = ts->ts_mbuf; - ni = ts->ts_ni; - KKASSERT(m != NULL); - KKASSERT(ni != NULL); - ts->ts_mbuf = NULL; - ts->ts_ni = NULL; - - if (ratectl) { - struct ieee80211_ratectl_res rc_res; - - rc_res.rc_res_rateidx = ts->ts_rateidx; - rc_res.rc_res_tries = data_retry + 1; - - ieee80211_ratectl_tx_complete(ni, m->m_pkthdr.len, - &rc_res, 1, - data_retry, rts_retry, - error); - } - - bus_dmamap_sync(dmat, ts->ts_dmamap, BUS_DMASYNC_POSTWRITE); - bus_dmamap_unload(dmat, ts->ts_dmamap); - m_freem(m); - ieee80211_free_node(ni); -} - -static __inline void -rtw_collect_txpkt(struct rtw_softc *sc, struct rtw_txdesc_blk *tdb, - struct rtw_txsoft *ts, int ndesc) -{ - uint32_t hstat; - int data_retry, rts_retry, error; - struct rtw_txdesc *tdn; - const char *condstring; - struct ifnet *ifp = &sc->sc_if; - - tdb->tdb_nfree += ndesc; - - tdn = &tdb->tdb_desc[ts->ts_last]; - - hstat = le32toh(tdn->td_stat); - rts_retry = __SHIFTOUT(hstat, RTW_TXSTAT_RTSRETRY_MASK); - data_retry = __SHIFTOUT(hstat, RTW_TXSTAT_DRC_MASK); - - ifp->if_collisions += rts_retry + data_retry; - - if ((hstat & RTW_TXSTAT_TOK) != 0) { - condstring = "ok"; - error = 0; - } else { - IFNET_STAT_INC(ifp, oerrors, 1); - condstring = "error"; - error = 1; - } - - rtw_txsoft_release(sc->sc_txsoft_dmat, ts, data_retry, rts_retry, - error, 1); - - DPRINTF(sc, RTW_DEBUG_XMIT_DESC, - ("%s: ts %p txdesc[%d, %d] %s tries rts %u data %u\n", - ifp->if_xname, ts, ts->ts_first, ts->ts_last, - condstring, rts_retry, data_retry)); -} - -static void -rtw_reset_oactive(struct rtw_softc *sc) -{ - int pri; -#ifdef RTW_DEBUG - short oflags = sc->sc_if.if_flags; -#endif - - for (pri = 0; pri < RTW_NTXPRI; pri++) { - struct rtw_txsoft_blk *tsb = &sc->sc_txsoft_blk[pri]; - struct rtw_txdesc_blk *tdb = &sc->sc_txdesc_blk[pri]; - - if (!STAILQ_EMPTY(&tsb->tsb_freeq) && tdb->tdb_nfree > 0) - ifq_clr_oactive(&sc->sc_if.if_snd); - } - -#ifdef RTW_DEBUG - if (oflags != sc->sc_if.if_flags) { - DPRINTF(sc, RTW_DEBUG_OACTIVE, - ("%s: reset OACTIVE\n", sc->sc_ic.ic_if.if_xname)); - } -#endif -} - -/* Collect transmitted packets. */ -static __inline void -rtw_collect_txring(struct rtw_softc *sc, struct rtw_txsoft_blk *tsb, - struct rtw_txdesc_blk *tdb, int force) -{ - struct rtw_txsoft *ts; - int ndesc; - - while ((ts = STAILQ_FIRST(&tsb->tsb_dirtyq)) != NULL) { - ndesc = 1 + ts->ts_last - ts->ts_first; - if (ts->ts_last < ts->ts_first) - ndesc += tdb->tdb_ndesc; - - KKASSERT(ndesc > 0); - - bus_dmamap_sync(tdb->tdb_dmat, tdb->tdb_dmamap, - BUS_DMASYNC_POSTREAD); - - if (force) { - int i; - - for (i = ts->ts_first; ; i = RTW_NEXT_IDX(tdb, i)) { - tdb->tdb_desc[i].td_stat &= - ~htole32(RTW_TXSTAT_OWN); - if (i == ts->ts_last) - break; - } - bus_dmamap_sync(tdb->tdb_dmat, tdb->tdb_dmamap, - BUS_DMASYNC_PREWRITE); - } else if ((tdb->tdb_desc[ts->ts_last].td_stat & - htole32(RTW_TXSTAT_OWN)) != 0) { - break; - } - - rtw_collect_txpkt(sc, tdb, ts, ndesc); - STAILQ_REMOVE_HEAD(&tsb->tsb_dirtyq, ts_q); - STAILQ_INSERT_TAIL(&tsb->tsb_freeq, ts, ts_q); - } - /* no more pending transmissions, cancel watchdog */ - if (ts == NULL) - tsb->tsb_tx_timer = 0; - rtw_reset_oactive(sc); -} - -static void -rtw_intr_tx(struct rtw_softc *sc, uint16_t isr) -{ - int pri; - - for (pri = 0; pri < RTW_NTXPRI; pri++) { - rtw_collect_txring(sc, &sc->sc_txsoft_blk[pri], - &sc->sc_txdesc_blk[pri], 0); - } - if (isr) { - rtw_start(&sc->sc_ic.ic_if, - ifq_get_subq_default(&sc->sc_ic.ic_if.if_snd)); - } -} - -static __inline struct mbuf * -rtw_beacon_alloc(struct rtw_softc *sc, struct ieee80211_node *ni) -{ - struct ieee80211com *ic = &sc->sc_ic; - struct ieee80211_beacon_offsets boff; - struct mbuf *m; - - m = ieee80211_beacon_alloc(ic, ni, &boff); - if (m != NULL) { - RTW_DPRINTF(RTW_DEBUG_BEACON, - ("%s: m %p len %u\n", ic->ic_if.if_xname, m, - m->m_len)); - } - return m; -} - -static void -rtw_intr_beacon(struct rtw_softc *sc, uint16_t isr) -{ - struct ieee80211com *ic = &sc->sc_ic; - struct rtw_regs *regs = &sc->sc_regs; - struct rtw_txdesc_blk *tdb = &sc->sc_txdesc_blk[RTW_TXPRIBCN]; - struct rtw_txsoft_blk *tsb = &sc->sc_txsoft_blk[RTW_TXPRIBCN]; - -#ifdef RTW_DEBUG - uint32_t tsfth, tsftl; - - tsfth = RTW_READ(regs, RTW_TSFTRH); - tsftl = RTW_READ(regs, RTW_TSFTRL); -#endif - - if (isr & (RTW_INTR_TBDOK | RTW_INTR_TBDER)) { -#ifdef RTW_DEBUG - int next = rtw_txring_next(regs, tdb); -#endif - - RTW_DPRINTF(RTW_DEBUG_BEACON, - ("%s: beacon ring %sprocessed, " - "isr = %#04x, next %d expected %d, %llu\n", - ic->ic_if.if_xname, - (next == tdb->tdb_next) ? "" : "un", - isr, next, tdb->tdb_next, - (uint64_t)tsfth << 32 | tsftl)); - - if ((RTW_READ8(regs, RTW_TPPOLL) & RTW_TPPOLL_BQ) == 0){ - rtw_collect_txring(sc, tsb, tdb, 1); - tdb->tdb_next = 0; - } - } - /* Start beacon transmission. */ - - if ((isr & RTW_INTR_BCNINT) && ic->ic_state == IEEE80211_S_RUN && - STAILQ_EMPTY(&tsb->tsb_dirtyq)) { - struct mbuf *m; - - RTW_DPRINTF(RTW_DEBUG_BEACON, - ("%s: beacon prep. time, isr = %#04x, %llu\n", - ic->ic_if.if_xname, isr, - (uint64_t)tsfth << 32 | tsftl)); - - m = rtw_beacon_alloc(sc, ic->ic_bss); - if (m == NULL) { - if_printf(&ic->ic_if, "could not allocate beacon\n"); - return; - } - - m->m_pkthdr.rcvif = (void *)ieee80211_ref_node(ic->ic_bss); - - IF_ENQUEUE(&sc->sc_beaconq, m); - - rtw_start(&ic->ic_if, ifq_get_subq_default(&ic->ic_if.if_snd)); - } -} - -static void -rtw_intr_atim(struct rtw_softc *sc) -{ - /* TBD */ - return; -} - -#ifdef RTW_DEBUG -static void -rtw_dump_rings(struct rtw_softc *sc) -{ - struct rtw_rxdesc_blk *rdb; - int desc, pri; - - if ((rtw_debug & RTW_DEBUG_IO_KICK) == 0) - return; - - for (pri = 0; pri < RTW_NTXPRI; pri++) { - struct rtw_txdesc_blk *tdb = &sc->sc_txdesc_blk[pri]; - - if_printf(&sc->sc_ic.ic_if, "txpri %d ndesc %d nfree %d\n", - pri, tdb->tdb_ndesc, tdb->tdb_nfree); - for (desc = 0; desc < tdb->tdb_ndesc; desc++) - rtw_print_txdesc(sc, ".", NULL, tdb, desc); - } - - rdb = &sc->sc_rxdesc_blk; - - for (desc = 0; desc < RTW_RXQLEN; desc++) { - struct rtw_rxdesc *rd = &rdb->rdb_desc[desc]; - - if_printf(&sc->sc_ic.ic_if, - "%sctl %08x rsvd0/rssi %08x buf/tsftl %08x " - "rsvd1/tsfth %08x\n", - (desc >= rdb->rdb_ndesc) ? "UNUSED " : "", - le32toh(rd->rd_ctl), le32toh(rd->rd_rssi), - le32toh(rd->rd_buf), le32toh(rd->rd_tsfth)); - } -} -#endif /* RTW_DEBUG */ - -static void -rtw_hwring_setup(struct rtw_softc *sc) -{ - struct rtw_regs *regs = &sc->sc_regs; - struct rtw_rxdesc_blk *rdb = &sc->sc_rxdesc_blk; - int pri; - - for (pri = 0; pri < RTW_NTXPRI; pri++) { - struct rtw_txdesc_blk *tdb = &sc->sc_txdesc_blk[pri]; - - RTW_WRITE(regs, tdb->tdb_basereg, tdb->tdb_base); - RTW_DPRINTF(RTW_DEBUG_XMIT_DESC, - ("%s: reg[tdb->tdb_basereg] <- %u\n", - sc->sc_ic.ic_if.if_xname, tdb->tdb_base)); - } - - RTW_WRITE(regs, RTW_RDSAR, rdb->rdb_base); - RTW_DPRINTF(RTW_DEBUG_RECV_DESC, - ("%s: reg[RDSAR] <- %u\n", sc->sc_ic.ic_if.if_xname, - rdb->rdb_base)); - - RTW_SYNC(regs, RTW_TLPDA, RTW_RDSAR); -} - -static int -rtw_swring_setup(struct rtw_softc *sc) -{ - int rc; - - rtw_txdesc_blk_init_all(sc); - rtw_txsoft_blk_init_all(sc); - - rc = rtw_rxsoft_blk_init_all(sc); - if (rc) { - if_printf(&sc->sc_ic.ic_if, "could not allocate rx buffers\n"); - return rc; - } - - rtw_rxdesc_blk_init_all(sc); - sc->sc_rxdesc_blk.rdb_next = 0; - return 0; -} - -static int -rtw_txring_next(struct rtw_regs *regs, struct rtw_txdesc_blk *tdb) -{ - return (le32toh(RTW_READ(regs, tdb->tdb_basereg)) - tdb->tdb_base) / - sizeof(struct rtw_txdesc); -} - -static void -rtw_txring_fixup(struct rtw_softc *sc) -{ - struct rtw_regs *regs = &sc->sc_regs; - int pri; - - for (pri = 0; pri < RTW_NTXPRI; pri++) { - struct rtw_txdesc_blk *tdb = &sc->sc_txdesc_blk[pri]; - int next; - - next = rtw_txring_next(regs, tdb); - if (tdb->tdb_next == next) - continue; - if_printf(&sc->sc_ic.ic_if, - "tx-ring %d expected next %d, read %d\n", - pri, tdb->tdb_next, next); - tdb->tdb_next = MIN(next, tdb->tdb_ndesc - 1); - } -} - -static void -rtw_rxring_fixup(struct rtw_softc *sc) -{ - struct rtw_rxdesc_blk *rdb = &sc->sc_rxdesc_blk; - uint32_t rdsar; - int next; - - rdsar = le32toh(RTW_READ(&sc->sc_regs, RTW_RDSAR)); - next = (rdsar - rdb->rdb_base) / sizeof(struct rtw_rxdesc); - - if (rdb->rdb_next != next) { - if_printf(&sc->sc_ic.ic_if, - "rx-ring expected next %d, read %d\n", - rdb->rdb_next, next); - rdb->rdb_next = MIN(next, rdb->rdb_ndesc - 1); - } -} - -static void -rtw_txdesc_blk_reset_all(struct rtw_softc *sc) -{ - int pri; - - for (pri = 0; pri < RTW_NTXPRI; pri++) { - rtw_collect_txring(sc, &sc->sc_txsoft_blk[pri], - &sc->sc_txdesc_blk[pri], 1); - } -} - -static void -rtw_intr_ioerror(struct rtw_softc *sc, uint16_t isr) -{ - struct rtw_regs *regs = &sc->sc_regs; - int xmtr = 0, rcvr = 0; - uint8_t cr = 0; - - if (isr & RTW_INTR_TXFOVW) { - if_printf(&sc->sc_ic.ic_if, "tx fifo underflow\n"); - rcvr = xmtr = 1; - cr |= RTW_CR_TE | RTW_CR_RE; - } - - if (isr & (RTW_INTR_RDU | RTW_INTR_RXFOVW)) { - cr |= RTW_CR_RE; - rcvr = 1; - } - - RTW_DPRINTF(RTW_DEBUG_BUGS, - ("%s: restarting xmit/recv, isr %04x\n", - sc->sc_ic.ic_if.if_xname, isr)); - -#ifdef RTW_DEBUG - rtw_dump_rings(sc); -#endif /* RTW_DEBUG */ - - rtw_io_enable(sc, cr, 0); - - /* Collect rx'd packets. Refresh rx buffers. */ - if (rcvr) - rtw_intr_rx(sc, 0); - - /* - * Collect tx'd packets. - * XXX let's hope this stops the transmit timeouts. - */ - if (xmtr) - rtw_txdesc_blk_reset_all(sc); - - RTW_WRITE16(regs, RTW_IMR, 0); - RTW_SYNC(regs, RTW_IMR, RTW_IMR); - - if (rtw_do_chip_reset) { - rtw_chip_reset1(sc); - rtw_wep_setkeys(sc); - } - - rtw_rxdesc_blk_init_all(sc); - -#ifdef RTW_DEBUG - rtw_dump_rings(sc); -#endif /* RTW_DEBUG */ - - RTW_WRITE16(regs, RTW_IMR, sc->sc_inten); - RTW_SYNC(regs, RTW_IMR, RTW_IMR); - - if (rcvr) - rtw_rxring_fixup(sc); - - rtw_io_enable(sc, cr, 1); - - if (xmtr) - rtw_txring_fixup(sc); -} - -static __inline void -rtw_suspend_ticks(struct rtw_softc *sc) -{ - RTW_DPRINTF(RTW_DEBUG_TIMEOUT, - ("%s: suspending ticks\n", sc->sc_ic.ic_if.if_xname)); - sc->sc_do_tick = 0; -} - -static void -rtw_resume_ticks(struct rtw_softc *sc) -{ - uint32_t tsftrl0, tsftrl1, next_tick; - struct rtw_regs *regs = &sc->sc_regs; - - tsftrl0 = RTW_READ(regs, RTW_TSFTRL); - - tsftrl1 = RTW_READ(regs, RTW_TSFTRL); - next_tick = tsftrl1 + 1000000; - RTW_WRITE(regs, RTW_TINT, next_tick); - - sc->sc_do_tick = 1; - - RTW_DPRINTF(RTW_DEBUG_TIMEOUT, - ("%s: resume ticks delta %#08x now %#08x next %#08x\n", - sc->sc_ic.ic_if.if_xname, tsftrl1 - tsftrl0, tsftrl1, - next_tick)); -} - -static void -rtw_intr_timeout(struct rtw_softc *sc) -{ - RTW_DPRINTF(RTW_DEBUG_TIMEOUT, - ("%s: timeout\n", sc->sc_ic.ic_if.if_xname)); - if (sc->sc_do_tick) - rtw_resume_ticks(sc); -} - -static void -rtw_intr(void *arg) -{ - struct rtw_softc *sc = arg; - struct rtw_regs *regs = &sc->sc_regs; - struct ifnet *ifp = &sc->sc_if; - int i; - - /* - * If the interface isn't running, the interrupt couldn't - * possibly have come from us. - */ - if ((sc->sc_flags & RTW_F_ENABLED) == 0 || - (ifp->if_flags & IFF_RUNNING) == 0) { - RTW_DPRINTF(RTW_DEBUG_INTR, - ("%s: stray interrupt\n", ifp->if_xname)); - return; - } - - for (i = 0; i < 10; i++) { - uint16_t isr; - - isr = RTW_READ16(regs, RTW_ISR); - - RTW_WRITE16(regs, RTW_ISR, isr); - RTW_WBR(regs, RTW_ISR, RTW_ISR); - - if (sc->sc_intr_ack != NULL) - sc->sc_intr_ack(regs); - - if (isr == 0) - break; - -#ifdef RTW_DEBUG -#define PRINTINTR(flag) do { \ - if ((isr & flag) != 0) { \ - kprintf("%s" #flag, delim); \ - delim = ","; \ - } \ -} while (0) - - if ((rtw_debug & RTW_DEBUG_INTR) != 0 && isr != 0) { - const char *delim = "<"; - - if_printf(ifp, "reg[ISR] = %x", isr); - - PRINTINTR(RTW_INTR_TXFOVW); - PRINTINTR(RTW_INTR_TIMEOUT); - PRINTINTR(RTW_INTR_BCNINT); - PRINTINTR(RTW_INTR_ATIMINT); - PRINTINTR(RTW_INTR_TBDER); - PRINTINTR(RTW_INTR_TBDOK); - PRINTINTR(RTW_INTR_THPDER); - PRINTINTR(RTW_INTR_THPDOK); - PRINTINTR(RTW_INTR_TNPDER); - PRINTINTR(RTW_INTR_TNPDOK); - PRINTINTR(RTW_INTR_RXFOVW); - PRINTINTR(RTW_INTR_RDU); - PRINTINTR(RTW_INTR_TLPDER); - PRINTINTR(RTW_INTR_TLPDOK); - PRINTINTR(RTW_INTR_RER); - PRINTINTR(RTW_INTR_ROK); - - kprintf(">\n"); - } -#undef PRINTINTR -#endif /* RTW_DEBUG */ - - if (isr & RTW_INTR_RX) - rtw_intr_rx(sc, isr & RTW_INTR_RX); - if (isr & RTW_INTR_TX) - rtw_intr_tx(sc, isr & RTW_INTR_TX); - if (isr & RTW_INTR_BEACON) - rtw_intr_beacon(sc, isr & RTW_INTR_BEACON); - if (isr & RTW_INTR_ATIMINT) - rtw_intr_atim(sc); - if (isr & RTW_INTR_IOERROR) - rtw_intr_ioerror(sc, isr & RTW_INTR_IOERROR); - if (isr & RTW_INTR_TIMEOUT) - rtw_intr_timeout(sc); - } -} - -/* Must be called at splnet. */ -void -rtw_stop(struct rtw_softc *sc, int disable) -{ - struct ieee80211com *ic = &sc->sc_ic; - struct ifnet *ifp = &ic->ic_if; - struct rtw_regs *regs = &sc->sc_regs; - int i; - - if ((sc->sc_flags & RTW_F_ENABLED) == 0) - return; - - rtw_suspend_ticks(sc); - - ieee80211_new_state(ic, IEEE80211_S_INIT, -1); - - if ((sc->sc_flags & RTW_F_INVALID) == 0) { - /* Disable interrupts. */ - RTW_WRITE16(regs, RTW_IMR, 0); - - RTW_WBW(regs, RTW_TPPOLL, RTW_IMR); - - /* - * Stop the transmit and receive processes. First stop DMA, - * then disable receiver and transmitter. - */ - RTW_WRITE8(regs, RTW_TPPOLL, RTW_TPPOLL_SALL); - - RTW_SYNC(regs, RTW_TPPOLL, RTW_IMR); - - rtw_io_enable(sc, RTW_CR_RE | RTW_CR_TE, 0); - } - - /* Free pending TX mbufs */ - for (i = 0; i < RTW_NTXPRI; ++i) { - struct rtw_txsoft_blk *tsb = &sc->sc_txsoft_blk[i]; - struct rtw_txsoft *ts; - - while ((ts = STAILQ_FIRST(&tsb->tsb_dirtyq)) != NULL) { - rtw_txsoft_release(sc->sc_txsoft_dmat, ts, 0, 0, 0, 0); - STAILQ_REMOVE_HEAD(&tsb->tsb_dirtyq, ts_q); - STAILQ_INSERT_TAIL(&tsb->tsb_freeq, ts, ts_q); - } - tsb->tsb_tx_timer = 0; - } - - /* Free pending RX mbufs */ - for (i = 0; i < RTW_RXQLEN; i++) { - struct rtw_rxsoft *rs = &sc->sc_rxsoft[i]; - - if (rs->rs_mbuf != NULL) { - bus_dmamap_sync(sc->sc_rxsoft_dmat, rs->rs_dmamap, - BUS_DMASYNC_POSTREAD); - bus_dmamap_unload(sc->sc_rxsoft_dmat, rs->rs_dmamap); - m_freem(rs->rs_mbuf); - rs->rs_mbuf = NULL; - } - } - - if (disable) - rtw_disable(sc); - - /* Mark the interface as not running. Cancel the watchdog timer. */ - ifp->if_flags &= ~IFF_RUNNING; - ifq_clr_oactive(&ifp->if_snd); - ifp->if_timer = 0; -} - -#ifdef RTW_DEBUG -const char * -rtw_pwrstate_string(enum rtw_pwrstate power) -{ - switch (power) { - case RTW_ON: - return "on"; - case RTW_SLEEP: - return "sleep"; - case RTW_OFF: - return "off"; - default: - return "unknown"; - } -} -#endif /* RTW_DEBUG */ - -/* - * XXX For Maxim, I am using the RFMD settings gleaned from the - * reference driver, plus a magic Maxim "ON" value that comes from - * the Realtek document "Windows PG for Rtl8180." - */ -static void -rtw_maxim_pwrstate(struct rtw_regs *regs, enum rtw_pwrstate power, - int before_rf, int digphy) -{ - uint32_t anaparm; - - anaparm = RTW_READ(regs, RTW_ANAPARM); - anaparm &= ~(RTW_ANAPARM_RFPOW_MASK | RTW_ANAPARM_TXDACOFF); - - switch (power) { - case RTW_OFF: - if (before_rf) - return; - anaparm |= RTW_ANAPARM_RFPOW_MAXIM_OFF; - anaparm |= RTW_ANAPARM_TXDACOFF; - break; - case RTW_SLEEP: - if (!before_rf) - return; - anaparm |= RTW_ANAPARM_RFPOW_MAXIM_SLEEP; - anaparm |= RTW_ANAPARM_TXDACOFF; - break; - case RTW_ON: - if (!before_rf) - return; - anaparm |= RTW_ANAPARM_RFPOW_MAXIM_ON; - break; - } - RTW_DPRINTF(RTW_DEBUG_PWR, - ("%s: power state %s, %s RF, reg[ANAPARM] <- %08x\n", - __func__, rtw_pwrstate_string(power), - (before_rf) ? "before" : "after", anaparm)); - - RTW_WRITE(regs, RTW_ANAPARM, anaparm); - RTW_SYNC(regs, RTW_ANAPARM, RTW_ANAPARM); -} - -/* XXX I am using the RFMD settings gleaned from the reference - * driver. They agree - */ -static void -rtw_rfmd_pwrstate(struct rtw_regs *regs, enum rtw_pwrstate power, - int before_rf, int digphy) -{ - uint32_t anaparm; - - anaparm = RTW_READ(regs, RTW_ANAPARM); - anaparm &= ~(RTW_ANAPARM_RFPOW_MASK | RTW_ANAPARM_TXDACOFF); - - switch (power) { - case RTW_OFF: - if (before_rf) - return; - anaparm |= RTW_ANAPARM_RFPOW_RFMD_OFF; - anaparm |= RTW_ANAPARM_TXDACOFF; - break; - case RTW_SLEEP: - if (!before_rf) - return; - anaparm |= RTW_ANAPARM_RFPOW_RFMD_SLEEP; - anaparm |= RTW_ANAPARM_TXDACOFF; - break; - case RTW_ON: - if (!before_rf) - return; - anaparm |= RTW_ANAPARM_RFPOW_RFMD_ON; - break; - } - RTW_DPRINTF(RTW_DEBUG_PWR, - ("%s: power state %s, %s RF, reg[ANAPARM] <- %08x\n", - __func__, rtw_pwrstate_string(power), - (before_rf) ? "before" : "after", anaparm)); - - RTW_WRITE(regs, RTW_ANAPARM, anaparm); - RTW_SYNC(regs, RTW_ANAPARM, RTW_ANAPARM); -} - -static void -rtw_philips_pwrstate(struct rtw_regs *regs, enum rtw_pwrstate power, - int before_rf, int digphy) -{ - uint32_t anaparm; - - anaparm = RTW_READ(regs, RTW_ANAPARM); - anaparm &= ~(RTW_ANAPARM_RFPOW_MASK | RTW_ANAPARM_TXDACOFF); - - switch (power) { - case RTW_OFF: - if (before_rf) - return; - anaparm |= RTW_ANAPARM_RFPOW_PHILIPS_OFF; - anaparm |= RTW_ANAPARM_TXDACOFF; - break; - case RTW_SLEEP: - if (!before_rf) - return; - anaparm |= RTW_ANAPARM_RFPOW_PHILIPS_SLEEP; - anaparm |= RTW_ANAPARM_TXDACOFF; - break; - case RTW_ON: - if (!before_rf) - return; - if (digphy) { - anaparm |= RTW_ANAPARM_RFPOW_DIG_PHILIPS_ON; - /* XXX guess */ - anaparm |= RTW_ANAPARM_TXDACOFF; - } else - anaparm |= RTW_ANAPARM_RFPOW_ANA_PHILIPS_ON; - break; - } - RTW_DPRINTF(RTW_DEBUG_PWR, - ("%s: power state %s, %s RF, reg[ANAPARM] <- %08x\n", - __func__, rtw_pwrstate_string(power), - (before_rf) ? "before" : "after", anaparm)); - - RTW_WRITE(regs, RTW_ANAPARM, anaparm); - RTW_SYNC(regs, RTW_ANAPARM, RTW_ANAPARM); -} - -static __inline void -rtw_pwrstate0(struct rtw_softc *sc, enum rtw_pwrstate power, int before_rf, - int digphy) -{ - rtw_set_access(sc, RTW_ACCESS_ANAPARM); - sc->sc_pwrstate_cb(&sc->sc_regs, power, before_rf, digphy); - rtw_set_access(sc, RTW_ACCESS_NONE); -} - -static int -rtw_pwrstate(struct rtw_softc *sc, enum rtw_pwrstate power) -{ - int rc; - - RTW_DPRINTF(RTW_DEBUG_PWR, - ("%s: %s->%s\n", sc->sc_ic.ic_if.if_xname, - rtw_pwrstate_string(sc->sc_pwrstate), - rtw_pwrstate_string(power))); - - if (sc->sc_pwrstate == power) - return 0; - - rtw_pwrstate0(sc, power, 1, sc->sc_flags & RTW_F_DIGPHY); - rc = rtw_rf_pwrstate(sc->sc_rf, power); - rtw_pwrstate0(sc, power, 0, sc->sc_flags & RTW_F_DIGPHY); - - switch (power) { - case RTW_ON: - /* TBD set LEDs */ - break; - case RTW_SLEEP: - /* TBD */ - break; - case RTW_OFF: - /* TBD */ - break; - } - if (rc == 0) - sc->sc_pwrstate = power; - else - sc->sc_pwrstate = RTW_OFF; - return rc; -} - -static int -rtw_tune(struct rtw_softc *sc) -{ - struct ieee80211com *ic = &sc->sc_ic; - struct rtw_tx_radiotap_header *rt = &sc->sc_txtap; - struct rtw_rx_radiotap_header *rr = &sc->sc_rxtap; - u_int chan; - int rc, antdiv, dflantb; - - antdiv = sc->sc_flags & RTW_F_ANTDIV; - dflantb = sc->sc_flags & RTW_F_DFLANTB; - - chan = ieee80211_chan2ieee(ic, ic->ic_curchan); - if (chan == IEEE80211_CHAN_ANY) - panic("%s: chan == IEEE80211_CHAN_ANY", ic->ic_if.if_xname); - - rt->rt_chan_freq = htole16(ic->ic_curchan->ic_freq); - rt->rt_chan_flags = htole16(ic->ic_curchan->ic_flags); - - rr->rr_chan_freq = htole16(ic->ic_curchan->ic_freq); - rr->rr_chan_flags = htole16(ic->ic_curchan->ic_flags); - - if (chan == sc->sc_cur_chan) { - RTW_DPRINTF(RTW_DEBUG_TUNE, - ("%s: already tuned chan #%d\n", - ic->ic_if.if_xname, chan)); - return 0; - } - - rtw_suspend_ticks(sc); - - rtw_io_enable(sc, RTW_CR_RE | RTW_CR_TE, 0); - - /* TBD wait for Tx to complete */ - - KKASSERT((sc->sc_flags & RTW_F_ENABLED) != 0); - - rc = rtw_phy_init(&sc->sc_regs, sc->sc_rf, - rtw_chan2txpower(&sc->sc_srom, ic, ic->ic_curchan), - sc->sc_csthr, ic->ic_curchan->ic_freq, antdiv, - dflantb, RTW_ON); - if (rc != 0) { - /* XXX condition on powersaving */ - kprintf("%s: phy init failed\n", ic->ic_if.if_xname); - } - - sc->sc_cur_chan = chan; - - rtw_io_enable(sc, RTW_CR_RE | RTW_CR_TE, 1); - - rtw_resume_ticks(sc); - - return rc; -} - -static void -rtw_disable(struct rtw_softc *sc) -{ - int rc; - - if ((sc->sc_flags & RTW_F_ENABLED) == 0) - return; - - /* turn off PHY */ - if ((sc->sc_flags & RTW_F_INVALID) == 0 && - (rc = rtw_pwrstate(sc, RTW_OFF)) != 0) - if_printf(&sc->sc_ic.ic_if, "failed to turn off PHY\n"); - - sc->sc_flags &= ~RTW_F_ENABLED; -} - -static int -rtw_enable(struct rtw_softc *sc) -{ - if ((sc->sc_flags & RTW_F_ENABLED) == 0) { - sc->sc_flags |= RTW_F_ENABLED; - /* - * Power may have been removed, and WEP keys thus reset. - */ - sc->sc_flags &= ~RTW_F_DK_VALID; - } - return (0); -} - -static void -rtw_transmit_config(struct rtw_regs *regs) -{ - uint32_t tcr; - - tcr = RTW_READ(regs, RTW_TCR); - - tcr |= RTW_TCR_CWMIN; - tcr &= ~RTW_TCR_MXDMA_MASK; - tcr |= RTW_TCR_MXDMA_256; - tcr |= RTW_TCR_SAT; /* send ACK as fast as possible */ - tcr &= ~RTW_TCR_LBK_MASK; - tcr |= RTW_TCR_LBK_NORMAL; /* normal operating mode */ - - /* set short/long retry limits */ - tcr &= ~(RTW_TCR_SRL_MASK|RTW_TCR_LRL_MASK); - tcr |= __SHIFTIN(4, RTW_TCR_SRL_MASK) | __SHIFTIN(4, RTW_TCR_LRL_MASK); - - tcr &= ~RTW_TCR_CRC; /* NIC appends CRC32 */ - - RTW_WRITE(regs, RTW_TCR, tcr); - RTW_SYNC(regs, RTW_TCR, RTW_TCR); -} - -static void -rtw_enable_interrupts(struct rtw_softc *sc) -{ - struct rtw_regs *regs = &sc->sc_regs; - - sc->sc_inten = RTW_INTR_RX|RTW_INTR_TX|RTW_INTR_BEACON|RTW_INTR_ATIMINT; - sc->sc_inten |= RTW_INTR_IOERROR|RTW_INTR_TIMEOUT; - - RTW_WRITE16(regs, RTW_IMR, sc->sc_inten); - RTW_WBW(regs, RTW_IMR, RTW_ISR); - RTW_WRITE16(regs, RTW_ISR, 0xffff); - RTW_SYNC(regs, RTW_IMR, RTW_ISR); - - /* XXX necessary? */ - if (sc->sc_intr_ack != NULL) - sc->sc_intr_ack(regs); -} - -static void -rtw_set_nettype(struct rtw_softc *sc, enum ieee80211_opmode opmode) -{ - struct rtw_regs *regs = &sc->sc_regs; - uint8_t msr; - - /* I'm guessing that MSR is protected as CONFIG[0123] are. */ - rtw_set_access(sc, RTW_ACCESS_CONFIG); - - msr = RTW_READ8(regs, RTW_MSR) & ~RTW_MSR_NETYPE_MASK; - - switch (opmode) { - case IEEE80211_M_AHDEMO: - case IEEE80211_M_IBSS: - msr |= RTW_MSR_NETYPE_ADHOC_OK; - break; - case IEEE80211_M_HOSTAP: - msr |= RTW_MSR_NETYPE_AP_OK; - break; - case IEEE80211_M_MONITOR: - /* XXX */ - msr |= RTW_MSR_NETYPE_NOLINK; - break; - case IEEE80211_M_STA: - msr |= RTW_MSR_NETYPE_INFRA_OK; - break; - } - RTW_WRITE8(regs, RTW_MSR, msr); - - rtw_set_access(sc, RTW_ACCESS_NONE); -} - -#define rtw_calchash(addr) \ - (ether_crc32_be((addr), IEEE80211_ADDR_LEN) >> 26) - -static void -rtw_pktfilt_load(struct rtw_softc *sc) -{ - struct rtw_regs *regs = &sc->sc_regs; - struct ieee80211com *ic = &sc->sc_ic; - struct ifnet *ifp = &ic->ic_if; - struct ifmultiaddr *ifma; - uint32_t hashes[2] = { 0, 0 }; - int hash; - - /* XXX might be necessary to stop Rx/Tx engines while setting filters */ - - sc->sc_rcr &= ~RTW_RCR_PKTFILTER_MASK; - sc->sc_rcr &= ~(RTW_RCR_MXDMA_MASK | RTW_RCR_RXFTH_MASK); - - sc->sc_rcr |= RTW_RCR_PKTFILTER_DEFAULT; - /* MAC auto-reset PHY (huh?) */ - sc->sc_rcr |= RTW_RCR_ENMARP; - /* DMA whole Rx packets, only. Set Tx DMA burst size to 1024 bytes. */ - sc->sc_rcr |= RTW_RCR_MXDMA_1024 | RTW_RCR_RXFTH_WHOLE; - - switch (ic->ic_opmode) { - case IEEE80211_M_MONITOR: - sc->sc_rcr |= RTW_RCR_MONITOR; - break; - case IEEE80211_M_AHDEMO: - case IEEE80211_M_IBSS: - /* receive broadcasts in our BSS */ - sc->sc_rcr |= RTW_RCR_ADD3; - break; - default: - break; - } - - ifp->if_flags &= ~IFF_ALLMULTI; - - /* XXX accept all broadcast if scanning */ - if ((ifp->if_flags & IFF_BROADCAST) != 0) - sc->sc_rcr |= RTW_RCR_AB; /* accept all broadcast */ - - if (ifp->if_flags & IFF_PROMISC) { - sc->sc_rcr |= RTW_RCR_AB; /* accept all broadcast */ -allmulti: - ifp->if_flags |= IFF_ALLMULTI; - goto setit; - } - - /* - * Program the 64-bit multicast hash filter. - */ - TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { - if (ifma->ifma_addr->sa_family != AF_LINK) - continue; - - hash = rtw_calchash( - LLADDR((struct sockaddr_dl *)ifma->ifma_addr)); - hashes[hash >> 5] |= (1 << (hash & 0x1f)); - sc->sc_rcr |= RTW_RCR_AM; - } - - /* all bits set => hash is useless */ - if (~(hashes[0] & hashes[1]) == 0) - goto allmulti; - -setit: - if (ifp->if_flags & IFF_ALLMULTI) { - sc->sc_rcr |= RTW_RCR_AM; /* accept all multicast */ - hashes[0] = hashes[1] = 0xffffffff; - } - - RTW_WRITE(regs, RTW_MAR0, hashes[0]); - RTW_WRITE(regs, RTW_MAR1, hashes[1]); - RTW_WRITE(regs, RTW_RCR, sc->sc_rcr); - RTW_SYNC(regs, RTW_MAR0, RTW_RCR); /* RTW_MAR0 < RTW_MAR1 < RTW_RCR */ - - DPRINTF(sc, RTW_DEBUG_PKTFILT, - ("%s: RTW_MAR0 %08x RTW_MAR1 %08x RTW_RCR %08x\n", - ifp->if_xname, RTW_READ(regs, RTW_MAR0), - RTW_READ(regs, RTW_MAR1), RTW_READ(regs, RTW_RCR))); -} - -/* Must be called at splnet. */ -static void -rtw_init(void *xsc) -{ - struct rtw_softc *sc = xsc; - struct ieee80211com *ic = &sc->sc_ic; - struct ifnet *ifp = &ic->ic_if; - struct rtw_regs *regs = &sc->sc_regs; - int rc = 0; - - rc = rtw_enable(sc); - if (rc) - goto out; - - /* Cancel pending I/O and reset. */ - rtw_stop(sc, 0); - - DPRINTF(sc, RTW_DEBUG_TUNE, - ("%s: channel %d freq %d flags 0x%04x\n", ifp->if_xname, - ieee80211_chan2ieee(ic, ic->ic_curchan), - ic->ic_curchan->ic_freq, ic->ic_curchan->ic_flags)); - - rc = rtw_pwrstate(sc, RTW_OFF); - if (rc) - goto out; - - rc = rtw_swring_setup(sc); - if (rc) - goto out; - - rtw_transmit_config(regs); - - rtw_set_access(sc, RTW_ACCESS_CONFIG); - - RTW_WRITE8(regs, RTW_MSR, 0x0); /* no link */ - RTW_WBW(regs, RTW_MSR, RTW_BRSR); - - /* long PLCP header, 1Mb/2Mb basic rate */ - RTW_WRITE16(regs, RTW_BRSR, RTW_BRSR_MBR8180_2MBPS); - RTW_SYNC(regs, RTW_BRSR, RTW_BRSR); - - rtw_set_access(sc, RTW_ACCESS_ANAPARM); - rtw_set_access(sc, RTW_ACCESS_NONE); - - /* XXX from reference sources */ - RTW_WRITE(regs, RTW_FEMR, 0xffff); - RTW_SYNC(regs, RTW_FEMR, RTW_FEMR); - - rtw_set_rfprog(sc); - - RTW_WRITE8(regs, RTW_PHYDELAY, sc->sc_phydelay); - /* from Linux driver */ - RTW_WRITE8(regs, RTW_CRCOUNT, RTW_CRCOUNT_MAGIC); - - RTW_SYNC(regs, RTW_PHYDELAY, RTW_CRCOUNT); - - rtw_enable_interrupts(sc); - - rtw_pktfilt_load(sc); - - rtw_hwring_setup(sc); - - rtw_wep_setkeys(sc); - - rtw_io_enable(sc, RTW_CR_RE | RTW_CR_TE, 1); - - ifp->if_flags |= IFF_RUNNING; - ic->ic_state = IEEE80211_S_INIT; - - RTW_WRITE16(regs, RTW_BSSID16, 0x0); - RTW_WRITE(regs, RTW_BSSID32, 0x0); - - rtw_resume_ticks(sc); - - rtw_set_nettype(sc, IEEE80211_M_MONITOR); - - if (ic->ic_opmode == IEEE80211_M_MONITOR) - ieee80211_new_state(ic, IEEE80211_S_RUN, -1); - else - ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); - -out: - if (rc) - if_printf(ifp, "interface not running\n"); -} - -static void -rtw_led_init(struct rtw_softc *sc) -{ - struct rtw_regs *regs = &sc->sc_regs; - uint8_t cfg0, cfg1; - - rtw_set_access(sc, RTW_ACCESS_CONFIG); - - cfg0 = RTW_READ8(regs, RTW_CONFIG0); - cfg0 |= RTW_CONFIG0_LEDGPOEN; - RTW_WRITE8(regs, RTW_CONFIG0, cfg0); - - cfg1 = RTW_READ8(regs, RTW_CONFIG1); - RTW_DPRINTF(RTW_DEBUG_LED, - ("%s: read %02x from reg[CONFIG1]\n", - sc->sc_ic.ic_if.if_xname, cfg1)); - - cfg1 &= ~RTW_CONFIG1_LEDS_MASK; - cfg1 |= RTW_CONFIG1_LEDS_TX_RX; - RTW_WRITE8(regs, RTW_CONFIG1, cfg1); - - rtw_set_access(sc, RTW_ACCESS_NONE); -} - -/* - * IEEE80211_S_INIT: LED1 off - * - * IEEE80211_S_AUTH, - * IEEE80211_S_ASSOC, - * IEEE80211_S_SCAN: LED1 blinks @ 1 Hz, blinks at 5Hz for tx/rx - * - * IEEE80211_S_RUN: LED1 on, blinks @ 5Hz for tx/rx - */ -static void -rtw_led_newstate(struct rtw_softc *sc, enum ieee80211_state nstate) -{ - struct rtw_led_state *ls = &sc->sc_led_state; - - switch (nstate) { - case IEEE80211_S_INIT: - rtw_led_init(sc); - callout_stop(&ls->ls_slow_ch); - callout_stop(&ls->ls_fast_ch); - ls->ls_slowblink = 0; - ls->ls_actblink = 0; - ls->ls_default = 0; - break; - case IEEE80211_S_SCAN: - callout_reset(&ls->ls_slow_ch, RTW_LED_SLOW_TICKS, - rtw_led_slowblink, sc); - callout_reset(&ls->ls_fast_ch, RTW_LED_FAST_TICKS, - rtw_led_fastblink, sc); - /*FALLTHROUGH*/ - case IEEE80211_S_AUTH: - case IEEE80211_S_ASSOC: - ls->ls_default = RTW_LED1; - ls->ls_actblink = RTW_LED1; - ls->ls_slowblink = RTW_LED1; - break; - case IEEE80211_S_RUN: - ls->ls_slowblink = 0; - break; - } - rtw_led_set(sc); -} - -static void -rtw_led_set(struct rtw_softc *sc) -{ - struct rtw_led_state *ls = &sc->sc_led_state; - struct rtw_regs *regs = &sc->sc_regs; - uint8_t led_condition, mask, newval, val; - bus_size_t ofs; - - led_condition = ls->ls_default; - - if (ls->ls_state & RTW_LED_S_SLOW) - led_condition ^= ls->ls_slowblink; - if (ls->ls_state & (RTW_LED_S_RX|RTW_LED_S_TX)) - led_condition ^= ls->ls_actblink; - - RTW_DPRINTF(RTW_DEBUG_LED, - ("%s: LED condition %02x\n", sc->sc_ic.ic_if.if_xname, - led_condition)); - - switch (sc->sc_hwverid) { - default: - case 'F': - ofs = RTW_PSR; - newval = mask = RTW_PSR_LEDGPO0 | RTW_PSR_LEDGPO1; - if (led_condition & RTW_LED0) - newval &= ~RTW_PSR_LEDGPO0; - if (led_condition & RTW_LED1) - newval &= ~RTW_PSR_LEDGPO1; - break; - case 'D': - ofs = RTW_9346CR; - mask = RTW_9346CR_EEM_MASK | RTW_9346CR_EEDI | RTW_9346CR_EECS; - newval = RTW_9346CR_EEM_PROGRAM; - if (led_condition & RTW_LED0) - newval |= RTW_9346CR_EEDI; - if (led_condition & RTW_LED1) - newval |= RTW_9346CR_EECS; - break; - } - val = RTW_READ8(regs, ofs); - RTW_DPRINTF(RTW_DEBUG_LED, - ("%s: read %02x from reg[%02x]\n", - sc->sc_ic.ic_if.if_xname, val, ofs)); - val &= ~mask; - val |= newval; - RTW_WRITE8(regs, ofs, val); - RTW_DPRINTF(RTW_DEBUG_LED, - ("%s: wrote %02x to reg[%02x]\n", - sc->sc_ic.ic_if.if_xname, val, ofs)); - RTW_SYNC(regs, ofs, ofs); -} - -static void -rtw_led_fastblink(void *arg) -{ - struct rtw_softc *sc = arg; - struct ifnet *ifp = &sc->sc_ic.ic_if; - struct rtw_led_state *ls = &sc->sc_led_state; - int ostate; - - lwkt_serialize_enter(ifp->if_serializer); - - ostate = ls->ls_state; - ls->ls_state ^= ls->ls_event; - - if ((ls->ls_event & RTW_LED_S_TX) == 0) - ls->ls_state &= ~RTW_LED_S_TX; - - if ((ls->ls_event & RTW_LED_S_RX) == 0) - ls->ls_state &= ~RTW_LED_S_RX; - - ls->ls_event = 0; - - if (ostate != ls->ls_state) - rtw_led_set(sc); - - callout_reset(&ls->ls_fast_ch, RTW_LED_FAST_TICKS, - rtw_led_fastblink, sc); - - lwkt_serialize_exit(ifp->if_serializer); -} - -static void -rtw_led_slowblink(void *arg) -{ - struct rtw_softc *sc = arg; - struct ifnet *ifp = &sc->sc_ic.ic_if; - struct rtw_led_state *ls = &sc->sc_led_state; - - lwkt_serialize_enter(ifp->if_serializer); - - ls->ls_state ^= RTW_LED_S_SLOW; - rtw_led_set(sc); - callout_reset(&ls->ls_slow_ch, RTW_LED_SLOW_TICKS, - rtw_led_slowblink, sc); - - lwkt_serialize_exit(ifp->if_serializer); -} - -static int -rtw_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *cr) -{ - struct rtw_softc *sc = ifp->if_softc; - int rc = 0; - - switch (cmd) { - case SIOCSIFFLAGS: - if (ifp->if_flags & IFF_UP) { - if ((ifp->if_flags & IFF_RUNNING) == 0) - rtw_init(sc); - RTW_PRINT_REGS(&sc->sc_regs, ifp->if_xname, __func__); - } else if (sc->sc_flags & RTW_F_ENABLED) { - RTW_PRINT_REGS(&sc->sc_regs, ifp->if_xname, __func__); - rtw_stop(sc, 1); - } - break; - case SIOCADDMULTI: - case SIOCDELMULTI: - if (ifp->if_flags & IFF_RUNNING) - rtw_pktfilt_load(sc); - break; - default: - rc = ieee80211_ioctl(&sc->sc_ic, cmd, data, cr); - if (rc == ENETRESET) { - if (sc->sc_flags & RTW_F_ENABLED) - rtw_init(sc); - rc = 0; - } - break; - } - return rc; -} - -/* - * Select a transmit ring with at least one h/w and s/w descriptor free. - * Return 0 on success, -1 on failure. - */ -static __inline int -rtw_txring_choose(struct rtw_softc *sc, struct rtw_txsoft_blk **tsbp, - struct rtw_txdesc_blk **tdbp, int pri) -{ - struct rtw_txsoft_blk *tsb; - struct rtw_txdesc_blk *tdb; - - KKASSERT(pri >= 0 && pri < RTW_NTXPRI); - - tsb = &sc->sc_txsoft_blk[pri]; - tdb = &sc->sc_txdesc_blk[pri]; - - if (STAILQ_EMPTY(&tsb->tsb_freeq) || tdb->tdb_nfree == 0) { - if (tsb->tsb_tx_timer == 0) - tsb->tsb_tx_timer = 5; - *tsbp = NULL; - *tdbp = NULL; - return -1; - } - *tsbp = tsb; - *tdbp = tdb; - return 0; -} - -static __inline struct mbuf * -rtw_80211_dequeue(struct rtw_softc *sc, struct ifqueue *ifq, int pri, - struct rtw_txsoft_blk **tsbp, struct rtw_txdesc_blk **tdbp, - struct ieee80211_node **nip) -{ - struct mbuf *m; - struct ifnet *ifp = &sc->sc_if; - - if (IF_QEMPTY(ifq)) - return NULL; - if (rtw_txring_choose(sc, tsbp, tdbp, pri) == -1) { - DPRINTF(sc, RTW_DEBUG_XMIT_RSRC, - ("%s: no ring %d descriptor\n", ifp->if_xname, pri)); - ifq_set_oactive(&ifp->if_snd); - ifp->if_timer = 1; - return NULL; - } - IF_DEQUEUE(ifq, m); - *nip = (struct ieee80211_node *)m->m_pkthdr.rcvif; - m->m_pkthdr.rcvif = NULL; - KKASSERT(*nip != NULL); - return m; -} - -/* - * Point *mp at the next 802.11 frame to transmit. Point *tsbp - * at the driver's selection of transmit control block for the packet. - */ -static int -rtw_dequeue(struct ifnet *ifp, struct rtw_txsoft_blk **tsbp, - struct rtw_txdesc_blk **tdbp, struct mbuf **mp, - struct ieee80211_node **nip) -{ - struct rtw_softc *sc = ifp->if_softc; - struct ether_header *eh; - struct mbuf *m0; - int pri; - - DPRINTF(sc, RTW_DEBUG_XMIT, - ("%s: enter %s\n", ifp->if_xname, __func__)); - - if (sc->sc_ic.ic_state == IEEE80211_S_RUN && - (*mp = rtw_80211_dequeue(sc, &sc->sc_beaconq, RTW_TXPRIBCN, tsbp, - tdbp, nip)) != NULL) { - DPRINTF(sc, RTW_DEBUG_XMIT, - ("%s: dequeue beacon frame\n", ifp->if_xname)); - return 0; - } - - if ((*mp = rtw_80211_dequeue(sc, &sc->sc_ic.ic_mgtq, RTW_TXPRIMD, tsbp, - tdbp, nip)) != NULL) { - DPRINTF(sc, RTW_DEBUG_XMIT, - ("%s: dequeue mgt frame\n", ifp->if_xname)); - return 0; - } - - *mp = NULL; - - if (sc->sc_ic.ic_state != IEEE80211_S_RUN) { - ifq_purge(&ifp->if_snd); - DPRINTF(sc, RTW_DEBUG_XMIT, - ("%s: not running\n", ifp->if_xname)); - return 0; - } - - m0 = ifq_dequeue(&ifp->if_snd); - if (m0 == NULL) { - DPRINTF(sc, RTW_DEBUG_XMIT, - ("%s: no frame ready\n", ifp->if_xname)); - return 0; - } - DPRINTF(sc, RTW_DEBUG_XMIT, - ("%s: dequeue data frame\n", ifp->if_xname)); - - pri = ((m0->m_flags & M_PWR_SAV) != 0) ? RTW_TXPRIHI : RTW_TXPRIMD; - - if (rtw_txring_choose(sc, tsbp, tdbp, pri) == -1) { - DPRINTF(sc, RTW_DEBUG_XMIT_RSRC, - ("%s: no ring %d descriptor\n", ifp->if_xname, pri)); - ifq_set_oactive(&ifp->if_snd); - ifq_prepend(&ifp->if_snd, m0); - sc->sc_if.if_timer = 1; - return 0; - } - - BPF_MTAP(ifp, m0); - - eh = mtod(m0, struct ether_header *); - *nip = ieee80211_find_txnode(&sc->sc_ic, eh->ether_dhost); - if (*nip == NULL) { - /* NB: ieee80211_find_txnode does stat+msg */ - m_freem(m0); - return -1; - } - - if ((m0 = ieee80211_encap(&sc->sc_ic, m0, *nip)) == NULL) { - DPRINTF(sc, RTW_DEBUG_XMIT, - ("%s: encap error\n", ifp->if_xname)); - ieee80211_free_node(*nip); - IFNET_STAT_INC(ifp, oerrors, 1); - return -1; - } - - IFNET_STAT_INC(ifp, opackets, 1); - DPRINTF(sc, RTW_DEBUG_XMIT, - ("%s: leave %s\n", ifp->if_xname, __func__)); - *mp = m0; - return 0; -} - -static __inline int -rtw_txsegs_too_short(struct rtw_txsegs *segs) -{ - int i; - - for (i = 0; i < segs->nseg; i++) { - if (segs->segs[i].ds_len < 4) - return 1; - } - return 0; -} - -static __inline int -rtw_txsegs_too_long(struct rtw_txsegs *segs) -{ - int i; - - for (i = 0; i < segs->nseg; i++) { - if (segs->segs[i].ds_len > RTW_TXLEN_LENGTH_MASK) - return 1; - } - return 0; -} - -static void -rtw_txbuf_dma_map(void *arg, bus_dma_segment_t *seg, int nseg, - bus_size_t mapsize, int error) -{ - struct rtw_txsegs *s = arg; - - if (error) - return; - - KASSERT(nseg <= RTW_MAXPKTSEGS, ("too many tx mbuf seg")); - - s->nseg = nseg; - bcopy(seg, s->segs, sizeof(*seg) * nseg); -} - -static struct mbuf * -rtw_load_txbuf(struct rtw_softc *sc, struct rtw_txsoft *ts, - struct rtw_txsegs *segs, int ndesc_free, struct mbuf *m) -{ - int unload = 0, error; - - error = bus_dmamap_load_mbuf(sc->sc_txsoft_dmat, ts->ts_dmamap, m, - rtw_txbuf_dma_map, segs, BUS_DMA_NOWAIT); - if (error && error != EFBIG) { - if_printf(&sc->sc_ic.ic_if, "can't load tx mbuf1\n"); - goto back; - } - - if (error || segs->nseg > ndesc_free || rtw_txsegs_too_short(segs)) { - struct mbuf *m_new; - - if (error == 0) - bus_dmamap_unload(sc->sc_txsoft_dmat, ts->ts_dmamap); - - m_new = m_defrag(m, M_NOWAIT); - if (m_new == NULL) { - if_printf(&sc->sc_ic.ic_if, "can't defrag tx mbuf\n"); - error = ENOBUFS; - goto back; - } - m = m_new; - - error = bus_dmamap_load_mbuf(sc->sc_txsoft_dmat, ts->ts_dmamap, - m, rtw_txbuf_dma_map, segs, - BUS_DMA_NOWAIT); - if (error) { - if_printf(&sc->sc_ic.ic_if, "can't load tx mbuf2\n"); - goto back; - } - unload = 1; - - error = EFBIG; - if (segs->nseg > ndesc_free) { - if_printf(&sc->sc_ic.ic_if, "not enough free txdesc\n"); - goto back; - } - if (rtw_txsegs_too_short(segs)) { - if_printf(&sc->sc_ic.ic_if, "segment too short\n"); - goto back; - } - error = 0; - } - - if (rtw_txsegs_too_long(segs)) { - if_printf(&sc->sc_ic.ic_if, "segment too long\n"); - unload = 1; - error = EFBIG; - } - -back: - if (error) { - if (unload) - bus_dmamap_unload(sc->sc_txsoft_dmat, ts->ts_dmamap); - m_freem(m); - m = NULL; - } else { - bus_dmamap_sync(sc->sc_txsoft_dmat, ts->ts_dmamap, - BUS_DMASYNC_PREWRITE); - } - return m; -} - -#ifdef RTW_DEBUG -static void -rtw_print_txdesc(struct rtw_softc *sc, const char *action, - struct rtw_txsoft *ts, struct rtw_txdesc_blk *tdb, int desc) -{ - struct rtw_txdesc *td = &tdb->tdb_desc[desc]; - - DPRINTF(sc, RTW_DEBUG_XMIT_DESC, - ("%s: %p %s txdesc[%d] " - "next %#08x buf %#08x " - "ctl0 %#08x ctl1 %#08x len %#08x\n", - sc->sc_ic.ic_if.if_xname, ts, action, - desc, le32toh(td->td_buf), le32toh(td->td_next), - le32toh(td->td_ctl0), le32toh(td->td_ctl1), - le32toh(td->td_len))); -} -#endif /* RTW_DEBUG */ - -static void -rtw_start(struct ifnet *ifp, struct ifaltq_subque *ifsq) -{ - struct rtw_softc *sc = ifp->if_softc; - struct ieee80211com *ic = &sc->sc_ic; - struct ieee80211_node *ni; - struct rtw_txsoft *ts; - struct mbuf *m0; - uint32_t proto_ctl0; - - ASSERT_ALTQ_SQ_DEFAULT(ifp, ifsq); - DPRINTF(sc, RTW_DEBUG_XMIT, - ("%s: enter %s\n", ifp->if_xname, __func__)); - - if ((ifp->if_flags & IFF_RUNNING) == 0 || ifq_is_oactive(&ifp->if_snd)) - goto out; - - /* XXX do real rate control */ - proto_ctl0 = RTW_TXCTL0_RTSRATE_1MBPS; - - if (ic->ic_flags & IEEE80211_F_SHPREAMBLE) - proto_ctl0 |= RTW_TXCTL0_SPLCP; - - for (;;) { - struct rtw_txsegs segs; - struct rtw_duration *d0; - struct ieee80211_frame_min *wh; - struct rtw_txsoft_blk *tsb; - struct rtw_txdesc_blk *tdb; - struct rtw_txdesc *td; - struct ieee80211_key *k; - uint32_t ctl0, ctl1; - uint8_t tppoll; - int desc, i, lastdesc, npkt, rate, rateidx, ratectl; - - if (rtw_dequeue(ifp, &tsb, &tdb, &m0, &ni) == -1) - continue; - if (m0 == NULL) - break; - - wh = mtod(m0, struct ieee80211_frame_min *); - - if ((wh->i_fc[1] & IEEE80211_FC1_PROTECTED) != 0 && - (k = ieee80211_crypto_encap(ic, ni, m0)) == NULL) { - ieee80211_free_node(ni); - m_freem(m0); - break; - } else { - k = NULL; - } - - ts = STAILQ_FIRST(&tsb->tsb_freeq); - - m0 = rtw_load_txbuf(sc, ts, &segs, tdb->tdb_nfree, m0); - if (m0 == NULL || segs.nseg == 0) { - DPRINTF(sc, RTW_DEBUG_XMIT, - ("%s: %s failed\n", ifp->if_xname, __func__)); - goto post_dequeue_err; - } - - /* - * Note well: rtw_load_txbuf may have created a new chain, - * so we must find the header once more. - */ - wh = mtod(m0, struct ieee80211_frame_min *); - - if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == - IEEE80211_FC0_TYPE_MGT) { - rateidx = 0; - rate = 2; /* 1Mbit/s */ - ratectl = 0; - } else { - ieee80211_ratectl_findrate(ni, m0->m_pkthdr.len, - &rateidx, 1); - rate = IEEE80211_RS_RATE(&ni->ni_rates, rateidx); - ratectl =1; - - if (rate == 0) { - if_printf(ifp, "incorrect rate\n"); - rateidx = 0; - rate = 2; /* 1Mbit/s */ - ratectl = 0; - } - } - -#ifdef RTW_DEBUG - if ((ifp->if_flags & (IFF_DEBUG | IFF_LINK2)) == - (IFF_DEBUG | IFF_LINK2)) { - ieee80211_dump_pkt(mtod(m0, uint8_t *), - (segs.nseg == 1) ? m0->m_pkthdr.len - : sizeof(wh), - rate, 0); - } -#endif /* RTW_DEBUG */ - ctl0 = proto_ctl0 | - __SHIFTIN(m0->m_pkthdr.len, RTW_TXCTL0_TPKTSIZE_MASK); - - switch (rate) { - default: - case 2: - ctl0 |= RTW_TXCTL0_RATE_1MBPS; - break; - case 4: - ctl0 |= RTW_TXCTL0_RATE_2MBPS; - break; - case 11: - ctl0 |= RTW_TXCTL0_RATE_5MBPS; - break; - case 22: - ctl0 |= RTW_TXCTL0_RATE_11MBPS; - break; - } - /* XXX >= ? Compare after fragmentation? */ - if (m0->m_pkthdr.len > ic->ic_rtsthreshold) - ctl0 |= RTW_TXCTL0_RTSEN; - - /* - * XXX Sometimes writes a bogus keyid; h/w doesn't - * seem to care, since we don't activate h/w Tx - * encryption. - */ - if (k != NULL) { - ctl0 |= __SHIFTIN(k->wk_keyix, RTW_TXCTL0_KEYID_MASK) & - RTW_TXCTL0_KEYID_MASK; - } - - if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == - IEEE80211_FC0_TYPE_MGT) { - ctl0 &= ~(RTW_TXCTL0_SPLCP | RTW_TXCTL0_RTSEN); - if ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == - IEEE80211_FC0_SUBTYPE_BEACON) - ctl0 |= RTW_TXCTL0_BEACON; - } - - if (rtw_compute_duration(wh, k, m0->m_pkthdr.len, - ic->ic_flags, ic->ic_fragthreshold, - rate, &ts->ts_d0, &ts->ts_dn, &npkt, - (ifp->if_flags & (IFF_DEBUG|IFF_LINK2)) == - (IFF_DEBUG|IFF_LINK2)) == -1) { - DPRINTF(sc, RTW_DEBUG_XMIT, - ("%s: fail compute duration\n", __func__)); - goto post_load_err; - } - - d0 = &ts->ts_d0; - - *(uint16_t*)wh->i_dur = htole16(d0->d_data_dur); - - ctl1 = __SHIFTIN(d0->d_plcp_len, RTW_TXCTL1_LENGTH_MASK) | - __SHIFTIN(d0->d_rts_dur, RTW_TXCTL1_RTSDUR_MASK); - - if (d0->d_residue) - ctl1 |= RTW_TXCTL1_LENGEXT; - - /* TBD fragmentation */ - - ts->ts_first = tdb->tdb_next; - KKASSERT(ts->ts_first < tdb->tdb_ndesc); - - if (ic->ic_rawbpf != NULL) - bpf_mtap(ic->ic_rawbpf, m0); - - if (sc->sc_radiobpf != NULL) { - struct rtw_tx_radiotap_header *rt = &sc->sc_txtap; - - rt->rt_flags = 0; - rt->rt_rate = rate; - - bpf_ptap(sc->sc_radiobpf, m0, rt, - sizeof(sc->sc_txtapu)); - } - - for (i = 0, lastdesc = desc = ts->ts_first; i < segs.nseg; - i++, desc = RTW_NEXT_IDX(tdb, desc)) { - td = &tdb->tdb_desc[desc]; - td->td_ctl0 = htole32(ctl0); - if (i != 0) - td->td_ctl0 |= htole32(RTW_TXCTL0_OWN); - td->td_ctl1 = htole32(ctl1); - td->td_buf = htole32(segs.segs[i].ds_addr); - td->td_len = htole32(segs.segs[i].ds_len); - lastdesc = desc; -#ifdef RTW_DEBUG - rtw_print_txdesc(sc, "load", ts, tdb, desc); -#endif /* RTW_DEBUG */ - } - - KKASSERT(desc < tdb->tdb_ndesc); - - ts->ts_ni = ni; - KKASSERT(ni != NULL); - ts->ts_mbuf = m0; - ts->ts_rateidx = rateidx; - ts->ts_ratectl = ratectl; - ts->ts_last = lastdesc; - tdb->tdb_desc[ts->ts_last].td_ctl0 |= htole32(RTW_TXCTL0_LS); - tdb->tdb_desc[ts->ts_first].td_ctl0 |= htole32(RTW_TXCTL0_FS); - -#ifdef RTW_DEBUG - rtw_print_txdesc(sc, "FS on", ts, tdb, ts->ts_first); - rtw_print_txdesc(sc, "LS on", ts, tdb, ts->ts_last); -#endif /* RTW_DEBUG */ - - tdb->tdb_nfree -= segs.nseg; - tdb->tdb_next = desc; - - tdb->tdb_desc[ts->ts_first].td_ctl0 |= htole32(RTW_TXCTL0_OWN); - -#ifdef RTW_DEBUG - rtw_print_txdesc(sc, "OWN on", ts, tdb, ts->ts_first); -#endif /* RTW_DEBUG */ - - STAILQ_REMOVE_HEAD(&tsb->tsb_freeq, ts_q); - STAILQ_INSERT_TAIL(&tsb->tsb_dirtyq, ts, ts_q); - - if (tsb != &sc->sc_txsoft_blk[RTW_TXPRIBCN]) - sc->sc_led_state.ls_event |= RTW_LED_S_TX; - tsb->tsb_tx_timer = 5; - ifp->if_timer = 1; - tppoll = RTW_READ8(&sc->sc_regs, RTW_TPPOLL); - tppoll &= ~RTW_TPPOLL_SALL; - tppoll |= tsb->tsb_poll & RTW_TPPOLL_ALL; - RTW_WRITE8(&sc->sc_regs, RTW_TPPOLL, tppoll); - RTW_SYNC(&sc->sc_regs, RTW_TPPOLL, RTW_TPPOLL); - - bus_dmamap_sync(tdb->tdb_dmat, tdb->tdb_dmamap, - BUS_DMASYNC_PREWRITE); - } -out: - DPRINTF(sc, RTW_DEBUG_XMIT, - ("%s: leave %s\n", ifp->if_xname, __func__)); - return; - -post_load_err: - bus_dmamap_unload(sc->sc_txsoft_dmat, ts->ts_dmamap); - m_freem(m0); -post_dequeue_err: - ieee80211_free_node(ni); - - DPRINTF(sc, RTW_DEBUG_XMIT, - ("%s: leave %s\n", ifp->if_xname, __func__)); -} - -static void -rtw_idle(struct rtw_softc *sc) -{ - struct rtw_regs *regs = &sc->sc_regs; - int active; - - /* request stop DMA; wait for packets to stop transmitting. */ - - RTW_WRITE8(regs, RTW_TPPOLL, RTW_TPPOLL_SALL); - RTW_WBR(regs, RTW_TPPOLL, RTW_TPPOLL); - - for (active = 0; - active < 300 && - (RTW_READ8(regs, RTW_TPPOLL) & RTW_TPPOLL_ACTIVE) != 0; - active++) - DELAY(10); - if_printf(&sc->sc_ic.ic_if, "transmit DMA idle in %dus\n", active * 10); -} - -static void -rtw_watchdog(struct ifnet *ifp) -{ - int pri, tx_timeouts = 0; - struct rtw_softc *sc = ifp->if_softc; - - ifp->if_timer = 0; - - if ((sc->sc_flags & RTW_F_ENABLED) == 0) - return; - - for (pri = 0; pri < RTW_NTXPRI; pri++) { - struct rtw_txsoft_blk *tsb = &sc->sc_txsoft_blk[pri]; - - if (tsb->tsb_tx_timer == 0) - continue; - else if (--tsb->tsb_tx_timer == 0) { - if (STAILQ_EMPTY(&tsb->tsb_dirtyq)) - continue; - if_printf(ifp, "transmit timeout, priority %d\n", pri); - IFNET_STAT_INC(ifp, oerrors, 1); - tx_timeouts++; - } else { - ifp->if_timer = 1; - } - } - - if (tx_timeouts > 0) { - /* - * Stop Tx DMA, disable xmtr, flush Tx rings, enable xmtr, - * reset s/w tx-ring pointers, and start transmission. - * - * TBD Stop/restart just the broken rings? - */ - rtw_idle(sc); - rtw_io_enable(sc, RTW_CR_TE, 0); - rtw_txdesc_blk_reset_all(sc); - rtw_io_enable(sc, RTW_CR_TE, 1); - rtw_txring_fixup(sc); - rtw_start(ifp, ifq_get_subq_default(&ifp->if_snd)); - } - ieee80211_watchdog(&sc->sc_ic); -} - -static void -rtw_next_scan(void *arg) -{ - struct ieee80211com *ic = arg; - struct ifnet *ifp = &ic->ic_if; - - lwkt_serialize_enter(ifp->if_serializer); - - /* don't call rtw_start w/o network interrupts blocked */ - if (ic->ic_state == IEEE80211_S_SCAN) - ieee80211_next_scan(ic); - - lwkt_serialize_exit(ifp->if_serializer); -} - -static void -rtw_join_bss(struct rtw_softc *sc, uint8_t *bssid, uint16_t intval0) -{ - uint16_t bcnitv, bintritv, intval; - int i; - struct rtw_regs *regs = &sc->sc_regs; - - for (i = 0; i < IEEE80211_ADDR_LEN; i++) - RTW_WRITE8(regs, RTW_BSSID + i, bssid[i]); - - RTW_SYNC(regs, RTW_BSSID16, RTW_BSSID32); - - rtw_set_access(sc, RTW_ACCESS_CONFIG); - - intval = MIN(intval0, __SHIFTOUT_MASK(RTW_BCNITV_BCNITV_MASK)); - - bcnitv = RTW_READ16(regs, RTW_BCNITV) & ~RTW_BCNITV_BCNITV_MASK; - bcnitv |= __SHIFTIN(intval, RTW_BCNITV_BCNITV_MASK); - RTW_WRITE16(regs, RTW_BCNITV, bcnitv); - /* interrupt host 1ms before the TBTT */ - bintritv = RTW_READ16(regs, RTW_BINTRITV) & ~RTW_BINTRITV_BINTRITV; - bintritv |= __SHIFTIN(1000, RTW_BINTRITV_BINTRITV); - RTW_WRITE16(regs, RTW_BINTRITV, bintritv); - /* magic from Linux */ - RTW_WRITE16(regs, RTW_ATIMWND, __SHIFTIN(1, RTW_ATIMWND_ATIMWND)); - RTW_WRITE16(regs, RTW_ATIMTRITV, __SHIFTIN(2, RTW_ATIMTRITV_ATIMTRITV)); - rtw_set_access(sc, RTW_ACCESS_NONE); - - rtw_io_enable(sc, RTW_CR_RE | RTW_CR_TE, 1); -} - -/* Synchronize the hardware state with the software state. */ -static int -rtw_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg) -{ - struct ifnet *ifp = ic->ic_ifp; - struct rtw_softc *sc = ifp->if_softc; - enum ieee80211_state ostate; - int error; - - ostate = ic->ic_state; - - ieee80211_ratectl_newstate(ic, nstate); - rtw_led_newstate(sc, nstate); - - if (nstate == IEEE80211_S_INIT) { - callout_stop(&sc->sc_scan_ch); - sc->sc_cur_chan = IEEE80211_CHAN_ANY; - return sc->sc_mtbl.mt_newstate(ic, nstate, arg); - } - - if (ostate == IEEE80211_S_INIT && nstate != IEEE80211_S_INIT) - rtw_pwrstate(sc, RTW_ON); - - error = rtw_tune(sc); - if (error != 0) - return error; - - switch (nstate) { - case IEEE80211_S_INIT: - panic("%s: unexpected state IEEE80211_S_INIT", __func__); - break; - case IEEE80211_S_SCAN: - if (ostate != IEEE80211_S_SCAN) { - memset(ic->ic_bss->ni_bssid, 0, IEEE80211_ADDR_LEN); - rtw_set_nettype(sc, IEEE80211_M_MONITOR); - } - - callout_reset(&sc->sc_scan_ch, rtw_dwelltime * hz / 1000, - rtw_next_scan, ic); - - break; - case IEEE80211_S_RUN: - switch (ic->ic_opmode) { - case IEEE80211_M_HOSTAP: - case IEEE80211_M_IBSS: - rtw_set_nettype(sc, IEEE80211_M_MONITOR); - /*FALLTHROUGH*/ - case IEEE80211_M_AHDEMO: - case IEEE80211_M_STA: - rtw_join_bss(sc, ic->ic_bss->ni_bssid, - ic->ic_bss->ni_intval); - break; - case IEEE80211_M_MONITOR: - break; - } - rtw_set_nettype(sc, ic->ic_opmode); - break; - case IEEE80211_S_ASSOC: - case IEEE80211_S_AUTH: - break; - } - - if (nstate != IEEE80211_S_SCAN) - callout_stop(&sc->sc_scan_ch); - - return sc->sc_mtbl.mt_newstate(ic, nstate, arg); -} - -/* Extend a 32-bit TSF timestamp to a 64-bit timestamp. */ -static uint64_t -rtw_tsf_extend(struct rtw_regs *regs, uint32_t rstamp) -{ - uint32_t tsftl, tsfth; - - tsfth = RTW_READ(regs, RTW_TSFTRH); - tsftl = RTW_READ(regs, RTW_TSFTRL); - if (tsftl < rstamp) /* Compensate for rollover. */ - tsfth--; - return ((uint64_t)tsfth << 32) | rstamp; -} - -static void -rtw_recv_mgmt(struct ieee80211com *ic, struct mbuf *m, - struct ieee80211_node *ni, int subtype, int rssi, uint32_t rstamp) -{ - struct ifnet *ifp = &ic->ic_if; - struct rtw_softc *sc = ifp->if_softc; - - sc->sc_mtbl.mt_recv_mgmt(ic, m, ni, subtype, rssi, rstamp); - - switch (subtype) { - case IEEE80211_FC0_SUBTYPE_PROBE_RESP: - case IEEE80211_FC0_SUBTYPE_BEACON: - if (ic->ic_opmode == IEEE80211_M_IBSS && - ic->ic_state == IEEE80211_S_RUN) { - uint64_t tsf = rtw_tsf_extend(&sc->sc_regs, rstamp); - - if (le64toh(ni->ni_tstamp.tsf) >= tsf) - ieee80211_ibss_merge(ni); - } - break; - default: - break; - } -} - -#ifdef foo -static struct ieee80211_node * -rtw_node_alloc(struct ieee80211_node_table *nt) -{ - struct ifnet *ifp = nt->nt_ic->ic_ifp; - struct rtw_softc *sc = (struct rtw_softc *)ifp->if_softc; - struct ieee80211_node *ni = (*sc->sc_mtbl.mt_node_alloc)(nt); - - DPRINTF(sc, RTW_DEBUG_NODE, - ("%s: alloc node %p\n", sc->sc_dev.dv_xname, ni)); - return ni; -} - -static void -rtw_node_free(struct ieee80211_node *ni) -{ - struct ieee80211com *ic = ni->ni_ic; - struct ifnet *ifp = ic->ic_ifp; - struct rtw_softc *sc = (struct rtw_softc *)ifp->if_softc; - char ethstr[ETHER_ADDRSTRLEN + 1]; - - DPRINTF(sc, RTW_DEBUG_NODE, - ("%s: freeing node %p %s\n", sc->sc_dev.dv_xname, ni, - kether_ntoa(ni->ni_bssid, ethstr))); - sc->sc_mtbl.mt_node_free(ni); -} -#endif - -static int -rtw_media_change(struct ifnet *ifp) -{ - int error; - - error = ieee80211_media_change(ifp); - if (error == ENETRESET) { - if ((ifp->if_flags & (IFF_RUNNING|IFF_UP)) == - (IFF_RUNNING|IFF_UP)) - rtw_init(ifp); /* XXX lose error */ - error = 0; - } - return error; -} - -static void -rtw_media_status(struct ifnet *ifp, struct ifmediareq *imr) -{ - struct rtw_softc *sc = ifp->if_softc; - - if ((sc->sc_flags & RTW_F_ENABLED) == 0) { - imr->ifm_active = IFM_IEEE80211 | IFM_NONE; - imr->ifm_status = 0; - return; - } - ieee80211_media_status(ifp, imr); -} - -static __inline void -rtw_set80211methods(struct rtw_mtbl *mtbl, struct ieee80211com *ic) -{ - mtbl->mt_newstate = ic->ic_newstate; - ic->ic_newstate = rtw_newstate; - - mtbl->mt_recv_mgmt = ic->ic_recv_mgmt; - ic->ic_recv_mgmt = rtw_recv_mgmt; - -#ifdef foo - mtbl->mt_node_free = ic->ic_node_free; - ic->ic_node_free = rtw_node_free; - - mtbl->mt_node_alloc = ic->ic_node_alloc; - ic->ic_node_alloc = rtw_node_alloc; -#endif - - ic->ic_crypto.cs_key_delete = rtw_key_delete; - ic->ic_crypto.cs_key_set = rtw_key_set; - ic->ic_crypto.cs_key_update_begin = rtw_key_update_begin; - ic->ic_crypto.cs_key_update_end = rtw_key_update_end; -} - -static __inline void -rtw_init_radiotap(struct rtw_softc *sc) -{ - sc->sc_rxtap.rr_ihdr.it_len = htole16(sizeof(sc->sc_rxtapu)); - sc->sc_rxtap.rr_ihdr.it_present = htole32(RTW_RX_RADIOTAP_PRESENT); - - sc->sc_txtap.rt_ihdr.it_len = htole16(sizeof(sc->sc_txtapu)); - sc->sc_txtap.rt_ihdr.it_present = htole32(RTW_TX_RADIOTAP_PRESENT); -} - -static struct rtw_rf * -rtw_rf_attach(struct rtw_softc *sc, enum rtw_rfchipid rfchipid, int digphy) -{ - rtw_rf_write_t rf_write; - struct rtw_rf *rf; - - switch (rfchipid) { - default: - rf_write = rtw_rf_hostwrite; - break; - case RTW_RFCHIPID_INTERSIL: - case RTW_RFCHIPID_PHILIPS: - case RTW_RFCHIPID_GCT: /* XXX a guess */ - case RTW_RFCHIPID_RFMD: - rf_write = (rtw_host_rfio) ? rtw_rf_hostwrite : rtw_rf_macwrite; - break; - } - - switch (rfchipid) { - case RTW_RFCHIPID_GCT: - rf = rtw_grf5101_create(&sc->sc_regs, rf_write, 0); - sc->sc_pwrstate_cb = rtw_maxim_pwrstate; - sc->sc_getrssi = rtw_gct_getrssi; - break; - case RTW_RFCHIPID_MAXIM: - rf = rtw_max2820_create(&sc->sc_regs, rf_write, 0); - sc->sc_pwrstate_cb = rtw_maxim_pwrstate; - sc->sc_getrssi = rtw_maxim_getrssi; - break; - case RTW_RFCHIPID_PHILIPS: - rf = rtw_sa2400_create(&sc->sc_regs, rf_write, digphy); - sc->sc_pwrstate_cb = rtw_philips_pwrstate; - sc->sc_getrssi = rtw_philips_getrssi; - break; - case RTW_RFCHIPID_RFMD: - /* XXX RFMD has no RF constructor */ - sc->sc_pwrstate_cb = rtw_rfmd_pwrstate; - /*FALLTHROUGH*/ - default: - return NULL; - } - rf->rf_continuous_tx_cb = - (rtw_continuous_tx_cb_t)rtw_continuous_tx_enable; - rf->rf_continuous_tx_arg = sc; - return rf; -} - -/* Revision C and later use a different PHY delay setting than - * revisions A and B. - */ -static uint8_t -rtw_check_phydelay(struct rtw_regs *regs, uint32_t old_rcr) -{ -#define REVAB (RTW_RCR_MXDMA_UNLIMITED | RTW_RCR_AICV) -#define REVC (REVAB | RTW_RCR_RXFTH_WHOLE) - - uint8_t phydelay = __SHIFTIN(0x6, RTW_PHYDELAY_PHYDELAY); - - RTW_WRITE(regs, RTW_RCR, REVAB); - RTW_WBW(regs, RTW_RCR, RTW_RCR); - RTW_WRITE(regs, RTW_RCR, REVC); - - RTW_WBR(regs, RTW_RCR, RTW_RCR); - if ((RTW_READ(regs, RTW_RCR) & REVC) == REVC) - phydelay |= RTW_PHYDELAY_REVC_MAGIC; - - RTW_WRITE(regs, RTW_RCR, old_rcr); /* restore RCR */ - RTW_SYNC(regs, RTW_RCR, RTW_RCR); - - return phydelay; -#undef REVC -#undef REVAB -} - -int -rtw_attach(device_t dev) -{ - struct rtw_softc *sc = device_get_softc(dev); - struct ieee80211com *ic = &sc->sc_ic; - const struct ieee80211_cipher *wep_cipher; - struct ifnet *ifp = &ic->ic_if; - int rc; - - wep_cipher = ieee80211_crypto_cipher(IEEE80211_CIPHER_WEP); - KKASSERT(wep_cipher != NULL); - - memcpy(&rtw_cipher_wep, wep_cipher, sizeof(rtw_cipher_wep)); - rtw_cipher_wep.ic_decap = rtw_wep_decap; - - if_initname(ifp, device_get_name(dev), device_get_unit(dev)); - - switch (RTW_READ(&sc->sc_regs, RTW_TCR) & RTW_TCR_HWVERID_MASK) { - case RTW_TCR_HWVERID_F: - sc->sc_hwverid = 'F'; - break; - case RTW_TCR_HWVERID_D: - sc->sc_hwverid = 'D'; - break; - default: - sc->sc_hwverid = '?'; - break; - } - - sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, - &sc->sc_irq_rid, - RF_ACTIVE | RF_SHAREABLE); - if (sc->sc_irq_res == NULL) { - device_printf(dev, "could not alloc irq res\n"); - return ENXIO; - } - - /* Allocate h/w desc blocks */ - rc = rtw_desc_blk_alloc(sc); - if (rc) - goto err; - - /* Allocate s/w desc blocks */ - rc = rtw_soft_blk_alloc(sc); - if (rc) - goto err; - - /* Reset the chip to a known state. */ - rc = rtw_reset(sc); - if (rc) { - device_printf(dev, "could not reset\n"); - goto err; - } - - sc->sc_rcr = RTW_READ(&sc->sc_regs, RTW_RCR); - - if ((sc->sc_rcr & RTW_RCR_9356SEL) != 0) - sc->sc_flags |= RTW_F_9356SROM; - - rc = rtw_srom_read(sc); - if (rc) - goto err; - - rc = rtw_srom_parse(sc); - if (rc) { - device_printf(dev, "malformed serial ROM\n"); - goto err; - } - - device_printf(dev, "%s PHY\n", - ((sc->sc_flags & RTW_F_DIGPHY) != 0) ? "digital" - : "analog"); - - device_printf(dev, "CS threshold %u\n", sc->sc_csthr); - - sc->sc_rf = rtw_rf_attach(sc, sc->sc_rfchipid, - sc->sc_flags & RTW_F_DIGPHY); - if (sc->sc_rf == NULL) { - device_printf(dev, "could not attach RF\n"); - rc = ENXIO; - goto err; - } - - sc->sc_phydelay = rtw_check_phydelay(&sc->sc_regs, sc->sc_rcr); - - RTW_DPRINTF(RTW_DEBUG_ATTACH, - ("%s: PHY delay %d\n", ifp->if_xname, sc->sc_phydelay)); - - if (sc->sc_locale == RTW_LOCALE_UNKNOWN) - rtw_identify_country(sc); - - rtw_init_channels(sc); - - rc = rtw_identify_sta(sc); - if (rc) - goto err; - - ifp->if_softc = sc; - ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST; - ifp->if_init = rtw_init; - ifp->if_ioctl = rtw_ioctl; - ifp->if_start = rtw_start; - ifp->if_watchdog = rtw_watchdog; - ifq_set_maxlen(&ifp->if_snd, IFQ_MAXLEN); -#ifdef notyet - ifq_set_ready(&ifp->if_snd); -#endif - - ic->ic_phytype = IEEE80211_T_DS; - ic->ic_opmode = IEEE80211_M_STA; - ic->ic_caps = IEEE80211_C_PMGT | - IEEE80211_C_IBSS | - IEEE80211_C_HOSTAP | - IEEE80211_C_MONITOR; - ic->ic_sup_rates[IEEE80211_MODE_11B] = rtw_rates_11b; - - /* initialize led callout */ - callout_init(&sc->sc_led_state.ls_fast_ch); - callout_init(&sc->sc_led_state.ls_slow_ch); - - IEEE80211_ONOE_PARAM_SETUP(&sc->sc_onoe_param); - ic->ic_ratectl.rc_st_ratectl_cap = IEEE80211_RATECTL_CAP_ONOE; - ic->ic_ratectl.rc_st_ratectl = IEEE80211_RATECTL_ONOE; - ic->ic_ratectl.rc_st_attach = rtw_ratectl_attach; - - /* - * Call MI attach routines. - */ - ieee80211_ifattach(&sc->sc_ic); - - /* Override some ieee80211 methods */ - rtw_set80211methods(&sc->sc_mtbl, &sc->sc_ic); - - /* - * possibly we should fill in our own sc_send_prresp, since - * the RTL8180 is probably sending probe responses in ad hoc - * mode. - */ - - /* complete initialization */ - ieee80211_media_init(&sc->sc_ic, rtw_media_change, rtw_media_status); - callout_init(&sc->sc_scan_ch); - - rtw_init_radiotap(sc); - - bpfattach_dlt(ifp, DLT_IEEE802_11_RADIO, - sizeof(struct ieee80211_frame) + 64, &sc->sc_radiobpf); - - ifq_set_cpuid(&ifp->if_snd, rman_get_cpuid(sc->sc_irq_res)); - - rc = bus_setup_intr(dev, sc->sc_irq_res, INTR_MPSAFE, rtw_intr, sc, - &sc->sc_irq_handle, ifp->if_serializer); - if (rc) { - device_printf(dev, "can't set up interrupt\n"); - bpfdetach(ifp); - ieee80211_ifdetach(ic); - goto err; - } - - device_printf(dev, "hardware version %c\n", sc->sc_hwverid); - if (bootverbose) - ieee80211_announce(ic); - return 0; -err: - rtw_detach(dev); - return rc; -} - -int -rtw_detach(device_t dev) -{ - struct rtw_softc *sc = device_get_softc(dev); - struct ifnet *ifp = &sc->sc_ic.ic_if; - - if (device_is_attached(dev)) { - lwkt_serialize_enter(ifp->if_serializer); - - rtw_stop(sc, 1); - sc->sc_flags |= RTW_F_INVALID; - - callout_stop(&sc->sc_scan_ch); - bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_irq_handle); - - lwkt_serialize_exit(ifp->if_serializer); - - ieee80211_ifdetach(&sc->sc_ic); - } - - if (sc->sc_rf != NULL) - rtw_rf_destroy(sc->sc_rf); - - if (sc->sc_srom.sr_content != NULL) - kfree(sc->sc_srom.sr_content, M_DEVBUF); - - if (sc->sc_irq_res != NULL) { - bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irq_rid, - sc->sc_irq_res); - } - - rtw_soft_blk_free(sc); - rtw_desc_blk_free(sc); - return 0; -} - -static void -rtw_desc_dma_addr(void *arg, bus_dma_segment_t *seg, int nseg, int error) -{ - if (error) - return; - - KASSERT(nseg == 1, ("too many desc segments")); - *((uint32_t *)arg) = seg->ds_addr; /* XXX bus_addr_t */ -} - -static int -rtw_dma_alloc(struct rtw_softc *sc, bus_dma_tag_t *dmat, int len, - void **desc, uint32_t *phyaddr, bus_dmamap_t *dmamap) -{ - int error; - - error = bus_dma_tag_create(NULL, RTW_DESC_ALIGNMENT, 0, - BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, - NULL, NULL, len, 1, len, 0, dmat); - if (error) { - if_printf(&sc->sc_ic.ic_if, "could not alloc desc DMA tag"); - return error; - } - - error = bus_dmamem_alloc(*dmat, desc, BUS_DMA_WAITOK | BUS_DMA_ZERO, - dmamap); - if (error) { - if_printf(&sc->sc_ic.ic_if, "could not alloc desc DMA mem"); - return error; - } - - error = bus_dmamap_load(*dmat, *dmamap, *desc, len, - rtw_desc_dma_addr, phyaddr, BUS_DMA_WAITOK); - if (error) { - if_printf(&sc->sc_ic.ic_if, "could not load desc DMA mem"); - bus_dmamem_free(*dmat, *desc, *dmamap); - *desc = NULL; - return error; - } - return 0; -} - -static void -rtw_dma_free(struct rtw_softc *sc __unused, bus_dma_tag_t *dmat, void **desc, - bus_dmamap_t *dmamap) -{ - if (*desc != NULL) { - bus_dmamap_unload(*dmat, *dmamap); - bus_dmamem_free(*dmat, *desc, *dmamap); - *desc = NULL; - } - - if (*dmat != NULL) { - bus_dma_tag_destroy(*dmat); - *dmat = NULL; - } -} - -static void -rtw_txdesc_blk_free(struct rtw_softc *sc, int q_no) -{ - struct rtw_txdesc_blk *tdb = &sc->sc_txdesc_blk[q_no]; - - rtw_dma_free(sc, &tdb->tdb_dmat, (void **)&tdb->tdb_desc, - &tdb->tdb_dmamap); -} - -static int -rtw_txdesc_blk_alloc(struct rtw_softc *sc, int q_len, int q_no, - bus_size_t q_basereg) -{ - struct rtw_txdesc_blk *tdb = &sc->sc_txdesc_blk[q_no]; - int i, error; - - /* - * Setup TX h/w desc - */ - error = rtw_dma_alloc(sc, &tdb->tdb_dmat, - q_len * sizeof(*tdb->tdb_desc), - (void **)&tdb->tdb_desc, &tdb->tdb_base, - &tdb->tdb_dmamap); - if (error) { - kprintf("%dth tx\n", q_no); - return error; - } - tdb->tdb_basereg = q_basereg; - - tdb->tdb_ndesc = q_len; - for (i = 0; i < tdb->tdb_ndesc; ++i) - tdb->tdb_desc[i].td_next = htole32(RTW_NEXT_DESC(tdb, i)); - - return 0; -} - -static void -rtw_rxdesc_blk_free(struct rtw_softc *sc) -{ - struct rtw_rxdesc_blk *rdb = &sc->sc_rxdesc_blk; - - rtw_dma_free(sc, &rdb->rdb_dmat, (void **)&rdb->rdb_desc, - &rdb->rdb_dmamap); -} - -static int -rtw_rxdesc_blk_alloc(struct rtw_softc *sc, int q_len) -{ - struct rtw_rxdesc_blk *rdb = &sc->sc_rxdesc_blk; - int error; - - /* - * Setup RX h/w desc - */ - error = rtw_dma_alloc(sc, &rdb->rdb_dmat, - q_len * sizeof(*rdb->rdb_desc), - (void **)&rdb->rdb_desc, &rdb->rdb_base, - &rdb->rdb_dmamap); - if (error) { - kprintf("rx\n"); - } else { - rdb->rdb_ndesc = q_len; - } - - return error; -} - -static void -rtw_txsoft_blk_free(struct rtw_softc *sc, int n_sd, int q_no) -{ - struct rtw_txsoft_blk *tsb = &sc->sc_txsoft_blk[q_no]; - - if (tsb->tsb_desc != NULL) { - int i; - - for (i = 0; i < n_sd; ++i) { - bus_dmamap_destroy(sc->sc_txsoft_dmat, - tsb->tsb_desc[i].ts_dmamap); - } - kfree(tsb->tsb_desc, M_DEVBUF); - tsb->tsb_desc = NULL; - } -} - -static int -rtw_txsoft_blk_alloc(struct rtw_softc *sc, int q_len, int q_no, uint8_t q_poll) -{ - struct rtw_txsoft_blk *tsb = &sc->sc_txsoft_blk[q_no]; - int i, error; - - STAILQ_INIT(&tsb->tsb_dirtyq); - STAILQ_INIT(&tsb->tsb_freeq); - tsb->tsb_ndesc = q_len; - tsb->tsb_desc = kmalloc(q_len * sizeof(*tsb->tsb_desc), M_DEVBUF, - M_WAITOK | M_ZERO); - tsb->tsb_poll = q_poll; - - for (i = 0; i < tsb->tsb_ndesc; ++i) { - error = bus_dmamap_create(sc->sc_txsoft_dmat, 0, - &tsb->tsb_desc[i].ts_dmamap); - if (error) { - if_printf(&sc->sc_ic.ic_if, "could not create DMA map " - "for soft tx desc\n"); - rtw_txsoft_blk_free(sc, i, q_no); - return error; - } - } - return 0; -} - -static void -rtw_rxsoft_blk_free(struct rtw_softc *sc, int n_sd) -{ - if (sc->sc_rxsoft_free) { - int i; - - for (i = 0; i < n_sd; ++i) { - bus_dmamap_destroy(sc->sc_rxsoft_dmat, - sc->sc_rxsoft[i].rs_dmamap); - } - sc->sc_rxsoft_free = 0; - } -} - -static int -rtw_rxsoft_blk_alloc(struct rtw_softc *sc, int q_len) -{ - int i, error; - - sc->sc_rxsoft_free = 1; - - /* - * Setup RX s/w desc - */ - for (i = 0; i < q_len; ++i) { - error = bus_dmamap_create(sc->sc_rxsoft_dmat, 0, - &sc->sc_rxsoft[i].rs_dmamap); - if (error) { - if_printf(&sc->sc_ic.ic_if, "could not create DMA map " - "for soft rx desc\n"); - rtw_rxsoft_blk_free(sc, i); - return error; - } - } - return 0; -} - -#define TXQ_PARAM(q, poll, breg) \ - [RTW_TXPRI ## q] = { \ - .txq_len = RTW_TXQLEN ## q, \ - .txq_poll = poll, \ - .txq_basereg = breg \ - } -static const struct { - int txq_len; - uint8_t txq_poll; - bus_size_t txq_basereg; -} txq_params[RTW_NTXPRI] = { - TXQ_PARAM(LO, RTW_TPPOLL_LPQ | RTW_TPPOLL_SLPQ, RTW_TLPDA), - TXQ_PARAM(MD, RTW_TPPOLL_NPQ | RTW_TPPOLL_SNPQ, RTW_TNPDA), - TXQ_PARAM(HI, RTW_TPPOLL_HPQ | RTW_TPPOLL_SHPQ, RTW_THPDA), - TXQ_PARAM(BCN, RTW_TPPOLL_BQ | RTW_TPPOLL_SBQ, RTW_TBDA) -}; -#undef TXQ_PARAM - -static int -rtw_desc_blk_alloc(struct rtw_softc *sc) -{ - int i, error; - - /* Create h/w TX desc */ - for (i = 0; i < RTW_NTXPRI; ++i) { - error = rtw_txdesc_blk_alloc(sc, txq_params[i].txq_len, i, - txq_params[i].txq_basereg); - if (error) - return error; - } - - /* Create h/w RX desc */ - return rtw_rxdesc_blk_alloc(sc, RTW_RXQLEN); -} - -static void -rtw_desc_blk_free(struct rtw_softc *sc) -{ - int i; - - for (i = 0; i < RTW_NTXPRI; ++i) - rtw_txdesc_blk_free(sc, i); - rtw_rxdesc_blk_free(sc); -} - -static int -rtw_soft_blk_alloc(struct rtw_softc *sc) -{ - int i, error; - - /* Create DMA tag for TX mbuf */ - error = bus_dma_tag_create(NULL, 1, 0, - BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, - NULL, NULL, - MCLBYTES, RTW_MAXPKTSEGS, MCLBYTES, - 0, &sc->sc_txsoft_dmat); - if (error) { - if_printf(&sc->sc_ic.ic_if, "could not alloc txsoft DMA tag\n"); - return error; - } - - /* Create DMA tag for RX mbuf */ - error = bus_dma_tag_create(NULL, 1, 0, - BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, - NULL, NULL, - MCLBYTES, 1, MCLBYTES, - 0, &sc->sc_rxsoft_dmat); - if (error) { - if_printf(&sc->sc_ic.ic_if, "could not alloc rxsoft DMA tag\n"); - return error; - } - - /* Create a spare DMA map for RX mbuf */ - error = bus_dmamap_create(sc->sc_rxsoft_dmat, 0, &sc->sc_rxsoft_dmamap); - if (error) { - if_printf(&sc->sc_ic.ic_if, "could not alloc spare rxsoft " - "DMA map\n"); - bus_dma_tag_destroy(sc->sc_rxsoft_dmat); - sc->sc_rxsoft_dmat = NULL; - return error; - } - - /* Create s/w TX desc */ - for (i = 0; i < RTW_NTXPRI; ++i) { - error = rtw_txsoft_blk_alloc(sc, txq_params[i].txq_len, i, - txq_params[i].txq_poll); - if (error) - return error; - } - - /* Create s/w RX desc */ - return rtw_rxsoft_blk_alloc(sc, RTW_RXQLEN); -} - -static void -rtw_soft_blk_free(struct rtw_softc *sc) -{ - int i; - - for (i = 0; i < RTW_NTXPRI; ++i) - rtw_txsoft_blk_free(sc, txq_params[i].txq_len, i); - - rtw_rxsoft_blk_free(sc, RTW_RXQLEN); - - if (sc->sc_txsoft_dmat != NULL) { - bus_dma_tag_destroy(sc->sc_txsoft_dmat); - sc->sc_txsoft_dmat = NULL; - } - - if (sc->sc_rxsoft_dmat != NULL) { - bus_dmamap_destroy(sc->sc_rxsoft_dmat, sc->sc_rxsoft_dmamap); - bus_dma_tag_destroy(sc->sc_rxsoft_dmat); - sc->sc_rxsoft_dmat = NULL; - } -} - -/* - * Arguments in: - * - * paylen: payload length (no FCS, no WEP header) - * - * hdrlen: header length - * - * rate: MSDU speed, units 500kb/s - * - * flags: IEEE80211_F_SHPREAMBLE (use short preamble), - * IEEE80211_F_SHSLOT (use short slot length) - * - * Arguments out: - * - * d: 802.11 Duration field for RTS, - * 802.11 Duration field for data frame, - * PLCP Length for data frame, - * residual octets at end of data slot - */ -static int -rtw_compute_duration1(int len, int use_ack, uint32_t icflags, int rate, - struct rtw_duration *d) -{ - int pre, ctsrate; - int ack, bitlen, data_dur, remainder; - - /* - * RTS reserves medium for SIFS | CTS | SIFS | (DATA) | SIFS | ACK - * DATA reserves medium for SIFS | ACK - * - * XXXMYC: no ACK on multicast/broadcast or control packets - */ - - bitlen = len * 8; - - pre = IEEE80211_DUR_DS_SIFS; - if (icflags & IEEE80211_F_SHPREAMBLE) { - pre += IEEE80211_DUR_DS_SHORT_PREAMBLE + - IEEE80211_DUR_DS_FAST_PLCPHDR; - } else { - pre += IEEE80211_DUR_DS_LONG_PREAMBLE + - IEEE80211_DUR_DS_SLOW_PLCPHDR; - } - - d->d_residue = 0; - data_dur = (bitlen * 2) / rate; - remainder = (bitlen * 2) % rate; - if (remainder != 0) { - d->d_residue = (rate - remainder) / 16; - data_dur++; - } - - switch (rate) { - case 2: /* 1 Mb/s */ - case 4: /* 2 Mb/s */ - /* 1 - 2 Mb/s WLAN: send ACK/CTS at 1 Mb/s */ - ctsrate = 2; - break; - case 11: /* 5.5 Mb/s */ - case 22: /* 11 Mb/s */ - case 44: /* 22 Mb/s */ - /* 5.5 - 11 Mb/s WLAN: send ACK/CTS at 2 Mb/s */ - ctsrate = 4; - break; - default: - /* TBD */ - return -1; - } - - d->d_plcp_len = data_dur; - - ack = (use_ack) ? pre + (IEEE80211_DUR_DS_SLOW_ACK * 2) / ctsrate : 0; - - d->d_rts_dur = pre + (IEEE80211_DUR_DS_SLOW_CTS * 2) / ctsrate + - pre + data_dur + - ack; - - d->d_data_dur = ack; - return 0; -} - -/* - * Arguments in: - * - * wh: 802.11 header - * - * paylen: payload length (no FCS, no WEP header) - * - * rate: MSDU speed, units 500kb/s - * - * fraglen: fragment length, set to maximum (or higher) for no - * fragmentation - * - * flags: IEEE80211_F_PRIVACY (hardware adds WEP), - * IEEE80211_F_SHPREAMBLE (use short preamble), - * IEEE80211_F_SHSLOT (use short slot length) - * - * Arguments out: - * - * d0: 802.11 Duration fields (RTS/Data), PLCP Length, Service fields - * of first/only fragment - * - * dn: 802.11 Duration fields (RTS/Data), PLCP Length, Service fields - * of last fragment - * - * rtw_compute_duration assumes crypto-encapsulation, if any, - * has already taken place. - */ -static int -rtw_compute_duration(const struct ieee80211_frame_min *wh, - const struct ieee80211_key *wk, int len, - uint32_t icflags, int fraglen, int rate, - struct rtw_duration *d0, struct rtw_duration *dn, - int *npktp, int debug) -{ - int ack, rc; - int cryptolen, /* crypto overhead: header+trailer */ - firstlen, /* first fragment's payload + overhead length */ - hdrlen, /* header length w/o driver padding */ - lastlen, /* last fragment's payload length w/ overhead */ - lastlen0, /* last fragment's payload length w/o overhead */ - npkt, /* number of fragments */ - overlen, /* non-802.11 header overhead per fragment */ - paylen; /* payload length w/o overhead */ - - hdrlen = ieee80211_anyhdrsize((const void *)wh); - - /* Account for padding required by the driver. */ - if (icflags & IEEE80211_F_DATAPAD) - paylen = len - roundup(hdrlen, sizeof(u_int32_t)); - else - paylen = len - hdrlen; - - overlen = IEEE80211_CRC_LEN; - - if (wk != NULL) { - cryptolen = wk->wk_cipher->ic_header + - wk->wk_cipher->ic_trailer; - paylen -= cryptolen; - overlen += cryptolen; - } - - npkt = paylen / fraglen; - lastlen0 = paylen % fraglen; - - if (npkt == 0) { /* no fragments */ - lastlen = paylen + overlen; - } else if (lastlen0 != 0) { /* a short "tail" fragment */ - lastlen = lastlen0 + overlen; - npkt++; - } else { /* full-length "tail" fragment */ - lastlen = fraglen + overlen; - } - - if (npktp != NULL) - *npktp = npkt; - - if (npkt > 1) - firstlen = fraglen + overlen; - else - firstlen = paylen + overlen; - - if (debug) { - kprintf("%s: npkt %d firstlen %d lastlen0 %d lastlen %d " - "fraglen %d overlen %d len %d rate %d icflags %08x\n", - __func__, npkt, firstlen, lastlen0, lastlen, fraglen, - overlen, len, rate, icflags); - } - - ack = (!IEEE80211_IS_MULTICAST(wh->i_addr1) && - (wh->i_fc[1] & IEEE80211_FC0_TYPE_MASK) != - IEEE80211_FC0_TYPE_CTL); - - rc = rtw_compute_duration1(firstlen + hdrlen, ack, icflags, rate, d0); - if (rc == -1) - return rc; - - if (npkt <= 1) { - *dn = *d0; - return 0; - } - return rtw_compute_duration1(lastlen + hdrlen, ack, icflags, rate, dn); -} - -static int -rtw_get_rssi(struct rtw_softc *sc, uint8_t raw, uint8_t sq) -{ - int rssi; - - rssi = sc->sc_getrssi(raw, sq); - - if (rssi == 0) - rssi = 1; - else if (rssi > 100) - rssi = 100; - - if (rssi > (RTW_NOISE_FLOOR + RTW_RSSI_CORR)) - rssi -= (RTW_NOISE_FLOOR + RTW_RSSI_CORR); - else - rssi = 0; - - return rssi; -} - -static int -rtw_maxim_getrssi(uint8_t raw, uint8_t sq __unused) -{ - int rssi = raw; - - rssi &= 0x7e; - rssi >>= 1; - rssi += 0x42; - if (raw & 0x1) - rssi += 0xa; - rssi &= 0xff; - - return rssi; -} - -static int -rtw_gct_getrssi(uint8_t raw, uint8_t sq __unused) -{ - int rssi = raw; - - rssi &= 0x7e; - if ((raw & 0x1) == 0 || rssi > 0x3c) - rssi = 100; - else - rssi = (100 * rssi) / 0x3c; - rssi &= 0xff; - - return rssi; -} - -static int -rtw_philips_getrssi(uint8_t raw, uint8_t sq) -{ - static const uint8_t sq_rssi_map[SA2400_SQ_RSSI_MAP_MAX] = - { SA2400_SQ_RSSI_MAP }; - - if (sq < SA2400_SQ_RSSI_MAP_MAX - 1) /* NB: -1 is intended */ - return sq_rssi_map[sq]; - - if (sq == 0x80) - return 1; - else - return 0x32; -} - -static void * -rtw_ratectl_attach(struct ieee80211com *ic, u_int rc) -{ - struct rtw_softc *sc = ic->ic_if.if_softc; - - switch (rc) { - case IEEE80211_RATECTL_ONOE: - return &sc->sc_onoe_param; - case IEEE80211_RATECTL_NONE: - /* This could only happen during detaching */ - return NULL; - default: - panic("unknown rate control algo %u", rc); - return NULL; - } -} diff --git a/sys/dev/netif/rtw/rtwphy.c b/sys/dev/netif/rtw/rtwphy.c deleted file mode 100644 index 5f956ec36d..0000000000 --- a/sys/dev/netif/rtw/rtwphy.c +++ /dev/null @@ -1,812 +0,0 @@ -/* - * Copyright (c) 2004, 2005 David Young. All rights reserved. - * - * Programmed for NetBSD by David Young. - * - * 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. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of David Young may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY David Young ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL David - * Young BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 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 DAMAGE. - * - * $NetBSD: rtwphy.c,v 1.9 2006/03/08 00:24:06 dyoung Exp $ - * $DragonFly: src/sys/dev/netif/rtw/rtwphy.c,v 1.5 2008/01/15 09:01:13 sephe Exp $ - */ - -/* - * Control the Philips SA2400 RF front-end and the baseband processor - * built into the Realtek RTL8180. - */ - -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -static int rtw_max2820_pwrstate(struct rtw_rf *, enum rtw_pwrstate); -static int rtw_sa2400_pwrstate(struct rtw_rf *, enum rtw_pwrstate); - -#define GCT_WRITE(__gr, __addr, __val, __label) \ -do { \ - if (rtw_rfbus_write(&(__gr)->gr_bus, RTW_RFCHIPID_GCT, \ - (__addr), (__val)) == -1) \ - goto __label; \ -} while(0) - -static int -rtw_bbp_preinit(struct rtw_regs *regs, u_int antatten0, int dflantb, u_int freq) -{ - u_int antatten = antatten0; - - if (dflantb) - antatten |= RTW_BBP_ANTATTEN_DFLANTB; - if (freq == 2484) /* channel 14 */ - antatten |= RTW_BBP_ANTATTEN_CHAN14; - return rtw_bbp_write(regs, RTW_BBP_ANTATTEN, antatten); -} - -static int -rtw_bbp_init(struct rtw_regs *regs, struct rtw_bbpset *bb, int antdiv, - int dflantb, uint8_t cs_threshold, u_int freq) -{ - int rc; - uint32_t sys2, sys3; - - sys2 = bb->bb_sys2; - if (antdiv) - sys2 |= RTW_BBP_SYS2_ANTDIV; - sys3 = bb->bb_sys3 | - __SHIFTIN(cs_threshold, RTW_BBP_SYS3_CSTHRESH_MASK); - -#define RTW_BBP_WRITE_OR_RETURN(reg, val) \ - if ((rc = rtw_bbp_write(regs, reg, val)) != 0) \ - return rc; - - RTW_BBP_WRITE_OR_RETURN(RTW_BBP_SYS1, bb->bb_sys1); - RTW_BBP_WRITE_OR_RETURN(RTW_BBP_TXAGC, bb->bb_txagc); - RTW_BBP_WRITE_OR_RETURN(RTW_BBP_LNADET, bb->bb_lnadet); - RTW_BBP_WRITE_OR_RETURN(RTW_BBP_IFAGCINI, bb->bb_ifagcini); - RTW_BBP_WRITE_OR_RETURN(RTW_BBP_IFAGCLIMIT, bb->bb_ifagclimit); - RTW_BBP_WRITE_OR_RETURN(RTW_BBP_IFAGCDET, bb->bb_ifagcdet); - - if ((rc = rtw_bbp_preinit(regs, bb->bb_antatten, dflantb, freq)) != 0) - return rc; - - RTW_BBP_WRITE_OR_RETURN(RTW_BBP_TRL, bb->bb_trl); - RTW_BBP_WRITE_OR_RETURN(RTW_BBP_SYS2, sys2); - RTW_BBP_WRITE_OR_RETURN(RTW_BBP_SYS3, sys3); - RTW_BBP_WRITE_OR_RETURN(RTW_BBP_CHESTLIM, bb->bb_chestlim); - RTW_BBP_WRITE_OR_RETURN(RTW_BBP_CHSQLIM, bb->bb_chsqlim); - return 0; -} - -static int -rtw_sa2400_txpower(struct rtw_rf *rf, uint8_t opaque_txpower) -{ - struct rtw_sa2400 *sa = (struct rtw_sa2400 *)rf; - struct rtw_rfbus *bus = &sa->sa_bus; - - return rtw_rfbus_write(bus, RTW_RFCHIPID_PHILIPS, SA2400_TX, - opaque_txpower); -} - -/* make sure we're using the same settings as the reference driver */ -static void -verify_syna(u_int freq, uint32_t val) -{ - uint32_t expected_val = ~val; - - switch (freq) { - case 2412: - expected_val = 0x0000096c; /* ch 1 */ - break; - case 2417: - expected_val = 0x00080970; /* ch 2 */ - break; - case 2422: - expected_val = 0x00100974; /* ch 3 */ - break; - case 2427: - expected_val = 0x00180978; /* ch 4 */ - break; - case 2432: - expected_val = 0x00000980; /* ch 5 */ - break; - case 2437: - expected_val = 0x00080984; /* ch 6 */ - break; - case 2442: - expected_val = 0x00100988; /* ch 7 */ - break; - case 2447: - expected_val = 0x0018098c; /* ch 8 */ - break; - case 2452: - expected_val = 0x00000994; /* ch 9 */ - break; - case 2457: - expected_val = 0x00080998; /* ch 10 */ - break; - case 2462: - expected_val = 0x0010099c; /* ch 11 */ - break; - case 2467: - expected_val = 0x001809a0; /* ch 12 */ - break; - case 2472: - expected_val = 0x000009a8; /* ch 13 */ - break; - case 2484: - expected_val = 0x000009b4; /* ch 14 */ - break; - } - KKASSERT(val == expected_val); -} - -/* freq is in MHz */ -static int -rtw_sa2400_tune(struct rtw_rf *rf, u_int freq) -{ - struct rtw_sa2400 *sa = (struct rtw_sa2400 *)rf; - struct rtw_rfbus *bus = &sa->sa_bus; - int rc; - uint32_t syna, synb, sync; - int n, nf; - - /* - * XO = 44MHz, R = 11, hence N is in units of XO / R = 4MHz. - * - * The channel spacing (5MHz) is not divisible by 4MHz, so - * we set the fractional part of N to compensate. - */ - n = freq / 4; - nf = (freq % 4) * 2; - - syna = __SHIFTIN(nf, SA2400_SYNA_NF_MASK) | - __SHIFTIN(n, SA2400_SYNA_N_MASK); - verify_syna(freq, syna); - - /* - * Divide the 44MHz crystal down to 4MHz. Set the fractional - * compensation charge pump value to agree with the fractional - * modulus. - */ - synb = __SHIFTIN(11, SA2400_SYNB_R_MASK) | SA2400_SYNB_L_NORMAL | - SA2400_SYNB_ON | SA2400_SYNB_ONE | - __SHIFTIN(80, SA2400_SYNB_FC_MASK); /* agrees w/ SA2400_SYNA_FM = 0 */ - - sync = SA2400_SYNC_CP_NORMAL; - - rc = rtw_rfbus_write(bus, RTW_RFCHIPID_PHILIPS, SA2400_SYNA, syna); - if (rc != 0) - return rc; - - rc = rtw_rfbus_write(bus, RTW_RFCHIPID_PHILIPS, SA2400_SYNB, synb); - if (rc != 0) - return rc; - - rc = rtw_rfbus_write(bus, RTW_RFCHIPID_PHILIPS, SA2400_SYNC, sync); - if (rc != 0) - return rc; - - return rtw_rfbus_write(bus, RTW_RFCHIPID_PHILIPS, SA2400_SYND, 0x0); -} - -static int -rtw_sa2400_pwrstate(struct rtw_rf *rf, enum rtw_pwrstate power) -{ - struct rtw_sa2400 *sa = (struct rtw_sa2400 *)rf; - struct rtw_rfbus *bus = &sa->sa_bus; - uint32_t opmode; - - opmode = SA2400_OPMODE_DEFAULTS; - switch (power) { - case RTW_ON: - opmode |= SA2400_OPMODE_MODE_TXRX; - break; - case RTW_SLEEP: - opmode |= SA2400_OPMODE_MODE_WAIT; - break; - case RTW_OFF: - opmode |= SA2400_OPMODE_MODE_SLEEP; - break; - } - - if (sa->sa_digphy) - opmode |= SA2400_OPMODE_DIGIN; - - return rtw_rfbus_write(bus, RTW_RFCHIPID_PHILIPS, SA2400_OPMODE, - opmode); -} - -static int -rtw_sa2400_manrx_init(struct rtw_sa2400 *sa) -{ - uint32_t manrx; - - /* - * XXX we are not supposed to be in RXMGC mode when we do this? - */ - manrx = SA2400_MANRX_AHSN; - manrx |= SA2400_MANRX_TEN; - manrx |= __SHIFTIN(1023, SA2400_MANRX_RXGAIN_MASK); - - return rtw_rfbus_write(&sa->sa_bus, RTW_RFCHIPID_PHILIPS, SA2400_MANRX, - manrx); -} - -static int -rtw_sa2400_vcocal_start(struct rtw_sa2400 *sa, int start) -{ - uint32_t opmode; - - opmode = SA2400_OPMODE_DEFAULTS; - if (start) - opmode |= SA2400_OPMODE_MODE_VCOCALIB; - else - opmode |= SA2400_OPMODE_MODE_SLEEP; - - if (sa->sa_digphy) - opmode |= SA2400_OPMODE_DIGIN; - - return rtw_rfbus_write(&sa->sa_bus, RTW_RFCHIPID_PHILIPS, SA2400_OPMODE, - opmode); -} - -static int -rtw_sa2400_vco_calibration(struct rtw_sa2400 *sa) -{ - int rc; - - /* calibrate VCO */ - if ((rc = rtw_sa2400_vcocal_start(sa, 1)) != 0) - return rc; - DELAY(2200); /* 2.2 milliseconds */ - /* XXX superfluous: SA2400 automatically entered SLEEP mode. */ - return rtw_sa2400_vcocal_start(sa, 0); -} - -static int -rtw_sa2400_filter_calibration(struct rtw_sa2400 *sa) -{ - uint32_t opmode; - - opmode = SA2400_OPMODE_DEFAULTS | SA2400_OPMODE_MODE_FCALIB; - if (sa->sa_digphy) - opmode |= SA2400_OPMODE_DIGIN; - - return rtw_rfbus_write(&sa->sa_bus, RTW_RFCHIPID_PHILIPS, SA2400_OPMODE, - opmode); -} - -static int -rtw_sa2400_dc_calibration(struct rtw_sa2400 *sa) -{ - struct rtw_rf *rf = &sa->sa_rf; - int rc; - uint32_t dccal; - - rf->rf_continuous_tx_cb(rf->rf_continuous_tx_arg, 1); - - dccal = SA2400_OPMODE_DEFAULTS | SA2400_OPMODE_MODE_TXRX; - - rc = rtw_rfbus_write(&sa->sa_bus, RTW_RFCHIPID_PHILIPS, SA2400_OPMODE, - dccal); - if (rc != 0) - return rc; - - /* - * DCALIB after being in Tx mode for 5 microseconds - */ - DELAY(5); - - dccal &= ~SA2400_OPMODE_MODE_MASK; - dccal |= SA2400_OPMODE_MODE_DCALIB; - - rc = rtw_rfbus_write(&sa->sa_bus, RTW_RFCHIPID_PHILIPS, SA2400_OPMODE, - dccal); - if (rc != 0) - return rc; - - DELAY(20); /* calibration takes at most 20 microseconds */ - - rf->rf_continuous_tx_cb(rf->rf_continuous_tx_arg, 0); - return 0; -} - -static int -rtw_sa2400_agc_init(struct rtw_sa2400 *sa) -{ - uint32_t agc; - - agc = __SHIFTIN(25, SA2400_AGC_MAXGAIN_MASK); - agc |= __SHIFTIN(7, SA2400_AGC_BBPDELAY_MASK); - agc |= __SHIFTIN(15, SA2400_AGC_LNADELAY_MASK); - agc |= __SHIFTIN(27, SA2400_AGC_RXONDELAY_MASK); - - return rtw_rfbus_write(&sa->sa_bus, RTW_RFCHIPID_PHILIPS, SA2400_AGC, - agc); -} - -static void -rtw_sa2400_destroy(struct rtw_rf *rf) -{ - struct rtw_sa2400 *sa = (struct rtw_sa2400 *)rf; - - memset(sa, 0, sizeof(*sa)); - kfree(sa, M_DEVBUF); -} - -static int -rtw_sa2400_calibrate(struct rtw_rf *rf, u_int freq) -{ - struct rtw_sa2400 *sa = (struct rtw_sa2400 *)rf; - int i, rc; - - /* XXX reference driver calibrates VCO twice. Is it a bug? */ - for (i = 0; i < 2; i++) { - if ((rc = rtw_sa2400_vco_calibration(sa)) != 0) - return rc; - } - /* VCO calibration erases synthesizer registers, so re-tune */ - if ((rc = rtw_sa2400_tune(rf, freq)) != 0) - return rc; - if ((rc = rtw_sa2400_filter_calibration(sa)) != 0) - return rc; - /* analog PHY needs DC calibration */ - if (!sa->sa_digphy) - return rtw_sa2400_dc_calibration(sa); - return 0; -} - -static int -rtw_sa2400_init(struct rtw_rf *rf, u_int freq, uint8_t opaque_txpower, - enum rtw_pwrstate power) -{ - struct rtw_sa2400 *sa = (struct rtw_sa2400 *)rf; - int rc; - - if ((rc = rtw_sa2400_txpower(rf, opaque_txpower)) != 0) - return rc; - - /* skip configuration if it's time to sleep or to power-down. */ - if (power == RTW_SLEEP || power == RTW_OFF) - return rtw_sa2400_pwrstate(rf, power); - - /* go to sleep for configuration */ - if ((rc = rtw_sa2400_pwrstate(rf, RTW_SLEEP)) != 0) - return rc; - - if ((rc = rtw_sa2400_tune(rf, freq)) != 0) - return rc; - if ((rc = rtw_sa2400_agc_init(sa)) != 0) - return rc; - if ((rc = rtw_sa2400_manrx_init(sa)) != 0) - return rc; - if ((rc = rtw_sa2400_calibrate(rf, freq)) != 0) - return rc; - - /* enter Tx/Rx mode */ - return rtw_sa2400_pwrstate(rf, power); -} - -struct rtw_rf * -rtw_sa2400_create(struct rtw_regs *regs, rtw_rf_write_t rf_write, int digphy) -{ - struct rtw_sa2400 *sa; - struct rtw_rfbus *bus; - struct rtw_rf *rf; - struct rtw_bbpset *bb; - - sa = kmalloc(sizeof(*sa), M_DEVBUF, M_WAITOK | M_ZERO); - - sa->sa_digphy = digphy; - - rf = &sa->sa_rf; - bus = &sa->sa_bus; - - rf->rf_init = rtw_sa2400_init; - rf->rf_destroy = rtw_sa2400_destroy; - rf->rf_txpower = rtw_sa2400_txpower; - rf->rf_tune = rtw_sa2400_tune; - rf->rf_pwrstate = rtw_sa2400_pwrstate; - bb = &rf->rf_bbpset; - - /* XXX magic */ - bb->bb_antatten = RTW_BBP_ANTATTEN_PHILIPS_MAGIC; - bb->bb_chestlim = 0x00; - bb->bb_chsqlim = 0xa0; - bb->bb_ifagcdet = 0x64; - bb->bb_ifagcini = 0x90; - bb->bb_ifagclimit = 0x1a; - bb->bb_lnadet = 0xe0; - bb->bb_sys1 = 0x98; - bb->bb_sys2 = 0x47; - bb->bb_sys3 = 0x90; - bb->bb_trl = 0x88; - bb->bb_txagc = 0x38; - - bus->b_regs = regs; - bus->b_write = rf_write; - - return &sa->sa_rf; -} - -static int -rtw_grf5101_txpower(struct rtw_rf *rf, uint8_t opaque_txpower) -{ - struct rtw_grf5101 *gr = (struct rtw_grf5101 *)rf; - - GCT_WRITE(gr, 0x15, 0, err); - GCT_WRITE(gr, 0x06, opaque_txpower, err); - GCT_WRITE(gr, 0x15, 0x10, err); - GCT_WRITE(gr, 0x15, 0x00, err); - return 0; -err: - return -1; -} - -static int -rtw_grf5101_pwrstate(struct rtw_rf *rf, enum rtw_pwrstate power) -{ - struct rtw_grf5101 *gr = (struct rtw_grf5101 *)rf; - - switch (power) { - case RTW_OFF: - case RTW_SLEEP: - GCT_WRITE(gr, 0x07, 0x0000, err); - GCT_WRITE(gr, 0x1f, 0x0045, err); - GCT_WRITE(gr, 0x1f, 0x0005, err); - GCT_WRITE(gr, 0x00, 0x08e4, err); - default: - break; - case RTW_ON: - GCT_WRITE(gr, 0x1f, 0x0001, err); - DELAY(10); - GCT_WRITE(gr, 0x1f, 0x0001, err); - DELAY(10); - GCT_WRITE(gr, 0x1f, 0x0041, err); - DELAY(10); - GCT_WRITE(gr, 0x1f, 0x0061, err); - DELAY(10); - GCT_WRITE(gr, 0x00, 0x0ae4, err); - DELAY(10); - GCT_WRITE(gr, 0x07, 0x1000, err); - DELAY(100); - break; - } - - return 0; -err: - return -1; -} - -static int -rtw_grf5101_tune(struct rtw_rf *rf, u_int freq) -{ - int channel; - struct rtw_grf5101 *gr = (struct rtw_grf5101 *)rf; - - if (freq == 2484) { - channel = 14; - } else if ((channel = (freq - 2412) / 5 + 1) < 1 || channel > 13) { - RTW_DPRINTF(RTW_DEBUG_PHY, - ("%s: invalid channel %d (freq %d)\n", __func__, channel, - freq)); - return -1; - } - - GCT_WRITE(gr, 0x07, 0, err); - GCT_WRITE(gr, 0x0b, channel - 1, err); - GCT_WRITE(gr, 0x07, 0x1000, err); - return 0; -err: - return -1; -} - -static int -rtw_grf5101_init(struct rtw_rf *rf, u_int freq, uint8_t opaque_txpower, - enum rtw_pwrstate power) -{ - int rc; - struct rtw_grf5101 *gr = (struct rtw_grf5101 *)rf; - - /* - * These values have been derived from the rtl8180-sa2400 - * Linux driver. It is unknown what they all do, GCT refuse - * to release any documentation so these are more than - * likely sub optimal settings - */ - - GCT_WRITE(gr, 0x01, 0x1a23, err); - GCT_WRITE(gr, 0x02, 0x4971, err); - GCT_WRITE(gr, 0x03, 0x41de, err); - GCT_WRITE(gr, 0x04, 0x2d80, err); - - GCT_WRITE(gr, 0x05, 0x61ff, err); - - GCT_WRITE(gr, 0x06, 0x0, err); - - GCT_WRITE(gr, 0x08, 0x7533, err); - GCT_WRITE(gr, 0x09, 0xc401, err); - GCT_WRITE(gr, 0x0a, 0x0, err); - GCT_WRITE(gr, 0x0c, 0x1c7, err); - GCT_WRITE(gr, 0x0d, 0x29d3, err); - GCT_WRITE(gr, 0x0e, 0x2e8, err); - GCT_WRITE(gr, 0x10, 0x192, err); - GCT_WRITE(gr, 0x11, 0x248, err); - GCT_WRITE(gr, 0x12, 0x0, err); - GCT_WRITE(gr, 0x13, 0x20c4, err); - GCT_WRITE(gr, 0x14, 0xf4fc, err); - GCT_WRITE(gr, 0x15, 0x0, err); - GCT_WRITE(gr, 0x16, 0x1500, err); - - if ((rc = rtw_grf5101_txpower(rf, opaque_txpower)) != 0) - return rc; - - if ((rc = rtw_grf5101_tune(rf, freq)) != 0) - return rc; - - return 0; -err: - return -1; -} - -static void -rtw_grf5101_destroy(struct rtw_rf *rf) -{ - struct rtw_grf5101 *gr = (struct rtw_grf5101 *)rf; - - memset(gr, 0, sizeof(*gr)); - kfree(gr, M_DEVBUF); -} - -struct rtw_rf * -rtw_grf5101_create(struct rtw_regs *regs, rtw_rf_write_t rf_write, int digphy) -{ - struct rtw_grf5101 *gr; - struct rtw_rfbus *bus; - struct rtw_rf *rf; - struct rtw_bbpset *bb; - - gr = kmalloc(sizeof(*gr), M_DEVBUF, M_WAITOK | M_ZERO); - - rf = &gr->gr_rf; - bus = &gr->gr_bus; - - rf->rf_init = rtw_grf5101_init; - rf->rf_destroy = rtw_grf5101_destroy; - rf->rf_txpower = rtw_grf5101_txpower; - rf->rf_tune = rtw_grf5101_tune; - rf->rf_pwrstate = rtw_grf5101_pwrstate; - bb = &rf->rf_bbpset; - - /* XXX magic */ - bb->bb_antatten = RTW_BBP_ANTATTEN_GCT_MAGIC; - bb->bb_chestlim = 0x00; - bb->bb_chsqlim = 0xa0; - bb->bb_ifagcdet = 0x64; - bb->bb_ifagcini = 0x90; - bb->bb_ifagclimit = 0x1e; - bb->bb_lnadet = 0xc0; - bb->bb_sys1 = 0xa8; - bb->bb_sys2 = 0x47; - bb->bb_sys3 = 0x9b; - bb->bb_trl = 0x88; - bb->bb_txagc = 0x08; - - bus->b_regs = regs; - bus->b_write = rf_write; - - return &gr->gr_rf; -} - -/* freq is in MHz */ -static int -rtw_max2820_tune(struct rtw_rf *rf, u_int freq) -{ - struct rtw_max2820 *mx = (struct rtw_max2820 *)rf; - struct rtw_rfbus *bus = &mx->mx_bus; - - if (freq < 2400 || freq > 2499) - return -1; - - return rtw_rfbus_write(bus, RTW_RFCHIPID_MAXIM, MAX2820_CHANNEL, - __SHIFTIN(freq - 2400, MAX2820_CHANNEL_CF_MASK)); -} - -static void -rtw_max2820_destroy(struct rtw_rf *rf) -{ - struct rtw_max2820 *mx = (struct rtw_max2820 *)rf; - - memset(mx, 0, sizeof(*mx)); - kfree(mx, M_DEVBUF); -} - -static int -rtw_max2820_init(struct rtw_rf *rf, u_int freq, uint8_t opaque_txpower, - enum rtw_pwrstate power) -{ - struct rtw_max2820 *mx = (struct rtw_max2820 *)rf; - struct rtw_rfbus *bus = &mx->mx_bus; - int rc; - - rc = rtw_rfbus_write(bus, RTW_RFCHIPID_MAXIM, MAX2820_TEST, - MAX2820_TEST_DEFAULT); - if (rc != 0) - return rc; - - rc = rtw_rfbus_write(bus, RTW_RFCHIPID_MAXIM, MAX2820_ENABLE, - MAX2820_ENABLE_DEFAULT); - if (rc != 0) - return rc; - - /* skip configuration if it's time to sleep or to power-down. */ - if ((rc = rtw_max2820_pwrstate(rf, power)) != 0) - return rc; - else if (power == RTW_OFF || power == RTW_SLEEP) - return 0; - - rc = rtw_rfbus_write(bus, RTW_RFCHIPID_MAXIM, MAX2820_SYNTH, - MAX2820_SYNTH_R_44MHZ); - if (rc != 0) - return rc; - - if ((rc = rtw_max2820_tune(rf, freq)) != 0) - return rc; - - /* - * XXX The MAX2820 datasheet indicates that 1C and 2C should not - * be changed from 7, however, the reference driver sets them - * to 4 and 1, respectively. - */ - rc = rtw_rfbus_write(bus, RTW_RFCHIPID_MAXIM, MAX2820_RECEIVE, - MAX2820_RECEIVE_DL_DEFAULT | - __SHIFTIN(4, MAX2820A_RECEIVE_1C_MASK) | - __SHIFTIN(1, MAX2820A_RECEIVE_2C_MASK)); - if (rc != 0) - return rc; - - return rtw_rfbus_write(bus, RTW_RFCHIPID_MAXIM, MAX2820_TRANSMIT, - MAX2820_TRANSMIT_PA_DEFAULT); -} - -static int -rtw_max2820_txpower(struct rtw_rf *rf, uint8_t opaque_txpower) -{ - /* TBD */ - return 0; -} - -static int -rtw_max2820_pwrstate(struct rtw_rf *rf, enum rtw_pwrstate power) -{ - uint32_t enable; - struct rtw_max2820 *mx; - struct rtw_rfbus *bus; - - mx = (struct rtw_max2820 *)rf; - bus = &mx->mx_bus; - - switch (power) { - case RTW_OFF: - case RTW_SLEEP: - default: - enable = 0x0; - break; - case RTW_ON: - enable = MAX2820_ENABLE_DEFAULT; - break; - } - return rtw_rfbus_write(bus, RTW_RFCHIPID_MAXIM, MAX2820_ENABLE, enable); -} - -struct rtw_rf * -rtw_max2820_create(struct rtw_regs *regs, rtw_rf_write_t rf_write, int is_a) -{ - struct rtw_max2820 *mx; - struct rtw_rfbus *bus; - struct rtw_rf *rf; - struct rtw_bbpset *bb; - - mx = kmalloc(sizeof(*mx), M_DEVBUF, M_WAITOK | M_ZERO); - - mx->mx_is_a = is_a; - - rf = &mx->mx_rf; - bus = &mx->mx_bus; - - rf->rf_init = rtw_max2820_init; - rf->rf_destroy = rtw_max2820_destroy; - rf->rf_txpower = rtw_max2820_txpower; - rf->rf_tune = rtw_max2820_tune; - rf->rf_pwrstate = rtw_max2820_pwrstate; - bb = &rf->rf_bbpset; - - /* XXX magic */ - bb->bb_antatten = RTW_BBP_ANTATTEN_MAXIM_MAGIC; - bb->bb_chestlim = 0; - bb->bb_chsqlim = 159; - bb->bb_ifagcdet = 100; - bb->bb_ifagcini = 144; - bb->bb_ifagclimit = 26; - bb->bb_lnadet = 248; - bb->bb_sys1 = 136; - bb->bb_sys2 = 71; - bb->bb_sys3 = 155; - bb->bb_trl = 136; - bb->bb_txagc = 8; - - bus->b_regs = regs; - bus->b_write = rf_write; - - return &mx->mx_rf; -} - -/* freq is in MHz */ -int -rtw_phy_init(struct rtw_regs *regs, struct rtw_rf *rf, uint8_t opaque_txpower, - uint8_t cs_threshold, u_int freq, int antdiv, int dflantb, - enum rtw_pwrstate power) -{ - int rc; - RTW_DPRINTF(RTW_DEBUG_PHY, - ("%s: txpower %u csthresh %u freq %u antdiv %u dflantb %u " - "pwrstate %s\n", __func__, opaque_txpower, cs_threshold, freq, - antdiv, dflantb, rtw_pwrstate_string(power))); - - /* XXX is this really necessary? */ - if ((rc = rtw_rf_txpower(rf, opaque_txpower)) != 0) - return rc; - - rc = rtw_bbp_preinit(regs, rf->rf_bbpset.bb_antatten, dflantb, freq); - if (rc != 0) - return rc; - - if ((rc = rtw_rf_tune(rf, freq)) != 0) - return rc; - - /* initialize RF */ - if ((rc = rtw_rf_init(rf, freq, opaque_txpower, power)) != 0) - return rc; -#if 0 /* what is this redundant tx power setting here for? */ - if ((rc = rtw_rf_txpower(rf, opaque_txpower)) != 0) - return rc; -#endif - return rtw_bbp_init(regs, &rf->rf_bbpset, antdiv, dflantb, cs_threshold, freq); -} diff --git a/sys/dev/netif/rtw/rtwphy.h b/sys/dev/netif/rtw/rtwphy.h deleted file mode 100644 index 08ac4f7102..0000000000 --- a/sys/dev/netif/rtw/rtwphy.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2004, 2005 David Young. All rights reserved. - * - * Programmed for NetBSD by David Young. - * - * 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. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of David Young may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY David Young ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL David - * Young BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 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 DAMAGE. - * - * $NetBSD: rtwphy.h,v 1.5 2005/12/29 22:27:17 dyoung Exp $ - * $DragonFly: src/sys/dev/netif/rtw/rtwphy.h,v 1.1 2006/09/03 07:37:58 sephe Exp $ - */ -#ifndef _DEV_IC_RTWPHY_H -#define _DEV_IC_RTWPHY_H - -struct rtw_rf *rtw_grf5101_create(struct rtw_regs *, rtw_rf_write_t, int); -struct rtw_rf *rtw_sa2400_create(struct rtw_regs *, rtw_rf_write_t, int); -struct rtw_rf *rtw_max2820_create(struct rtw_regs *, rtw_rf_write_t, int); - -int rtw_phy_init(struct rtw_regs *, struct rtw_rf *, uint8_t, - uint8_t, u_int, int, int, enum rtw_pwrstate); - -#endif /* _DEV_IC_RTWPHY_H */ diff --git a/sys/dev/netif/rtw/rtwphyio.c b/sys/dev/netif/rtw/rtwphyio.c deleted file mode 100644 index 61cb25c8dc..0000000000 --- a/sys/dev/netif/rtw/rtwphyio.c +++ /dev/null @@ -1,361 +0,0 @@ -/* - * Copyright (c) 2004, 2005 David Young. All rights reserved. - * - * Programmed for NetBSD by David Young. - * - * 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. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of David Young may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY David Young ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL David - * Young BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 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 DAMAGE. - * - * $NetBSD: rtwphyio.c,v 1.11 2006/03/08 00:24:06 dyoung Exp $ - * $DragonFly: src/sys/dev/netif/rtw/rtwphyio.c,v 1.5 2008/01/15 09:01:13 sephe Exp $ - */ - -/* - * Control input/output with the Philips SA2400 RF front-end and - * the baseband processor built into the Realtek RTL8180. - */ - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -static int rtw_macbangbits_timeout = 100; - -uint8_t -rtw_bbp_read(struct rtw_regs *regs, u_int addr) -{ - KKASSERT((addr & ~__SHIFTOUT_MASK(RTW_BB_ADDR_MASK)) == 0); - RTW_WRITE(regs, RTW_BB, - __SHIFTIN(addr, RTW_BB_ADDR_MASK) | - RTW_BB_RD_MASK | RTW_BB_WR_MASK); - DELAY(10); /* XXX */ - RTW_WBR(regs, RTW_BB, RTW_BB); - return __SHIFTOUT(RTW_READ(regs, RTW_BB), RTW_BB_RD_MASK); -} - -int -rtw_bbp_write(struct rtw_regs *regs, u_int addr, u_int val) -{ -#define BBP_WRITE_ITERS 50 -#define BBP_WRITE_DELAY 1 - int i; - uint32_t wrbbp, rdbbp; - - RTW_DPRINTF(RTW_DEBUG_PHYIO, - ("%s: bbp[%u] <- %u\n", __func__, addr, val)); - - KKASSERT((addr & ~__SHIFTOUT_MASK(RTW_BB_ADDR_MASK)) == 0); - KKASSERT((val & ~__SHIFTOUT_MASK(RTW_BB_WR_MASK)) == 0); - - wrbbp = __SHIFTIN(addr, RTW_BB_ADDR_MASK) | RTW_BB_WREN | - __SHIFTIN(val, RTW_BB_WR_MASK) | RTW_BB_RD_MASK, - - rdbbp = __SHIFTIN(addr, RTW_BB_ADDR_MASK) | - RTW_BB_WR_MASK | RTW_BB_RD_MASK; - - RTW_DPRINTF(RTW_DEBUG_PHYIO, - ("%s: rdbbp = %#08x, wrbbp = %#08x\n", __func__, rdbbp, wrbbp)); - - for (i = BBP_WRITE_ITERS; --i >= 0; ) { - RTW_RBW(regs, RTW_BB, RTW_BB); - RTW_WRITE(regs, RTW_BB, wrbbp); - RTW_SYNC(regs, RTW_BB, RTW_BB); - RTW_WRITE(regs, RTW_BB, rdbbp); - RTW_SYNC(regs, RTW_BB, RTW_BB); - DELAY(BBP_WRITE_DELAY); /* 1 microsecond */ - if (__SHIFTOUT(RTW_READ(regs, RTW_BB), - RTW_BB_RD_MASK) == val) { - RTW_DPRINTF(RTW_DEBUG_PHYIO, - ("%s: finished in %dus\n", __func__, - BBP_WRITE_DELAY * (BBP_WRITE_ITERS - i))); - return 0; - } - DELAY(BBP_WRITE_DELAY); /* again */ - } - kprintf("%s: timeout\n", __func__); - return -1; -} - -/* Help rtw_rf_hostwrite bang bits to RF over 3-wire interface. */ -static __inline void -rtw_rf_hostbangbits(struct rtw_regs *regs, uint32_t bits, int lo_to_hi, - u_int nbits) -{ - int i; - uint32_t mask, reg; - - KKASSERT(nbits <= 32); - - RTW_DPRINTF(RTW_DEBUG_PHYIO, - ("%s: %u bits, %#08x, %s\n", __func__, nbits, bits, - (lo_to_hi) ? "lo to hi" : "hi to lo")); - - reg = RTW_PHYCFG_HST; - RTW_WRITE(regs, RTW_PHYCFG, reg); - RTW_SYNC(regs, RTW_PHYCFG, RTW_PHYCFG); - - if (lo_to_hi) - mask = 0x1; - else - mask = 1 << (nbits - 1); - - for (i = 0; i < nbits; i++) { - RTW_DPRINTF(RTW_DEBUG_PHYBITIO, - ("%s: bits %#08x mask %#08x -> bit %#08x\n", - __func__, bits, mask, bits & mask)); - - if ((bits & mask) != 0) - reg |= RTW_PHYCFG_HST_DATA; - else - reg &= ~RTW_PHYCFG_HST_DATA; - - reg |= RTW_PHYCFG_HST_CLK; - RTW_WRITE(regs, RTW_PHYCFG, reg); - RTW_SYNC(regs, RTW_PHYCFG, RTW_PHYCFG); - - DELAY(2); /* arbitrary delay */ - - reg &= ~RTW_PHYCFG_HST_CLK; - RTW_WRITE(regs, RTW_PHYCFG, reg); - RTW_SYNC(regs, RTW_PHYCFG, RTW_PHYCFG); - - if (lo_to_hi) - mask <<= 1; - else - mask >>= 1; - } - - reg |= RTW_PHYCFG_HST_EN; - KKASSERT((reg & RTW_PHYCFG_HST_CLK) == 0); - RTW_WRITE(regs, RTW_PHYCFG, reg); - RTW_SYNC(regs, RTW_PHYCFG, RTW_PHYCFG); -} - -/* Help rtw_rf_macwrite: tell MAC to bang bits to RF over the 3-wire - * interface. - */ -static __inline int -rtw_rf_macbangbits(struct rtw_regs *regs, uint32_t reg) -{ - int i; - - RTW_DPRINTF(RTW_DEBUG_PHY, ("%s: %#08x\n", __func__, reg)); - - RTW_WRITE(regs, RTW_PHYCFG, RTW_PHYCFG_MAC_POLL | reg); - - RTW_WBR(regs, RTW_PHYCFG, RTW_PHYCFG); - - for (i = rtw_macbangbits_timeout; --i >= 0; DELAY(1)) { - if ((RTW_READ(regs, RTW_PHYCFG) & RTW_PHYCFG_MAC_POLL) == 0) { - RTW_DPRINTF(RTW_DEBUG_PHY, - ("%s: finished in %dus\n", __func__, - rtw_macbangbits_timeout - i)); - return 0; - } - RTW_RBR(regs, RTW_PHYCFG, RTW_PHYCFG); /* XXX paranoia? */ - } - - kprintf("%s: RTW_PHYCFG_MAC_POLL still set.\n", __func__); - return -1; -} - -static uint32_t -rtw_grf5101_host_crypt(u_int addr, uint32_t val) -{ - /* TBD */ - return 0; -} - -static uint32_t -rtw_grf5101_mac_crypt(u_int addr, uint32_t val) -{ - uint32_t data_and_addr; -#define EXTRACT_NIBBLE(d, which) (((d) >> (4 * (which))) & 0xf) - static uint8_t caesar[16] = {0x0, 0x8, 0x4, 0xc, - 0x2, 0xa, 0x6, 0xe, - 0x1, 0x9, 0x5, 0xd, - 0x3, 0xb, 0x7, 0xf}; - - data_and_addr = caesar[EXTRACT_NIBBLE(val, 2)] | - (caesar[EXTRACT_NIBBLE(val, 1)] << 4) | - (caesar[EXTRACT_NIBBLE(val, 0)] << 8) | - (caesar[(addr >> 1) & 0xf] << 12) | - ((addr & 0x1) << 16) | - (caesar[EXTRACT_NIBBLE(val, 3)] << 24); - return __SHIFTIN(data_and_addr, - RTW_PHYCFG_MAC_PHILIPS_ADDR_MASK|RTW_PHYCFG_MAC_PHILIPS_DATA_MASK); -#undef EXTRACT_NIBBLE -} - -static __inline const char * -rtw_rfchipid_string(enum rtw_rfchipid rfchipid) -{ - switch (rfchipid) { - case RTW_RFCHIPID_MAXIM: - return "Maxim"; - case RTW_RFCHIPID_PHILIPS: - return "Philips"; - case RTW_RFCHIPID_GCT: - return "GCT"; - case RTW_RFCHIPID_RFMD: - return "RFMD"; - case RTW_RFCHIPID_INTERSIL: - return "Intersil"; - default: - return "unknown"; - } -} - -/* Bang bits over the 3-wire interface. */ -int -rtw_rf_hostwrite(struct rtw_regs *regs, enum rtw_rfchipid rfchipid, - u_int addr, uint32_t val) -{ - u_int nbits; - int lo_to_hi; - uint32_t bits; - - RTW_DPRINTF(RTW_DEBUG_PHYIO, ("%s: %s[%u] <- %#08x\n", __func__, - rtw_rfchipid_string(rfchipid), addr, val)); - - switch (rfchipid) { - case RTW_RFCHIPID_MAXIM: - nbits = 16; - lo_to_hi = 0; - bits = __SHIFTIN(val, MAX2820_TWI_DATA_MASK) | - __SHIFTIN(addr, MAX2820_TWI_ADDR_MASK); - break; - case RTW_RFCHIPID_PHILIPS: - KKASSERT((addr & ~__SHIFTOUT_MASK(SA2400_TWI_ADDR_MASK)) == 0); - KKASSERT((val & ~__SHIFTOUT_MASK(SA2400_TWI_DATA_MASK)) == 0); - bits = __SHIFTIN(val, SA2400_TWI_DATA_MASK) | - __SHIFTIN(addr, SA2400_TWI_ADDR_MASK) | SA2400_TWI_WREN; - nbits = 32; - lo_to_hi = 1; - break; - case RTW_RFCHIPID_GCT: - KKASSERT((addr & ~__SHIFTOUT_MASK(SI4126_TWI_ADDR_MASK)) == 0); - KKASSERT((val & ~__SHIFTOUT_MASK(SI4126_TWI_DATA_MASK)) == 0); - bits = rtw_grf5101_host_crypt(addr, val); - nbits = 21; - lo_to_hi = 1; - break; - case RTW_RFCHIPID_RFMD: - KKASSERT((addr & ~__SHIFTOUT_MASK(SI4126_TWI_ADDR_MASK)) == 0); - KKASSERT((val & ~__SHIFTOUT_MASK(SI4126_TWI_DATA_MASK)) == 0); - bits = __SHIFTIN(val, SI4126_TWI_DATA_MASK) | - __SHIFTIN(addr, SI4126_TWI_ADDR_MASK); - nbits = 22; - lo_to_hi = 0; - break; - case RTW_RFCHIPID_INTERSIL: - default: - kprintf("%s: unknown rfchipid %d\n", __func__, rfchipid); - return -1; - } - - rtw_rf_hostbangbits(regs, bits, lo_to_hi, nbits); - - return 0; -} - -static uint32_t -rtw_maxim_swizzle(u_int addr, uint32_t val) -{ - uint32_t hidata, lodata; - - KKASSERT((val & ~(RTW_MAXIM_LODATA_MASK|RTW_MAXIM_HIDATA_MASK)) == 0); - lodata = __SHIFTOUT(val, RTW_MAXIM_LODATA_MASK); - hidata = __SHIFTOUT(val, RTW_MAXIM_HIDATA_MASK); - return __SHIFTIN(lodata, RTW_PHYCFG_MAC_MAXIM_LODATA_MASK) | - __SHIFTIN(hidata, RTW_PHYCFG_MAC_MAXIM_HIDATA_MASK) | - __SHIFTIN(addr, RTW_PHYCFG_MAC_MAXIM_ADDR_MASK); -} - -/* Tell the MAC what to bang over the 3-wire interface. */ -int -rtw_rf_macwrite(struct rtw_regs *regs, enum rtw_rfchipid rfchipid, - u_int addr, uint32_t val) -{ - uint32_t reg; - - RTW_DPRINTF(RTW_DEBUG_PHYIO, ("%s: %s[%u] <- %#08x\n", __func__, - rtw_rfchipid_string(rfchipid), addr, val)); - - switch (rfchipid) { - case RTW_RFCHIPID_GCT: - reg = rtw_grf5101_mac_crypt(addr, val); - break; - case RTW_RFCHIPID_MAXIM: - reg = rtw_maxim_swizzle(addr, val); - break; - default: /* XXX */ - case RTW_RFCHIPID_PHILIPS: - KKASSERT( - (addr & ~__SHIFTOUT_MASK(RTW_PHYCFG_MAC_PHILIPS_ADDR_MASK)) == 0); - KKASSERT( - (val & ~__SHIFTOUT_MASK(RTW_PHYCFG_MAC_PHILIPS_DATA_MASK)) == 0); - - reg = __SHIFTIN(addr, RTW_PHYCFG_MAC_PHILIPS_ADDR_MASK) | - __SHIFTIN(val, RTW_PHYCFG_MAC_PHILIPS_DATA_MASK); - } - - switch (rfchipid) { - case RTW_RFCHIPID_GCT: - case RTW_RFCHIPID_MAXIM: - case RTW_RFCHIPID_RFMD: - reg |= RTW_PHYCFG_MAC_RFTYPE_RFMD; - break; - case RTW_RFCHIPID_INTERSIL: - reg |= RTW_PHYCFG_MAC_RFTYPE_INTERSIL; - break; - case RTW_RFCHIPID_PHILIPS: - reg |= RTW_PHYCFG_MAC_RFTYPE_PHILIPS; - break; - default: - kprintf("%s: unknown rfchipid %d\n", __func__, rfchipid); - return -1; - } - - return rtw_rf_macbangbits(regs, reg); -} diff --git a/sys/dev/netif/rtw/rtwphyio.h b/sys/dev/netif/rtw/rtwphyio.h deleted file mode 100644 index af12c86fe9..0000000000 --- a/sys/dev/netif/rtw/rtwphyio.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2004, 2005 David Young. All rights reserved. - * - * Programmed for NetBSD by David Young. - * - * 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. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of David Young may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY David Young ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL David - * Young BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 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 DAMAGE. - * - * $NetBSD: rtwphyio.h,v 1.3 2005/12/11 12:21:28 christos Exp $ - * $DragonFly: src/sys/dev/netif/rtw/rtwphyio.h,v 1.1 2006/09/03 07:37:58 sephe Exp $ - */ -#ifndef _DEV_IC_RTWPHYIO_H -#define _DEV_IC_RTWPHYIO_H - -int rtw_rf_hostwrite(struct rtw_regs *, enum rtw_rfchipid, u_int, uint32_t); -int rtw_rf_macwrite(struct rtw_regs *, enum rtw_rfchipid, u_int, uint32_t); -uint8_t rtw_bbp_read(struct rtw_regs *, u_int); -int rtw_bbp_write(struct rtw_regs *, u_int, u_int); - -#endif /* _DEV_IC_RTWPHYIO_H */ diff --git a/sys/dev/netif/rtw/rtwreg.h b/sys/dev/netif/rtw/rtwreg.h deleted file mode 100644 index b444218a10..0000000000 --- a/sys/dev/netif/rtw/rtwreg.h +++ /dev/null @@ -1,1103 +0,0 @@ -/* - * Copyright (c) 2004, 2005 David Young. All rights reserved. - * - * Programmed for NetBSD by David Young. - * - * 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. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of David Young may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY David Young ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL David - * Young BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 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 DAMAGE. - * - * $NetBSD: rtwreg.h,v 1.19 2006/03/10 23:37:35 dyoung Exp $ - * $DragonFly: src/sys/dev/netif/rtw/rtwreg.h,v 1.3 2007/10/14 04:15:17 sephe Exp $ - */ - -/* RTL8180L Host Control and Status Registers */ - -#define RTW_IDR0 0x00 /* ID Register: MAC addr, 6 bytes. - * Auto-loaded from EEPROM. Read by byte, - * by word, or by double word, but write - * only by double word. - */ -#define RTW_IDR1 0x04 - -#define RTW_MAR0 0x08 /* Multicast filter, 64b. */ -#define RTW_MAR1 0x0c - -#define RTW_TSFTRL 0x18 /* Timing Synchronization Function Timer - * Register, low word, 32b, read-only. - */ -#define RTW_TSFTRH 0x1c /* High word, 32b, read-only. */ -#define RTW_TLPDA 0x20 /* Transmit Low Priority Descriptors Start - * Address, 32b, 256-byte alignment. - */ -#define RTW_TNPDA 0x24 /* Transmit Normal Priority Descriptors Start - * Address, 32b, 256-byte alignment. - */ -#define RTW_THPDA 0x28 /* Transmit High Priority Descriptors Start - * Address, 32b, 256-byte alignment. - */ - -#define RTW_BRSR 0x2c /* Basic Rate Set Register, 16b */ -#define RTW_BRSR_BPLCP __BIT(8)/* 1: use short PLCP header for CTS/ACK packet, - * 0: use long PLCP header - */ -#define RTW_BRSR_MBR8180_MASK __BITS(1,0) /* Maximum Basic Service Rate */ -#define RTW_BRSR_MBR8180_1MBPS __SHIFTIN(0, RTW_BRSR_MBR8180_MASK) -#define RTW_BRSR_MBR8180_2MBPS __SHIFTIN(1, RTW_BRSR_MBR8180_MASK) -#define RTW_BRSR_MBR8180_5MBPS __SHIFTIN(2, RTW_BRSR_MBR8180_MASK) -#define RTW_BRSR_MBR8180_11MBPS __SHIFTIN(3, RTW_BRSR_MBR8180_MASK) - -/* 8181 and 8180 docs conflict! */ -#define RTW_BRSR_MBR8181_1MBPS __BIT(0) -#define RTW_BRSR_MBR8181_2MBPS __BIT(1) -#define RTW_BRSR_MBR8181_5MBPS __BIT(2) -#define RTW_BRSR_MBR8181_11MBPS __BIT(3) - -#define RTW_BSSID 0x2e -/* BSSID, 6 bytes */ -#define RTW_BSSID16 0x2e /* first two bytes */ -#define RTW_BSSID32 (0x2e + 4) /* remaining four bytes */ -#define RTW_BSSID0 RTW_BSSID16 /* BSSID[0], 8b */ -#define RTW_BSSID1 (RTW_BSSID0 + 1) /* BSSID[1], 8b */ -#define RTW_BSSID2 (RTW_BSSID1 + 1) /* BSSID[2], 8b */ -#define RTW_BSSID3 (RTW_BSSID2 + 1) /* BSSID[3], 8b */ -#define RTW_BSSID4 (RTW_BSSID3 + 1) /* BSSID[4], 8b */ -#define RTW_BSSID5 (RTW_BSSID4 + 1) /* BSSID[5], 8b */ - -#define RTW_CR 0x37 /* Command Register, 8b */ -#define RTW_CR_RST __BIT(4)/* Reset: host sets to 1 to disable - * transmitter & receiver, reinitialize FIFO. - * RTL8180L sets to 0 to signal completion. - */ -#define RTW_CR_RE __BIT(3)/* Receiver Enable: host enables receiver - * by writing 1. RTL8180L indicates receiver - * is active with 1. After power-up, host - * must wait for reset before writing. - */ -#define RTW_CR_TE __BIT(2)/* Transmitter Enable: host enables transmitter - * by writing 1. RTL8180L indicates transmitter - * is active with 1. After power-up, host - * must wait for reset before writing. - */ -#define RTW_CR_MULRW __BIT(0)/* PCI Multiple Read/Write enable: 1 enables, - * 0 disables. XXX RTL8180, only? - */ - -#define RTW_IMR 0x3c /* Interrupt Mask Register, 16b */ -#define RTW_ISR 0x3e /* Interrupt status register, 16b */ - -#define RTW_INTR_TXFOVW __BIT(15) /* Tx FIFO underflow */ -#define RTW_INTR_TIMEOUT __BIT(14) /* Time Out: 1 indicates - * RTW_TSFTR[0:31] = RTW_TINT - */ -/* Beacon Time Out: time for host to prepare beacon: - * RTW_TSFTR % (RTW_BCNITV_BCNITV * TU) = - * (RTW_BCNITV_BCNITV * TU - RTW_BINTRITV) - */ -#define RTW_INTR_BCNINT __BIT(13) -/* ATIM Time Out: ATIM interval will pass, - * RTW_TSFTR % (RTW_BCNITV_BCNITV * TU) = - * (RTW_ATIMWND_ATIMWND * TU - RTW_ATIMTRITV) - */ -#define RTW_INTR_ATIMINT __BIT(12) -/* Tx Beacon Descriptor Error: beacon transmission aborted because frame Rx'd */ -#define RTW_INTR_TBDER __BIT(11) -#define RTW_INTR_TBDOK __BIT(10) /* Tx Beacon Descriptor OK */ -#define RTW_INTR_THPDER __BIT(9)/* Tx High Priority Descriptor Error: - * reached short/long retry limit - */ -#define RTW_INTR_THPDOK __BIT(8)/* Tx High Priority Descriptor OK */ -#define RTW_INTR_TNPDER __BIT(7)/* Tx Normal Priority Descriptor Error: - * reached short/long retry limit - */ -#define RTW_INTR_TNPDOK __BIT(6)/* Tx Normal Priority Descriptor OK */ -#define RTW_INTR_RXFOVW __BIT(5)/* Rx FIFO Overflow: either RDU (see below) - * or PCI bus too slow/busy - */ -#define RTW_INTR_RDU __BIT(4)/* Rx Descriptor Unavailable */ -#define RTW_INTR_TLPDER __BIT(3)/* Tx Normal Priority Descriptor Error - * reached short/long retry limit - */ -#define RTW_INTR_TLPDOK __BIT(2)/* Tx Normal Priority Descriptor OK */ -#define RTW_INTR_RER __BIT(1)/* Rx Error: CRC32 or ICV error */ -#define RTW_INTR_ROK __BIT(0)/* Rx OK */ - -/* Convenient interrupt conjunctions. */ -#define RTW_INTR_RX (RTW_INTR_RER|RTW_INTR_ROK) -#define RTW_INTR_TX (RTW_INTR_TLPDER|RTW_INTR_TLPDOK|RTW_INTR_THPDER|\ - RTW_INTR_THPDOK|RTW_INTR_TNPDER|RTW_INTR_TNPDOK|\ - RTW_INTR_TBDER|RTW_INTR_TBDOK) -#define RTW_INTR_BEACON (RTW_INTR_BCNINT|RTW_INTR_TBDER|RTW_INTR_TBDOK) -#define RTW_INTR_IOERROR (RTW_INTR_TXFOVW|RTW_INTR_RXFOVW|RTW_INTR_RDU) - -#define RTW_TCR 0x40 /* Transmit Configuration Register, 32b */ -#define RTW_TCR_CWMIN __BIT(31)/* 1: CWmin = 8, 0: CWmin = 32. */ -#define RTW_TCR_SWSEQ __BIT(30)/* 1: host assigns 802.11 sequence number, - * 0: hardware assigns sequence number - */ -/* Hardware version ID, read-only */ -#define RTW_TCR_HWVERID_MASK __BITS(29, 25) -#define RTW_TCR_HWVERID_D __SHIFTIN(26, RTW_TCR_HWVERID_MASK) -#define RTW_TCR_HWVERID_F __SHIFTIN(27, RTW_TCR_HWVERID_MASK) -#define RTW_TCR_HWVERID_RTL8180 RTW_TCR_HWVERID_F - -/* Set ACK/CTS Timeout (EIFS). - * 1: ACK rate = max(RTW_BRSR_MBR, Rx rate) (XXX not min? typo in datasheet?) - * 0: ACK rate = 1Mbps - */ -#define RTW_TCR_SAT __BIT(24) -/* Max DMA Burst Size per Tx DMA Burst */ -#define RTW_TCR_MXDMA_MASK __BITS(23,21) -#define RTW_TCR_MXDMA_16 __SHIFTIN(0, RTW_TCR_MXDMA_MASK) -#define RTW_TCR_MXDMA_32 __SHIFTIN(1, RTW_TCR_MXDMA_MASK) -#define RTW_TCR_MXDMA_64 __SHIFTIN(2, RTW_TCR_MXDMA_MASK) -#define RTW_TCR_MXDMA_128 __SHIFTIN(3, RTW_TCR_MXDMA_MASK) -#define RTW_TCR_MXDMA_256 __SHIFTIN(4, RTW_TCR_MXDMA_MASK) -#define RTW_TCR_MXDMA_512 __SHIFTIN(5, RTW_TCR_MXDMA_MASK) -#define RTW_TCR_MXDMA_1024 __SHIFTIN(6, RTW_TCR_MXDMA_MASK) -#define RTW_TCR_MXDMA_2048 __SHIFTIN(7, RTW_TCR_MXDMA_MASK) - -/* disable 802.11 random backoff */ -#define RTW_TCR_DISCW __BIT(20) - -/* host lets RTL8180 append ICV to WEP packets */ -#define RTW_TCR_ICV __BIT(19) - -/* Loopback Test: disables TXI/TXQ outputs. */ -#define RTW_TCR_LBK_MASK __BITS(18,17) -#define RTW_TCR_LBK_NORMAL __SHIFTIN(0, RTW_TCR_LBK_MASK) /* normal ops */ -#define RTW_TCR_LBK_MAC __SHIFTIN(1, RTW_TCR_LBK_MASK) /* MAC loopback */ -#define RTW_TCR_LBK_BBP __SHIFTIN(2, RTW_TCR_LBK_MASK) /* baseband loop. */ -#define RTW_TCR_LBK_CONT __SHIFTIN(3, RTW_TCR_LBK_MASK) /* continuous Tx */ - -#define RTW_TCR_CRC __BIT(16) /* 0: RTL8180 appends CRC32 - * 1: host appends CRC32 - * - * (I *think* this is right. - * The docs have a mysterious - * description in the - * passive voice.) - */ -#define RTW_TCR_SRL_MASK __BITS(15,8) /* Short Retry Limit */ -#define RTW_TCR_LRL_MASK __BITS(7,0) /* Long Retry Limit */ - -#define RTW_RCR 0x44 /* Receive Configuration Register, 32b */ -/* only do Early Rx on packets longer than 1536 bytes */ -#define RTW_RCR_ONLYERLPKT __BIT(31) -/* enable carrier sense method 2 */ -#define RTW_RCR_ENCS2 __BIT(30) -/* enable carrier sense method 1 */ -#define RTW_RCR_ENCS1 __BIT(29) -#define RTW_RCR_ENMARP __BIT(28) /* enable MAC auto-reset PHY */ -/* Check BSSID/ToDS/FromDS: set "Link On" when received BSSID - * matches RTW_BSSID and received ToDS/FromDS are appropriate - * according to RTW_MSR_NETYPE. - */ -#define RTW_RCR_CBSSID __BIT(23) - /* accept packets w/ PWRMGMT bit set */ -#define RTW_RCR_APWRMGT __BIT(22) -/* when RTW_MSR_NETYPE == RTW_MSR_NETYPE_INFRA_OK, accept - * broadcast/multicast packets whose 3rd address matches RTL8180's MAC. - */ -#define RTW_RCR_ADD3 __BIT(21) -#define RTW_RCR_AMF __BIT(20) /* accept management frames */ -#define RTW_RCR_ACF __BIT(19) /* accept control frames */ -#define RTW_RCR_ADF __BIT(18) /* accept data frames */ -/* Rx FIFO Threshold: RTL8180 begins PCI transfer when this many data - * bytes are received - */ -#define RTW_RCR_RXFTH_MASK __BITS(15,13) -#define RTW_RCR_RXFTH_64 __SHIFTIN(2, RTW_RCR_RXFTH_MASK) -#define RTW_RCR_RXFTH_128 __SHIFTIN(3, RTW_RCR_RXFTH_MASK) -#define RTW_RCR_RXFTH_256 __SHIFTIN(4, RTW_RCR_RXFTH_MASK) -#define RTW_RCR_RXFTH_512 __SHIFTIN(5, RTW_RCR_RXFTH_MASK) -#define RTW_RCR_RXFTH_1024 __SHIFTIN(6, RTW_RCR_RXFTH_MASK) -#define RTW_RCR_RXFTH_WHOLE __SHIFTIN(7, RTW_RCR_RXFTH_MASK) - -#define RTW_RCR_AICV __BIT(12)/* accept frames w/ ICV errors */ - -/* Max DMA Burst Size per Rx DMA Burst */ -#define RTW_RCR_MXDMA_MASK __BITS(10,8) -#define RTW_RCR_MXDMA_16 __SHIFTIN(0, RTW_RCR_MXDMA_MASK) -#define RTW_RCR_MXDMA_32 __SHIFTIN(1, RTW_RCR_MXDMA_MASK) -#define RTW_RCR_MXDMA_64 __SHIFTIN(2, RTW_RCR_MXDMA_MASK) -#define RTW_RCR_MXDMA_128 __SHIFTIN(3, RTW_RCR_MXDMA_MASK) -#define RTW_RCR_MXDMA_256 __SHIFTIN(4, RTW_RCR_MXDMA_MASK) -#define RTW_RCR_MXDMA_512 __SHIFTIN(5, RTW_RCR_MXDMA_MASK) -#define RTW_RCR_MXDMA_1024 __SHIFTIN(6, RTW_RCR_MXDMA_MASK) -#define RTW_RCR_MXDMA_UNLIMITED __SHIFTIN(7, RTW_RCR_MXDMA_MASK) - -/* EEPROM type, read-only. 1: EEPROM is 93c56, 0: 93c46 */ -#define RTW_RCR_9356SEL __BIT(6) - -#define RTW_RCR_ACRC32 __BIT(5)/* accept frames w/ CRC32 errors */ -#define RTW_RCR_AB __BIT(3)/* accept broadcast frames */ -#define RTW_RCR_AM __BIT(2)/* accept multicast frames */ -/* accept physical match frames. XXX means PLCP header ok? */ -#define RTW_RCR_APM __BIT(1) -#define RTW_RCR_AAP __BIT(0)/* accept frames w/ destination */ - -/* Additional bits to set in monitor mode. */ -#define RTW_RCR_MONITOR ( \ - RTW_RCR_AAP | \ - RTW_RCR_ACF | \ - RTW_RCR_ACRC32 | \ - RTW_RCR_AICV | \ - 0) - -/* The packet filter bits. */ -#define RTW_RCR_PKTFILTER_MASK (\ - RTW_RCR_AAP | \ - RTW_RCR_AB | \ - RTW_RCR_ACF | \ - RTW_RCR_ACRC32 | \ - RTW_RCR_ADD3 | \ - RTW_RCR_ADF | \ - RTW_RCR_AICV | \ - RTW_RCR_AM | \ - RTW_RCR_AMF | \ - RTW_RCR_APM | \ - RTW_RCR_APWRMGT | \ - 0) - -/* Receive power-management frames and mgmt/ctrl/data frames. */ -#define RTW_RCR_PKTFILTER_DEFAULT ( \ - RTW_RCR_ADF | \ - RTW_RCR_AMF | \ - RTW_RCR_APM | \ - RTW_RCR_APWRMGT | \ - 0) - -#define RTW_TINT 0x48 /* Timer Interrupt Register, 32b */ -#define RTW_TBDA 0x4c /* Transmit Beacon Descriptor Start Address, - * 32b, 256-byte alignment - */ -#define RTW_9346CR 0x50 /* 93c46/93c56 Command Register, 8b */ -#define RTW_9346CR_EEM_MASK __BITS(7,6) /* Operating Mode */ -#define RTW_9346CR_EEM_NORMAL __SHIFTIN(0, RTW_9346CR_EEM_MASK) -/* Load the EEPROM. Reset registers to defaults. - * Takes ~2ms. RTL8180 indicates completion with RTW_9346CR_EEM_NORMAL. - * XXX RTL8180 only? - */ -#define RTW_9346CR_EEM_AUTOLOAD __SHIFTIN(1, RTW_9346CR_EEM_MASK) -/* Disable network & bus-master operations and enable - * _EECS, _EESK, _EEDI, _EEDO. - * XXX RTL8180 only? - */ -#define RTW_9346CR_EEM_PROGRAM __SHIFTIN(2, RTW_9346CR_EEM_MASK) -/* Enable RTW_CONFIG[0123] registers. */ -#define RTW_9346CR_EEM_CONFIG __SHIFTIN(3, RTW_9346CR_EEM_MASK) -/* EEPROM pin status/control in _EEM_CONFIG, _EEM_AUTOLOAD modes. - * XXX RTL8180 only? - */ -#define RTW_9346CR_EECS __BIT(3) -#define RTW_9346CR_EESK __BIT(2) -#define RTW_9346CR_EEDI __BIT(1) -#define RTW_9346CR_EEDO __BIT(0) /* read-only */ - -#define RTW_CONFIG0 0x51 /* Configuration Register 0, 8b */ -#define RTW_CONFIG0_WEP40 __BIT(7)/* implements 40-bit WEP, - * XXX RTL8180 only? - */ -#define RTW_CONFIG0_WEP104 __BIT(6)/* implements 104-bit WEP, - * from EEPROM, read-only - * XXX RTL8180 only? - */ -#define RTW_CONFIG0_LEDGPOEN __BIT(4)/* 1: RTW_PSR_LEDGPO[01] control - * LED[01] pins. - * 0: LED behavior defined by - * RTW_CONFIG1_LEDS10_MASK - * XXX RTL8180 only? - */ -/* auxiliary power is present, read-only */ -#define RTW_CONFIG0_AUXPWR __BIT(3) -/* Geographic Location, read-only */ -#define RTW_CONFIG0_GL_MASK __BITS(1,0) -/* _RTW_CONFIG0_GL_* is what the datasheet says, but RTW_CONFIG0_GL_* - * work. - */ -#define _RTW_CONFIG0_GL_USA __SHIFTIN(3, RTW_CONFIG0_GL_MASK) -#define RTW_CONFIG0_GL_EUROPE __SHIFTIN(2, RTW_CONFIG0_GL_MASK) -#define RTW_CONFIG0_GL_JAPAN __SHIFTIN(1, RTW_CONFIG0_GL_MASK) -#define RTW_CONFIG0_GL_USA __SHIFTIN(0, RTW_CONFIG0_GL_MASK) -/* RTL8181 datasheet says RTW_CONFIG0_GL_JAPAN = 0. */ - -#define RTW_CONFIG1 0x52 /* Configuration Register 1, 8b */ - -/* LED configuration. From EEPROM. Read/write. - * - * Setting LED0 LED1 - * ------- ---- ---- - * RTW_CONFIG1_LEDS_ACT_INFRA Activity Infrastructure - * RTW_CONFIG1_LEDS_ACT_LINK Activity Link - * RTW_CONFIG1_LEDS_TX_RX Tx Rx - * RTW_CONFIG1_LEDS_LINKACT_INFRA Link/Activity Infrastructure - */ -#define RTW_CONFIG1_LEDS_MASK __BITS(7,6) -#define RTW_CONFIG1_LEDS_ACT_INFRA __SHIFTIN(0, RTW_CONFIG1_LEDS_MASK) -#define RTW_CONFIG1_LEDS_ACT_LINK __SHIFTIN(1, RTW_CONFIG1_LEDS_MASK) -#define RTW_CONFIG1_LEDS_TX_RX __SHIFTIN(2, RTW_CONFIG1_LEDS_MASK) -#define RTW_CONFIG1_LEDS_LINKACT_INFRA __SHIFTIN(3, RTW_CONFIG1_LEDS_MASK) - -/* LWAKE Output Signal. Only applicable to Cardbus. Pulse width is 150ms. - * - * RTW_CONFIG1_LWACT - * 0 1 - * RTW_CONFIG4_LWPTN 0 active high active low - * 1 positive pulse negative pulse - */ -#define RTW_CONFIG1_LWACT __BIT(4) - -#define RTW_CONFIG1_MEMMAP __BIT(3)/* using PCI memory space, read-only */ -#define RTW_CONFIG1_IOMAP __BIT(2)/* using PCI I/O space, read-only */ -#define RTW_CONFIG1_VPD __BIT(1)/* if set, VPD from offsets - * 0x40-0x7f in EEPROM are at - * registers 0x60-0x67 of PCI - * Configuration Space (XXX huh?) - */ -#define RTW_CONFIG1_PMEN __BIT(0)/* Power Management Enable: TBD */ - -#define RTW_CONFIG2 0x53 /* Configuration Register 2, 8b */ -#define RTW_CONFIG2_LCK __BIT(7)/* clocks are locked, read-only: - * Tx frequency & symbol clocks - * are derived from the same OSC - */ -#define RTW_CONFIG2_ANT __BIT(6) /* diversity enabled, read-only */ -#define RTW_CONFIG2_DPS __BIT(3) /* Descriptor Polling State: enable - * test mode. - */ -#define RTW_CONFIG2_PAPESIGN __BIT(2) /* TBD, from EEPROM */ -#define RTW_CONFIG2_PAPETIME_MASK __BITS(1,0) /* TBD, from EEPROM */ - -#define RTW_ANAPARM 0x54 /* Analog parameter, 32b */ -#define RTW_ANAPARM_RFPOW0_MASK __BITS(30,28) /* undocumented bits - * which appear to - * control the power - * state of the RF - * components - */ -#define RTW_ANAPARM_RFPOW_MASK \ - (RTW_ANAPARM_RFPOW0_MASK|RTW_ANAPARM_RFPOW1_MASK) - -#define RTW_ANAPARM_TXDACOFF __BIT(27) /* 1: disable Tx DAC, - * 0: enable - */ -#define RTW_ANAPARM_RFPOW1_MASK __BITS(26,20) /* undocumented bits - * which appear to - * control the power - * state of the RF - * components - */ - -/* - * Maxim On/Sleep/Off control - */ -#define RTW_ANAPARM_RFPOW_MAXIM_ON __SHIFTIN(0x8, RTW_ANAPARM_RFPOW1_MASK) - -/* reg[RTW_ANAPARM] |= RTW_ANAPARM_TXDACOFF; */ -#define RTW_ANAPARM_RFPOW_MAXIM_SLEEP __SHIFTIN(0x378, RTW_ANAPARM_RFPOW1_MASK) - -/* reg[RTW_ANAPARM] |= RTW_ANAPARM_TXDACOFF; */ -#define RTW_ANAPARM_RFPOW_MAXIM_OFF __SHIFTIN(0x379, RTW_ANAPARM_RFPOW1_MASK) - -/* - * RFMD On/Sleep/Off control - */ -#define RTW_ANAPARM_RFPOW_RFMD_ON __SHIFTIN(0x408, RTW_ANAPARM_RFPOW1_MASK) - -/* reg[RTW_ANAPARM] |= RTW_ANAPARM_TXDACOFF; */ -#define RTW_ANAPARM_RFPOW_RFMD_SLEEP __SHIFTIN(0x378, RTW_ANAPARM_RFPOW1_MASK) - -/* reg[RTW_ANAPARM] |= RTW_ANAPARM_TXDACOFF; */ -#define RTW_ANAPARM_RFPOW_RFMD_OFF __SHIFTIN(0x379, RTW_ANAPARM_RFPOW1_MASK) - -/* - * Philips On/Sleep/Off control - */ -#define RTW_ANAPARM_RFPOW_ANA_PHILIPS_ON \ - __SHIFTIN(0x328, RTW_ANAPARM_RFPOW1_MASK) -#define RTW_ANAPARM_RFPOW_DIG_PHILIPS_ON \ - __SHIFTIN(0x008, RTW_ANAPARM_RFPOW1_MASK) - -/* reg[RTW_ANAPARM] |= RTW_ANAPARM_TXDACOFF; */ -#define RTW_ANAPARM_RFPOW_PHILIPS_SLEEP\ - __SHIFTIN(0x378, RTW_ANAPARM_RFPOW1_MASK) - -/* reg[RTW_ANAPARM] |= RTW_ANAPARM_TXDACOFF; */ -#define RTW_ANAPARM_RFPOW_PHILIPS_OFF\ - __SHIFTIN(0x379, RTW_ANAPARM_RFPOW1_MASK) - -#define RTW_ANAPARM_RFPOW_PHILIPS_ON __SHIFTIN(0x328, RTW_ANAPARM_RFPOW1_MASK) - -#define RTW_ANAPARM_CARDSP_MASK __BITS(19,0) /* undocumented - * card-specific - * bits from the - * EEPROM. - */ - -#define RTW_MSR 0x58 /* Media Status Register, 8b */ -/* Network Type and Link Status */ -#define RTW_MSR_NETYPE_MASK __BITS(3,2) -/* AP, XXX RTL8181 only? */ -#define RTW_MSR_NETYPE_AP_OK __SHIFTIN(3, RTW_MSR_NETYPE_MASK) -/* infrastructure link ok */ -#define RTW_MSR_NETYPE_INFRA_OK __SHIFTIN(2, RTW_MSR_NETYPE_MASK) -/* ad-hoc link ok */ -#define RTW_MSR_NETYPE_ADHOC_OK __SHIFTIN(1, RTW_MSR_NETYPE_MASK) -/* no link */ -#define RTW_MSR_NETYPE_NOLINK __SHIFTIN(0, RTW_MSR_NETYPE_MASK) - -#define RTW_CONFIG3 0x59 /* Configuration Register 3, 8b */ -#define RTW_CONFIG3_GNTSEL __BIT(7) /* Grant Select, read-only */ -#define RTW_CONFIG3_PARMEN __BIT(6) /* Set RTW_CONFIG3_PARMEN and - * RTW_9346CR_EEM_CONFIG to - * allow RTW_ANAPARM writes. - */ -#define RTW_CONFIG3_MAGIC __BIT(5)/* Valid when RTW_CONFIG1_PMEN is - * set. If set, RTL8180 wakes up - * OS when Magic Packet is Rx'd. - */ -#define RTW_CONFIG3_CARDBEN __BIT(3)/* Cardbus-related registers - * and functions are enabled, - * read-only. XXX RTL8180 only. - */ -#define RTW_CONFIG3_CLKRUNEN __BIT(2)/* CLKRUN enabled, read-only. - * XXX RTL8180 only. - */ -#define RTW_CONFIG3_FUNCREGEN __BIT(1)/* Function Registers Enabled, - * read-only. XXX RTL8180 only. - */ -#define RTW_CONFIG3_FBTBEN __BIT(0)/* Fast back-to-back enabled, - * read-only. - */ -#define RTW_CONFIG4 0x5A /* Configuration Register 4, 8b */ -#define RTW_CONFIG4_VCOPDN __BIT(7)/* VCO Power Down - * 0: normal operation - * (power-on default) - * 1: power-down VCO, RF front-end, - * and most RTL8180 components. - */ -#define RTW_CONFIG4_PWROFF __BIT(6)/* Power Off - * 0: normal operation - * (power-on default) - * 1: power-down RF front-end, - * and most RTL8180 components, - * but leave VCO on. - * - * XXX RFMD front-end only? - */ -#define RTW_CONFIG4_PWRMGT __BIT(5)/* Power Management - * 0: normal operation - * (power-on default) - * 1: set Tx packet's PWRMGMT bit. - */ -#define RTW_CONFIG4_LWPME __BIT(4)/* LANWAKE vs. PMEB: Cardbus-only - * 0: LWAKE & PMEB asserted - * simultaneously - * 1: LWAKE asserted only if - * both PMEB is asserted and - * ISOLATEB is low. - * XXX RTL8180 only. - */ -#define RTW_CONFIG4_LWPTN __BIT(2)/* see RTW_CONFIG1_LWACT - * XXX RTL8180 only. - */ -/* Radio Front-End Programming Method */ -#define RTW_CONFIG4_RFTYPE_MASK __BITS(1,0) -#define RTW_CONFIG4_RFTYPE_INTERSIL __SHIFTIN(1, RTW_CONFIG4_RFTYPE_MASK) -#define RTW_CONFIG4_RFTYPE_RFMD __SHIFTIN(2, RTW_CONFIG4_RFTYPE_MASK) -#define RTW_CONFIG4_RFTYPE_PHILIPS __SHIFTIN(3, RTW_CONFIG4_RFTYPE_MASK) - -#define RTW_TESTR 0x5B /* TEST mode register, 8b */ - -#define RTW_PSR 0x5e /* Page Select Register, 8b */ -#define RTW_PSR_GPO __BIT(7)/* Control/status of pin 52. */ -#define RTW_PSR_GPI __BIT(6)/* Status of pin 64. */ -#define RTW_PSR_LEDGPO1 __BIT(5)/* Status/control of LED1 pin if - * RTW_CONFIG0_LEDGPOEN is set. - */ -#define RTW_PSR_LEDGPO0 __BIT(4)/* Status/control of LED0 pin if - * RTW_CONFIG0_LEDGPOEN is set. - */ -#define RTW_PSR_UWF __BIT(1)/* Enable Unicast Wakeup Frame */ -#define RTW_PSR_PSEN __BIT(0)/* 1: page 1, 0: page 0 */ - -#define RTW_SCR 0x5f /* Security Configuration Register, 8b */ -#define RTW_SCR_KM_MASK __BITS(5,4) /* Key Mode */ -#define RTW_SCR_KM_WEP104 __SHIFTIN(1, RTW_SCR_KM_MASK) -#define RTW_SCR_KM_WEP40 __SHIFTIN(0, RTW_SCR_KM_MASK) -#define RTW_SCR_TXSECON __BIT(1)/* Enable Tx WEP. Invalid if - * neither RTW_CONFIG0_WEP40 nor - * RTW_CONFIG0_WEP104 is set. - */ -#define RTW_SCR_RXSECON __BIT(0)/* Enable Rx WEP. Invalid if - * neither RTW_CONFIG0_WEP40 nor - * RTW_CONFIG0_WEP104 is set. - */ - -#define RTW_BCNITV 0x70 /* Beacon Interval Register, 16b */ -#define RTW_BCNITV_BCNITV_MASK __BITS(9,0) /* TU between TBTT, written - * by host. - */ -#define RTW_ATIMWND 0x72 /* ATIM Window Register, 16b */ -#define RTW_ATIMWND_ATIMWND __BITS(9,0) /* ATIM Window length in TU, - * written by host. - */ - -#define RTW_BINTRITV 0x74 /* Beacon Interrupt Interval Register, 16b */ -#define RTW_BINTRITV_BINTRITV __BITS(9,0) /* RTL8180 wakes host with - * RTW_INTR_BCNINT at BINTRITV - * microseconds before TBTT - */ -#define RTW_ATIMTRITV 0x76 /* ATIM Interrupt Interval Register, 16b */ -#define RTW_ATIMTRITV_ATIMTRITV __BITS(9,0) /* RTL8180 wakes host with - * RTW_INTR_ATIMINT at ATIMTRITV - * microseconds before end of - * ATIM Window - */ - -#define RTW_PHYDELAY 0x78 /* PHY Delay Register, 8b */ -#define RTW_PHYDELAY_REVC_MAGIC __BIT(3) /* Rev. C magic from reference - * driver - */ -#define RTW_PHYDELAY_PHYDELAY __BITS(2,0) /* microsecond Tx delay between - * MAC and RF front-end - */ -#define RTW_CRCOUNT 0x79 /* Carrier Sense Counter, 8b */ -#define RTW_CRCOUNT_MAGIC 0x4c - -#define RTW_CRC16ERR 0x7a /* CRC16 error count, 16b, XXX RTL8181 only? */ - -#define RTW_BB 0x7c /* Baseband interface, 32b */ -/* used for writing RTL8180's integrated baseband processor */ -#define RTW_BB_RD_MASK __BITS(23,16) /* data to read */ -#define RTW_BB_WR_MASK __BITS(15,8) /* data to write */ -#define RTW_BB_WREN __BIT(7) /* write enable */ -#define RTW_BB_ADDR_MASK __BITS(6,0) /* address */ - -#define RTW_PHYADDR 0x7c /* Address register for PHY interface, 8b */ -#define RTW_PHYDATAW 0x7d /* Write data to PHY, 8b, write-only */ -#define RTW_PHYDATAR 0x7e /* Read data from PHY, 8b (?), read-only */ - -#define RTW_PHYCFG 0x80 /* PHY Configuration Register, 32b */ -#define RTW_PHYCFG_MAC_POLL __BIT(31) /* if !RTW_PHYCFG_HST, - * host sets. MAC clears - * after banging bits. - */ -#define RTW_PHYCFG_HST __BIT(30) /* 1: host bangs bits - * 0: MAC bangs bits - */ -#define RTW_PHYCFG_MAC_RFTYPE_MASK __BITS(29,28) -#define RTW_PHYCFG_MAC_RFTYPE_INTERSIL __SHIFTIN(0, RTW_PHYCFG_MAC_RFTYPE_MASK) -#define RTW_PHYCFG_MAC_RFTYPE_RFMD __SHIFTIN(1, RTW_PHYCFG_MAC_RFTYPE_MASK) -#define RTW_PHYCFG_MAC_RFTYPE_GCT RTW_PHYCFG_MAC_RFTYPE_RFMD -#define RTW_PHYCFG_MAC_RFTYPE_PHILIPS __SHIFTIN(3, RTW_PHYCFG_MAC_RFTYPE_MASK) -#define RTW_PHYCFG_MAC_PHILIPS_ADDR_MASK __BITS(27,24) -#define RTW_PHYCFG_MAC_PHILIPS_DATA_MASK __BITS(23,0) -#define RTW_PHYCFG_MAC_MAXIM_LODATA_MASK __BITS(27,24) -#define RTW_PHYCFG_MAC_MAXIM_ADDR_MASK __BITS(11,8) -#define RTW_PHYCFG_MAC_MAXIM_HIDATA_MASK __BITS(7,0) -#define RTW_PHYCFG_HST_EN __BIT(2) -#define RTW_PHYCFG_HST_CLK __BIT(1) -#define RTW_PHYCFG_HST_DATA __BIT(0) - -#define RTW_MAXIM_HIDATA_MASK __BITS(11,4) -#define RTW_MAXIM_LODATA_MASK __BITS(3,0) - -/** - ** 0x84 - 0xD3, page 1, selected when RTW_PSR[PSEN] == 1. - **/ - -#define RTW_WAKEUP0L 0x84 /* Power Management Wakeup Frame */ -#define RTW_WAKEUP0H 0x88 /* 32b */ - -#define RTW_WAKEUP1L 0x8c -#define RTW_WAKEUP1H 0x90 - -#define RTW_WAKEUP2LL 0x94 -#define RTW_WAKEUP2LH 0x98 - -#define RTW_WAKEUP2HL 0x9c -#define RTW_WAKEUP2HH 0xa0 - -#define RTW_WAKEUP3LL 0xa4 -#define RTW_WAKEUP3LH 0xa8 - -#define RTW_WAKEUP3HL 0xac -#define RTW_WAKEUP3HH 0xb0 - -#define RTW_WAKEUP4LL 0xb4 -#define RTW_WAKEUP4LH 0xb8 - -#define RTW_WAKEUP4HL 0xbc -#define RTW_WAKEUP4HH 0xc0 - -#define RTW_CRC0 0xc4 /* CRC of wakeup frame 0, 16b */ -#define RTW_CRC1 0xc6 /* CRC of wakeup frame 1, 16b */ -#define RTW_CRC2 0xc8 /* CRC of wakeup frame 2, 16b */ -#define RTW_CRC3 0xca /* CRC of wakeup frame 3, 16b */ -#define RTW_CRC4 0xcc /* CRC of wakeup frame 4, 16b */ - -/** - ** 0x84 - 0xD3, page 0, selected when RTW_PSR[PSEN] == 0. - **/ - -/* Default Key Registers, each 128b - * - * If RTW_SCR_KM_WEP104, 104 lsb are the key. - * If RTW_SCR_KM_WEP40, 40 lsb are the key. - */ -#define RTW_DK0 0x90 /* Default Key 0 Register, 128b */ -#define RTW_DK1 0xa0 /* Default Key 1 Register, 128b */ -#define RTW_DK2 0xb0 /* Default Key 2 Register, 128b */ -#define RTW_DK3 0xc0 /* Default Key 3 Register, 128b */ - -#define RTW_CONFIG5 0xd8 /* Configuration Register 5, 8b */ -#define RTW_CONFIG5_TXFIFOOK __BIT(7)/* Tx FIFO self-test pass, read-only */ -#define RTW_CONFIG5_RXFIFOOK __BIT(6)/* Rx FIFO self-test pass, read-only */ -#define RTW_CONFIG5_CALON __BIT(5)/* 1: start calibration cycle - * and raise AGCRESET pin. - * 0: lower AGCRESET pin - */ -#define RTW_CONFIG5_EACPI __BIT(2)/* Enable ACPI Wake up, default 0 */ -#define RTW_CONFIG5_LANWAKE __BIT(1)/* Enable LAN Wake signal, - * from EEPROM - */ -#define RTW_CONFIG5_PMESTS __BIT(0)/* 1: both software & PCI Reset - * reset PME_Status - * 0: only software resets PME_Status - * - * From EEPROM. - */ - -#define RTW_TPPOLL 0xd9 /* Transmit Priority Polling Register, 8b, - * write-only. - */ -#define RTW_TPPOLL_BQ __BIT(7)/* RTL8180 clears to notify host of a beacon - * Tx. Host writes have no effect. - */ -#define RTW_TPPOLL_HPQ __BIT(6)/* Host writes 1 to notify RTL8180 of - * high-priority Tx packets, RTL8180 clears - * to after high-priority Tx is complete. - */ -#define RTW_TPPOLL_NPQ __BIT(5)/* If RTW_CONFIG2_DPS is set, - * host writes 1 to notify RTL8180 of - * normal-priority Tx packets, RTL8180 clears - * after normal-priority Tx is complete. - * - * If RTW_CONFIG2_DPS is clear, host writes - * have no effect. RTL8180 clears after - * normal-priority Tx is complete. - */ -#define RTW_TPPOLL_LPQ __BIT(4)/* Host writes 1 to notify RTL8180 of - * low-priority Tx packets, RTL8180 clears - * after low-priority Tx is complete. - */ -#define RTW_TPPOLL_SBQ __BIT(3)/* Host writes 1 to tell RTL8180 to - * stop beacon DMA. This bit is invalid - * when RTW_CONFIG2_DPS is set. - */ -#define RTW_TPPOLL_SHPQ __BIT(2)/* Host writes 1 to tell RTL8180 to - * stop high-priority DMA. - */ -#define RTW_TPPOLL_SNPQ __BIT(1)/* Host writes 1 to tell RTL8180 to - * stop normal-priority DMA. This bit is invalid - * when RTW_CONFIG2_DPS is set. - */ -#define RTW_TPPOLL_SLPQ __BIT(0)/* Host writes 1 to tell RTL8180 to - * stop low-priority DMA. - */ - -/* Start all queues. */ -#define RTW_TPPOLL_ALL (RTW_TPPOLL_BQ | RTW_TPPOLL_HPQ | \ - RTW_TPPOLL_NPQ | RTW_TPPOLL_LPQ) -/* Check all queues' activity. */ -#define RTW_TPPOLL_ACTIVE RTW_TPPOLL_ALL -/* Stop all queues. */ -#define RTW_TPPOLL_SALL (RTW_TPPOLL_SBQ | RTW_TPPOLL_SHPQ | \ - RTW_TPPOLL_SNPQ | RTW_TPPOLL_SLPQ) - -#define RTW_CWR 0xdc /* Contention Window Register, 16b, read-only */ -/* Contention Window: indicates number of contention windows before Tx - */ -#define RTW_CWR_CW __BITS(9,0) - -/* Retry Count Register, 16b, read-only */ -#define RTW_RETRYCTR 0xde -/* Retry Count: indicates number of retries after Tx */ -#define RTW_RETRYCTR_RETRYCT __BITS(7,0) - -#define RTW_RDSAR 0xe4 /* Receive descriptor Start Address Register, - * 32b, 256-byte alignment. - */ -/* Function Event Register, 32b, Cardbus only. Only valid when - * both RTW_CONFIG3_CARDBEN and RTW_CONFIG3_FUNCREGEN are set. - */ -#define RTW_FER 0xf0 -#define RTW_FER_INTR __BIT(15) /* set when RTW_FFER_INTR is set */ -#define RTW_FER_GWAKE __BIT(4) /* General Wakeup */ -/* Function Event Mask Register, 32b, Cardbus only. Only valid when - * both RTW_CONFIG3_CARDBEN and RTW_CONFIG3_FUNCREGEN are set. - */ -#define RTW_FEMR 0xf4 -#define RTW_FEMR_INTR __BIT(15) /* set when RTW_FFER_INTR is set */ -#define RTW_FEMR_WKUP __BIT(14) /* Wakeup Mask */ -#define RTW_FEMR_GWAKE __BIT(4) /* General Wakeup */ -/* Function Present State Register, 32b, read-only, Cardbus only. - * Only valid when both RTW_CONFIG3_CARDBEN and RTW_CONFIG3_FUNCREGEN - * are set. - */ -#define RTW_FPSR 0xf8 -#define RTW_FPSR_INTR __BIT(15) /* TBD */ -#define RTW_FPSR_GWAKE __BIT(4) /* General Wakeup: TBD */ -/* Function Force Event Register, 32b, write-only, Cardbus only. - * Only valid when both RTW_CONFIG3_CARDBEN and RTW_CONFIG3_FUNCREGEN - * are set. - */ -#define RTW_FFER 0xfc -#define RTW_FFER_INTR __BIT(15) /* TBD */ -#define RTW_FFER_GWAKE __BIT(4) /* General Wakeup: TBD */ - -/* Serial EEPROM offsets */ -#define RTW_SR_ID 0x00 /* 16b */ -#define RTW_SR_VID 0x02 /* 16b */ -#define RTW_SR_DID 0x04 /* 16b */ -#define RTW_SR_SVID 0x06 /* 16b */ -#define RTW_SR_SMID 0x08 /* 16b */ -#define RTW_SR_MNGNT 0x0a -#define RTW_SR_MXLAT 0x0b -#define RTW_SR_RFCHIPID 0x0c -#define RTW_SR_CONFIG3 0x0d -#define RTW_SR_MAC 0x0e /* 6 bytes */ -#define RTW_SR_CONFIG0 0x14 -#define RTW_SR_CONFIG1 0x15 -#define RTW_SR_PMC 0x16 /* Power Management Capabilities, 16b */ -#define RTW_SR_CONFIG2 0x18 -#define RTW_SR_CONFIG4 0x19 -#define RTW_SR_ANAPARM 0x1a /* Analog Parameters, 32b */ -#define RTW_SR_TESTR 0x1e -#define RTW_SR_CONFIG5 0x1f -#define RTW_SR_TXPOWER1 0x20 -#define RTW_SR_TXPOWER2 0x21 -#define RTW_SR_TXPOWER3 0x22 -#define RTW_SR_TXPOWER4 0x23 -#define RTW_SR_TXPOWER5 0x24 -#define RTW_SR_TXPOWER6 0x25 -#define RTW_SR_TXPOWER7 0x26 -#define RTW_SR_TXPOWER8 0x27 -#define RTW_SR_TXPOWER9 0x28 -#define RTW_SR_TXPOWER10 0x29 -#define RTW_SR_TXPOWER11 0x2a -#define RTW_SR_TXPOWER12 0x2b -#define RTW_SR_TXPOWER13 0x2c -#define RTW_SR_TXPOWER14 0x2d -#define RTW_SR_CHANNELPLAN 0x2e /* bitmap of channels to scan */ -#define RTW_SR_ENERGYDETTHR 0x2f /* energy-detect threshold */ -#define RTW_SR_ENERGYDETTHR_DEFAULT 0x0c /* use this if old SROM */ -#define RTW_SR_CISPOINTER 0x30 /* 16b */ -#define RTW_SR_RFPARM 0x32 /* RF-specific parameter */ -#define RTW_SR_RFPARM_DIGPHY __BIT(0) /* 1: digital PHY */ -#define RTW_SR_RFPARM_DFLANTB __BIT(1) /* 1: antenna B is default */ -#define RTW_SR_RFPARM_CS_MASK __BITS(2,3) /* carrier-sense type */ -#define RTW_SR_VERSION 0x3c /* EEPROM content version, 16b */ -#define RTW_SR_CRC 0x3e /* EEPROM content CRC, 16b */ -#define RTW_SR_VPD 0x40 /* Vital Product Data, 64 bytes */ -#define RTW_SR_CIS 0x80 /* CIS Data, 93c56 only, 128 bytes*/ - -/* - * RTL8180 Transmit/Receive Descriptors - */ - -/* the first descriptor in each ring must be on a 256-byte boundary */ -#define RTW_DESC_ALIGNMENT 256 - -/* Tx descriptor */ -struct rtw_txdesc { - uint32_t td_ctl0; - uint32_t td_ctl1; - uint32_t td_buf; - uint32_t td_len; - uint32_t td_next; - uint32_t td_rsvd[3]; -}; - -#define td_stat td_ctl0 - -#define RTW_TXCTL0_OWN __BIT(31) /* 1: ready to Tx */ -#define RTW_TXCTL0_RSVD0 __BIT(30) /* reserved */ -#define RTW_TXCTL0_FS __BIT(29) /* first segment */ -#define RTW_TXCTL0_LS __BIT(28) /* last segment */ - -#define RTW_TXCTL0_RATE_MASK __BITS(27,24) /* Tx rate */ -#define RTW_TXCTL0_RATE_1MBPS __SHIFTIN(0, RTW_TXCTL0_RATE_MASK) -#define RTW_TXCTL0_RATE_2MBPS __SHIFTIN(1, RTW_TXCTL0_RATE_MASK) -#define RTW_TXCTL0_RATE_5MBPS __SHIFTIN(2, RTW_TXCTL0_RATE_MASK) -#define RTW_TXCTL0_RATE_11MBPS __SHIFTIN(3, RTW_TXCTL0_RATE_MASK) - -#define RTW_TXCTL0_RTSEN __BIT(23) /* RTS Enable */ - -#define RTW_TXCTL0_RTSRATE_MASK __BITS(22,19) /* Tx rate */ -#define RTW_TXCTL0_RTSRATE_1MBPS __SHIFTIN(0, RTW_TXCTL0_RTSRATE_MASK) -#define RTW_TXCTL0_RTSRATE_2MBPS __SHIFTIN(1, RTW_TXCTL0_RTSRATE_MASK) -#define RTW_TXCTL0_RTSRATE_5MBPS __SHIFTIN(2, RTW_TXCTL0_RTSRATE_MASK) -#define RTW_TXCTL0_RTSRATE_11MBPS __SHIFTIN(3, RTW_TXCTL0_RTSRATE_MASK) - -#define RTW_TXCTL0_BEACON __BIT(18) /* packet is a beacon */ -#define RTW_TXCTL0_MOREFRAG __BIT(17) /* another fragment - * follows - */ -/* add short PLCP preamble and header */ -#define RTW_TXCTL0_SPLCP __BIT(16) -#define RTW_TXCTL0_KEYID_MASK __BITS(15,14) /* default key id */ -#define RTW_TXCTL0_RSVD1_MASK __BITS(13,12) /* reserved */ -#define RTW_TXCTL0_TPKTSIZE_MASK __BITS(11,0) /* Tx packet size - * in bytes - */ - -#define RTW_TXSTAT_OWN RTW_TXCTL0_OWN -#define RTW_TXSTAT_RSVD0 RTW_TXCTL0_RSVD0 -#define RTW_TXSTAT_FS RTW_TXCTL0_FS -#define RTW_TXSTAT_LS RTW_TXCTL0_LS -#define RTW_TXSTAT_RSVD1_MASK __BITS(27,16) -#define RTW_TXSTAT_TOK __BIT(15) -#define RTW_TXSTAT_RTSRETRY_MASK __BITS(14,8) /* RTS retry count */ -#define RTW_TXSTAT_DRC_MASK __BITS(7,0) /* Data retry count */ - -#define RTW_TXCTL1_LENGEXT __BIT(31) /* supplements _LENGTH - * in packets sent 5.5Mb/s or - * faster - */ -#define RTW_TXCTL1_LENGTH_MASK __BITS(30,16) /* PLCP length (microseconds) */ -#define RTW_TXCTL1_RTSDUR_MASK __BITS(15,0) /* RTS Duration - * (microseconds) - */ - -#define RTW_TXLEN_LENGTH_MASK __BITS(11,0) /* Tx buffer length in bytes */ - -/* Rx descriptor */ -struct rtw_rxdesc { - uint32_t rd_ctl; - uint32_t rd_rsvd0; - uint32_t rd_buf; - uint32_t rd_rsvd1; -}; - -#define rd_stat rd_ctl -#define rd_rssi rd_rsvd0 -#define rd_tsftl rd_buf /* valid only when RTW_RXSTAT_LS is set */ -#define rd_tsfth rd_rsvd1 /* valid only when RTW_RXSTAT_LS is set */ - -#define RTW_RXCTL_OWN __BIT(31) /* 1: owned by NIC */ -#define RTW_RXCTL_EOR __BIT(30) /* end of ring */ -#define RTW_RXCTL_FS __BIT(29) /* first segment */ -#define RTW_RXCTL_LS __BIT(28) /* last segment */ -#define RTW_RXCTL_RSVD0_MASK __BITS(29,12) /* reserved */ -#define RTW_RXCTL_LENGTH_MASK __BITS(11,0) /* Rx buffer length */ - -#define RTW_RXSTAT_OWN RTW_RXCTL_OWN -#define RTW_RXSTAT_EOR RTW_RXCTL_EOR -#define RTW_RXSTAT_FS RTW_RXCTL_FS /* first segment */ -#define RTW_RXSTAT_LS RTW_RXCTL_LS /* last segment */ -#define RTW_RXSTAT_DMAFAIL __BIT(27) /* DMA failure on this pkt */ -#define RTW_RXSTAT_BOVF __BIT(26) /* buffer overflow XXX means - * FIFO exhausted? - */ -#define RTW_RXSTAT_SPLCP __BIT(25) /* Rx'd with short preamble - * and PLCP header - */ -#define RTW_RXSTAT_RSVD1 __BIT(24) /* reserved */ -#define RTW_RXSTAT_RATE_MASK __BITS(23,20) /* Rx rate */ -#define RTW_RXSTAT_RATE_1MBPS __SHIFTIN(0, RTW_RXSTAT_RATE_MASK) -#define RTW_RXSTAT_RATE_2MBPS __SHIFTIN(1, RTW_RXSTAT_RATE_MASK) -#define RTW_RXSTAT_RATE_5MBPS __SHIFTIN(2, RTW_RXSTAT_RATE_MASK) -#define RTW_RXSTAT_RATE_11MBPS __SHIFTIN(3, RTW_RXSTAT_RATE_MASK) -#define RTW_RXSTAT_MIC __BIT(19) /* XXX from reference driver */ -#define RTW_RXSTAT_MAR __BIT(18) /* is multicast */ -#define RTW_RXSTAT_PAR __BIT(17) /* matches RTL8180's MAC */ -#define RTW_RXSTAT_BAR __BIT(16) /* is broadcast */ -#define RTW_RXSTAT_RES __BIT(15) /* error summary. valid when - * RTW_RXSTAT_LS set. indicates - * that either RTW_RXSTAT_CRC32 - * or RTW_RXSTAT_ICV is set. - */ -#define RTW_RXSTAT_PWRMGT __BIT(14) /* 802.11 PWRMGMT bit is set */ -#define RTW_RXSTAT_CRC16 __BIT(14) /* XXX CRC16 error, from - * reference driver - */ -#define RTW_RXSTAT_CRC32 __BIT(13) /* CRC32 error */ -#define RTW_RXSTAT_ICV __BIT(12) /* ICV error */ -#define RTW_RXSTAT_LENGTH_MASK __BITS(11,0) /* frame length, including - * CRC32 - */ - -/* Convenient status conjunction. */ -#define RTW_RXSTAT_ONESEG (RTW_RXSTAT_FS|RTW_RXSTAT_LS) -/* Convenient status disjunctions. */ -#define RTW_RXSTAT_IOERROR (RTW_RXSTAT_DMAFAIL|RTW_RXSTAT_BOVF) -#define RTW_RXSTAT_DEBUG (RTW_RXSTAT_SPLCP|RTW_RXSTAT_MAR|\ - RTW_RXSTAT_PAR|RTW_RXSTAT_BAR|\ - RTW_RXSTAT_PWRMGT|RTW_RXSTAT_CRC32|\ - RTW_RXSTAT_ICV) - - -#define RTW_RXRSSI_VLAN __BITS(31,16) /* XXX from reference driver */ -/* for Philips RF front-ends */ -#define RTW_RXRSSI_RSSI __BITS(15,8) /* RF energy at the PHY */ -/* for RF front-ends by Intersil, Maxim, RFMD */ -#define RTW_RXRSSI_IMR_RSSI __BITS(15,9) /* RF energy at the PHY */ -#define RTW_RXRSSI_IMR_LNA __BIT(8) /* 1: LNA activated */ -#define RTW_RXRSSI_SQ __BITS(7,0) /* Barker code-lock quality */ - -#define RTW_READ8(regs, ofs) \ - bus_space_read_1((regs)->r_bt, (regs)->r_bh, (ofs)) - -#define RTW_READ16(regs, ofs) \ - bus_space_read_2((regs)->r_bt, (regs)->r_bh, (ofs)) - -#define RTW_READ(regs, ofs) \ - bus_space_read_4((regs)->r_bt, (regs)->r_bh, (ofs)) - -#define RTW_WRITE8(regs, ofs, val) \ - bus_space_write_1((regs)->r_bt, (regs)->r_bh, (ofs), (val)) - -#define RTW_WRITE16(regs, ofs, val) \ - bus_space_write_2((regs)->r_bt, (regs)->r_bh, (ofs), (val)) - -#define RTW_WRITE(regs, ofs, val) \ - bus_space_write_4((regs)->r_bt, (regs)->r_bh, (ofs), (val)) - -#define RTW_ISSET(regs, reg, mask) \ - (RTW_READ((regs), (reg)) & (mask)) - -#define RTW_CLR(regs, reg, mask) \ - RTW_WRITE((regs), (reg), RTW_READ((regs), (reg)) & ~(mask)) - -/* bus_space(9) lied? */ -#ifndef BUS_SPACE_BARRIER_SYNC -#define BUS_SPACE_BARRIER_SYNC (BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE) -#endif - -#ifndef BUS_SPACE_BARRIER_READ_BEFORE_READ -#define BUS_SPACE_BARRIER_READ_BEFORE_READ BUS_SPACE_BARRIER_READ -#endif - -#ifndef BUS_SPACE_BARRIER_READ_BEFORE_WRITE -#define BUS_SPACE_BARRIER_READ_BEFORE_WRITE BUS_SPACE_BARRIER_READ -#endif - -#ifndef BUS_SPACE_BARRIER_WRITE_BEFORE_READ -#define BUS_SPACE_BARRIER_WRITE_BEFORE_READ BUS_SPACE_BARRIER_WRITE -#endif - -#ifndef BUS_SPACE_BARRIER_WRITE_BEFORE_WRITE -#define BUS_SPACE_BARRIER_WRITE_BEFORE_WRITE BUS_SPACE_BARRIER_WRITE -#endif - -/* - * Bus barrier - * - * Complete outstanding read and/or write ops on [reg0, reg1] - * ([reg1, reg0]) before starting new ops on the same region. See - * acceptable bus_space_barrier(9) for the flag definitions. - */ -#define RTW_BARRIER(regs, reg0, reg1, flags) \ - bus_space_barrier((regs)->r_bh, (regs)->r_bt, \ - MIN(reg0, reg1), MAX(reg0, reg1) - MIN(reg0, reg1) + 4, flags) - -/* - * Barrier convenience macros. - */ -/* sync */ -#define RTW_SYNC(regs, reg0, reg1) \ - RTW_BARRIER(regs, reg0, reg1, BUS_SPACE_BARRIER_SYNC) - -/* write-before-write */ -#define RTW_WBW(regs, reg0, reg1) \ - RTW_BARRIER(regs, reg0, reg1, BUS_SPACE_BARRIER_WRITE_BEFORE_WRITE) - -/* write-before-read */ -#define RTW_WBR(regs, reg0, reg1) \ - RTW_BARRIER(regs, reg0, reg1, BUS_SPACE_BARRIER_WRITE_BEFORE_READ) - -/* read-before-read */ -#define RTW_RBR(regs, reg0, reg1) \ - RTW_BARRIER(regs, reg0, reg1, BUS_SPACE_BARRIER_READ_BEFORE_READ) - -/* read-before-read */ -#define RTW_RBW(regs, reg0, reg1) \ - RTW_BARRIER(regs, reg0, reg1, BUS_SPACE_BARRIER_READ_BEFORE_WRITE) - -#define RTW_WBRW(regs, reg0, reg1) \ - RTW_BARRIER(regs, reg0, reg1, \ - BUS_SPACE_BARRIER_WRITE_BEFORE_READ | \ - BUS_SPACE_BARRIER_WRITE_BEFORE_WRITE) - -/* - * Registers for RTL8180L's built-in baseband modem. - */ -#define RTW_BBP_SYS1 0x00 -#define RTW_BBP_TXAGC 0x03 /* guess: transmit auto gain control */ -#define RTW_BBP_LNADET 0x04 /* guess: low-noise amplifier activation - * threshold - */ -#define RTW_BBP_IFAGCINI 0x05 /* guess: intermediate frequency (IF) - * auto-gain control (AGC) initial value - */ -#define RTW_BBP_IFAGCLIMIT 0x06 /* guess: IF AGC maximum value */ -#define RTW_BBP_IFAGCDET 0x07 /* guess: activation threshold for - * IF AGC loop - */ - -#define RTW_BBP_ANTATTEN 0x10 /* guess: antenna & attenuation */ -#define RTW_BBP_ANTATTEN_GCT_MAGIC 0xa3 -#define RTW_BBP_ANTATTEN_PHILIPS_MAGIC 0x91 -#define RTW_BBP_ANTATTEN_INTERSIL_MAGIC 0x92 -#define RTW_BBP_ANTATTEN_RFMD_MAGIC 0x93 -#define RTW_BBP_ANTATTEN_MAXIM_MAGIC 0xb3 -#define RTW_BBP_ANTATTEN_DFLANTB 0x40 -#define RTW_BBP_ANTATTEN_CHAN14 0x0c - -#define RTW_BBP_TRL 0x11 /* guess: transmit/receive - * switch latency - */ -#define RTW_BBP_SYS2 0x12 -#define RTW_BBP_SYS2_ANTDIV 0x80 /* enable antenna diversity */ -#define RTW_BBP_SYS2_RATE_MASK __BITS(5,4) /* loopback rate? - * 0: 1Mbps - * 1: 2Mbps - * 2: 5.5Mbps - * 3: 11Mbps - */ -#define RTW_BBP_SYS3 0x13 -/* carrier-sense threshold */ -#define RTW_BBP_SYS3_CSTHRESH_MASK __BITS(0,3) -#define RTW_BBP_CHESTLIM 0x19 /* guess: channel energy-detect - * threshold - */ -#define RTW_BBP_CHSQLIM 0x1a /* guess: channel signal-quality - * threshold - */ - -#define RTW_NOISE_FLOOR -95 /* guess */ -#define RTW_RSSI_CORR 131 /* Linux driver (256 - 125) */ diff --git a/sys/dev/netif/rtw/rtwvar.h b/sys/dev/netif/rtw/rtwvar.h deleted file mode 100644 index d1df6aaa5a..0000000000 --- a/sys/dev/netif/rtw/rtwvar.h +++ /dev/null @@ -1,534 +0,0 @@ -/* - * Copyright (c) 2004, 2005 David Young. All rights reserved. - * - * Driver for the Realtek RTL8180 802.11 MAC/BBP by David Young. - * - * 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. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of David Young may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY David Young ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL David - * Young BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 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 DAMAGE. - * - * $NetBSD: rtwvar.h,v 1.28 2006/02/16 20:17:16 perry Exp $ - * $DragonFly: src/sys/dev/netif/rtw/rtwvar.h,v 1.5 2008/01/15 09:01:13 sephe Exp $ - */ - -#ifndef _DEV_IC_RTWVAR_H_ -#define _DEV_IC_RTWVAR_H_ - -/* - * 802.11 frame duration definitions. - */ - -struct rtw_duration { - uint16_t d_rts_dur; - uint16_t d_data_dur; - uint16_t d_plcp_len; - uint8_t d_residue; /* unused octets in time slot */ -}; - -#ifdef RTW_DEBUG -#define RTW_DEBUG_TUNE 0x0000001 -#define RTW_DEBUG_PKTFILT 0x0000002 -#define RTW_DEBUG_XMIT 0x0000004 -#define RTW_DEBUG_XMIT_DESC 0x0000008 -#define RTW_DEBUG_NODE 0x0000010 -#define RTW_DEBUG_PWR 0x0000020 -#define RTW_DEBUG_ATTACH 0x0000040 -#define RTW_DEBUG_REGDUMP 0x0000080 -#define RTW_DEBUG_ACCESS 0x0000100 -#define RTW_DEBUG_RESET 0x0000200 -#define RTW_DEBUG_INIT 0x0000400 -#define RTW_DEBUG_IOSTATE 0x0000800 -#define RTW_DEBUG_RECV 0x0001000 -#define RTW_DEBUG_RECV_DESC 0x0002000 -#define RTW_DEBUG_IO_KICK 0x0004000 -#define RTW_DEBUG_INTR 0x0008000 -#define RTW_DEBUG_PHY 0x0010000 -#define RTW_DEBUG_PHYIO 0x0020000 -#define RTW_DEBUG_PHYBITIO 0x0040000 -#define RTW_DEBUG_TIMEOUT 0x0080000 -#define RTW_DEBUG_BUGS 0x0100000 -#define RTW_DEBUG_BEACON 0x0200000 -#define RTW_DEBUG_LED 0x0400000 -#define RTW_DEBUG_KEY 0x0800000 -#define RTW_DEBUG_XMIT_RSRC 0x1000000 -#define RTW_DEBUG_OACTIVE 0x2000000 -#define RTW_DEBUG_MAX 0x3ffffff - -extern int rtw_debug; -#define RTW_DPRINTF(__flags, __x) \ - if ((rtw_debug & (__flags)) != 0) kprintf __x -#define DPRINTF(__sc, __flags, __x) \ - if (((__sc)->sc_if.if_flags & IFF_DEBUG) != 0) \ - RTW_DPRINTF(__flags, __x) -#define RTW_PRINT_REGS(__regs, __dvname, __where) \ - rtw_print_regs((__regs), (__dvname), (__where)) -#else /* RTW_DEBUG */ -#define RTW_DPRINTF(__flags, __x) -#define DPRINTF(__sc, __flags, __x) -#define RTW_PRINT_REGS(__regs, __dvname, __where) -#endif /* RTW_DEBUG */ - -enum rtw_locale { - RTW_LOCALE_USA = 0, - RTW_LOCALE_EUROPE, - RTW_LOCALE_JAPAN, - RTW_LOCALE_UNKNOWN -}; - -enum rtw_rfchipid { - RTW_RFCHIPID_RESERVED = 0, - RTW_RFCHIPID_INTERSIL = 1, - RTW_RFCHIPID_RFMD = 2, - RTW_RFCHIPID_PHILIPS = 3, - RTW_RFCHIPID_MAXIM = 4, - RTW_RFCHIPID_GCT = 5 -}; - -/* sc_flags */ -#define RTW_F_ENABLED 0x00000001 /* chip is enabled */ -#define RTW_F_DIGPHY 0x00000002 /* digital PHY */ -#define RTW_F_DFLANTB 0x00000004 /* B antenna is default */ -#define RTW_F_ANTDIV 0x00000010 /* h/w antenna diversity */ -#define RTW_F_9356SROM 0x00000020 /* 93c56 SROM */ -#define RTW_F_SLEEP 0x00000040 /* chip is asleep */ -#define RTW_F_INVALID 0x00000080 /* chip is absent */ -#define RTW_F_DK_VALID 0x00000100 /* keys in DK0-DK3 are valid */ -#define RTW_C_RXWEP_40 0x00000200 /* h/w decrypts 40-bit WEP */ -#define RTW_C_RXWEP_104 0x00000400 /* h/w decrypts 104-bit WEP */ - /* all PHY flags */ -#define RTW_F_ALLPHY (RTW_F_DIGPHY|RTW_F_DFLANTB|RTW_F_ANTDIV) - -enum rtw_access { - RTW_ACCESS_NONE = 0, - RTW_ACCESS_CONFIG = 1, - RTW_ACCESS_ANAPARM = 2 -}; - -struct rtw_regs { - bus_space_tag_t r_bt; - bus_space_handle_t r_bh; - enum rtw_access r_access; - int r_type; - int r_rid; - struct resource *r_res; -}; - -#define RTW_SR_GET(sr, ofs) \ - (((sr)->sr_content[(ofs)/2] >> (((ofs) % 2 == 0) ? 0 : 8)) & 0xff) - -#define RTW_SR_GET16(sr, ofs) \ - (RTW_SR_GET((sr), (ofs)) | (RTW_SR_GET((sr), (ofs) + 1) << 8)) - -struct rtw_srom { - uint16_t *sr_content; - uint16_t sr_size; -}; - -struct rtw_rxsoft { - struct mbuf *rs_mbuf; - bus_dmamap_t rs_dmamap; - bus_addr_t rs_phyaddr; -}; - -struct rtw_txsoft { - STAILQ_ENTRY(rtw_txsoft) ts_q; - struct mbuf *ts_mbuf; - bus_dmamap_t ts_dmamap; - struct ieee80211_node *ts_ni; /* destination node */ - int ts_ratectl; - int ts_rateidx; - u_int ts_first; /* 1st hw descriptor */ - u_int ts_last; /* last hw descriptor */ - struct rtw_duration ts_d0; - struct rtw_duration ts_dn; -}; - -#define RTW_NTXPRI 4 /* number of Tx priorities */ -#define RTW_TXPRILO 0 -#define RTW_TXPRIMD 1 -#define RTW_TXPRIHI 2 -#define RTW_TXPRIBCN 3 /* beacon priority */ - -#define RTW_MAXPKTSEGS 64 /* Max 64 segments per Tx packet */ - -#define CASSERT(cond, complaint) \ - complaint[(cond) ? 0 : -1] = complaint[(cond) ? 0 : -1] - -/* - * Note well: the descriptor rings must begin on RTW_DESC_ALIGNMENT - * boundaries. I allocate them consecutively from one buffer, so - * just round up. - */ -#define RTW_TXQLENLO 64 /* low-priority queue length */ -#define RTW_TXQLENMD 64 /* medium-priority */ -#define RTW_TXQLENHI 64 /* high-priority */ -#define RTW_TXQLENBCN 8 /* beacon */ - -#define RTW_NTXDESCLO RTW_TXQLENLO -#define RTW_NTXDESCMD RTW_TXQLENMD -#define RTW_NTXDESCHI RTW_TXQLENHI -#define RTW_NTXDESCBCN RTW_TXQLENBCN - -#define RTW_NTXDESCTOTAL (RTW_NTXDESCLO + RTW_NTXDESCMD + \ - RTW_NTXDESCHI + RTW_NTXDESCBCN) - -#define RTW_RXQLEN 64 - -struct rtw_rxdesc_blk { - int rdb_ndesc; - int rdb_next; - - bus_dma_tag_t rdb_dmat; - bus_dmamap_t rdb_dmamap; - struct rtw_rxdesc *rdb_desc; - - uint32_t rdb_base; /* XXX bus_addr_t */ -}; - -struct rtw_txdesc_blk { - int tdb_ndesc; - int tdb_next; - int tdb_nfree; - - bus_dma_tag_t tdb_dmat; - bus_dmamap_t tdb_dmamap; - struct rtw_txdesc *tdb_desc; - - bus_size_t tdb_basereg; - uint32_t tdb_base; /* XXX bus_addr_t */ -}; - -#define RTW_NEXT_IDX(__htc, __idx) (((__idx) + 1) % (__htc)->tdb_ndesc) - -#define RTW_NEXT_DESC(__htc, __idx) \ - ((__htc)->tdb_base + \ - sizeof(struct rtw_txdesc) * RTW_NEXT_IDX((__htc), (__idx))) - -STAILQ_HEAD(rtw_txq, rtw_txsoft); - -struct rtw_txsoft_blk { - /* dirty/free s/w descriptors */ - struct rtw_txq tsb_dirtyq; - struct rtw_txq tsb_freeq; - u_int tsb_ndesc; - int tsb_tx_timer; - struct rtw_txsoft *tsb_desc; - uint8_t tsb_poll; -}; - -struct rtw_descs { - struct rtw_txdesc hd_txlo[RTW_NTXDESCLO]; - struct rtw_txdesc hd_txmd[RTW_NTXDESCMD]; - struct rtw_txdesc hd_txhi[RTW_NTXDESCMD]; - struct rtw_rxdesc hd_rx[RTW_RXQLEN]; - struct rtw_txdesc hd_bcn[RTW_NTXDESCBCN]; -}; -#define RTW_DESC_OFFSET(ring, i) offsetof(struct rtw_descs, ring[i]) -#define RTW_RING_OFFSET(ring) RTW_DESC_OFFSET(ring, 0) -#define RTW_RING_BASE(sc, ring) ((sc)->sc_desc_physaddr + \ - RTW_RING_OFFSET(ring)) - -/* Radio capture format for RTL8180. */ - -#define RTW_RX_RADIOTAP_PRESENT \ - ((1 << IEEE80211_RADIOTAP_TSFT) | \ - (1 << IEEE80211_RADIOTAP_FLAGS) | \ - (1 << IEEE80211_RADIOTAP_RATE) | \ - (1 << IEEE80211_RADIOTAP_CHANNEL) | \ - (1 << IEEE80211_RADIOTAP_LOCK_QUALITY) | \ - (1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL) | \ - 0) - -struct rtw_rx_radiotap_header { - struct ieee80211_radiotap_header rr_ihdr; - uint64_t rr_tsft; - uint8_t rr_flags; - uint8_t rr_rate; - uint16_t rr_chan_freq; - uint16_t rr_chan_flags; - uint16_t rr_barker_lock; - uint8_t rr_antsignal; -} __packed; - -#define RTW_TX_RADIOTAP_PRESENT \ - ((1 << IEEE80211_RADIOTAP_FLAGS) | \ - (1 << IEEE80211_RADIOTAP_RATE) | \ - (1 << IEEE80211_RADIOTAP_CHANNEL) | \ - 0) - -struct rtw_tx_radiotap_header { - struct ieee80211_radiotap_header rt_ihdr; - uint8_t rt_flags; - uint8_t rt_rate; - uint16_t rt_chan_freq; - uint16_t rt_chan_flags; -} __packed; - -enum rtw_attach_state {FINISHED, FINISH_DESCMAP_LOAD, FINISH_DESCMAP_CREATE, - FINISH_DESC_MAP, FINISH_DESC_ALLOC, FINISH_RXMAPS_CREATE, - FINISH_TXMAPS_CREATE, FINISH_RESET, FINISH_READ_SROM, FINISH_PARSE_SROM, - FINISH_RF_ATTACH, FINISH_ID_STA, FINISH_TXDESCBLK_SETUP, - FINISH_TXCTLBLK_SETUP, DETACHED}; - -struct rtw_hooks { - void *rh_shutdown; /* shutdown hook */ - void *rh_power; /* power management hook */ -}; - -struct rtw_mtbl { - int (*mt_newstate)(struct ieee80211com *, - enum ieee80211_state, int); - void (*mt_recv_mgmt)(struct ieee80211com *, - struct mbuf *, - struct ieee80211_node *, - int, int, uint32_t); - struct ieee80211_node *(*mt_node_alloc)(struct ieee80211_node_table*); - void (*mt_node_free)(struct ieee80211_node *); -}; - -enum rtw_pwrstate { RTW_OFF = 0, RTW_SLEEP, RTW_ON }; - -typedef void (*rtw_continuous_tx_cb_t)(void *arg, int); - -struct rtw_phy { - struct rtw_rf *p_rf; - struct rtw_regs *p_regs; -}; - -struct rtw_bbpset { - u_int bb_antatten; - u_int bb_chestlim; - u_int bb_chsqlim; - u_int bb_ifagcdet; - u_int bb_ifagcini; - u_int bb_ifagclimit; - u_int bb_lnadet; - u_int bb_sys1; - u_int bb_sys2; - u_int bb_sys3; - u_int bb_trl; - u_int bb_txagc; -}; - -struct rtw_rf { - void (*rf_destroy)(struct rtw_rf *); - /* args: frequency, txpower, power state */ - int (*rf_init)(struct rtw_rf *, u_int, uint8_t, - enum rtw_pwrstate); - /* arg: power state */ - int (*rf_pwrstate)(struct rtw_rf *, - enum rtw_pwrstate); - /* arg: frequency */ - int (*rf_tune)(struct rtw_rf *, u_int); - /* arg: txpower */ - int (*rf_txpower)(struct rtw_rf *, uint8_t); - rtw_continuous_tx_cb_t rf_continuous_tx_cb; - void *rf_continuous_tx_arg; - struct rtw_bbpset rf_bbpset; -}; - -static __inline void -rtw_rf_destroy(struct rtw_rf *rf) -{ - rf->rf_destroy(rf); -} - -static __inline int -rtw_rf_init(struct rtw_rf *rf, u_int freq, uint8_t opaque_txpower, - enum rtw_pwrstate power) -{ - return rf->rf_init(rf, freq, opaque_txpower, power); -} - -static __inline int -rtw_rf_pwrstate(struct rtw_rf *rf, enum rtw_pwrstate power) -{ - return rf->rf_pwrstate(rf, power); -} - -static __inline int -rtw_rf_tune(struct rtw_rf *rf, u_int freq) -{ - return rf->rf_tune(rf, freq); -} - -static __inline int -rtw_rf_txpower(struct rtw_rf *rf, uint8_t opaque_txpower) -{ - return rf->rf_txpower(rf, opaque_txpower); -} - -typedef int (*rtw_rf_write_t)(struct rtw_regs *, enum rtw_rfchipid, u_int, - uint32_t); - -struct rtw_rfbus { - struct rtw_regs *b_regs; - rtw_rf_write_t b_write; -}; - -static __inline int -rtw_rfbus_write(struct rtw_rfbus *bus, enum rtw_rfchipid rfchipid, u_int addr, - uint32_t val) -{ - return bus->b_write(bus->b_regs, rfchipid, addr, val); -} - -struct rtw_max2820 { - struct rtw_rf mx_rf; - struct rtw_rfbus mx_bus; - int mx_is_a; /* 1: MAX2820A/MAX2821A */ -}; - -struct rtw_grf5101 { - struct rtw_rf gr_rf; - struct rtw_rfbus gr_bus; -}; - -struct rtw_sa2400 { - struct rtw_rf sa_rf; - struct rtw_rfbus sa_bus; - int sa_digphy; /* 1: digital PHY */ -}; - -union rtw_keys { - uint8_t rk_keys[4][16]; - uint32_t rk_words[16]; -}; - -#define RTW_LED_SLOW_TICKS MAX(1, hz/2) -#define RTW_LED_FAST_TICKS MAX(1, hz/10) - -struct rtw_led_state { -#define RTW_LED0 0x1 -#define RTW_LED1 0x2 - uint8_t ls_slowblink:2; - uint8_t ls_actblink:2; - uint8_t ls_default:2; - uint8_t ls_state; - uint8_t ls_event; -#define RTW_LED_S_RX 0x1 -#define RTW_LED_S_TX 0x2 -#define RTW_LED_S_SLOW 0x4 - struct callout ls_slow_ch; - struct callout ls_fast_ch; -}; - -struct rtw_softc { - struct ieee80211com sc_ic; - struct rtw_regs sc_regs; - uint32_t sc_flags; - - struct resource *sc_irq_res; - int sc_irq_rid; - void *sc_irq_handle; - - enum rtw_rfchipid sc_rfchipid; - enum rtw_locale sc_locale; - uint8_t sc_phydelay; - - /* s/w Tx/Rx descriptors */ - bus_dma_tag_t sc_txsoft_dmat; - struct rtw_txsoft_blk sc_txsoft_blk[RTW_NTXPRI]; - struct rtw_txdesc_blk sc_txdesc_blk[RTW_NTXPRI]; - - int sc_rxsoft_free; - bus_dmamap_t sc_rxsoft_dmamap; - bus_dma_tag_t sc_rxsoft_dmat; - struct rtw_rxsoft sc_rxsoft[RTW_RXQLEN]; - struct rtw_rxdesc_blk sc_rxdesc_blk; - - struct rtw_srom sc_srom; - - enum rtw_pwrstate sc_pwrstate; - - void (*sc_pwrstate_cb) - (struct rtw_regs *, enum rtw_pwrstate, - int, int); - - int (*sc_getrssi)(uint8_t, uint8_t); - - struct rtw_rf *sc_rf; - - uint16_t sc_inten; - - /* interrupt acknowledge hook */ - void (*sc_intr_ack)(struct rtw_regs *); - - void (*sc_power)(struct rtw_softc *, int); - struct rtw_mtbl sc_mtbl; - struct rtw_hooks sc_hooks; - - struct bpf_if *sc_radiobpf; - - struct callout sc_scan_ch; - u_int sc_cur_chan; - - uint32_t sc_tsfth; /* most significant TSFT bits */ - uint32_t sc_rcr; /* RTW_RCR */ - uint8_t sc_csthr; /* carrier-sense threshold */ - - int sc_do_tick; /* indicate 1s ticks */ - struct timeval sc_tick0; /* first tick */ - - uint8_t sc_rev; /* PCI/Cardbus revision */ - - uint32_t sc_anaparm; /* register RTW_ANAPARM */ - - union { - struct rtw_rx_radiotap_header tap; - uint8_t pad[64]; - } sc_rxtapu; - union { - struct rtw_tx_radiotap_header tap; - uint8_t pad[64]; - } sc_txtapu; - union rtw_keys sc_keys; - struct ifqueue sc_beaconq; - struct rtw_led_state sc_led_state; - int sc_hwverid; - struct ieee80211_onoe_param sc_onoe_param; -}; - -#define sc_if sc_ic.ic_if -#define sc_rxtap sc_rxtapu.tap -#define sc_txtap sc_txtapu.tap - -extern devclass_t rtw_devclass; - -#if 0 -void rtw_txdac_enable(struct rtw_softc *, int); -void rtw_anaparm_enable(struct rtw_regs *, int); -void rtw_config0123_enable(struct rtw_regs *, int); -void rtw_continuous_tx_enable(struct rtw_softc *, int); -void rtw_set_access(struct rtw_regs *, enum rtw_access); -#endif - -int rtw_attach(device_t); -int rtw_detach(device_t); -void rtw_stop(struct rtw_softc *, int); -#ifdef RTW_DEBUG -const char *rtw_pwrstate_string(enum rtw_pwrstate); -#endif - -#endif /* _DEV_IC_RTWVAR_H_ */ diff --git a/sys/dev/netif/rtw/sa2400reg.h b/sys/dev/netif/rtw/sa2400reg.h deleted file mode 100644 index 1e208c4d37..0000000000 --- a/sys/dev/netif/rtw/sa2400reg.h +++ /dev/null @@ -1,284 +0,0 @@ -/* - * Copyright (c) 2005 David Young. All rights reserved. - * - * This code was written by David Young. - * - * 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. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY David Young ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL David - * Young BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 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 DAMAGE. - * - * $NetBSD: sa2400reg.h,v 1.6 2006/03/08 08:26:50 dyoung Exp $ - * $DragonFly: src/sys/dev/netif/rtw/sa2400reg.h,v 1.3 2007/10/14 04:15:17 sephe Exp $ - */ - -#ifndef _DEV_IC_SA2400REG_H_ -#define _DEV_IC_SA2400REG_H_ - -/* - * Serial bus format for Philips SA2400 Single-chip Transceiver. - */ -#define SA2400_TWI_DATA_MASK __BITS(31,8) -#define SA2400_TWI_WREN __BIT(7) /* enable write */ -#define SA2400_TWI_ADDR_MASK __BITS(6,0) - -/* - * Registers for Philips SA2400 Single-chip Transceiver. - */ -#define SA2400_SYNA 0 /* Synthesizer Register A */ -#define SA2400_SYNA_FM __BIT(21) /* fractional modulus select, - * 0: /8 (default) - * 1: /5 - */ -#define SA2400_SYNA_NF_MASK __BITS(20,18) /* fractional increment value, - * 0 to 7, default 4 - */ -#define SA2400_SYNA_N_MASK __BITS(17,2) /* main divider division ratio, - * 512 to 65535, default 615 - */ - -#define SA2400_SYNB 1 /* Synthesizer Register B */ -#define SA2400_SYNB_R_MASK __BITS(21,12) /* reference divider ratio, - * 4 to 1023, default 11 - */ -#define SA2400_SYNB_L_MASK __BITS(11,10) /* lock detect mode */ -#define SA2400_SYNB_L_INACTIVE0 __SHIFTIN(0, SA2400_SYNB_L_MASK) -#define SA2400_SYNB_L_INACTIVE1 __SHIFTIN(1, SA2400_SYNB_L_MASK) -#define SA2400_SYNB_L_NORMAL __SHIFTIN(2, SA2400_SYNB_L_MASK) -#define SA2400_SYNB_L_INACTIVE2 __SHIFTIN(3, SA2400_SYNB_L_MASK) - -#define SA2400_SYNB_ON __BIT(9) /* power on/off, - * 0: inverted chip mode control - * 1: as defined by chip mode - * (see SA2400_OPMODE) - */ -#define SA2400_SYNB_ONE __BIT(8) /* always 1 */ -#define SA2400_SYNB_FC_MASK __BITS(7,0) /* fractional compensation - * charge pump current DAC, - * 0 to 255, default 80. - */ - -#define SA2400_SYNC 2 /* Synthesizer Register C */ -#define SA2400_SYNC_CP_MASK __BITS(7,6) /* charge pump current - * setting - */ -#define SA2400_SYNC_CP_NORMAL_ __SHIFTIN(0, SA2400_SYNC_CP_MASK) -#define SA2400_SYNC_CP_THIRD_ __SHIFTIN(1, SA2400_SYNC_CP_MASK) -#define SA2400_SYNC_CP_NORMAL __SHIFTIN(2, SA2400_SYNC_CP_MASK) /* recommended */ -#define SA2400_SYNC_CP_THIRD __SHIFTIN(3, SA2400_SYNC_CP_MASK) - -#define SA2400_SYNC_SM_MASK __BITS(5,3) /* comparison divider select, - * 0 to 4, extra division - * ratio is 2**SM. - */ -#define SA2400_SYNC_ZERO __BIT(2) /* always 0 */ - -#define SA2400_SYND 3 /* Synthesizer Register D */ -#define SA2400_SYND_ZERO1_MASK __BITS(21,17) /* always 0 */ -#define SA2400_SYND_TPHPSU __BIT(16) /* T[phpsu], 1: disable - * PHP speedup pump, - * overrides SA2400_SYND_TSPU - */ -#define SA2400_SYND_TPSU __BIT(15) /* T[spu], 1: speedup on, - * 0: speedup off - */ -#define SA2400_SYND_ZERO2_MASK __BITS(14,3) /* always 0 */ - -#define SA2400_OPMODE 4 /* Operating mode, filter tuner, - * other controls - */ -/* 1: in Rx mode, RSSI-ADC always on 0: RSSI-ADC only on during AGC */ -#define SA2400_OPMODE_ADC __BIT(19) -/* read-only filter tuner error: 1 if tuner out of range */ -#define SA2400_OPMODE_FTERR __BIT(18) -/* Rx & Tx filter tuning, write tuning value (test mode only) or - * read tuner setting (in normal mode). - */ -#define SA2400_OPMODE_FILTTUNE_MASK __BITS(17,15) - -/* external reference voltage (pad v2p5) on */ -#define SA2400_OPMODE_V2P5 __BIT(14) -/* external reference current ... */ -#define SA2400_OPMODE_I1M __BIT(13) -/* external reference current ... */ -#define SA2400_OPMODE_I0P3 __BIT(12) -#define SA2400_OPMODE_IN22 __BIT(10) /* xtal input frequency, - * 0: 44 MHz - * 1: 22 MHz - */ -#define SA2400_OPMODE_CLK __BIT(9) /* reference clock output on */ -#define SA2400_OPMODE_XO __BIT(8) /* xtal oscillator on */ -#define SA2400_OPMODE_DIGIN __BIT(7) /* use digital Tx inputs - * (FIRDAC) - */ -#define SA2400_OPMODE_RXLV __BIT(6) /* Rx output common mode - * voltage, - * 0: V[DD]/2 - * 1: 1.25V - */ -#define SA2400_OPMODE_VEO __BIT(5) /* make internal vco - * available at vco pads - * (vcoextout) - */ -#define SA2400_OPMODE_VEI __BIT(4) /* use external vco input - * (vcoextin) - */ -/* main operating mode */ -#define SA2400_OPMODE_MODE_MASK __BITS(3,0) -#define SA2400_OPMODE_MODE_SLEEP __SHIFTIN(0, SA2400_OPMODE_MODE_MASK) -#define SA2400_OPMODE_MODE_TXRX __SHIFTIN(1, SA2400_OPMODE_MODE_MASK) -#define SA2400_OPMODE_MODE_WAIT __SHIFTIN(2, SA2400_OPMODE_MODE_MASK) -#define SA2400_OPMODE_MODE_RXMGC __SHIFTIN(3, SA2400_OPMODE_MODE_MASK) -#define SA2400_OPMODE_MODE_FCALIB __SHIFTIN(4, SA2400_OPMODE_MODE_MASK) -#define SA2400_OPMODE_MODE_DCALIB __SHIFTIN(5, SA2400_OPMODE_MODE_MASK) -#define SA2400_OPMODE_MODE_FASTTXRXMGC __SHIFTIN(6, SA2400_OPMODE_MODE_MASK) -#define SA2400_OPMODE_MODE_RESET __SHIFTIN(7, SA2400_OPMODE_MODE_MASK) -#define SA2400_OPMODE_MODE_VCOCALIB __SHIFTIN(8, SA2400_OPMODE_MODE_MASK) - -#define SA2400_OPMODE_DEFAULTS \ - (SA2400_OPMODE_XO | SA2400_OPMODE_RXLV | SA2400_OPMODE_CLK | \ - SA2400_OPMODE_I0P3 | __SHIFTIN(3, SA2400_OPMODE_FILTTUNE_MASK)) - -#define SA2400_AGC 5 /* AGC adjustment */ -#define SA2400_AGC_TARGETSIGN __BIT(23) /* fine-tune AGC target: - * -7dB to 7dB, sign bit ... */ -#define SA2400_AGC_TARGET_MASK __BITS(22,20) /* ... plus 0dB - 7dB */ -#define SA2400_AGC_MAXGAIN_MASK __BITS(19,15) /* maximum AGC gain, 0 to 31, - * (yields 54dB to 85dB) - */ -/* write: settling time after baseband gain switching, units of - * 182 nanoseconds. - * read: output of RSSI/Tx-peak detector's ADC in 5-bit Gray code. - */ -#define SA2400_AGC_BBPDELAY_MASK __BITS(14,10) -#define SA2400_AGC_ADCVAL_MASK SA2400_AGC_BBPDELAY_MASK - -/* write: settling time after LNA gain switching, units of - * 182 nanoseconds - * read: 2nd sample of RSSI in AGC cycle - */ -#define SA2400_AGC_LNADELAY_MASK __BITS(9,5) -#define SA2400_AGC_SAMPLE2_MASK SA2400_AGC_LNADELAY_MASK - -/* write: time between turning on Rx and AGCSET, units of - * 182 nanoseconds - * read: 1st sample of RSSI in AGC cycle - */ -#define SA2400_AGC_RXONDELAY_MASK __BITS(4,0) -#define SA2400_AGC_SAMPLE1_MASK SA2400_AGC_RXONDELAY_MASK - -#define SA2400_MANRX 6 /* Manual receiver control settings */ -#define SA2400_MANRX_AHSN __BIT(23) /* 1: AGC w/ high S/N---switch - * LNA at step 52 - * (recommended) - * 0: switch LNA at step 60 - */ - -/* If _RXOSQON, Q offset is - * (_RXOSQSIGN ? -1 : 1) * (1 + _RXOSQ_MASK) * 8 millivolts, - * otherwise, Q offset is 0. - * - * Ditto I offset. - */ -#define SA2400_MANRX_RXOSQON __BIT(22) /* Rx Q-channel correction. */ -#define SA2400_MANRX_RXOSQSIGN __BIT(21) -#define SA2400_MANRX_RXOSQ_MASK __BITS(20,18) - -#define SA2400_MANRX_RXOSION __BIT(17) /* Rx I-channel correction. */ -#define SA2400_MANRX_RXOSISIGN __BIT(16) -#define SA2400_MANRX_RXOSI_MASK __BITS(15,13) -#define SA2400_MANRX_TEN __BIT(12) /* use 10MHz offset cancellation - * cornerpoint for brief period - * after each gain change - */ - -/* DC offset cancellation cornerpoint select - * write: in RXMGC, set the cornerpoint - * read: in other modes, read AGC-controlled cornerpoint - */ -#define SA2400_MANRX_CORNERFREQ_MASK __BITS(11,10) - -/* write: in RXMGC mode, sets receiver gain - * read: in other modes, read AGC-controlled gain - */ -#define SA2400_MANRX_RXGAIN_MASK __BITS(9,0) - -#define SA2400_TX 7 /* Transmitter settings */ -/* Tx offsets - * - * write: in test mode, sets the offsets - * read: in normal mode, returns automatic settings - */ -#define SA2400_TX_TXOSQON __BIT(19) -#define SA2400_TX_TXOSQSIGN __BIT(18) -#define SA2400_TX_TXOSQ_MASK __BITS(17,15) -#define SA2400_TX_TXOSION __BIT(14) -#define SA2400_TX_TXOSISIGN __BIT(13) -#define SA2400_TX_TXOSI_MASK __BITS(12,10) - -#define SA2400_TX_RAMP_MASK __BITS(9,8) /* Ramp-up delay, - * 0: 1us - * 1: 2us - * 2: 3us - * 3: 4us - * datasheet says, "ramp-up - * time always 1us". huh? - */ -#define SA2400_TX_HIGAIN_MASK __BITS(7,4) /* Transmitter gain settings - * for TXHI output - */ -#define SA2400_TX_LOGAIN_MASK __BITS(3,0) /* Transmitter gain settings - * for TXLO output - */ - -#define SA2400_VCO 8 /* VCO settings */ -#define SA2400_VCO_ZERO __BITS(6,5) /* always zero */ -#define SA2400_VCO_VCERR __BIT(4)/* VCO calibration error flag---no - * band with low enough frequency - * could be found - */ -#define SA2400_VCO_VCOBAND_MASK __BITS(3,0) /* VCO band, - * write: in test mode, sets - * VCO band - * read: in normal mode, - * the result of - * calibration (VCOCAL). - * 0 = highest - * frequencies - */ - -#define SA2400_SQ_RSSI_MAP \ - 0x64, 0x64, 0x63, 0x62, 0x61, 0x60, 0x5f, 0x5e, \ - 0x5d, 0x5c, 0x5b, 0x5a, 0x57, 0x54, 0x52, 0x50, \ - 0x4e, 0x4c, 0x4a, 0x48, 0x46, 0x44, 0x41, 0x3f, \ - 0x3c, 0x3a, 0x37, 0x36, 0x36, 0x1c, 0x1c, 0x1b, \ - 0x1b, 0x1a, 0x1a, 0x19, 0x19, 0x18, 0x18, 0x17, \ - 0x17, 0x16, 0x16, 0x15, 0x15, 0x14, 0x14, 0x13, \ - 0x13, 0x12, 0x12, 0x11, 0x11, 0x10, 0x10, 0x0f, \ - 0x0f, 0x0e, 0x0e, 0x0d, 0x0d, 0x0c, 0x0c, 0x0b, \ - 0x0b, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x07, \ - 0x07, 0x06, 0x06, 0x05, 0x04, 0x03, 0x02, 0x00 - -#define SA2400_SQ_RSSI_MAP_MAX 80 - -#endif /* _DEV_IC_SA2400REG_H_ */ diff --git a/sys/dev/netif/rtw/si4136reg.h b/sys/dev/netif/rtw/si4136reg.h deleted file mode 100644 index 7a206d2078..0000000000 --- a/sys/dev/netif/rtw/si4136reg.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2005 David Young. All rights reserved. - * - * This code was written by David Young. - * - * 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. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY David Young ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL David - * Young BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 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 DAMAGE. - * - * $NetBSD: si4136reg.h,v 1.4 2006/03/08 08:26:50 dyoung Exp $ - * $DragonFly: src/sys/dev/netif/rtw/si4136reg.h,v 1.2 2007/10/14 04:15:17 sephe Exp $ - */ - -#ifndef _DEV_IC_SI4136REG_H_ -#define _DEV_IC_SI4136REG_H_ - -/* - * Serial bus format for Silicon Laboratories Si4126/Si4136 RF synthesizer. - */ -#define SI4126_TWI_DATA_MASK __BITS(21, 4) -#define SI4126_TWI_ADDR_MASK __BITS(3, 0) - -/* - * Registers for Silicon Laboratories Si4126/Si4136 RF synthesizer. - */ -#define SI4126_MAIN 0 /* main configuration */ -#define SI4126_MAIN_AUXSEL_MASK __BITS(13, 12) /* aux. output pin function */ -/* reserved */ -#define SI4126_MAIN_AUXSEL_RSVD __SHIFTIN(0x0, SI4126_MAIN_AUXSEL_MASK) -/* force low */ -#define SI4126_MAIN_AUXSEL_FRCLOW __SHIFTIN(0x1, SI4126_MAIN_AUXSEL_MASK) -/* Lock Detect (LDETB) */ -#define SI4126_MAIN_AUXSEL_LDETB __SHIFTIN(0x3, SI4126_MAIN_AUXSEL_MASK) - -#define SI4126_MAIN_IFDIV_MASK __BITS(11, 10) /* IFOUT = IFVCO - * frequency / 2**IFDIV. - */ - -/* 1: divide crystal input (XIN) by 2 */ -#define SI4126_MAIN_XINDIV2 __BIT(6) -#define SI4126_MAIN_LPWR __BIT(5) /* 1: low-power mode */ -#define SI4126_MAIN_AUTOPDB __BIT(3) /* 1: equivalent to - * reg[SI4126_POWER] <- - * SI4126_POWER_PDIB | - * SI4126_POWER_PDRB. - * - * 0: power-down under control - * of reg[SI4126_POWER]. - */ - -#define SI4126_GAIN 1 /* phase detector gain */ -#define SI4126_GAIN_KPI_MASK __BITS(5, 4) /* IF phase detector gain */ -#define SI4126_GAIN_KP2_MASK __BITS(3, 2) /* RF2 phase detector gain */ -#define SI4126_GAIN_KP1_MASK __BITS(1, 0) /* RF1 phase detector gain */ - -#define SI4126_POWER 2 /* powerdown */ -#define SI4126_POWER_PDIB __BIT(1) /* 1: IF synthesizer on */ -#define SI4126_POWER_PDRB __BIT(0) /* 1: RF synthesizer on */ - -#define SI4126_RF1N 3 /* RF1 N divider */ -#define SI4126_RF2N 4 /* RF2 N divider */ -#define SI4126_IFN 5 /* IF N divider */ -#define SI4126_RF1R 6 /* RF1 R divider */ -#define SI4126_RF2R 7 /* RF2 R divider */ -#define SI4126_IFR 8 /* IF R divider */ - -#endif /* _DEV_IC_SI4136REG_H_ */ diff --git a/sys/dev/netif/rtw/smc93cx6.c b/sys/dev/netif/rtw/smc93cx6.c deleted file mode 100644 index b19a0a9ec3..0000000000 --- a/sys/dev/netif/rtw/smc93cx6.c +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Interface for the 93C66/56/46/26/06 serial eeprom parts. - * - * Copyright (c) 1995, 1996 Daniel M. Eischen - * 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 immediately at the beginning of the file, without modification, - * this list of conditions, and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Absolutely no warranty of function or purpose is made by the author - * Daniel M. Eischen. - * 4. Modifications may be freely made to this file if the above conditions - * are met. - * - * $FreeBSD: src/sys/dev/aic7xxx/93cx6.c,v 1.5 2000/01/07 23:08:17 gibbs Exp $ - * $NetBSD: smc93cx6.c,v 1.12 2005/12/11 12:21:28 christos Exp $ - * $DragonFly: src/sys/dev/netif/rtw/smc93cx6.c,v 1.5 2007/10/14 04:15:17 sephe Exp $ - */ - -/* - * The instruction set of the 93C66/56/46/26/06 chips are as follows: - * - * Start OP * - * Function Bit Code Address** Data Description - * ------------------------------------------------------------------- - * READ 1 10 A5 - A0 Reads data stored in memory, - * starting at specified address - * EWEN 1 00 11XXXX Write enable must precede - * all programming modes - * ERASE 1 11 A5 - A0 Erase register A5A4A3A2A1A0 - * WRITE 1 01 A5 - A0 D15 - D0 Writes register - * ERAL 1 00 10XXXX Erase all registers - * WRAL 1 00 01XXXX D15 - D0 Writes to all registers - * EWDS 1 00 00XXXX Disables all programming - * instructions - * *Note: A value of X for address is a don't care condition. - * **Note: There are 8 address bits for the 93C56/66 chips unlike - * the 93C46/26/06 chips which have 6 address bits. - * - * The 93C46 has a four wire interface: clock, chip select, data in, and - * data out. In order to perform one of the above functions, you need - * to enable the chip select for a clock period (typically a minimum of - * 1 usec, with the clock high and low a minimum of 750 and 250 nsec - * respectively). While the chip select remains high, you can clock in - * the instructions (above) starting with the start bit, followed by the - * OP code, Address, and Data (if needed). For the READ instruction, the - * requested 16-bit register contents is read from the data out line but - * is preceded by an initial zero (leading 0, followed by 16-bits, MSB - * first). The clock cycling from low to high initiates the next data - * bit to be sent from the chip. - * - */ - -#include "opt_aic7xxx.h" - -#include -#include -#include - -#include - -/* - * Right now, we only have to read the SEEPROM. But we make it easier to - * add other 93Cx6 functions. - */ -static struct seeprom_cmd { - unsigned char len; - unsigned char bits[3]; -} seeprom_read = {3, {1, 1, 0}}; - -/* XXX bus barriers */ -#define CLOCK_PULSE(sd, rdy) do { \ - /* \ - * Wait for the SEERDY to go high; about 800 ns. \ - */ \ - int cpi = 1000; \ - if (rdy == 0) { \ - DELAY(4); /* more than long enough */ \ - break; \ - } \ - while ((SEEPROM_STATUS_INB(sd) & rdy) == 0 && cpi-- > 0) { \ - ; /* Do nothing */ \ - } \ - (void)SEEPROM_INB(sd); /* Clear clock */ \ -} while (0) - -/* - * Read the serial EEPROM and returns 1 if successful and 0 if - * not successful. - */ -int -read_seeprom(struct seeprom_descriptor *sd, u_int16_t *buf, - bus_size_t start_addr, bus_size_t count) -{ - int i = 0; - u_int k = 0; - u_int16_t v; - u_int32_t temp; - - /* - * Read the requested registers of the seeprom. The loop - * will range from 0 to count-1. - */ - for (k = start_addr; k < count + start_addr; k++) { - /* Send chip select for one clock cycle. */ - temp = sd->sd_MS ^ sd->sd_CS; - SEEPROM_OUTB(sd, temp ^ sd->sd_CK); - CLOCK_PULSE(sd, sd->sd_RDY); - - /* - * Now we're ready to send the read command followed by the - * address of the 16-bit register we want to read. - */ - for (i = 0; i < seeprom_read.len; i++) { - if (seeprom_read.bits[i] != 0) - temp ^= sd->sd_DO; - SEEPROM_OUTB(sd, temp); - CLOCK_PULSE(sd, sd->sd_RDY); - SEEPROM_OUTB(sd, temp ^ sd->sd_CK); - CLOCK_PULSE(sd, sd->sd_RDY); - if (seeprom_read.bits[i] != 0) - temp ^= sd->sd_DO; - } - /* Send the 6 or 8 bit address (MSB first, LSB last). */ - for (i = (sd->sd_chip - 1); i >= 0; i--) { - if ((k & (1 << i)) != 0) - temp ^= sd->sd_DO; - SEEPROM_OUTB(sd, temp); - CLOCK_PULSE(sd, sd->sd_RDY); - SEEPROM_OUTB(sd, temp ^ sd->sd_CK); - CLOCK_PULSE(sd, sd->sd_RDY); - if ((k & (1 << i)) != 0) - temp ^= sd->sd_DO; - } - - /* - * Now read the 16 bit register. An initial 0 precedes the - * register contents which begins with bit 15 (MSB) and ends - * with bit 0 (LSB). The initial 0 will be shifted off the - * top of our word as we let the loop run from 0 to 16. - */ - v = 0; - for (i = 16; i >= 0; i--) { - SEEPROM_OUTB(sd, temp); - CLOCK_PULSE(sd, sd->sd_RDY); - v <<= 1; - if (SEEPROM_DATA_INB(sd) & sd->sd_DI) - v |= 1; - SEEPROM_OUTB(sd, temp ^ sd->sd_CK); - CLOCK_PULSE(sd, sd->sd_RDY); - } - - buf[k - start_addr] = v; - - /* Reset the chip select for the next command cycle. */ - temp = sd->sd_MS; - SEEPROM_OUTB(sd, temp); - CLOCK_PULSE(sd, sd->sd_RDY); - SEEPROM_OUTB(sd, temp ^ sd->sd_CK); - CLOCK_PULSE(sd, sd->sd_RDY); - SEEPROM_OUTB(sd, temp); - CLOCK_PULSE(sd, sd->sd_RDY); - } -#ifdef AHC_DUMP_EEPROM - kprintf("\nSerial EEPROM:\n\t"); - for (k = 0; k < count; k = k + 1) { - if (((k % 8) == 0) && (k != 0)) { - kprintf ("\n\t"); - } - kprintf (" 0x%x", buf[k]); - } - kprintf ("\n"); -#endif - return (1); -} diff --git a/sys/dev/netif/rtw/smc93cx6var.h b/sys/dev/netif/rtw/smc93cx6var.h deleted file mode 100644 index b6a5d19d49..0000000000 --- a/sys/dev/netif/rtw/smc93cx6var.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Interface to the 93C46 serial EEPROM that is used to store BIOS - * settings for the aic7xxx based adaptec SCSI controllers. It can - * also be used for 93C26 and 93C06 serial EEPROMS. - * - * Copyright (c) 1994, 1995 Justin T. Gibbs. - * 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. The name of the author may not 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 - * the GNU Public License ("GPL"). - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, 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 DAMAGE. - * - * $FreeBSD: src/sys/dev/aic7xxx/aic7xxx.c,v 1.40 2000/01/07 23:08:17 gibbs Exp $ - * $NetBSD: smc93cx6var.h,v 1.9 2005/12/11 12:21:28 christos Exp $ - * $DragonFly: src/sys/dev/netif/rtw/smc93cx6var.h,v 1.1 2006/09/03 07:37:58 sephe Exp $ - */ - -typedef enum { - C46 = 6, - C56_66 = 8 -} seeprom_chip_t; - -struct seeprom_descriptor { - bus_space_tag_t sd_tag; - bus_space_handle_t sd_bsh; - bus_size_t sd_regsize; - bus_size_t sd_control_offset; - bus_size_t sd_status_offset; - bus_size_t sd_dataout_offset; - seeprom_chip_t sd_chip; - uint32_t sd_MS; - uint32_t sd_RDY; - uint32_t sd_CS; - uint32_t sd_CK; - uint32_t sd_DO; - uint32_t sd_DI; -}; - -/* - * This function will read count 16-bit words from the serial EEPROM and - * return their value in buf. The port address of the aic7xxx serial EEPROM - * control register is passed in as offset. The following parameters are - * also passed in: - * - * CS - Chip select - * CK - Clock - * DO - Data out - * DI - Data in - * RDY - SEEPROM ready - * MS - Memory port mode select - * - * A failed read attempt returns 0, and a successful read returns 1. - */ - -/* XXX bus barriers */ -#define SEEPROM_INB(sd) \ - (((sd)->sd_regsize == 4) \ - ? bus_space_read_4((sd)->sd_tag, (sd)->sd_bsh, \ - (sd)->sd_control_offset) \ - : bus_space_read_1((sd)->sd_tag, (sd)->sd_bsh, \ - (sd)->sd_control_offset)) - -#define SEEPROM_OUTB(sd, value) do { \ - if ((sd)->sd_regsize == 4) \ - bus_space_write_4((sd)->sd_tag, (sd)->sd_bsh, \ - (sd)->sd_control_offset, (value)); \ - else \ - bus_space_write_1((sd)->sd_tag, (sd)->sd_bsh, \ - (sd)->sd_control_offset, (u_int8_t) (value)); \ -} while (0) - -#define SEEPROM_STATUS_INB(sd) \ - (((sd)->sd_regsize == 4) \ - ? bus_space_read_4((sd)->sd_tag, (sd)->sd_bsh, \ - (sd)->sd_status_offset) \ - : bus_space_read_1((sd)->sd_tag, (sd)->sd_bsh, \ - (sd)->sd_status_offset)) - -#define SEEPROM_DATA_INB(sd) \ - (((sd)->sd_regsize == 4) \ - ? bus_space_read_4((sd)->sd_tag, (sd)->sd_bsh, \ - (sd)->sd_dataout_offset) \ - : bus_space_read_1((sd)->sd_tag, (sd)->sd_bsh, \ - (sd)->sd_dataout_offset)) - -int read_seeprom(struct seeprom_descriptor *, uint16_t *, bus_size_t, - bus_size_t); -- 2.41.0