rtwn(4), urtwn(4): merge common code, add support for 11ac devices.

All devices:
- add support for rate adaptation via ieee80211_amrr(9);
- use short preamble for transmitted frames when needed;
- multi-bss support:
 * for RTL8821AU: 2 VAPs at the same time;
 * other: 1 any VAP + 1 sta VAP.
RTL8188CE:
- fix IQ calibration bug (reason of significant speed degradation);
- add h/w crypto acceleration support.
USB:
- A-MPDU Tx support;
- short GI support;
Other:
- add support for RTL8812AU / RTL8821AU chipsets
(a/b/g/n only; no ac yet);
- split merged code into subparts:
 * bus glue (usb/*, pci/*, rtl*/usb/*, rtl*/pci/*)
 * common (if_rtwn*)
 * chip-specific (rtl*/*)
- various other bugfixes.

Due to code reorganization, module names / requirements were changed too:
urtwn urtwnfw -> rtwn rtwn_usb rtwnfw
rtwn  rtwnfw  -> rtwn rtwn_pci rtwnfw

Tested with RTL8188CE, RTL8188CUS, RTL8188EU and RTL8821AU.

Tested by:	kevlo, garga,
		Peter Garshtja <peter.garshtja@ambient-md.com>,
		Kevin McAleavey <kevin.mcaleavey@knosproject.com>,
		Ilias-Dimitrios Vrachnis <id@vrachnis.com>,
		<otacilio.neto@bsd.com.br>
Relnotes:	yes
This commit is contained in:
Andriy Voskoboinyk 2016-10-17 20:38:24 +00:00
parent a1a604ca90
commit 7453645f2a
201 changed files with 28772 additions and 14591 deletions

View File

@ -38,6 +38,9 @@
# xargs -n1 | sort | uniq -d;
# done
# 20161016: urtwn(4) was merged into rtwn(4)
OLD_FILES+=usr/share/man/man4/urtwn.4.gz
OLD_FILES+=usr/share/man/man4/urtwnfw.4.gz
# 20161015: Remove GNU rcs
OLD_FILES+=usr/bin/ci
OLD_FILES+=usr/bin/co

View File

@ -24,7 +24,7 @@ options {
[0-9]+";
set wifi-driver-regex
"(ath|bwi|bwn|ipw|iwi|iwm|iwn|malo|mwl|ral|rsu|rum|run|uath|\
upgt|ural|urtw|urtwn|wi|wpi|wtap|zyd)[0-9]+";
upgt|ural|urtw|rtwn_usb|wi|wpi|wtap|zyd)[0-9]+";
};
# Note that the attach/detach with the highest value wins, so that one can

View File

@ -181,6 +181,14 @@ nomatch 32 {
action "kldload -n if_otus";
};
nomatch 32 {
match "bus" "uhub[0-9]+";
match "mode" "host";
match "vendor" "0x0409";
match "product" "0x0408";
action "kldload -n if_rtwn_usb";
};
nomatch 32 {
match "bus" "uhub[0-9]+";
match "mode" "host";
@ -301,6 +309,14 @@ nomatch 32 {
action "kldload -n if_run";
};
nomatch 32 {
match "bus" "uhub[0-9]+";
match "mode" "host";
match "vendor" "0x0411";
match "product" "(0x0242|0x025d)";
action "kldload -n if_rtwn_usb";
};
nomatch 32 {
match "bus" "uhub[0-9]+";
match "mode" "host";
@ -549,6 +565,14 @@ nomatch 32 {
action "kldload -n if_run";
};
nomatch 32 {
match "bus" "uhub[0-9]+";
match "mode" "host";
match "vendor" "0x04bb";
match "product" "0x0952";
action "kldload -n if_rtwn_usb";
};
nomatch 32 {
match "bus" "uhub[0-9]+";
match "mode" "host";
@ -682,7 +706,7 @@ nomatch 32 {
match "mode" "host";
match "vendor" "0x04f2";
match "product" "(0xaff7|0xaff8|0xaff9|0xaffa|0xaffa)";
action "kldload -n if_urtwn";
action "kldload -n if_rtwn_usb";
};
nomatch 32 {
@ -754,7 +778,7 @@ nomatch 32 {
match "mode" "host";
match "vendor" "0x050d";
match "product" "0x1102";
action "kldload -n if_urtwn";
action "kldload -n if_rtwn_usb";
};
nomatch 32 {
@ -778,7 +802,7 @@ nomatch 32 {
match "mode" "host";
match "vendor" "0x050d";
match "product" "(0x2102|0x2103)";
action "kldload -n if_urtwn";
action "kldload -n if_rtwn_usb";
};
nomatch 32 {
@ -1050,7 +1074,7 @@ nomatch 32 {
match "mode" "host";
match "vendor" "0x056e";
match "product" "0x4008";
action "kldload -n if_urtwn";
action "kldload -n if_rtwn_usb";
};
nomatch 32 {
@ -1146,7 +1170,7 @@ nomatch 32 {
match "mode" "host";
match "vendor" "0x0586";
match "product" "0x341f";
action "kldload -n if_urtwn";
action "kldload -n if_rtwn_usb";
};
nomatch 32 {
@ -1157,6 +1181,14 @@ nomatch 32 {
action "kldload -n if_run";
};
nomatch 32 {
match "bus" "uhub[0-9]+";
match "mode" "host";
match "vendor" "0x0586";
match "product" "0x3426";
action "kldload -n if_rtwn_usb";
};
nomatch 32 {
match "bus" "uhub[0-9]+";
match "mode" "host";
@ -1442,7 +1474,7 @@ nomatch 32 {
match "mode" "host";
match "vendor" "0x06f8";
match "product" "0xe033";
action "kldload -n if_urtwn";
action "kldload -n if_rtwn_usb";
};
nomatch 32 {
@ -1658,7 +1690,7 @@ nomatch 32 {
match "mode" "host";
match "vendor" "0x07aa";
match "product" "0x0056";
action "kldload -n if_urtwn";
action "kldload -n if_rtwn_usb";
};
nomatch 32 {
@ -1722,7 +1754,7 @@ nomatch 32 {
match "mode" "host";
match "vendor" "0x07b8";
match "product" "(0x8178|0x8179|0x8188|0x8189)";
action "kldload -n if_urtwn";
action "kldload -n if_rtwn_usb";
};
nomatch 32 {
@ -2026,7 +2058,7 @@ nomatch 32 {
match "mode" "host";
match "vendor" "0x0846";
match "product" "0x9021";
action "kldload -n if_urtwn";
action "kldload -n if_rtwn_usb";
};
nomatch 32 {
@ -2041,8 +2073,8 @@ nomatch 32 {
match "bus" "uhub[0-9]+";
match "mode" "host";
match "vendor" "0x0846";
match "product" "0x9041";
action "kldload -n if_urtwn";
match "product" "(0x9041|0x9052)";
action "kldload -n if_rtwn_usb";
};
nomatch 32 {
@ -2498,7 +2530,7 @@ nomatch 32 {
match "mode" "host";
match "vendor" "0x0b05";
match "product" "0x17ab";
action "kldload -n if_urtwn";
action "kldload -n if_rtwn_usb";
};
nomatch 32 {
@ -2522,7 +2554,7 @@ nomatch 32 {
match "mode" "host";
match "vendor" "0x0b05";
match "product" "0x17ba";
action "kldload -n if_urtwn";
action "kldload -n if_rtwn_usb";
};
nomatch 32 {
@ -2533,6 +2565,14 @@ nomatch 32 {
action "kldload -n ng_ubt";
};
nomatch 32 {
match "bus" "uhub[0-9]+";
match "mode" "host";
match "vendor" "0x0b05";
match "product" "0x17d2";
action "kldload -n if_rtwn_usb";
};
nomatch 32 {
match "bus" "uhub[0-9]+";
match "mode" "host";
@ -2658,7 +2698,7 @@ nomatch 32 {
match "mode" "host";
match "vendor" "0x0bda";
match "product" "(0x0179|0x018a|0x317f)";
action "kldload -n if_urtwn";
action "kldload -n if_rtwn_usb";
};
nomatch 32 {
@ -2682,7 +2722,7 @@ nomatch 32 {
match "mode" "host";
match "vendor" "0x0bda";
match "product" "0x8170";
action "kldload -n if_urtwn";
action "kldload -n if_rtwn_usb";
};
nomatch 32 {
@ -2698,7 +2738,7 @@ nomatch 32 {
match "mode" "host";
match "vendor" "0x0bda";
match "product" "(0x8176|0x8177|0x8178|0x8179|0x817a|0x817b|0x817c|0x817d|0x817e|0x817f)";
action "kldload -n if_urtwn";
action "kldload -n if_rtwn_usb";
};
nomatch 32 {
@ -2714,7 +2754,7 @@ nomatch 32 {
match "mode" "host";
match "vendor" "0x0bda";
match "product" "(0x818a|0x8191)";
action "kldload -n if_urtwn";
action "kldload -n if_rtwn_usb";
};
nomatch 32 {
@ -2738,7 +2778,7 @@ nomatch 32 {
match "mode" "host";
match "vendor" "0x0bda";
match "product" "0x8754";
action "kldload -n if_urtwn";
action "kldload -n if_rtwn_usb";
};
nomatch 32 {
@ -3162,7 +3202,7 @@ nomatch 32 {
match "mode" "host";
match "vendor" "0x0df6";
match "product" "0x0052";
action "kldload -n if_urtwn";
action "kldload -n if_rtwn_usb";
};
nomatch 32 {
@ -3178,7 +3218,7 @@ nomatch 32 {
match "mode" "host";
match "vendor" "0x0df6";
match "product" "(0x005c|0x0061)";
action "kldload -n if_urtwn";
action "kldload -n if_rtwn_usb";
};
nomatch 32 {
@ -3189,6 +3229,14 @@ nomatch 32 {
action "kldload -n if_axge";
};
nomatch 32 {
match "bus" "uhub[0-9]+";
match "mode" "host";
match "vendor" "0x0df6";
match "product" "0x0074";
action "kldload -n if_rtwn_usb";
};
nomatch 32 {
match "bus" "uhub[0-9]+";
match "mode" "host";
@ -3257,8 +3305,8 @@ nomatch 32 {
match "bus" "uhub[0-9]+";
match "mode" "host";
match "vendor" "0x0e66";
match "product" "0x0019";
action "kldload -n if_urtwn";
match "product" "(0x0019|0x0023)";
action "kldload -n if_rtwn_usb";
};
nomatch 32 {
@ -3330,7 +3378,7 @@ nomatch 32 {
match "mode" "host";
match "vendor" "0x0eb0";
match "product" "0x9071";
action "kldload -n if_urtwn";
action "kldload -n if_rtwn_usb";
};
nomatch 32 {
@ -3490,7 +3538,7 @@ nomatch 32 {
match "mode" "host";
match "vendor" "0x103c";
match "product" "0x1629";
action "kldload -n if_urtwn";
action "kldload -n if_rtwn_usb";
};
nomatch 32 {
@ -3973,6 +4021,14 @@ nomatch 32 {
action "kldload -n if_run";
};
nomatch 32 {
match "bus" "uhub[0-9]+";
match "mode" "host";
match "vendor" "0x13b1";
match "product" "0x003f";
action "kldload -n if_rtwn_usb";
};
nomatch 32 {
match "bus" "uhub[0-9]+";
match "mode" "host";
@ -4018,7 +4074,7 @@ nomatch 32 {
match "mode" "host";
match "vendor" "0x13d3";
match "product" "(0x3357|0x3358|0x3359)";
action "kldload -n if_urtwn";
action "kldload -n if_rtwn_usb";
};
nomatch 32 {
@ -4565,6 +4621,14 @@ nomatch 32 {
action "kldload -n if_run";
};
nomatch 32 {
match "bus" "uhub[0-9]+";
match "mode" "host";
match "vendor" "0x1740";
match "product" "0x0100";
action "kldload -n if_rtwn_usb";
};
nomatch 32 {
match "bus" "uhub[0-9]+";
match "mode" "host";
@ -4961,8 +5025,8 @@ nomatch 32 {
match "bus" "uhub[0-9]+";
match "mode" "host";
match "vendor" "0x2001";
match "product" "(0x3307|0x3308|0x3309|0x330a|0x330d|0x330f|0x3310)";
action "kldload -n if_urtwn";
match "product" "(0x3307|0x3308|0x3309|0x330a|0x330d|0x330f|0x3310|0x3314|0x3315|0x3316|0x3318)";
action "kldload -n if_rtwn_usb";
};
nomatch 32 {
@ -5042,7 +5106,7 @@ nomatch 32 {
match "mode" "host";
match "vendor" "0x2019";
match "product" "(0x1201|0x4902)";
action "kldload -n if_urtwn";
action "kldload -n if_rtwn_usb";
};
nomatch 32 {
@ -5089,8 +5153,8 @@ nomatch 32 {
match "bus" "uhub[0-9]+";
match "mode" "host";
match "vendor" "0x2019";
match "product" "(0xab2a|0xab2b|0xab2e)";
action "kldload -n if_urtwn";
match "product" "(0xab2a|0xab2b|0xab2e|0xab30)";
action "kldload -n if_rtwn_usb";
};
nomatch 32 {
@ -5130,7 +5194,7 @@ nomatch 32 {
match "mode" "host";
match "vendor" "0x2019";
match "product" "0xed17";
action "kldload -n if_urtwn";
action "kldload -n if_rtwn_usb";
};
nomatch 32 {
@ -5170,7 +5234,7 @@ nomatch 32 {
match "mode" "host";
match "vendor" "0x20f4";
match "product" "0x624d";
action "kldload -n if_urtwn";
action "kldload -n if_rtwn_usb";
};
nomatch 32 {
@ -5185,8 +5249,8 @@ nomatch 32 {
match "bus" "uhub[0-9]+";
match "mode" "host";
match "vendor" "0x20f4";
match "product" "0x648b";
action "kldload -n if_urtwn";
match "product" "(0x648b|0x805b)";
action "kldload -n if_rtwn_usb";
};
nomatch 32 {
@ -5229,6 +5293,14 @@ nomatch 32 {
action "kldload -n u3g";
};
nomatch 32 {
match "bus" "uhub[0-9]+";
match "mode" "host";
match "vendor" "0x2357";
match "product" "0x0101";
action "kldload -n if_rtwn_usb";
};
nomatch 32 {
match "bus" "uhub[0-9]+";
match "mode" "host";
@ -5354,7 +5426,7 @@ nomatch 32 {
match "mode" "host";
match "vendor" "0x4855";
match "product" "(0x0090|0x0091)";
action "kldload -n if_urtwn";
action "kldload -n if_rtwn_usb";
};
nomatch 32 {
@ -5465,8 +5537,8 @@ nomatch 32 {
match "bus" "uhub[0-9]+";
match "mode" "host";
match "vendor" "0x7392";
match "product" "(0x7811|0x7822)";
action "kldload -n if_urtwn";
match "product" "(0x7811|0x7822|0xa811|0xa812|0xa822)";
action "kldload -n if_rtwn_usb";
};
nomatch 32 {
@ -5522,7 +5594,7 @@ nomatch 32 {
match "mode" "host";
match "vendor" "0x9846";
match "product" "0x9041";
action "kldload -n if_urtwn";
action "kldload -n if_rtwn_usb";
};
nomatch 32 {
@ -5817,5 +5889,5 @@ nomatch 32 {
action "kldload -n umass";
};
# 2722 USB entries processed
# 2743 USB entries processed

View File

@ -1,6 +1,6 @@
# $FreeBSD$
FILES= ${.CURDIR}/../../../../sys/contrib/dev/urtwn/LICENSE
FILES= ${.CURDIR}/../../../../sys/contrib/dev/rtwn/LICENSE
FILESDIR= ${SHAREDIR}/doc/legal
FILESNAME= realtek.LICENSE

View File

@ -433,6 +433,7 @@ MAN= aac.4 \
rp.4 \
rtwn.4 \
rtwnfw.4 \
rtwn_pci.4 \
rue.4 \
rum.4 \
run.4 \
@ -692,6 +693,8 @@ MLINKS+=pms.4 pmspcv.4
MLINKS+=ral.4 if_ral.4
MLINKS+=re.4 if_re.4
MLINKS+=rl.4 if_rl.4
MLINKS+=rtwn.4 if_rtwn.4
MLINKS+=rtwn_pci.4 if_rtwn_pci.4
MLINKS+=rue.4 if_rue.4
MLINKS+=rum.4 if_rum.4
MLINKS+=run.4 if_run.4
@ -886,6 +889,7 @@ MAN+= \
otusfw.4 \
rsu.4 \
rsufw.4 \
rtwn_usb.4 \
u3g.4 \
uark.4 \
uart.4 \
@ -928,8 +932,6 @@ MAN+= \
urio.4 \
urndis.4 \
${_urtw.4} \
urtwn.4 \
urtwnfw.4 \
usb.4 \
usb_quirk.4 \
usb_template.4 \
@ -941,6 +943,7 @@ MAN+= \
MLINKS+=otus.4 if_otus.4
MLINKS+=rsu.4 if_rsu.4
MLINKS+=rtwn_usb.4 if_rtwn_usb.4
MLINKS+=u3g.4 u3gstub.4
MLINKS+=uath.4 if_uath.4
MLINKS+=udav.4 if_udav.4
@ -948,7 +951,6 @@ MLINKS+=upgt.4 if_upgt.4
MLINKS+=ural.4 if_ural.4
MLINKS+=urndis.4 if_urndis.4
MLINKS+=${_urtw.4} ${_if_urtw.4}
MLINKS+=urtwn.4 if_urtwn.4
.endif
.include <bsd.prog.mk>

View File

@ -2,6 +2,7 @@
.\"
.\" Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
.\" Copyright (c) 2015 Stefan Sperling <stsp@openbsd.org>
.\" Copyright (c) 2016 Andriy Voskoboinyk <avos@freebsd.org>
.\"
.\" Permission to use, copy, modify, and distribute this software for any
.\" purpose with or without fee is hereby granted, provided that the above
@ -17,89 +18,88 @@
.\"
.\" $FreeBSD$
.\"
.Dd October 28, 2015
.Dd September 19, 2016
.Dt RTWN 4
.Os
.Sh NAME
.Nm rtwn
.Nd Realtek RTL8188CE PCIe IEEE 802.11b/g/n wireless network device
.Nd Realtek IEEE 802.11 wireless network driver
.Sh SYNOPSIS
.Cd "options RTWN_DEBUG"
.Cd "options RTWN_WITHOUT_UCODE"
.Pp
To compile this driver into the kernel,
place the following lines in your
kernel configuration file:
.Bd -ragged -offset indent
.Cd "device rtwn"
.Cd "device rtwnfw"
.Cd "device rtwn_usb"
.Cd "device rtwn_pci"
.Cd "device wlan"
.Cd "device firmware"
.Ed
.Pp
Alternatively, to load the driver as a
module at boot time, place the following line in
module at boot time, place following lines in
.Xr loader.conf 5 :
.Bd -literal -offset indent
if_rtwn_load="YES"
.Ed
.Pp
After you have read the license in
.Pa /usr/share/doc/legal/realtek.LICENSE
you will want to add the following lines to
.Xr loader.conf 5 :
.Bd -literal -offset indent
legal.realtek.license_ack=1
rtwn-rtl8192cfwU_load="YES"
rtwn-rtl8192cfwU_B_load="YES"
if_rtwn_pci_load="YES"
if_rtwn_usb_load="YES"
.Ed
.Sh DESCRIPTION
The
.Nm
driver supports PCIe wireless network devices based on the Realtek
RTL8188CE chipset.
driver provides support for wireless network devices based on
the Realtek RTL8192C, RTL8188E, RTL8812A and RTL8821A programming APIs.
These APIs are used by a wide variety of chips; most chips with USB
and some with PCI interface are supported.
.Pp
The RTL8188CE is a highly integrated 802.11n adapter that combines a MAC,
a 1T1R capable baseband and an RF in a single chip.
It operates in the 2GHz spectrum only.
To enable use for PCI/PCIe systems, see the rtwn_pci(4) driver;
for USB devices, use the rtwn_usb(4) driver.
.Pp
These are the modes the
.Nm
driver can operate in:
.Bl -tag -width "IBSS-masterXX"
.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 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
The driver supports
.Cm station ,
.Cm adhoc ,
.Cm hostap
and
.Cm monitor
mode operation.
There are no limitations for number of
.Cm monitor
mode
virtual interfaces; in addition to any other virtual interface
one
.Cm station
interface can be added (Note: RTL8821AU supports two non-monitor
mode interfaces at the same time).
.Pp
The
.Nm
driver can be configured to use
Wired Equivalent Privacy (WEP) or
Wi-Fi Protected Access (WPA-PSK and WPA2-PSK).
WPA is the current encryption standard for wireless networks.
It is strongly recommended that WEP
not be used as the sole mechanism
to secure wireless communication,
due to serious weaknesses in it.
All chips have hardware support for WEP, AES-CCM and TKIP encryption.
.Pp
The
.Nm
driver can be configured at runtime with
.Xr ifconfig 8 .
.Sh FILES
The driver needs at least version 1.0 of the following firmware files,
which are loaded when an interface is brought up:
.Bl -tag -width ".Pa /usr/share/doc/legal/realtek.LICENSE" -compact
.It Pa /usr/share/doc/legal/realtek.LICENSE
.Nm
firmware license
.El
.Pp
The driver (if not compiled with
.Cd options RTWN_WITHOUT_UCODE
) may use following firmware files, which are loaded
when an interface is brought up:
.Bl -tag -width Ds -offset indent -compact
.It Pa /boot/kernel/rtwn-rtl8188eufw.ko
.It Pa /boot/kernel/rtwn-rtl8192cfwE_B.ko
.It Pa /boot/kernel/rtwn-rtl8192cfwE.ko
.It Pa /boot/kernel/rtwn-rtl8192cfwT.ko
.It Pa /boot/kernel/rtwn-rtl8192cfwU.ko
.It Pa /boot/kernel/rtwn-rtl8192cfwU_B.ko
.It Pa /boot/kernel/rtwn-rtl8812aufw.ko
.It Pa /boot/kernel/rtwn-rtl8821aufw.ko
.El
.Sh EXAMPLES
Join an existing BSS network (i.e., connect to an access point):
@ -118,48 +118,124 @@ Join a specific BSS network with 64-bit WEP encryption:
ifconfig wlan create wlandev rtwn0 ssid my_net \e
wepmode on wepkey 0x1234567890 weptxkey 1 up
.Ed
.Pp
Create an IBSS network with 128-bit WEP encryption on the channel 4:
.Bd -literal -offset indent
ifconfig wlan create wlandev rtwn0 wlanmode adhoc ssid my_net \e
wepmode on wepkey 0x01020304050607080910111213 weptxkey 1 \e
channel 4
.Ed
.Pp
Join/create an 802.11b IBSS network with network name
.Dq Li my_net :
.Bd -literal -offset indent
ifconfig wlan0 create wlandev rtwn0 wlanmode adhoc
ifconfig wlan0 inet 192.168.0.22 netmask 0xffffff00 ssid my_net \e
mode 11b
.Ed
.Pp
Create a host-based access point:
.Bd -literal -offset indent
ifconfig wlan0 create wlandev rtwn0 wlanmode hostap
ifconfig wlan0 inet 192.168.0.10 netmask 0xffffff00 ssid my_ap
.Ed
.Sh LOADER TUNABLES
Tunables can be set at the
.Xr loader 8
prompt before booting the kernel or stored in
.Xr loader.conf 5 .
.Bl -tag -width indent
.It Va dev.rtwn.%d.hwcrypto
This tunable controls how key slots are assigned:
.br
0 - disable h/w crypto support. Features that require access
to frame contents (e.g., TCP/UDP/IP Rx checksum validation)
will not work;
.br
1 - use h/w crypto support for pairwise keys only;
.br
2 - use h/w crypto support for all keys; may not work for
multi-vap configurations.
.br
By default it is set to 1.
.It Va dev.rtwn.%d.ratectl
This tunable switches between rate control implementations:
.br
0 - no rate control;
.br
1 - driver sends 'tx complete' reports to net80211; algorithm
is controlled via net80211;
.br
2 - firmware-based rate control.
.br
By default it is set to 1; however driver may choose another
algorithm in case if it is not implemented
.br
Currently selected algorithm is reported via
.Em Va dev.rtwn.%d.ratectl_selected
read-only OID.
.El
.Sh DIAGNOSTICS
.Bl -diag
.It "could not read firmware %s"
.It "rtwn%d: could not read efuse byte at address 0x%x"
.It "rtwn%d: %s: cannot read rom, error %d"
There was an error while reading ROM; device attach will be aborted.
This should not happen.
.It "rtwn%d: failed loadfirmware of file %s"
For some reason, the driver was unable to read the microcode file from the
filesystem.
The file might be missing or corrupted.
.It "device timeout"
The driver will disable firmware-dependent features.
.It "rtwn%d: wrong firmware size (%zu)"
.It "rtwn%d: %s: failed to upload firmware %s (error %d)"
.It "rtwn%d: timeout waiting for firmware readiness"
Firmware upload failed; the file might be corrupted.
The driver will disable firmware-dependent features.
This should not happen.
.It "rtwn%d: device timeout"
A frame dispatched to the hardware for transmission did not complete in time.
The driver will reset the hardware.
This should not happen.
.El
.Sh SEE ALSO
.Xr pci 4 ,
.Xr intro 4 ,
.Xr netintro 4 ,
.Xr rtwn_pci 4 ,
.Xr rtwn_usb 4 ,
.Xr rtwnfw 4 ,
.Xr wlan 4 ,
.Xr wlan_amrr 4 ,
.Xr wlan_ccmp 4 ,
.Xr wlan_tkip 4 ,
.Xr wlan_wep 4 ,
.Xr wlan_xauth 4 ,
.Xr hostapd 4 ,
.Xr ifconfig 8 ,
.Xr wpa_supplicant 8
.Sh HISTORY
The
.Cm urtwn
driver first appeared in
.Ox 4.9
and
.Fx 10.0 ;
the
.Nm
driver first appeared in
.Ox 5.8 .
.Sh AUTHORS
The
.Nm
driver was written by
driver was initially written by
.An -nosplit
.An Stefan Sperling Aq Mt stsp@openbsd.org
and ported by
.An Kevin Lo Aq Mt kevlo@freebsd.org .
It was based on the
.Xr urtwn 4
.Cm urtwn
driver written by
.An Damien Bergamini Aq Mt damien.bergamini@free.fr .
.Sh CAVEATS
.Sh BUGS
The
.Nm
driver does not support any of the 802.11n capabilities offered by the
adapters.
Additional work is required in
.Xr ieee80211 9
before those features can be supported.
driver currently does not implement firmware-based rate control.

63
share/man/man4/rtwn_pci.4 Normal file
View File

@ -0,0 +1,63 @@
.\"-
.\" Copyright (c) 2011 Adrian Chadd, Xenion Pty Ltd
.\" Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
.\" All rights reserved.
.\""
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer,
.\" without modification.
.\" 2. Redistributions in binary form must reproduce at minimum a disclaimer
.\" similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
.\" redistribution must be conditioned upon including a substantially
.\" similar Disclaimer requirement for further binary redistribution.
.\"
.\" NO WARRANTY
.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
.\" LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
.\" AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
.\" THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
.\" OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
.\" IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
.\" THE POSSIBILITY OF SUCH DAMAGES.
.\"
.\" $FreeBSD$
.\"/
.Dd September 19, 2016
.Dt RTWN_PCI 4
.Os
.Sh NAME
.Nm rtwn_pci
.Nd "Realtek PCI device glue"
.Sh SYNOPSIS
To compile this driver into the kernel,
place the following lines in your
kernel configuration file:
.Bd -ragged -offset indent
.Cd "device rtwn_pci"
.Cd "device pci"
.Cd "device wlan"
.Ed
.Sh DESCRIPTION
The
.Nm
driver supports PCIe wireless network devices based on the Realtek
RTL8188CE chipset.
.Pp
The RTL8188CE is a highly integrated 802.11n adapter that combines a MAC,
a 1T1R capable baseband and an RF in a single chip.
It operates in the 2GHz spectrum only.
.Sh SEE ALSO
.Xr rtwn 4 ,
.Xr rtwnfw 4 ,
.Xr rtwn_usb 4 ,
.Xr pci 4
.Sh CAVEATS
Most 802.11 capabilities were turned off; some more testing
is required to re-enable them.

111
share/man/man4/rtwn_usb.4 Normal file
View File

@ -0,0 +1,111 @@
.\"-
.\" Copyright (c) 2011 Adrian Chadd, Xenion Pty Ltd
.\" Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
.\" All rights reserved.
.\""
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer,
.\" without modification.
.\" 2. Redistributions in binary form must reproduce at minimum a disclaimer
.\" similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
.\" redistribution must be conditioned upon including a substantially
.\" similar Disclaimer requirement for further binary redistribution.
.\"
.\" NO WARRANTY
.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
.\" LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
.\" AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
.\" THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
.\" OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
.\" IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
.\" THE POSSIBILITY OF SUCH DAMAGES.
.\"
.\" $FreeBSD$
.\"/
.Dd September 19, 2016
.Dt RTWN_USB 4
.Os
.Sh NAME
.Nm rtwn_usb
.Nd "Realtek USB device glue"
.Sh SYNOPSIS
To compile this driver into the kernel,
place the following lines in your
kernel configuration file:
.Bd -ragged -offset indent
.Cd "device xhci"
.Cd "device ehci"
.Cd "device uhci"
.Cd "device ohci"
.Cd "device usb"
.Cd "device rtwn_usb"
.Cd "device wlan"
.Ed
.Sh DESCRIPTION
This module provides the USB bus glue needed for the devices supported
by the
.Xr rtwn 4
driver.
.Sh HARDWARE
The
.Nm
driver supports Realtek RTL8188CU/RTL8188RU/RTL8188EU/RTL8192CU/RTL8812AU/RTL8821AU
based USB wireless network adapters, including:
.Pp
.Bl -column -compact "Belkin F7D1102 Surf Wireless Micro" "Bus"
.It Em Card Ta Em Bus
.It "Alfa AWUS036NHR v2" Ta USB 2.0
.It "ASUS USB-AC56" Ta USB 3.0
.It "ASUS USB-N10 NANO" Ta USB 2.0
.It "Belkin F7D1102 Surf Wireless Micro" Ta USB 2.0
.It "Buffalo WI-U2-433DM" Ta USB 2.0
.It "Buffalo WI-U3-866D" Ta USB 3.0
.It "D-Link DWA-123 rev D1" Ta USB 2.0
.It "D-Link DWA-125 rev D1" Ta USB 2.0
.It "D-Link DWA-131" Ta USB 2.0
.It "D-Link DWA-171 rev A1" Ta USB 2.0
.It "D-Link DWA-172 rev A1" Ta USB 2.0
.It "D-Link DWA-180 rev A1" Ta USB 2.0
.It "D-Link DWA-182 rev C1" Ta USB 3.0
.It "Edimax EW-7811Un" Ta USB 2.0
.It "Edimax EW-7811UTC" Ta USB 2.0
.It "Edimax EW-7822UAC" Ta USB 3.0
.It "Elecom WDC-150SU2M" Ta USB 2.0
.It "EnGenius EUB1200AC" Ta USB 3.0
.It "Hawking HD65U" Ta USB 2.0
.It "Hercules Wireless N USB Pico" Ta USB 2.0
.It "I-O Data WN-AC867U" Ta USB 3.0
.It "Linksys WUSB6300" Ta USB 3.0
.It "NEC AtermWL900U PA-WL900U" Ta USB 3.0
.It "Netgear A6100" Ta USB 2.0
.It "Netgear WNA1000M" Ta USB 2.0
.It "Planex GW-900D" Ta USB 3.0
.It "Realtek RTL8192CU" Ta USB 2.0
.It "Realtek RTL8188CUS" Ta USB 2.0
.It "Sitecom WLA-7100" Ta USB 3.0
.It "TP-Link Archer T4U" Ta USB 3.0
.It "TP-LINK TL-WN723N v3" Ta USB 2.0
.It "TP-LINK TL-WN725N v2" Ta USB 2.0
.It "TRENDnet TEW-805UB" Ta USB 3.0
.It "ZyXEL NWD6605" Ta USB 3.0
.El
.Sh SEE ALSO
.Xr rtwn 4 ,
.Xr rtwnfw 4 ,
.Xr rtwn_pci 4 ,
.Xr usb 4
.Sh BUGS
The
.Nm
driver does not support any of the 802.11ac capabilities offered by the
adapters.
Additional work is required in
.Xr ieee80211 9
before those features can be supported.

View File

@ -1,4 +1,5 @@
.\" Copyright (c) 2015 Kevin Lo
.\" Copyright (c) 2016 Andriy Voskoboinyk
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
@ -36,26 +37,39 @@ kernel configuration file:
.Cd "device rtwnfw"
.Ed
.Pp
This will include three firmware images inside the kernel.
This will include all firmware images inside the kernel.
If you want to pick only the firmware image for your network adapter choose one
of the following:
.Bd -ragged -offset indent
.Cd "device rtwn-rtl8188eufw"
.Cd "device rtwn-rtl8192cfwE_B"
.Cd "device rtwn-rtl8192cfwE"
.Cd "device rtwn-rtl8192cfwT"
.Cd "device rtwn-rtl8192cfwU"
.Cd "device rtwn-rtl8192cfwU_B"
.Cd "device rtwn-rtl8812aufw"
.Cd "device rtwn-rtl8821aufw"
.Ed
.Pp
Alternatively, to load the driver as a
Alternatively, to load all firmware images as a
module at boot time, place the following line in
.Xr loader.conf 5 :
.Bd -literal -offset indent
rtwn-rtl8188eufw_load="YES"
rtwn-rtl8192cfwE_B_load="YES"
rtwn-rtl8192cfwE_load="YES"
rtwn-rtl8192cfwT_load="YES"
rtwn-rtl8192cfwU_load="YES"
rtwn-rtl8192cfwU_B_load="YES"
rtwn-rtl8812aufw_load="YES"
rtwn-rtl8821aufw_load="YES"
.Ed
.Sh DESCRIPTION
This module provides access to firmware sets for the
Realtek RTL8188CE chip based PCIe adapters.
It may be
statically linked into the kernel, or loaded as a module.
rtwn-rtl8192cfwE and rtl8192cfwE_B modules provide access
to firmware sets for the Realtek RTL8188CE chip based PCIe adapters.
Other modules provide access to firmware sets for the Realtek RTL8188CUS,
RTL8188CE-VAU, RTL8188EUS, RTL8188RU, RTL8192CU, RTL8812AU and RTL8821AU
chip based USB WiFi adapters.
They may be
statically linked into the kernel, or loaded as a modules.
.Pp
For the loaded firmware to be enabled for use the license at
.Pa /usr/share/doc/legal/realtek.LICENSE

View File

@ -1,190 +0,0 @@
.\" Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
.\"
.\" 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.
.\"
.\" $FreeBSD$
.\"
.Dd June 9, 2016
.Dt URTWN 4
.Os
.Sh NAME
.Nm urtwn
.Nd Realtek RTL8188CU/RTL8188RU/RTL8188EU/RTL8192CU USB IEEE 802.11b/g/n wireless network device
.Sh SYNOPSIS
.Cd "options URTWN_WITHOUT_UCODE"
.Pp
To compile this driver into the kernel,
place the following lines in your
kernel configuration file:
.Bd -ragged -offset indent
.Cd "device ehci"
.Cd "device uhci"
.Cd "device ohci"
.Cd "device usb"
.Cd "device urtwn"
.Cd "device wlan"
.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_urtwn_load="YES"
.Ed
.Sh DESCRIPTION
The
.Nm
driver supports USB 2.0 wireless network devices based on Realtek
RTL8188CUS, RTL8188CE-VAU, RTL8188EUS, RTL8188RU and RTL8192CU chipsets.
.Pp
The RTL8188CUS and RTL8188EUS are highly integrated 802.11n adapters that
combine a MAC, a 1T1R capable baseband and an RF in a single chip.
They operate in the 2GHz spectrum only.
The RTL8188RU is a high-power variant of the RTL8188CUS.
The RTL8188CE-VAU is a PCI Express Mini Card adapter that attaches
to the USB interface.
.Pp
The RTL8192CU is a highly integrated multiple-in, multiple-out (MIMO)
802.11n adapter that combines a MAC, a 2T2R capable baseband and an
RF in a single chip.
It operates in the 2GHz spectrum only.
.Pp
All chips have hardware support for WEP, AES-CCM and TKIP encryption.
.Pp
The driver supports
.Cm station ,
.Cm adhoc ,
.Cm hostap ,
and
.Cm monitor
mode operation.
Only one virtual interface may be configured at any time.
.Pp
This driver may use the firmware built with the
.Nm urtwnfw
module for some additional features
(when URTWN_WITHOUT_UCODE kernel option is not set).
.Sh FILES
.Bl -tag -width ".Pa /usr/share/doc/legal/realtek.LICENSE" -compact
.It Pa /usr/share/doc/legal/realtek.LICENSE
.Nm
firmware license
.El
.Sh HARDWARE
The
.Nm
driver supports Realtek RTL8188CU/RTL8188RU/RTL8188EU/RTL8192CU based USB
IEEE 802.11b/g/n wireless network adapters, including:
.Pp
.Bl -tag -width Ds -offset indent -compact
.It Alfa AWUS036NHR v2
.It ASUS USB-N10 NANO
.It Belkin F7D1102 Surf Wireless Micro
.It D-Link DWA-123 rev D1
.It D-Link DWA-125 rev D1
.It D-Link DWA-131
.It Edimax EW-7811Un
.It Elecom WDC-150SU2M
.It Netgear WNA1000M
.It Realtek RTL8192CU
.It Realtek RTL8188CUS
.It TP-LINK TL-WN723N v3
.It TP-LINK TL-WN725N v2
.El
.Sh EXAMPLES
Join an existing BSS network (i.e., connect to an access point):
.Bd -literal -offset indent
ifconfig wlan create wlandev urtwn0 inet 192.168.0.20 \e
netmask 0xffffff00
.Ed
.Pp
Join a specific BSS network with network name
.Dq Li my_net :
.Pp
.Dl "ifconfig wlan create wlandev urtwn0 ssid my_net up"
.Pp
Join a specific BSS network with 64-bit WEP encryption:
.Bd -literal -offset indent
ifconfig wlan create wlandev urtwn0 ssid my_net \e
wepmode on wepkey 0x1234567890 weptxkey 1 up
.Ed
.Pp
Create an IBSS network with 128-bit WEP encryption on the channel 4:
.Bd -literal -offset indent
ifconfig wlan0 create wlandev urtwn0 wlanmode adhoc ssid my_net \e
wepmode on wepkey 0x01020304050607080910111213 weptxkey 1 \e
channel 4
.Ed
.Pp
Join/create an 802.11b IBSS network with network name
.Dq Li my_net :
.Bd -literal -offset indent
ifconfig wlan0 create wlandev urtwn0 wlanmode adhoc
ifconfig wlan0 inet 192.168.0.22 netmask 0xffffff00 ssid my_net \e
mode 11b
.Ed
.Pp
Create an 802.11g host-based access point:
.Bd -literal -offset indent
ifconfig wlan0 create wlandev urtwn0 wlanmode hostap
ifconfig wlan0 inet 192.168.0.10 netmask 0xffffff00 ssid my_ap \e
mode 11g
.Ed
.Sh DIAGNOSTICS
.Bl -diag
.It "urtwn%d: error %d, could not read firmware %s"
For some reason, the driver was unable to read the microcode file from the
filesystem.
The file might be missing or corrupted.
.It "urtwn%d: device timeout"
A frame dispatched to the hardware for transmission did not complete in time.
The driver will reset the hardware.
This should not happen.
.El
.Sh SEE ALSO
.Xr intro 4 ,
.Xr netintro 4 ,
.Xr urtwnfw 4 ,
.Xr usb 4 ,
.Xr wlan 4 ,
.Xr wlan_amrr 4 ,
.Xr wlan_ccmp 4 ,
.Xr wlan_tkip 4 ,
.Xr wlan_wep 4 ,
.Xr ifconfig 8 ,
.Xr wpa_supplicant 8
.Rs
.%T Realtek
.%U http://www.realtek.com.tw
.Re
.Sh HISTORY
The
.Nm
driver first appeared in
.Ox 4.9
and
.Fx 10.0 .
.Sh AUTHORS
The
.Nm
driver was written by
.An Damien Bergamini Aq Mt damien@openbsd.org .
.Sh CAVEATS
The
.Nm
driver currently does not support A-MPDU 802.11n transmit aggregation.
.Pp
For non-RTL8188EUS chips
.Dq "rate control"
algorithm is absent; this may result in increased packet loss in noisy
networks.

View File

@ -1,77 +0,0 @@
.\" Copyright (c) 2013 Kevin Lo
.\" 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. The name of the author may not be used to endorse or promote products
.\" derived from this software without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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$
.\"
.Dd October 15, 2015
.Dt URTWNFW 4
.Os
.Sh NAME
.Nm urtwnfw
.Nd "Firmware Module for Realtek Wireless driver"
.Sh SYNOPSIS
To compile this module into the kernel,
place the following line in your
kernel configuration file:
.Bd -ragged -offset indent
.Cd "device urtwnfw"
.Ed
.Pp
This will include three firmware images inside the kernel.
If you want to pick only the firmware image for your network adapter choose one
of the following:
.Bd -ragged -offset indent
.Cd "device urtwn-rtl8192cfwT"
.Cd "device urtwn-rtl8192cfwU"
.Cd "device urtwn-rtl8188eufw"
.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
urtwn-rtl8192cfwT_load="YES"
urtwn-rtl8192cfwU_load="YES"
urtwn-rtl8188eufw_load="YES"
.Ed
.Sh DESCRIPTION
This module provides access to firmware sets for the
Realtek RTL8188CUS, RTL8188CE-VAU, RTL8188EUS, RTL8188RU and RTL8192CU
chip based USB WiFi adapters.
It may be
statically linked into the kernel, or loaded as a module.
.Pp
For the loaded firmware to be enabled for use the license at
.Pa /usr/share/doc/legal/realtek.LICENSE
must be agreed to by adding the following line to
.Xr loader.conf 5 :
.Pp
.Dl "legal.realtek.license_ack=1"
.Sh FILES
.Bl -tag -width ".Pa /usr/share/doc/legal/realtek.LICENSE" -compact
.It Pa /usr/share/doc/legal/realtek.LICENSE
.Nm
firmware license
.El
.Sh SEE ALSO
.Xr urtwn 4 ,
.Xr firmware 9

View File

@ -185,13 +185,13 @@ may not interoperate.
.Xr otus 4 ,
.Xr ral 4 ,
.Xr rsu 4 ,
.Xr rtwn 4 ,
.Xr rum 4 ,
.Xr run 4 ,
.Xr uath 4 ,
.Xr upgt 4 ,
.Xr ural 4 ,
.Xr urtw 4 ,
.Xr urtwn 4 ,
.Xr wi 4 ,
.Xr wlan_acl 4 ,
.Xr wlan_ccmp 4 ,

View File

@ -11,6 +11,7 @@ nodevice fxp
nodevice ispfw
nodevice mwlfw
nodevice ralfw
nodevice rtwnfw
nodevice runfw
nodevice sf
nodevice ti
@ -41,5 +42,3 @@ nodevice rum
nodevice uath
nodevice zyd
nodevice kue
nodevice urtwn
nodevice urtwnfw

View File

@ -2490,7 +2490,147 @@ dev/rndtest/rndtest.c optional rndtest
dev/rp/rp.c optional rp
dev/rp/rp_isa.c optional rp isa
dev/rp/rp_pci.c optional rp pci
#
dev/rtwn/if_rtwn.c optional rtwn
dev/rtwn/if_rtwn_beacon.c optional rtwn
dev/rtwn/if_rtwn_calib.c optional rtwn
dev/rtwn/if_rtwn_cam.c optional rtwn
dev/rtwn/if_rtwn_efuse.c optional rtwn
dev/rtwn/if_rtwn_fw.c optional rtwn
dev/rtwn/if_rtwn_rx.c optional rtwn
dev/rtwn/if_rtwn_task.c optional rtwn
dev/rtwn/if_rtwn_tx.c optional rtwn
#
dev/rtwn/pci/rtwn_pci_attach.c optional rtwn_pci pci
dev/rtwn/pci/rtwn_pci_reg.c optional rtwn_pci pci
dev/rtwn/pci/rtwn_pci_rx.c optional rtwn_pci pci
dev/rtwn/pci/rtwn_pci_tx.c optional rtwn_pci pci
#
dev/rtwn/usb/rtwn_usb_attach.c optional rtwn_usb
dev/rtwn/usb/rtwn_usb_ep.c optional rtwn_usb
dev/rtwn/usb/rtwn_usb_reg.c optional rtwn_usb
dev/rtwn/usb/rtwn_usb_rx.c optional rtwn_usb
dev/rtwn/usb/rtwn_usb_tx.c optional rtwn_usb
# RTL8188E
dev/rtwn/rtl8188e/r88e_beacon.c optional rtwn
dev/rtwn/rtl8188e/r88e_calib.c optional rtwn
dev/rtwn/rtl8188e/r88e_chan.c optional rtwn
dev/rtwn/rtl8188e/r88e_fw.c optional rtwn
dev/rtwn/rtl8188e/r88e_init.c optional rtwn
dev/rtwn/rtl8188e/r88e_led.c optional rtwn
dev/rtwn/rtl8188e/r88e_tx.c optional rtwn
dev/rtwn/rtl8188e/r88e_rf.c optional rtwn
dev/rtwn/rtl8188e/r88e_rom.c optional rtwn
dev/rtwn/rtl8188e/r88e_rx.c optional rtwn
dev/rtwn/rtl8188e/usb/r88eu_attach.c optional rtwn_usb
dev/rtwn/rtl8188e/usb/r88eu_init.c optional rtwn_usb
dev/rtwn/rtl8188e/usb/r88eu_rx.c optional rtwn_usb
# RTL8192C
dev/rtwn/rtl8192c/r92c_attach.c optional rtwn
dev/rtwn/rtl8192c/r92c_beacon.c optional rtwn
dev/rtwn/rtl8192c/r92c_calib.c optional rtwn
dev/rtwn/rtl8192c/r92c_chan.c optional rtwn
dev/rtwn/rtl8192c/r92c_fw.c optional rtwn
dev/rtwn/rtl8192c/r92c_init.c optional rtwn
dev/rtwn/rtl8192c/r92c_rf.c optional rtwn
dev/rtwn/rtl8192c/r92c_rom.c optional rtwn
dev/rtwn/rtl8192c/r92c_rx.c optional rtwn
dev/rtwn/rtl8192c/r92c_tx.c optional rtwn
dev/rtwn/rtl8192c/pci/r92ce_attach.c optional rtwn_pci pci
dev/rtwn/rtl8192c/pci/r92ce_calib.c optional rtwn_pci pci
dev/rtwn/rtl8192c/pci/r92ce_fw.c optional rtwn_pci pci
dev/rtwn/rtl8192c/pci/r92ce_init.c optional rtwn_pci pci
dev/rtwn/rtl8192c/pci/r92ce_led.c optional rtwn_pci pci
dev/rtwn/rtl8192c/pci/r92ce_rx.c optional rtwn_pci pci
dev/rtwn/rtl8192c/pci/r92ce_tx.c optional rtwn_pci pci
dev/rtwn/rtl8192c/usb/r92cu_attach.c optional rtwn_usb
dev/rtwn/rtl8192c/usb/r92cu_init.c optional rtwn_usb
dev/rtwn/rtl8192c/usb/r92cu_led.c optional rtwn_usb
dev/rtwn/rtl8192c/usb/r92cu_rx.c optional rtwn_usb
dev/rtwn/rtl8192c/usb/r92cu_tx.c optional rtwn_usb
# RTL8812A
dev/rtwn/rtl8812a/r12a_beacon.c optional rtwn
dev/rtwn/rtl8812a/r12a_calib.c optional rtwn
dev/rtwn/rtl8812a/r12a_caps.c optional rtwn
dev/rtwn/rtl8812a/r12a_chan.c optional rtwn
dev/rtwn/rtl8812a/r12a_fw.c optional rtwn
dev/rtwn/rtl8812a/r12a_init.c optional rtwn
dev/rtwn/rtl8812a/r12a_led.c optional rtwn
dev/rtwn/rtl8812a/r12a_rf.c optional rtwn
dev/rtwn/rtl8812a/r12a_rom.c optional rtwn
dev/rtwn/rtl8812a/r12a_rx.c optional rtwn
dev/rtwn/rtl8812a/r12a_tx.c optional rtwn
dev/rtwn/rtl8812a/usb/r12au_attach.c optional rtwn_usb
dev/rtwn/rtl8812a/usb/r12au_init.c optional rtwn_usb
dev/rtwn/rtl8812a/usb/r12au_rx.c optional rtwn_usb
dev/rtwn/rtl8812a/usb/r12au_tx.c optional rtwn_usb
# RTL8821A
dev/rtwn/rtl8821a/r21a_beacon.c optional rtwn
dev/rtwn/rtl8821a/r21a_calib.c optional rtwn
dev/rtwn/rtl8821a/r21a_chan.c optional rtwn
dev/rtwn/rtl8821a/r21a_fw.c optional rtwn
dev/rtwn/rtl8821a/r21a_init.c optional rtwn
dev/rtwn/rtl8821a/r21a_led.c optional rtwn
dev/rtwn/rtl8821a/r21a_rom.c optional rtwn
dev/rtwn/rtl8821a/r21a_rx.c optional rtwn
dev/rtwn/rtl8821a/usb/r21au_attach.c optional rtwn_usb
dev/rtwn/rtl8821a/usb/r21au_init.c optional rtwn_usb
rtwn-rtl8188eufw.c optional rtwn-rtl8188eufw | rtwnfw \
compile-with "${AWK} -f $S/tools/fw_stub.awk rtwn-rtl8188eufw.fw:rtwn-rtl8188eufw:111 -mrtwn-rtl8188eufw -c${.TARGET}" \
no-implicit-rule before-depend local \
clean "rtwn-rtl8188eufw.c"
rtwn-rtl8188eufw.fwo optional rtwn-rtl8188eufw | rtwnfw \
dependency "rtwn-rtl8188eufw.fw" \
compile-with "${NORMAL_FWO}" \
no-implicit-rule \
clean "rtwn-rtl8188eufw.fwo"
rtwn-rtl8188eufw.fw optional rtwn-rtl8188eufw | rtwnfw \
dependency "$S/contrib/dev/rtwn/rtwn-rtl8188eufw.fw.uu" \
compile-with "${NORMAL_FW}" \
no-obj no-implicit-rule \
clean "rtwn-rtl8188eufw.fw"
rtwn-rtl8192cfwE.c optional rtwn-rtl8192cfwE | rtwnfw \
compile-with "${AWK} -f $S/tools/fw_stub.awk rtwn-rtl8192cfwE.fw:rtwn-rtl8192cfwE:111 -mrtwn-rtl8192cfwE -c${.TARGET}" \
no-implicit-rule before-depend local \
clean "rtwn-rtl8192cfwE.c"
rtwn-rtl8192cfwE.fwo optional rtwn-rtl8192cfwE | rtwnfw \
dependency "rtwn-rtl8192cfwE.fw" \
compile-with "${NORMAL_FWO}" \
no-implicit-rule \
clean "rtwn-rtl8192cfwE.fwo"
rtwn-rtl8192cfwE.fw optional rtwn-rtl8192cfwE | rtwnfw \
dependency "$S/contrib/dev/rtwn/rtwn-rtl8192cfwE.fw.uu" \
compile-with "${NORMAL_FW}" \
no-obj no-implicit-rule \
clean "rtwn-rtl8192cfwE.fw"
rtwn-rtl8192cfwE_B.c optional rtwn-rtl8192cfwE_B | rtwnfw \
compile-with "${AWK} -f $S/tools/fw_stub.awk rtwn-rtl8192cfwE_B.fw:rtwn-rtl8192cfwE_B:111 -mrtwn-rtl8192cfwE_B -c${.TARGET}" \
no-implicit-rule before-depend local \
clean "rtwn-rtl8192cfwE_B.c"
rtwn-rtl8192cfwE_B.fwo optional rtwn-rtl8192cfwE_B | rtwnfw \
dependency "rtwn-rtl8192cfwE_B.fw" \
compile-with "${NORMAL_FWO}" \
no-implicit-rule \
clean "rtwn-rtl8192cfwE_B.fwo"
rtwn-rtl8192cfwE_B.fw optional rtwn-rtl8192cfwE_B | rtwnfw \
dependency "$S/contrib/dev/rtwn/rtwn-rtl8192cfwE_B.fw.uu" \
compile-with "${NORMAL_FW}" \
no-obj no-implicit-rule \
clean "rtwn-rtl8192cfwE_B.fw"
rtwn-rtl8192cfwT.c optional rtwn-rtl8192cfwT | rtwnfw \
compile-with "${AWK} -f $S/tools/fw_stub.awk rtwn-rtl8192cfwT.fw:rtwn-rtl8192cfwT:111 -mrtwn-rtl8192cfwT -c${.TARGET}" \
no-implicit-rule before-depend local \
clean "rtwn-rtl8192cfwT.c"
rtwn-rtl8192cfwT.fwo optional rtwn-rtl8192cfwT | rtwnfw \
dependency "rtwn-rtl8192cfwT.fw" \
compile-with "${NORMAL_FWO}" \
no-implicit-rule \
clean "rtwn-rtl8192cfwT.fwo"
rtwn-rtl8192cfwT.fw optional rtwn-rtl8192cfwT | rtwnfw \
dependency "$S/contrib/dev/rtwn/rtwn-rtl8192cfwT.fw.uu" \
compile-with "${NORMAL_FW}" \
no-obj no-implicit-rule \
clean "rtwn-rtl8192cfwT.fw"
rtwn-rtl8192cfwU.c optional rtwn-rtl8192cfwU | rtwnfw \
compile-with "${AWK} -f $S/tools/fw_stub.awk rtwn-rtl8192cfwU.fw:rtwn-rtl8192cfwU:111 -mrtwn-rtl8192cfwU -c${.TARGET}" \
no-implicit-rule before-depend local \
@ -2505,20 +2645,34 @@ rtwn-rtl8192cfwU.fw optional rtwn-rtl8192cfwU | rtwnfw \
compile-with "${NORMAL_FW}" \
no-obj no-implicit-rule \
clean "rtwn-rtl8192cfwU.fw"
rtwn-rtl8192cfwU_B.c optional rtwn-rtl8192cfwU_B | rtwnfw \
compile-with "${AWK} -f $S/tools/fw_stub.awk rtwn-rtl8192cfwU_B.fw:rtwn-rtl8192cfwU_B:111 -mrtwn-rtl8192cfwU_B -c${.TARGET}" \
rtwn-rtl8812aufw.c optional rtwn-rtl8812aufw | rtwnfw \
compile-with "${AWK} -f $S/tools/fw_stub.awk rtwn-rtl8812aufw.fw:rtwn-rtl8812aufw:111 -mrtwn-rtl8812aufw -c${.TARGET}" \
no-implicit-rule before-depend local \
clean "rtwn-rtl8192cfwU_B.c"
rtwn-rtl8192cfwU_B.fwo optional rtwn-rtl8192cfwU_B | rtwnfw \
dependency "rtwn-rtl8192cfwU_B.fw" \
clean "rtwn-rtl8812aufw.c"
rtwn-rtl8812aufw.fwo optional rtwn-rtl8812aufw | rtwnfw \
dependency "rtwn-rtl8812aufw.fw" \
compile-with "${NORMAL_FWO}" \
no-implicit-rule \
clean "rtwn-rtl8192cfwU_B.fwo"
rtwn-rtl8192cfwU_B.fw optional rtwn-rtl8192cfwU_B | rtwnfw \
dependency "$S/contrib/dev/rtwn/rtwn-rtl8192cfwU_B.fw.uu" \
clean "rtwn-rtl8812aufw.fwo"
rtwn-rtl8812aufw.fw optional rtwn-rtl8812aufw | rtwnfw \
dependency "$S/contrib/dev/rtwn/rtwn-rtl8812aufw.fw.uu" \
compile-with "${NORMAL_FW}" \
no-obj no-implicit-rule \
clean "rtwn-rtl8192cfwU_B.fw"
clean "rtwn-rtl8812aufw.fw"
rtwn-rtl8821aufw.c optional rtwn-rtl8821aufw | rtwnfw \
compile-with "${AWK} -f $S/tools/fw_stub.awk rtwn-rtl8821aufw.fw:rtwn-rtl8821aufw:111 -mrtwn-rtl8821aufw -c${.TARGET}" \
no-implicit-rule before-depend local \
clean "rtwn-rtl8821aufw.c"
rtwn-rtl8821aufw.fwo optional rtwn-rtl8821aufw | rtwnfw \
dependency "rtwn-rtl8821aufw.fw" \
compile-with "${NORMAL_FWO}" \
no-implicit-rule \
clean "rtwn-rtl8821aufw.fwo"
rtwn-rtl8821aufw.fw optional rtwn-rtl8821aufw | rtwnfw \
dependency "$S/contrib/dev/rtwn/rtwn-rtl8821aufw.fw.uu" \
compile-with "${NORMAL_FW}" \
no-obj no-implicit-rule \
clean "rtwn-rtl8821aufw.fw"
dev/safe/safe.c optional safe
dev/scc/scc_if.m optional scc
dev/scc/scc_bfe_ebus.c optional scc ebus

View File

@ -678,8 +678,9 @@ UPLCOM_INTR_INTERVAL opt_uplcom.h
UVSCOM_DEFAULT_OPKTSIZE opt_uvscom.h
UVSCOM_INTR_INTERVAL opt_uvscom.h
# options for the Realtek RTL8188*U/RTL8192CU driver (urtwn)
URTWN_WITHOUT_UCODE opt_urtwn.h
# options for the Realtek rtwn driver
RTWN_DEBUG opt_rtwn.h
RTWN_WITHOUT_UCODE opt_rtwn.h
# Embedded system options
INIT_PATH

View File

@ -1,4 +1,4 @@
Copyright (c) 2010, Realtek Semiconductor Corporation
Copyright (c) 2010-2011, Realtek Semiconductor Corporation
All rights reserved.
Redistribution. Redistribution and use in binary form, without

View File

@ -1,4 +1,4 @@
begin 644 urtwn-rtl8188eufw.fw.uu
begin 644 rtwn-rtl8188eufw.fw.uu
MX8@0``L``0`!(1$G,#8``"T'```````````````````"14X`````````````
M````````P6\`````````````````````````````````````````````````
M````````````H>8````````"5O<`````````````````````````````````

View File

@ -0,0 +1,333 @@
begin 444 rtwn-rtl8192cfwE.fw.uu
MP8@"`$@````%$!!3PCD!`(%C`0`````````````````"0[H`````````````
M`````````E!$````````````````````````````````````````````````
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
-29"77>`D_Y*O(@"'%P``
`
end

View File

@ -1,4 +1,4 @@
begin 444 rtwn-rtl8192cfwU_B.fw.uu
begin 444 rtwn-rtl8192cfwE_B.fw.uu
MPH@"`%@``@`'%11$K#\!`,S,S,P````````````````"19L`````````````
M`````````EE4````````````````````````````````````````````````
M`````````````F2,```````"2[(```4$`P(``P8%!`,`!`8%!`(`!`@'!@0`

View File

@ -0,0 +1,362 @@
begin 644 rtwn-rtl8192cfwT.fw.uu
MP8@"!5@``@`2!1<2WCX``)08`@`````````````````"1C``````````````
M`````````F#R````````````````````````````````````````````````
M`````````````FB1```````"2X<```4$`P(``P8%!`,`!`8%!`(`!`@'!@0`
M!@H)"`8`"`H)"`0`"`H)"`(`"`H)"```"!(1$`@`$!H9&!``&"(A(!@`("(A
M(!``("(A(`@`("(A'`@`("(A%`@`("(@&`@`(#$P(!``,#$P&```,#$O$!``
M,#$L$!``,#$H$```,#$@$```,#$0$```,`0$!`4$!`4'!P<("@0$!`0&"@L-
M!04'!P@+#0\$!`0%!P<)"0P.$!(&!PD*#`X1$PD)"0D,#A$3````````````
M)"8J&!H='R$G*2H````?(R@J+``$``0`"``0`!@`)``P`$@`8`"0`,``V`!0
M`'@`H`#(`4`!D`'@`C`!+`%``>`"T`/H!+`&0`?0``(``@`$``@`#``2`!@`
M)``P`$@`8`!L`"@`/`!0`&0`H`#(`/`!&`!D`*``\`%H`?0"6`,@`^@"`@("
M`@(#`P0$!0<"`P0*#`X0$@4'!P@+$B0\`0$!`0$"`P0%!@<(`0(#!`4&!P@%
M!@<("0H+#"`>'!@0&```````````````````````````````````````````
M````````````````````````````````````````````````NP$,Y8(I]8+E
M@SKU@^`B4`;I)8+XYB*[_@;I)8+XXB+E@BGU@N6#.O6#Y),BNP$&B8**@_`B
M4`+W(KO^`?,B^+L!#>6"*?6"Y8,Z]8/H\")0!NDE@LCV(KO^!>DE@LCR(L7P
M^*/@*/#%\/CE@A6"<`(5@^`X\"*[`0J)@HJ#X/7PH^`B4`:'\`GG&2*[_@?C
M]?`)XQDBB8**@^23]?!T`9,BNP$0Y8(I]8+E@SKU@^#U\*/@(E`)Z26"^(;P
M".8BN_X*Z26"^.+U\`CB(N6#*O6#Z9/U\*/IDR*[`0J)@HJ#\.7PH_`B4`;W
M":?P&2*[_@;SY?`)\QDB^+L!$>6"*?6"Y8,Z]8/H\.7PH_`B4`GI)8+(]@BF
M\"*[_@GI)8+(\N7P"/(B[TO_[DK^[4G][$C\(N#\H^#]H^#^H^#_(J0E@O6"
MY?`U@_6#(N#[H^#ZH^#Y(OC@^Z.CX/DE\/#E@A6"<`(5@^#Z./`BZ_"CZO"C
MZ?`BT(/0@OCDDW`2=`&3<`VCHY/X=`&3]8*(@^1S=`*3:&#OHZ.C@-_0@]""
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
05)"+3^1U\`$20H&`Q@"2````
`
end

View File

@ -1,17 +1,17 @@
begin 444 rtwn-rtl8192cfwU.fw.uu
MP8@"`$@````%$!!3PCD!`(%C`0`````````````````"0[H`````````````
M`````````E!$````````````````````````````````````````````````
M`````````````E;@```````"2VH```4$`P(``P8%!`,`!`8%!`(`!`@'!@0`
begin 644 rtwn-rtl8192cfwU.fw.uu
MP8@"!5@``@`2!1<1WCX!`)08`@`````````````````"1C``````````````
M`````````F#R````````````````````````````````````````````````
M`````````````FB1```````"2X<```4$`P(``P8%!`,`!`8%!`(`!`@'!@0`
M!@H)"`8`"`H)"`0`"`H)"`(`"`H)"```"!(1$`@`$!H9&!``&"(A(!@`("(A
M(!``("(A(`@`("(A'`@`("(A%`@`("(@&`@`(#$P(!``,#$P&```,#$O$!``
M,#$L$!``,#$H$```,#$@$```,#$0$```,`0$!`4$!`0%!04&!@0$!`4%!08&
M!`0%!04%!@8$!`4%!04&!PH+#1`$!04&!@D,$0@("0D*#!`1!`0$!00$!0<'
M!P@*!`0$!`8*"PT%!0<'"`L-#P0$!`4'!PD)#`X0$@0$!04&"A$3"0D)"0P.
M$1,````````````D)BH8&AT?(2<I*@```!\C*"HL``0`!``(`!``&``D`#``
M2`!@`)``P`#8`%``>`"@`,@!0`&0`>`",`$L`4`!X`+0`^@$L`9`!]```@`"
M``0`"``,`!(`&``D`#``2`!@`&P`*``\`%``9`"@`,@`\`$8`&0`H`#P`6@!
M]`)8`R`#Z`("`@("`@,#!`0%!P0$!PH*#`P2!0<'"`L2)#P!`0$!`0(#!`4&
M!P@!`@,$!08'"`4&!P@)"@L,(!X<&!`8````````````````NP$,Y8(I]8+E
M,#$L$!``,#$H$```,#$@$```,#$0$```,`0$!`4$!`4'!P<("@0$!`0&"@L-
M!04'!P@+#0\$!`0%!P<)"0P.$!(&!PD*#`X1$PD)"0D,#A$3````````````
M)"8J&!H='R$G*2H````?(R@J+``$``0`"``0`!@`)``P`$@`8`"0`,``V`!0
M`'@`H`#(`4`!D`'@`C`!+`%``>`"T`/H!+`&0`?0``(``@`$``@`#``2`!@`
M)``P`$@`8`!L`"@`/`!0`&0`H`#(`/`!&`!D`*``\`%H`?0"6`,@`^@"`@("
M`@(#`P0$!0<"`P0*#`X0$@4'!P@+$B0\`0$!`0$"`P0%!@<(`0(#!`4&!P@%
M!@<("0H+#"`>'!@0&```````````````````````````````````````````
M````````````````````````````````````````````````NP$,Y8(I]8+E
M@SKU@^`B4`;I)8+XYB*[_@;I)8+XXB+E@BGU@N6#.O6#Y),BNP$&B8**@_`B
M4`+W(KO^`?,B^+L!#>6"*?6"Y8,Z]8/H\")0!NDE@LCV(KO^!>DE@LCR(L7P
M^*/@*/#%\/CE@A6"<`(5@^`X\"*[`0J)@HJ#X/7PH^`B4`:'\`GG&2*[_@?C
@ -20,314 +20,343 @@ M".8BN_X*Z26"^.+U\`CB(N6#*O6#Z9/U\*/IDR*[`0J)@HJ#\.7PH_`B4`;W
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
-29"77>`D_Y*O(@"'%P``
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
0%9"+3^1U\`$20H&`Q@#[F```
`
end

View File

@ -0,0 +1,716 @@
begin 644 rtwn-rtl8812aufw.fw.uu
M`940`!D````'(Q,D''T``/X)```````````````````"2Z`":%0`````````
M`````````FES``````````````````)P_0``````````````````````````
M`````````````FC7```````";Y@``!7P_P\````5\`\`````!?#_#P````7P
M#P`````0\/\/````$/`/`````/4/``````#P#P``````#0```````!#P__\`
M```0\#\`````%?`_`````!7PS_\````6#1<.%P\8$!D1&A(:$QH4&A4;_Q<.
M&!`9$1(:&Q4<_QW_'O\?____%`T.%14/%A`7$1@2&!,8_Q4-%A`0%Q@2&?\:
M_QO_'/\`````!`0,#`T,#@T7#Q@0&1$9$1D2&A0,#!8-%P\8$!D3&A0;%1P;
M'1P>'00$#!0-%`X4#Q40%A<1$A<,#!0.%0\6$!<2&!@9&1H9"@@#`P`$"0<#
M`P`$"`8#`@`$"`4#`0`$#0H'!0`(#`H'!``("PH&!0`("PH%`P`("PH#`@`(
M%!(,!``0%!()!``0)"(<$@`@)"(8#``@)"(4!@`@)"(/!``@)"$*!``@(R$,
M!``@(Q\*!``@(A\/!``@(1\6#``@,2\@%``P,2\8$``P,2P8#``P,2H4#``P
M,2@4```P,204```P,1X4```P!`0$!00$!0<'!P@*!`<*#A$3%!4#!`<'"`L-
M#P4%!P<("PT/!04'!P@+#0\'"`@*"@P.$!$1!PD)"PL-#Q$1$@4%!P<("PT/
M#P\%!0<'"`L-#P\/!`0$!0<'"0D,#A`2!08'#1`1$A('"`D)#`X1$PD)"0D,
M#A$3"0D)"0P.$1,%!@@)#`X2$A,4!P@*"PT0$1$4%@D)"0D,#A$3$Q,)"0D)
M#`X1$Q,3````````````)"8J````'R$E)R@`````(R8H*@`````C)B@J````
M`",F*"H`````("4G*2DJ`````"`E)RDI*@`````C)B@J*BH````?(R8H*BHJ
M````!`````0````(````$````!@````D````,````$@```!@````D````,``
M``#8````/````&0```!X````H````/````%````!D````>````"@````\```
M`4````&0```"6````R````2P```&0````,@```$8```!X````M````/H```$
ML```!D````?0````R````1@```'@```"T````^@```2P```&0```!]`````\
M````9````'@```"@````\````4````&0```!X````E@```,@````R````1@`
M``'@```"T````^@```?0```+N```$X@``!=P```?0````,@```$8```!X```
M`M````/H```$L```!D````?0```'T```!]````#(```!&````>````+0```#
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
4$E`$Y/"``W0!\)#]$.WPKP8BCIL`
`
end

View File

@ -0,0 +1,621 @@
begin 644 rtwn-rtl8821aufw.fw.uu
M`2$0`!8````1(A,Q?&P``%H-```````````````````"2;$"9],`````````
M`````````FA<``````````````````)OO@``````````````````````````
M`````````````F@$```````"7GD```````)OO17P_P\````5\`\`````!?#_
M#P````7P#P`````0\/\/````$/`/`````/4/``````#P#P``````#0``````
M`!#P__\````0\#\`````%?`_`````!7PS_\````*"`,#``0)!P,#``0(!@,"
M``0(!0,!``0-"@<%``@,"@<$``@+"@8%``@+"@4#``@+"@,"``@4$@P$`!`4
M$@D$`!`D(AP2`"`D(A@,`"`D(A0&`"`D(@\$`"`D(0H$`"`C(0P$`"`C'PH$
M`"`B'P\$`"`A'Q8,`"`Q+R`4`#`Q+Q@0`#`Q+!@,`#`Q*A0,`#`Q*!0``#`Q
M)!0``#`Q'A0``#`$!`0%!`0%!P<'"`H$!PH.$1,4%0,$!P<("PT/!04'!P@+
M#0\%!0<'"`L-#P<("`H*#`X0$1$'"0D+"PT/$1$2!04'!P@+#0\/#P4%!P<(
M"PT/#P\$!`0%!P<)"0P.$!(%!@<-$!$2$@<("0D,#A$3"0D)"0P.$1,)"0D)
M#`X1$P4&"`D,#A(2$Q0'"`H+#1`1$106"0D)"0P.$1,3$PD)"0D,#A$3$Q,`
M```````````D)BH````?(24G*``````C)B@J`````",F*"H`````(R8H*@``
M```@)2<I*2H`````("4G*2DJ`````",F*"HJ*@```!\C)B@J*BH````$````
M!`````@````0````&````"0````P````2````&````"0````P````-@````\
M````9````'@```"@````\````4````&0```!X````*````#P```!0````9``
M``)8```#(```!+````9`````R````1@```'@```"T````^@```2P```&0```
M!]````#(```!&````>````+0```#Z```!+````9````'T````#P```!D````
M>````*````#P```!0````9````'@```"6````R````#(```!&````>````+0
M```#Z```!]````NX```3B```%W```!]`````R````1@```'@```"T````^@`
M``2P```&0```!]````?0```'T````,@```$8```!X````M````/H```$L```
M!D````?0```'T```!]```@`"``0`"``,`!(`&``D`#``2`!@`&P`%``R`#P`
M4`!X`*``R`#P`%``>`"@`,@!+`&0`E@#(`!D`(P`\`%H`?0"6`,@`^@`9`",
M`/`!:`'T`E@#(`/H`!X`,@`\`%``>`"@`,@`\`$L`9``9`",`/`!:`'T`^@%
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
GX%3O\)"A1>#_D*$CX-.?0`^0H)#@M`$+D*$7X%3[\"(26%4B`!Y3
`
end

View File

@ -1,39 +0,0 @@
Copyright (c) 2010, Realtek Semiconductor Corporation
All rights reserved.
Redistribution. Redistribution and use in binary form, without
modification, are permitted provided that the following conditions are
met:
* Redistributions must reproduce the above copyright notice and the
following disclaimer in the documentation and/or other materials
provided with the distribution.
* Neither the name of Realtek Semiconductor Corporation nor the names of its
suppliers may be used to endorse or promote products derived from this
software without specific prior written permission.
* No reverse engineering, decompilation, or disassembly of this software
is permitted.
Limited patent license. Realtek Semiconductor Corporation grants a world-wide,
royalty-free, non-exclusive license under patents it now or hereafter
owns or controls to make, have made, use, import, offer to sell and
sell ("Utilize") this software, but solely to the extent that any
such patent is necessary to Utilize the software alone, or in
combination with an operating system licensed under an approved Open
Source license as listed by the Open Source Initiative at
http://opensource.org/licenses. The patent license shall not apply to
any other combinations which include this software. No hardware per
se is licensed hereunder.
DISCLAIMER. 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 OWNER 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.

View File

@ -1,285 +0,0 @@
begin-base64 644 urtwn-rtl8192cfwT.fw.uu
wYgCADwAAAAKKBQZrD4AAEM0AQAAAAAAAAAAAAAAAAACdFwAAAAAAAAAAAAAAAAAAAAAAlmZAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAnK6AAAAAAACaAEAAAUE
AwIAAwYFBAMABAYFBAIABAgHBgQABgoJCAYACAoJCAQACAoJCAIACAoJCAAACBIREAgAEBoZGBAA
GCIhIBgAICIhIBAAICIhIAgAICIhHAgAICIhFAgAICIgGAgAIDEwIBAAMDEwGAAAMDEvEBAAMDEs
EBAAMDEoEAAAMDEgEAAAMDEQEAAAMAQEBAUEBAUHBwcICgQEBAQGCg0OBQUHBwgMFBQEBAQFBwcJ
CQwOExMEBAQEBQoREwkJCQkMExQVBQUFBQUFBQYGBgYGBQUFBgYGBgYFBQYGBgYGBgUFBQUJCQkJ
Cw0QEgUJCgwNDhASCQkODhAQEhIAAAAAAAAAAAAkJioYGh0fIScpKgAAAB8jKCosAAQABAAIABAA
GAAkADAASABgAJAAwADYAFAAeACgAMgBQAGQAeACMAEsAUAB4ALQA+gEsAZAB9AAAgACAAQACAAM
ABIAGAAkADAASABgAGwAKAA8AFAAZACgAMgA8AEYAGQAoADwAWgB9AJYAyAD6AAAAAABAgICAwQF
CAECAgIEBw8eBQYHDxIjRmQBAQEBAQIDBAUGBwgBAgMEBQYHCAUGBwgJCgsMIh8eGAAgAAAAAAAA
AAAAAAAAqwd0hCv1guQ0BPWD4FR/kJd08OBUH6Pw+nXwCeukJGf1guXwNJP1g+D5kJd38Osl4CSB
9YLkNJL1g+D/o+CQl3jP8KPv8Osl4CQE9YLkNJb1g+D/o+CQl3rP8KPv8Ool4CRm9YLkNEH1g+ST
/nQBk//k/P3rJeAl4CTh9YLkNJL1gxIqf+rDmUADAkNZkJd14P90xSv1guQ0lvWD7/DvBJCXdvCQ
l3fg/5CXduD+059AAwJDmO7DlBBAIe4k8P90AX4AqAcIgAXDM84zztj5/5CXeOBe/qPgX05wJ5CX
duD/w5QQUEp0AX4AqAcIgAXDM84zztj5/5CXeuBe/qPgX05gLZCXduD/ZBNgCe9kEmAE77QRDZCX
eOAw4AaQl3Z0GPCQl3bgkJd18JCXdPCASJCXduAE8AJCxJCXd+D6kJd14P9qcHl0xSv1guQ0lvWD
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
l1rg/yXgJMD1guQ0kfWD5PCj8O8l4CSD9YLkNJT1g+Two/DvJeAkw/WC5DSU9YPk8KPwkJda4ATw
AkUOIu9wAwJQxZCXTeBgAwJVB5CXOeD8o+D9o+D+o+D/kICFEip/f4x+CBIv2ZCW5eD8o+D9o+D+
o+D/kICFEip/f0R+CBIv2ZCW6eD8o+D9o+D+o+D/kICFEip/f1x+CBIv2ZCW7eD8o+D9o+D+o+D/
kICFEip/f2x+DhIv2ZCW8eD8o+D9o+D+o+D/kICFEip/f3B+DhIv2ZCW9eD8o+D9o+D+o+D/kICF
Eip/f3R+DhIv2ZCW+eD8o+D9o+D+o+D/kICFEip/f3h+DhIv2ZCW/eD8o+D9o+D+o+D/kICFEip/
f3x+DhIv2ZCXAeD8o+D9o+D+o+D/kICFEip/f4B+DhIv2ZCXBeD8o+D9o+D+o+D/kICFEip/f4R+
DhIv2ZCXCeD8o+D9o+D+o+D/kICFEip/f4h+DhIv2ZCXDeD8o+D9o+D+o+D/kICFEip/f4x+DhIv
2ZCXEeD8o+D9o+D+o+D/kICFEip/f9B+DhIv2ZCXFeD8o+D9o+D+o+D/kICFEip/f9R+DhIv2ZCX
GeD8o+D9o+D+o+D/kICFEip/f9h+DhIv2ZCXHeD8o+D9o+D+o+D/kICFEip/f9x+DhIv2ZCXIeD8
o+D9o+D+o+D/kICFEip/f+B+DhIv2ZCXJeD8o+D9o+D+o+D/kICFEip/f+x+DhIv2ZCXKeD8o+D9
o+D+o+D/kICFEip/fwR+DBIv2ZCXLeD8o+D9o+D+o+D/kICFEip/fwR+DRIv2ZCXMeD8o+D9o+D+
o+D/kICFEip/fwx+CRIv2ZCXNeD8o+D9o+D+o+D/kICFEip/fwR+CBIv2ZCXTXQB8CKQl03gZAFg
AwJVB3+MfggSJ96QlzkSKn9/RH4IEifekJblEip/f1x+CBIn3pCW6RIqf39sfg4SJ96Qlu0SKn9/
cH4OEifekJbxEip/f3R+DhIn3pCW9RIqf394fg4SJ96QlvkSKn9/fH4OEifekJb9Eip/f4B+DhIn
3pCXARIqf3+Efg4SJ96QlwUSKn9/iH4OEifekJcJEip/f4x+DhIn3pCXDRIqf3/Qfg4SJ96QlxES
Kn9/1H4OEifekJcVEip/f9h+DhIn3pCXGRIqf3/cfg4SJ96Qlx0SKn9/4H4OEifekJchEip/f+x+
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
RAN1RQDk+/1/VH4BEjWrkAFXdAXw5S4w5DqQATZ0EPDlZWQBcC7lZmAqkAFX5PCQATx0AvCQl67k
8JCXr+BU/fDgVANwDpCXqfCQl6vg/30BEm9J5S4w5RKQATZ0IPDlZbQBB+VmYAMSffrlLjDmKpAB
NnRA8OVlZAFwHuVmYBqQl6/gVP7w4FQDcA6Ql6nwkJer4P99ARJvSeUvMOEJkAE3dALwEnwodJkE
kAHE8HRZo/DQB9AG0AXQBNAD0ALQAdAA0NDQgtCD0PDQ4DKQBER0EfCjdPDwo3QP8KPk8JCXWvCQ
l1rg/8OUEFAUdKQv9YLkNAT1g+TwkJda4ATwgOLkkJda8JCXWuD7w5QgQAMCXzHg/3XwCqQkAPWC
5fA0kPWD5PCj8HXwCu+kJAL1guXwNJD1g+Two/B18ArvpCQE9YLl8DSQ9YPk8KPwdfAK76QkBvWC
5fA0kPWD5PCj8HXwCu+kJAj1guXwNJD1g+Two/B0pC/1guQ0lvWDdBPwdGQv9YLkNJX1g+Tw7yXg
JMD1guQ0kfWD5PCj8O8l4CSD9YLkNJT1g+Two/DvJeAkA/WC5DSV9YPk8KPw7yXgJMP1guQ0lPWD
5PCj8O8l4CSE9YLkNJX1g+Two/DvJeAkxPWC5DSV9YPk8KPwdGQv9YLkNJb1g+TwdEQv9YLkNJb1
g+TwdIQv9YLkNJb1g+TwkEHEk/50AZP/kEGMdAGTL//kkz7DE/7vE//k/P3rJeAl4CTh9YLkNJL1
gxIqf3XwCeukJGr1guXwNJP1g3QB8HXwCeukJGn1guXwNJP1g3QB8HTBK/WC5DSS9YN0DPB18Anr
pCRl9YLl8DST9YN0//Cj8HXwCeukJGP1guXwNJP1g+Two3QP8HXwCeukJGf1guXwNJP1g3QT8HXw
CeukJGj1guXwNJP1g+TwdIQr9YLkNAT1g3QT8JCXWuAE8AJdZiKpB3SEKfWC5DQE9YPgVH+Ql3Tw
4FQf/5CXd/B18AnppCRo9YLl8DST9YPgkJd58HXwCemkJGf1guXwNJP1g+D+kJd68Okl4CQE9YLk
NJb1g+D7o+CQl3vL8KPr8Okl4CSB9YLkNJL1g+D7o+CQl33L8KPr8O/TnkAMkJd64JCXd/CQl3Tw
7XADAmCRkJd47fCQl3TgMOYOkJd34JCXdPCQl3jgFPCQl3jgcAMCYJGQl3fg/9OUAFADAmCR5JCX
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
4fs=
====

View File

@ -1,285 +0,0 @@
begin-base64 644 urtwn-rtl8192cfwU.fw.uu
wYgCADwAAAAKKBQkrD4BAEM0AQAAAAAAAAAAAAAAAAACdFwAAAAAAAAAAAAAAAAAAAAAAlmZAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAnK6AAAAAAACaAEAAAUE
AwIAAwYFBAMABAYFBAIABAgHBgQABgoJCAYACAoJCAQACAoJCAIACAoJCAAACBIREAgAEBoZGBAA
GCIhIBgAICIhIBAAICIhIAgAICIhHAgAICIhFAgAICIgGAgAIDEwIBAAMDEwGAAAMDEvEBAAMDEs
EBAAMDEoEAAAMDEgEAAAMDEQEAAAMAQEBAUEBAUHBwcICgQEBAQGCg0OBQUHBwgMFBQEBAQFBwcJ
CQwOExMEBAQEBQoREwkJCQkMExQVBQUFBQUFBQYGBgYGBQUFBgYGBgYFBQYGBgYGBgUFBQUJCQkJ
Cw0QEgUJCgwNDhASCQkODhAQEhIAAAAAAAAAAAAkJioYGh0fIScpKgAAAB8jKCosAAQABAAIABAA
GAAkADAASABgAJAAwADYAFAAeACgAMgBQAGQAeACMAEsAUAB4ALQA+gEsAZAB9AAAgACAAQACAAM
ABIAGAAkADAASABgAGwAKAA8AFAAZACgAMgA8AEYAGQAoADwAWgB9AJYAyAD6AAAAAABAgICAwQF
CAECAgIEBw8eBQYHDxIjRmQBAQEBAQIDBAUGBwgBAgMEBQYHCAUGBwgJCgsMIh8eGAAgAAAAAAAA
AAAAAAAAqwd0hCv1guQ0BPWD4FR/kJd08OBUH6Pw+nXwCeukJGf1guXwNJP1g+D5kJd38Osl4CSB
9YLkNJL1g+D/o+CQl3jP8KPv8Osl4CQE9YLkNJb1g+D/o+CQl3rP8KPv8Ool4CRm9YLkNEH1g+ST
/nQBk//k/P3rJeAl4CTh9YLkNJL1gxIlCOrDmUADAkNZkJd14P90xSv1guQ0lvWD7/DvBJCXdvCQ
l3fg/5CXduD+059AAwJDmO7DlBBAIe4k8P90AX4AqAcIgAXDM84zztj5/5CXeOBe/qPgX05wJ5CX
duD/w5QQUEp0AX4AqAcIgAXDM84zztj5/5CXeuBe/qPgX05gLZCXduD/ZBNgCe9kEmAE77QRDZCX
eOAw4AaQl3Z0GPCQl3bgkJd18JCXdPCASJCXduAE8AJCxJCXd+D6kJd14P9qcHl0xSv1guQ0lvWD
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
l1rg/yXgJMD1guQ0kfWD5PCj8O8l4CSD9YLkNJT1g+Two/DvJeAkw/WC5DSU9YPk8KPwkJda4ATw
AkUOIu9wAwJQxZCXTeBgAwJVB5CXOeD8o+D9o+D+o+D/kICWEiUIf4x+CBIrCJCW5eD8o+D9o+D+
o+D/kICWEiUIf0R+CBIrCJCW6eD8o+D9o+D+o+D/kICWEiUIf1x+CBIrCJCW7eD8o+D9o+D+o+D/
kICWEiUIf2x+DhIrCJCW8eD8o+D9o+D+o+D/kICWEiUIf3B+DhIrCJCW9eD8o+D9o+D+o+D/kICW
EiUIf3R+DhIrCJCW+eD8o+D9o+D+o+D/kICWEiUIf3h+DhIrCJCW/eD8o+D9o+D+o+D/kICWEiUI
f3x+DhIrCJCXAeD8o+D9o+D+o+D/kICWEiUIf4B+DhIrCJCXBeD8o+D9o+D+o+D/kICWEiUIf4R+
DhIrCJCXCeD8o+D9o+D+o+D/kICWEiUIf4h+DhIrCJCXDeD8o+D9o+D+o+D/kICWEiUIf4x+DhIr
CJCXEeD8o+D9o+D+o+D/kICWEiUIf9B+DhIrCJCXFeD8o+D9o+D+o+D/kICWEiUIf9R+DhIrCJCX
GeD8o+D9o+D+o+D/kICWEiUIf9h+DhIrCJCXHeD8o+D9o+D+o+D/kICWEiUIf9x+DhIrCJCXIeD8
o+D9o+D+o+D/kICWEiUIf+B+DhIrCJCXJeD8o+D9o+D+o+D/kICWEiUIf+x+DhIrCJCXKeD8o+D9
o+D+o+D/kICWEiUIfwR+DBIrCJCXLeD8o+D9o+D+o+D/kICWEiUIfwR+DRIrCJCXMeD8o+D9o+D+
o+D/kICWEiUIfwx+CRIrCJCXNeD8o+D9o+D+o+D/kICWEiUIfwR+CBIrCJCXTXQB8CKQl03gZAFg
AwJVB3+MfggSImWQlzkSJQh/RH4IEiJlkJblEiUIf1x+CBIiZZCW6RIlCH9sfg4SImWQlu0SJQh/
cH4OEiJlkJbxEiUIf3R+DhIiZZCW9RIlCH94fg4SImWQlvkSJQh/fH4OEiJlkJb9EiUIf4B+DhIi
ZZCXARIlCH+Efg4SImWQlwUSJQh/iH4OEiJlkJcJEiUIf4x+DhIiZZCXDRIlCH/Qfg4SImWQlxES
JQh/1H4OEiJlkJcVEiUIf9h+DhIiZZCXGRIlCH/cfg4SImWQlx0SJQh/4H4OEiJlkJchEiUIf+x+
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
RAN1RQDk+/1/VH4BEjBikAFXdAXw5S4w5DqQATZ0EPDlZWQBcC7lZmAqkAFX5PCQATx0AvCQl67k
8JCXr+BU/fDgVANwDpCXqfCQl6vg/30BEm9J5S4w5RKQATZ0IPDlZbQBB+VmYAMSffrlLjDmKpAB
NnRA8OVlZAFwHuVmYBqQl6/gVP7w4FQDcA6Ql6nwkJer4P99ARJvSeUvMOEJkAE3dALwEnwodJkE
kAHE8HRZo/DQB9AG0AXQBNAD0ALQAdAA0NDQgtCD0PDQ4DKQBER0EfCjdPDwo3QP8KPk8JCXWvCQ
l1rg/8OUEFAUdKQv9YLkNAT1g+TwkJda4ATwgOLkkJda8JCXWuD7w5QgQAMCXzHg/3XwCqQkAPWC
5fA0kPWD5PCj8HXwCu+kJAL1guXwNJD1g+Two/B18ArvpCQE9YLl8DSQ9YPk8KPwdfAK76QkBvWC
5fA0kPWD5PCj8HXwCu+kJAj1guXwNJD1g+Two/B0pC/1guQ0lvWDdBPwdGQv9YLkNJX1g+Tw7yXg
JMD1guQ0kfWD5PCj8O8l4CSD9YLkNJT1g+Two/DvJeAkA/WC5DSV9YPk8KPw7yXgJMP1guQ0lPWD
5PCj8O8l4CSE9YLkNJX1g+Two/DvJeAkxPWC5DSV9YPk8KPwdGQv9YLkNJb1g+TwdEQv9YLkNJb1
g+TwdIQv9YLkNJb1g+TwkEHEk/50AZP/kEGMdAGTL//kkz7DE/7vE//k/P3rJeAl4CTh9YLkNJL1
gxIlCHXwCeukJGr1guXwNJP1g3QB8HXwCeukJGn1guXwNJP1g3QB8HTBK/WC5DSS9YN0DPB18Anr
pCRl9YLl8DST9YN0//Cj8HXwCeukJGP1guXwNJP1g+Two3QP8HXwCeukJGf1guXwNJP1g3QT8HXw
CeukJGj1guXwNJP1g+TwdIQr9YLkNAT1g3QT8JCXWuAE8AJdZiKpB3SEKfWC5DQE9YPgVH+Ql3Tw
4FQf/5CXd/B18AnppCRo9YLl8DST9YPgkJd58HXwCemkJGf1guXwNJP1g+D+kJd68Okl4CQE9YLk
NJb1g+D7o+CQl3vL8KPr8Okl4CSB9YLkNJL1g+D7o+CQl33L8KPr8O/TnkAMkJd64JCXd/CQl3Tw
7XADAmCRkJd47fCQl3TgMOYOkJd34JCXdPCQl3jgFPCQl3jgcAMCYJGQl3fg/9OUAFADAmCR5JCX
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
po4=
====

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,213 @@
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/if_rtwn_beacon.h>
#include <dev/rtwn/if_rtwn_debug.h>
#include <dev/rtwn/if_rtwn_tx.h>
#include <dev/rtwn/rtl8192c/r92c_reg.h>
static void
rtwn_reset_beacon_valid(struct rtwn_softc *sc, int id)
{
KASSERT (id == 0 || id == 1, ("wrong port id %d\n", id));
rtwn_setbits_1_shift(sc, sc->bcn_status_reg[id],
R92C_TDECTRL_BCN_VALID, 0, 2);
RTWN_DPRINTF(sc, RTWN_DEBUG_BEACON,
"%s: 'beacon valid' bit for vap %d was unset\n",
__func__, id);
}
static int
rtwn_check_beacon_valid(struct rtwn_softc *sc, int id)
{
uint16_t reg;
int ntries;
if (id == RTWN_VAP_ID_INVALID)
return (0);
reg = sc->bcn_status_reg[id];
for (ntries = 0; ntries < 10; ntries++) {
if (rtwn_read_4(sc, reg) & R92C_TDECTRL_BCN_VALID) {
RTWN_DPRINTF(sc, RTWN_DEBUG_BEACON,
"%s: beacon for vap %d was recognized\n",
__func__, id);
break;
}
rtwn_delay(sc, 100);
}
if (ntries == 10)
return (ETIMEDOUT);
return (0);
}
void
rtwn_switch_bcnq(struct rtwn_softc *sc, int id)
{
if (sc->cur_bcnq_id != id) {
/* Wait until any previous transmit completes. */
(void) rtwn_check_beacon_valid(sc, sc->cur_bcnq_id);
/* Change current port. */
rtwn_beacon_select(sc, id);
sc->cur_bcnq_id = id;
}
/* Reset 'beacon valid' bit. */
rtwn_reset_beacon_valid(sc, id);
}
int
rtwn_setup_beacon(struct rtwn_softc *sc, struct ieee80211_node *ni)
{
struct ieee80211vap *vap = ni->ni_vap;
struct rtwn_vap *uvp = RTWN_VAP(vap);
struct mbuf *m;
RTWN_ASSERT_LOCKED(sc);
if (ni->ni_chan == IEEE80211_CHAN_ANYC)
return (EINVAL);
m = ieee80211_beacon_alloc(ni);
if (m == NULL) {
device_printf(sc->sc_dev,
"%s: could not allocate beacon frame\n", __func__);
return (ENOMEM);
}
if (uvp->bcn_mbuf != NULL)
m_freem(uvp->bcn_mbuf);
uvp->bcn_mbuf = m;
rtwn_beacon_set_rate(sc, &uvp->bcn_desc.txd[0],
IEEE80211_IS_CHAN_5GHZ(ni->ni_chan));
return (rtwn_tx_beacon_check(sc, uvp));
}
/*
* Push a beacon frame into the chip. Beacon will
* be repeated by the chip every R92C_BCN_INTERVAL.
*/
static int
rtwn_tx_beacon(struct rtwn_softc *sc, struct rtwn_vap *uvp)
{
int error;
RTWN_ASSERT_LOCKED(sc);
RTWN_DPRINTF(sc, RTWN_DEBUG_BEACON,
"%s: sending beacon for vap %d\n", __func__, uvp->id);
error = rtwn_tx_start(sc, NULL, uvp->bcn_mbuf, &uvp->bcn_desc.txd[0],
IEEE80211_FC0_TYPE_MGT, uvp->id);
return (error);
}
void
rtwn_update_beacon(struct ieee80211vap *vap, int item)
{
struct rtwn_softc *sc = vap->iv_ic->ic_softc;
struct rtwn_vap *uvp = RTWN_VAP(vap);
struct ieee80211_beacon_offsets *bo = &vap->iv_bcn_off;
struct ieee80211_node *ni = vap->iv_bss;
int mcast = 0;
RTWN_LOCK(sc);
if (uvp->bcn_mbuf == NULL) {
uvp->bcn_mbuf = ieee80211_beacon_alloc(ni);
if (uvp->bcn_mbuf == NULL) {
device_printf(sc->sc_dev,
"%s: could not allocate beacon frame\n", __func__);
RTWN_UNLOCK(sc);
return;
}
}
RTWN_UNLOCK(sc);
if (item == IEEE80211_BEACON_TIM)
mcast = 1; /* XXX */
setbit(bo->bo_flags, item);
ieee80211_beacon_update(ni, uvp->bcn_mbuf, mcast);
RTWN_LOCK(sc);
rtwn_tx_beacon(sc, uvp);
RTWN_UNLOCK(sc);
}
int
rtwn_tx_beacon_check(struct rtwn_softc *sc, struct rtwn_vap *uvp)
{
int ntries, error;
for (ntries = 0; ntries < 5; ntries++) {
rtwn_reset_beacon_valid(sc, uvp->id);
error = rtwn_tx_beacon(sc, uvp);
if (error != 0)
continue;
error = rtwn_check_beacon_valid(sc, uvp->id);
if (error == 0)
break;
}
if (ntries == 5) {
device_printf(sc->sc_dev,
"%s: cannot push beacon into chip, error %d!\n",
__func__, error);
return (error);
}
return (0);
}

View File

@ -0,0 +1,27 @@
/*-
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $FreeBSD$
*/
#ifndef IF_RTWN_BEACON_H
#define IF_RTWN_BEACON_H
void rtwn_switch_bcnq(struct rtwn_softc *, int);
int rtwn_setup_beacon(struct rtwn_softc *, struct ieee80211_node *);
void rtwn_update_beacon(struct ieee80211vap *, int);
int rtwn_tx_beacon_check(struct rtwn_softc *, struct rtwn_vap *);
#endif /* IF_RTWN_BEACON_H */

View File

@ -0,0 +1,128 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/if_rtwn_calib.h>
#include <dev/rtwn/if_rtwn_debug.h>
#include <dev/rtwn/if_rtwn_task.h>
static void
rtwn_temp_calib(struct rtwn_softc *sc)
{
uint8_t temp;
RTWN_ASSERT_LOCKED(sc);
if (!(sc->sc_flags & RTWN_TEMP_MEASURED)) {
/* Start measuring temperature. */
RTWN_DPRINTF(sc, RTWN_DEBUG_TEMP,
"%s: start measuring temperature\n", __func__);
rtwn_temp_measure(sc);
sc->sc_flags |= RTWN_TEMP_MEASURED;
return;
}
sc->sc_flags &= ~RTWN_TEMP_MEASURED;
/* Read measured temperature. */
temp = rtwn_temp_read(sc);
if (temp == 0) { /* Read failed, skip. */
RTWN_DPRINTF(sc, RTWN_DEBUG_TEMP,
"%s: temperature read failed, skipping\n", __func__);
return;
}
RTWN_DPRINTF(sc, RTWN_DEBUG_TEMP,
"temperature: previous %u, current %u\n",
sc->thcal_temp, temp);
/*
* Redo LC/IQ calibration if temperature changed significantly since
* last calibration.
*/
if (sc->thcal_temp == 0xff) {
/* efuse value is absent; do LCK at initial status. */
rtwn_lc_calib(sc);
sc->thcal_temp = temp;
} else if (abs(temp - sc->thcal_temp) > sc->temp_delta) {
RTWN_DPRINTF(sc, RTWN_DEBUG_TEMP,
"%s: LC/IQ calib triggered by temp: %u -> %u\n",
__func__, sc->thcal_temp, temp);
rtwn_lc_calib(sc);
rtwn_iq_calib(sc);
/* Record temperature of last calibration. */
sc->thcal_temp = temp;
}
}
static void
rtwn_calib_cb(struct rtwn_softc *sc, union sec_param *data)
{
/* Do temperature compensation. */
rtwn_temp_calib(sc);
#ifndef RTWN_WITHOUT_UCODE
if (sc->sc_ratectl == RTWN_RATECTL_FW) {
/* Refresh per-node RSSI. */
rtwn_set_rssi(sc);
}
#endif
if (sc->vaps_running > sc->monvaps_running)
callout_reset(&sc->sc_calib_to, 2*hz, rtwn_calib_to, sc);
}
void
rtwn_calib_to(void *arg)
{
struct rtwn_softc *sc = arg;
/* Do it in a process context. */
rtwn_cmd_sleepable(sc, NULL, 0, rtwn_calib_cb);
}

View File

@ -0,0 +1,24 @@
/*-
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $FreeBSD$
*/
#ifndef IF_RTWN_CALIB_H
#define IF_RTWN_CALIB_H
void rtwn_calib_to(void *);
#endif /* IF_RTWN_CALIB_H */

360
sys/dev/rtwn/if_rtwn_cam.c Normal file
View File

@ -0,0 +1,360 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/if_rtwn_cam.h>
#include <dev/rtwn/if_rtwn_debug.h>
#include <dev/rtwn/if_rtwn_task.h>
#include <dev/rtwn/rtl8192c/r92c_reg.h>
void
rtwn_init_cam(struct rtwn_softc *sc)
{
/* Invalidate all CAM entries. */
rtwn_write_4(sc, R92C_CAMCMD,
R92C_CAMCMD_POLLING | R92C_CAMCMD_CLR);
}
static int
rtwn_cam_write(struct rtwn_softc *sc, uint32_t addr, uint32_t data)
{
int error;
error = rtwn_write_4(sc, R92C_CAMWRITE, data);
if (error != 0)
return (error);
error = rtwn_write_4(sc, R92C_CAMCMD,
R92C_CAMCMD_POLLING | R92C_CAMCMD_WRITE |
SM(R92C_CAMCMD_ADDR, addr));
return (error);
}
void
rtwn_init_seccfg(struct rtwn_softc *sc)
{
uint16_t seccfg;
/* Select decryption / encryption flags. */
seccfg = 0;
switch (sc->sc_hwcrypto) {
case RTWN_CRYPTO_SW:
break; /* nothing to do */
case RTWN_CRYPTO_PAIR:
/* NB: TXUCKEY_DEF / RXUCKEY_DEF are required for RTL8192C */
seccfg = R92C_SECCFG_TXUCKEY_DEF | R92C_SECCFG_RXUCKEY_DEF |
R92C_SECCFG_TXENC_ENA | R92C_SECCFG_RXDEC_ENA |
R92C_SECCFG_MC_SRCH_DIS;
break;
case RTWN_CRYPTO_FULL:
seccfg = R92C_SECCFG_TXUCKEY_DEF | R92C_SECCFG_RXUCKEY_DEF |
R92C_SECCFG_TXENC_ENA | R92C_SECCFG_RXDEC_ENA |
R92C_SECCFG_TXBCKEY_DEF | R92C_SECCFG_RXBCKEY_DEF;
break;
default:
KASSERT(0, ("%s: case %d was not handled\n", __func__,
sc->sc_hwcrypto));
break;
}
RTWN_DPRINTF(sc, RTWN_DEBUG_KEY, "%s: seccfg %04X, hwcrypto %d\n",
__func__, seccfg, sc->sc_hwcrypto);
rtwn_write_2(sc, R92C_SECCFG, seccfg);
}
int
rtwn_key_alloc(struct ieee80211vap *vap, struct ieee80211_key *k,
ieee80211_keyix *keyix, ieee80211_keyix *rxkeyix)
{
struct rtwn_softc *sc = vap->iv_ic->ic_softc;
int i, start;
if (&vap->iv_nw_keys[0] <= k &&
k < &vap->iv_nw_keys[IEEE80211_WEP_NKID]) {
*keyix = k - vap->iv_nw_keys;
if (sc->sc_hwcrypto != RTWN_CRYPTO_FULL)
k->wk_flags |= IEEE80211_KEY_SWCRYPT;
else {
RTWN_LOCK(sc);
if (isset(sc->keys_bmap, *keyix)) {
device_printf(sc->sc_dev,
"%s: group key slot %d is already used!\n",
__func__, *keyix);
/* XXX recover? */
RTWN_UNLOCK(sc);
return (0);
}
setbit(sc->keys_bmap, *keyix);
RTWN_UNLOCK(sc);
}
goto end;
}
start = sc->cam_entry_limit;
switch (sc->sc_hwcrypto) {
case RTWN_CRYPTO_SW:
k->wk_flags |= IEEE80211_KEY_SWCRYPT;
*keyix = 0;
goto end;
case RTWN_CRYPTO_PAIR:
/* all slots for pairwise keys. */
start = 0;
RTWN_LOCK(sc);
if (sc->sc_flags & RTWN_FLAG_CAM_FIXED)
start = 4;
RTWN_UNLOCK(sc);
break;
case RTWN_CRYPTO_FULL:
/* first 4 - for group keys, others for pairwise. */
start = 4;
break;
default:
KASSERT(0, ("%s: case %d was not handled!\n",
__func__, sc->sc_hwcrypto));
break;
}
RTWN_LOCK(sc);
for (i = start; i < sc->cam_entry_limit; i++) {
if (isclr(sc->keys_bmap, i)) {
setbit(sc->keys_bmap, i);
*keyix = i;
break;
}
}
RTWN_UNLOCK(sc);
if (i == sc->cam_entry_limit) {
#if __FreeBSD_version > 1200008
/* XXX check and remove keys with the same MAC address */
k->wk_flags |= IEEE80211_KEY_SWCRYPT;
*keyix = 0;
#else
device_printf(sc->sc_dev,
"%s: no free space in the key table\n", __func__);
return (0);
#endif
}
end:
*rxkeyix = *keyix;
return (1);
}
static int
rtwn_key_set_cb0(struct rtwn_softc *sc, const struct ieee80211_key *k)
{
uint8_t algo, keyid;
int i, error;
if (sc->sc_hwcrypto == RTWN_CRYPTO_FULL &&
k->wk_keyix < IEEE80211_WEP_NKID)
keyid = k->wk_keyix;
else
keyid = 0;
/* Map net80211 cipher to HW crypto algorithm. */
switch (k->wk_cipher->ic_cipher) {
case IEEE80211_CIPHER_WEP:
if (k->wk_keylen < 8)
algo = R92C_CAM_ALGO_WEP40;
else
algo = R92C_CAM_ALGO_WEP104;
break;
case IEEE80211_CIPHER_TKIP:
algo = R92C_CAM_ALGO_TKIP;
break;
case IEEE80211_CIPHER_AES_CCM:
algo = R92C_CAM_ALGO_AES;
break;
default:
device_printf(sc->sc_dev, "%s: unknown cipher %u\n",
__func__, k->wk_cipher->ic_cipher);
return (EINVAL);
}
RTWN_DPRINTF(sc, RTWN_DEBUG_KEY,
"%s: keyix %u, keyid %u, algo %u/%u, flags %04X, len %u, "
"macaddr %s\n", __func__, k->wk_keyix, keyid,
k->wk_cipher->ic_cipher, algo, k->wk_flags, k->wk_keylen,
ether_sprintf(k->wk_macaddr));
/* Clear high bits. */
rtwn_cam_write(sc, R92C_CAM_CTL6(k->wk_keyix), 0);
rtwn_cam_write(sc, R92C_CAM_CTL7(k->wk_keyix), 0);
/* Write key. */
for (i = 0; i < 4; i++) {
error = rtwn_cam_write(sc, R92C_CAM_KEY(k->wk_keyix, i),
le32dec(&k->wk_key[i * 4]));
if (error != 0)
goto fail;
}
/* Write CTL0 last since that will validate the CAM entry. */
error = rtwn_cam_write(sc, R92C_CAM_CTL1(k->wk_keyix),
le32dec(&k->wk_macaddr[2]));
if (error != 0)
goto fail;
error = rtwn_cam_write(sc, R92C_CAM_CTL0(k->wk_keyix),
SM(R92C_CAM_ALGO, algo) |
SM(R92C_CAM_KEYID, keyid) |
SM(R92C_CAM_MACLO, le16dec(&k->wk_macaddr[0])) |
R92C_CAM_VALID);
if (error != 0)
goto fail;
return (0);
fail:
device_printf(sc->sc_dev, "%s fails, error %d\n", __func__, error);
return (error);
}
static void
rtwn_key_set_cb(struct rtwn_softc *sc, union sec_param *data)
{
const struct ieee80211_key *k = &data->key;
(void) rtwn_key_set_cb0(sc, k);
}
int
rtwn_init_static_keys(struct rtwn_softc *sc, struct rtwn_vap *rvp)
{
int i, error;
if (sc->sc_hwcrypto != RTWN_CRYPTO_FULL)
return (0); /* nothing to do */
for (i = 0; i < IEEE80211_WEP_NKID; i++) {
const struct ieee80211_key *k = rvp->keys[i];
if (k != NULL) {
error = rtwn_key_set_cb0(sc, k);
if (error != 0)
return (error);
}
}
return (0);
}
static void
rtwn_key_del_cb(struct rtwn_softc *sc, union sec_param *data)
{
struct ieee80211_key *k = &data->key;
int i;
RTWN_DPRINTF(sc, RTWN_DEBUG_KEY,
"%s: keyix %u, flags %04X, macaddr %s\n", __func__,
k->wk_keyix, k->wk_flags, ether_sprintf(k->wk_macaddr));
rtwn_cam_write(sc, R92C_CAM_CTL0(k->wk_keyix), 0);
rtwn_cam_write(sc, R92C_CAM_CTL1(k->wk_keyix), 0);
/* Clear key. */
for (i = 0; i < 4; i++)
rtwn_cam_write(sc, R92C_CAM_KEY(k->wk_keyix, i), 0);
clrbit(sc->keys_bmap, k->wk_keyix);
}
static int
rtwn_process_key(struct ieee80211vap *vap, const struct ieee80211_key *k,
int set)
{
struct rtwn_softc *sc = vap->iv_ic->ic_softc;
if (k->wk_flags & IEEE80211_KEY_SWCRYPT) {
/* Not for us. */
return (1);
}
if (&vap->iv_nw_keys[0] <= k &&
k < &vap->iv_nw_keys[IEEE80211_WEP_NKID]) {
#if __FreeBSD_version <= 1200008
struct ieee80211_key *k1 = &vap->iv_nw_keys[k->wk_keyix];
if (sc->sc_hwcrypto != RTWN_CRYPTO_FULL) {
k1->wk_flags |= IEEE80211_KEY_SWCRYPT;
return (k->wk_cipher->ic_setkey(k1));
} else {
#else
if (sc->sc_hwcrypto == RTWN_CRYPTO_FULL) {
#endif
struct rtwn_vap *rvp = RTWN_VAP(vap);
RTWN_LOCK(sc);
rvp->keys[k->wk_keyix] = (set ? k : NULL);
if ((sc->sc_flags & RTWN_RUNNING) == 0) {
if (!set)
clrbit(sc->keys_bmap, k->wk_keyix);
RTWN_UNLOCK(sc);
return (1);
}
RTWN_UNLOCK(sc);
}
}
return (!rtwn_cmd_sleepable(sc, k, sizeof(*k),
set ? rtwn_key_set_cb : rtwn_key_del_cb));
}
int
rtwn_key_set(struct ieee80211vap *vap, const struct ieee80211_key *k)
{
return (rtwn_process_key(vap, k, 1));
}
int
rtwn_key_delete(struct ieee80211vap *vap, const struct ieee80211_key *k)
{
return (rtwn_process_key(vap, k, 0));
}

View File

@ -0,0 +1,30 @@
/*-
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $FreeBSD$
*/
#ifndef IF_RTWN_CAM_H
#define IF_RTWN_CAM_H
void rtwn_init_cam(struct rtwn_softc *);
void rtwn_init_seccfg(struct rtwn_softc *);
int rtwn_key_alloc(struct ieee80211vap *, struct ieee80211_key *,
ieee80211_keyix *, ieee80211_keyix *);
int rtwn_key_set(struct ieee80211vap *, const struct ieee80211_key *);
int rtwn_init_static_keys(struct rtwn_softc *, struct rtwn_vap *);
int rtwn_key_delete(struct ieee80211vap *, const struct ieee80211_key *);
#endif /* IF_RTWN_CAM_H */

View File

@ -0,0 +1,59 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $FreeBSD$
*/
#ifndef IF_RTWN_DEBUG_H
#define IF_RTWN_DEBUG_H
#include "opt_rtwn.h"
#ifdef RTWN_DEBUG
enum {
RTWN_DEBUG_XMIT = 0x00000001, /* basic xmit operation */
RTWN_DEBUG_XMIT_DESC = 0x00000002, /* xmit descriptors */
RTWN_DEBUG_RECV = 0x00000004, /* basic recv operation */
RTWN_DEBUG_RECV_DESC = 0x00000008, /* recv descriptors */
RTWN_DEBUG_STATE = 0x00000010, /* 802.11 state transitions */
RTWN_DEBUG_RA = 0x00000020, /* f/w rate adaptation setup */
RTWN_DEBUG_USB = 0x00000040, /* usb requests */
RTWN_DEBUG_FIRMWARE = 0x00000080, /* firmware(9) loading debug */
RTWN_DEBUG_BEACON = 0x00000100, /* beacon handling */
RTWN_DEBUG_INTR = 0x00000200, /* ISR */
RTWN_DEBUG_TEMP = 0x00000400, /* temperature calibration */
RTWN_DEBUG_ROM = 0x00000800, /* various ROM info */
RTWN_DEBUG_KEY = 0x00001000, /* crypto keys management */
RTWN_DEBUG_TXPWR = 0x00002000, /* dump Tx power values */
RTWN_DEBUG_RSSI = 0x00004000, /* dump RSSI lookups */
RTWN_DEBUG_RESET = 0x00008000, /* initialization progress */
RTWN_DEBUG_CALIB = 0x00010000, /* calibration progress */
RTWN_DEBUG_ANY = 0xffffffff
};
#define RTWN_DPRINTF(_sc, _m, ...) do { \
if ((_sc)->sc_debug & (_m)) \
device_printf((_sc)->sc_dev, __VA_ARGS__); \
} while(0)
#else
#define RTWN_DPRINTF(_sc, _m, ...) do { (void) _sc; } while (0)
#endif
#endif /* IF_RTWN_DEBUG_H */

View File

@ -0,0 +1,265 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/if_rtwn_debug.h>
#include <dev/rtwn/if_rtwn_efuse.h>
#include <dev/rtwn/rtl8192c/r92c_reg.h>
static int
rtwn_efuse_switch_power(struct rtwn_softc *sc)
{
uint32_t reg;
int error;
error = rtwn_write_1(sc, R92C_EFUSE_ACCESS, R92C_EFUSE_ACCESS_ON);
if (error != 0)
return (error);
reg = rtwn_read_2(sc, R92C_SYS_FUNC_EN);
if (!(reg & R92C_SYS_FUNC_EN_ELDR)) {
error = rtwn_write_2(sc, R92C_SYS_FUNC_EN,
reg | R92C_SYS_FUNC_EN_ELDR);
if (error != 0)
return (error);
}
reg = rtwn_read_2(sc, R92C_SYS_CLKR);
if ((reg & (R92C_SYS_CLKR_LOADER_EN | R92C_SYS_CLKR_ANA8M)) !=
(R92C_SYS_CLKR_LOADER_EN | R92C_SYS_CLKR_ANA8M)) {
error = rtwn_write_2(sc, R92C_SYS_CLKR,
reg | R92C_SYS_CLKR_LOADER_EN | R92C_SYS_CLKR_ANA8M);
if (error != 0)
return (error);
}
return (0);
}
int
rtwn_efuse_read_next(struct rtwn_softc *sc, uint8_t *val)
{
uint32_t reg;
int ntries, error;
if (sc->next_rom_addr >= sc->efuse_maxlen)
return (EFAULT);
reg = rtwn_read_4(sc, R92C_EFUSE_CTRL);
reg = RW(reg, R92C_EFUSE_CTRL_ADDR, sc->next_rom_addr);
reg &= ~R92C_EFUSE_CTRL_VALID;
error = rtwn_write_4(sc, R92C_EFUSE_CTRL, reg);
if (error != 0)
return (error);
/* Wait for read operation to complete. */
for (ntries = 0; ntries < 100; ntries++) {
reg = rtwn_read_4(sc, R92C_EFUSE_CTRL);
if (reg & R92C_EFUSE_CTRL_VALID)
break;
rtwn_delay(sc, 10);
}
if (ntries == 100) {
device_printf(sc->sc_dev,
"could not read efuse byte at address 0x%x\n",
sc->next_rom_addr);
return (ETIMEDOUT);
}
*val = MS(reg, R92C_EFUSE_CTRL_DATA);
sc->next_rom_addr++;
return (0);
}
static int
rtwn_efuse_read_data(struct rtwn_softc *sc, uint8_t *rom, uint8_t off,
uint8_t msk)
{
uint8_t reg;
int addr, i, error;
for (i = 0; i < 4; i++) {
if (msk & (1 << i))
continue;
addr = off * 8 + i * 2;
if (addr + 1 >= sc->efuse_maplen)
return (EFAULT);
error = rtwn_efuse_read_next(sc, &reg);
if (error != 0)
return (error);
RTWN_DPRINTF(sc, RTWN_DEBUG_ROM, "rom[0x%03X] == 0x%02X\n",
addr, reg);
rom[addr] = reg;
error = rtwn_efuse_read_next(sc, &reg);
if (error != 0)
return (error);
RTWN_DPRINTF(sc, RTWN_DEBUG_ROM, "rom[0x%03X] == 0x%02X\n",
addr + 1, reg);
rom[addr + 1] = reg;
}
return (0);
}
#ifdef RTWN_DEBUG
static void
rtwn_dump_rom_contents(struct rtwn_softc *sc, uint8_t *rom, uint16_t size)
{
int i;
/* Dump ROM contents. */
device_printf(sc->sc_dev, "%s:", __func__);
for (i = 0; i < size; i++) {
if (i % 32 == 0)
printf("\n%03X: ", i);
else if (i % 4 == 0)
printf(" ");
printf("%02X", rom[i]);
}
printf("\n");
}
#endif
static int
rtwn_efuse_read(struct rtwn_softc *sc, uint8_t *rom, uint16_t size)
{
#define RTWN_CHK(res) do { \
if ((error = res) != 0) \
goto end; \
} while(0)
uint8_t msk, off, reg;
int error;
/* Read full ROM image. */
sc->next_rom_addr = 0;
memset(rom, 0xff, size);
RTWN_CHK(rtwn_efuse_read_next(sc, &reg));
while (reg != 0xff) {
/* check for extended header */
if ((sc->sc_flags & RTWN_FLAG_EXT_HDR) &&
(reg & 0x1f) == 0x0f) {
off = reg >> 5;
RTWN_CHK(rtwn_efuse_read_next(sc, &reg));
if ((reg & 0x0f) != 0x0f)
off = ((reg & 0xf0) >> 1) | off;
else
continue;
} else
off = reg >> 4;
msk = reg & 0xf;
RTWN_CHK(rtwn_efuse_read_data(sc, rom, off, msk));
RTWN_CHK(rtwn_efuse_read_next(sc, &reg));
}
end:
#ifdef RTWN_DEBUG
if (sc->sc_debug & RTWN_DEBUG_ROM)
rtwn_dump_rom_contents(sc, rom, size);
#endif
/* Device-specific. */
rtwn_efuse_postread(sc);
if (error != 0) {
device_printf(sc->sc_dev, "%s: error while reading ROM\n",
__func__);
}
return (error);
#undef RTWN_CHK
}
static int
rtwn_efuse_read_prepare(struct rtwn_softc *sc, uint8_t *rom, uint16_t size)
{
int error;
error = rtwn_efuse_switch_power(sc);
if (error != 0)
goto fail;
error = rtwn_efuse_read(sc, rom, size);
fail:
rtwn_write_1(sc, R92C_EFUSE_ACCESS, R92C_EFUSE_ACCESS_OFF);
return (error);
}
int
rtwn_read_rom(struct rtwn_softc *sc)
{
uint8_t *rom;
int error;
rom = malloc(sc->efuse_maplen, M_TEMP, M_WAITOK);
/* Read full ROM image. */
RTWN_LOCK(sc);
error = rtwn_efuse_read_prepare(sc, rom, sc->efuse_maplen);
RTWN_UNLOCK(sc);
if (error != 0)
goto fail;
/* Parse & save data in softc. */
rtwn_parse_rom(sc, rom);
fail:
free(rom, M_TEMP);
return (error);
}

View File

@ -0,0 +1,25 @@
/*-
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $FreeBSD$
*/
#ifndef IF_RTWN_EFUSE_H
#define IF_RTWN_EFUSE_H
int rtwn_efuse_read_next(struct rtwn_softc *, uint8_t *);
int rtwn_read_rom(struct rtwn_softc *);
#endif /* IF_RTWN_EFUSE_H */

224
sys/dev/rtwn/if_rtwn_fw.c Normal file
View File

@ -0,0 +1,224 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <sys/firmware.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/if_rtwn_debug.h>
#include <dev/rtwn/if_rtwn_fw.h>
#include <dev/rtwn/rtl8192c/r92c_reg.h>
#ifndef RTWN_WITHOUT_UCODE
static int
rtwn_fw_loadpage(struct rtwn_softc *sc, int page, const uint8_t *buf,
int len)
{
uint32_t reg;
uint16_t off;
int mlen, error;
reg = rtwn_read_4(sc, R92C_MCUFWDL);
reg = RW(reg, R92C_MCUFWDL_PAGE, page);
rtwn_write_4(sc, R92C_MCUFWDL, reg);
error = 0;
off = R92C_FW_START_ADDR;
while (len > 0) {
if (len > R92C_FW_MAX_BLOCK_SIZE)
mlen = R92C_FW_MAX_BLOCK_SIZE;
else if (len > 4)
mlen = 4;
else
mlen = 1;
error = rtwn_fw_write_block(sc, buf, off, mlen);
if (error != 0)
break;
off += mlen;
buf += mlen;
len -= mlen;
}
if (error != 0) {
RTWN_DPRINTF(sc, RTWN_DEBUG_FIRMWARE,
"%s: could not load firmware page %d (offset %u)\n",
__func__, page, off);
}
return (error);
}
static int
rtwn_fw_checksum_report(struct rtwn_softc *sc)
{
int ntries;
for (ntries = 0; ntries < 25; ntries++) {
if (rtwn_read_4(sc, R92C_MCUFWDL) & R92C_MCUFWDL_CHKSUM_RPT)
break;
rtwn_delay(sc, 10000);
}
if (ntries == 25) {
RTWN_DPRINTF(sc, RTWN_DEBUG_FIRMWARE,
"timeout waiting for checksum report\n");
return (ETIMEDOUT);
}
return (0);
}
int
rtwn_load_firmware(struct rtwn_softc *sc)
{
const struct firmware *fw;
const struct r92c_fw_hdr *hdr;
const u_char *ptr;
size_t len;
int ntries, error;
/* Read firmware image from the filesystem. */
RTWN_UNLOCK(sc);
fw = firmware_get(sc->fwname);
RTWN_LOCK(sc);
if (fw == NULL) {
device_printf(sc->sc_dev,
"failed loadfirmware of file %s\n", sc->fwname);
return (ENOENT);
}
len = fw->datasize;
if (len < sizeof(*hdr) || len > sc->fwsize_limit) {
device_printf(sc->sc_dev, "wrong firmware size (%zu)\n", len);
error = EINVAL;
goto fail;
}
ptr = fw->data;
hdr = (const struct r92c_fw_hdr *)ptr;
/* Check if there is a valid FW header and skip it. */
if ((le16toh(hdr->signature) >> 4) == sc->fwsig) {
sc->fwver = le16toh(hdr->version);
RTWN_DPRINTF(sc, RTWN_DEBUG_FIRMWARE,
"FW V%u.%u %02u-%02u %02u:%02u\n",
le16toh(hdr->version), le16toh(hdr->subversion),
hdr->month, hdr->date, hdr->hour, hdr->minute);
ptr += sizeof(*hdr);
len -= sizeof(*hdr);
}
if (rtwn_read_1(sc, R92C_MCUFWDL) & R92C_MCUFWDL_RAM_DL_SEL) {
rtwn_write_1(sc, R92C_MCUFWDL, 0);
rtwn_fw_reset(sc, RTWN_FW_RESET_DOWNLOAD);
}
/* Enable firmware download. */
rtwn_fw_download_enable(sc, 1);
error = 0; /* compiler warning */
for (ntries = 0; ntries < 3; ntries++) {
const u_char *curr_ptr = ptr;
const int maxpages = len / R92C_FW_PAGE_SIZE;
int page;
/* Reset the FWDL checksum. */
rtwn_setbits_1(sc, R92C_MCUFWDL, 0, R92C_MCUFWDL_CHKSUM_RPT);
for (page = 0; page < maxpages; page++) {
error = rtwn_fw_loadpage(sc, page, curr_ptr,
R92C_FW_PAGE_SIZE);
if (error != 0)
break;
curr_ptr += R92C_FW_PAGE_SIZE;
}
if (page != maxpages)
continue;
if (len % R92C_FW_PAGE_SIZE != 0) {
error = rtwn_fw_loadpage(sc, page, curr_ptr,
len % R92C_FW_PAGE_SIZE);
if (error != 0)
continue;
}
/* Wait for checksum report. */
error = rtwn_fw_checksum_report(sc);
if (error == 0)
break;
}
if (ntries == 3) {
device_printf(sc->sc_dev,
"%s: failed to upload firmware %s (error %d)\n",
__func__, sc->fwname, error);
goto fail;
}
/* Disable firmware download. */
rtwn_fw_download_enable(sc, 0);
rtwn_setbits_4(sc, R92C_MCUFWDL, R92C_MCUFWDL_WINTINI_RDY,
R92C_MCUFWDL_RDY);
rtwn_fw_reset(sc, RTWN_FW_RESET_CHECKSUM);
/* Wait for firmware readiness. */
for (ntries = 0; ntries < 20; ntries++) {
if (rtwn_read_4(sc, R92C_MCUFWDL) & R92C_MCUFWDL_WINTINI_RDY)
break;
rtwn_delay(sc, 10000);
}
if (ntries == 20) {
device_printf(sc->sc_dev,
"timeout waiting for firmware readiness\n");
error = ETIMEDOUT;
goto fail;
}
fail:
firmware_put(fw, FIRMWARE_UNLOAD);
return (error);
}
#endif

59
sys/dev/rtwn/if_rtwn_fw.h Normal file
View File

@ -0,0 +1,59 @@
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $
* $FreeBSD$
*/
#ifndef IF_RTWN_FW_H
#define IF_RTWN_FW_H
/*
* Firmware base address.
*/
#define R92C_FW_START_ADDR 0x1000
#define R92C_FW_PAGE_SIZE 4096
#define R92C_FW_MAX_BLOCK_SIZE 196
/*
* Firmware image header.
*/
struct r92c_fw_hdr {
/* QWORD0 */
uint16_t signature;
uint8_t category;
uint8_t function;
uint16_t version;
uint16_t subversion;
/* QWORD1 */
uint8_t month;
uint8_t date;
uint8_t hour;
uint8_t minute;
uint16_t ramcodesize;
uint16_t reserved2;
/* QWORD2 */
uint32_t svnidx;
uint32_t reserved3;
/* QWORD3 */
uint32_t reserved4;
uint32_t reserved5;
} __packed;
int rtwn_load_firmware(struct rtwn_softc *);
#endif /* IF_RTWN_FW_H */

View File

@ -0,0 +1,69 @@
/*-
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $FreeBSD$
*/
#ifndef IF_RTWN_NOP_H
#define IF_RTWN_NOP_H
static __inline void
rtwn_nop_softc(struct rtwn_softc *sc)
{
}
static __inline int
rtwn_nop_int_softc(struct rtwn_softc *sc)
{
return (0);
}
static __inline int
rtwn_nop_int_softc_mbuf(struct rtwn_softc *sc, struct mbuf *m)
{
return (0);
}
static __inline void
rtwn_nop_softc_int(struct rtwn_softc *sc, int id)
{
}
static __inline void
rtwn_nop_softc_uint32(struct rtwn_softc *sc, uint32_t reg)
{
}
static __inline void
rtwn_nop_softc_chan(struct rtwn_softc *sc, struct ieee80211_channel *c)
{
}
static __inline void
rtwn_nop_softc_vap(struct rtwn_softc *sc, struct ieee80211vap *vap)
{
}
static __inline void
rtwn_nop_softc_uint8_int(struct rtwn_softc *sc, uint8_t *buf, int len)
{
}
static __inline void
rtwn_nop_void_int(void *buf, int is5ghz)
{
}
#endif /* IF_RTWN_NOP_H */

View File

@ -0,0 +1,94 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $FreeBSD$
*/
#ifndef IF_RTWN_RIDX_H
#define IF_RTWN_RIDX_H
/* HW rate indices. */
#define RTWN_RIDX_CCK1 0
#define RTWN_RIDX_CCK2 1
#define RTWN_RIDX_CCK55 2
#define RTWN_RIDX_CCK11 3
#define RTWN_RIDX_OFDM6 4
#define RTWN_RIDX_OFDM9 5
#define RTWN_RIDX_OFDM12 6
#define RTWN_RIDX_OFDM18 7
#define RTWN_RIDX_OFDM24 8
#define RTWN_RIDX_OFDM36 9
#define RTWN_RIDX_OFDM48 10
#define RTWN_RIDX_OFDM54 11
#define RTWN_RIDX_MCS(i) (12 + (i))
#define RTWN_RIDX_COUNT 28
#define RTWN_RIDX_UNKNOWN (uint8_t)-1
#define RTWN_RATE_IS_CCK(rate) ((rate) <= RTWN_RIDX_CCK11)
#define RTWN_RATE_IS_OFDM(rate) \
((rate) >= RTWN_RIDX_OFDM6 && (rate) != RTWN_RIDX_UNKNOWN)
static const uint8_t ridx2rate[] =
{ 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
static __inline uint8_t
rate2ridx(uint8_t rate)
{
if (rate & IEEE80211_RATE_MCS) {
/* 11n rates start at idx 12 */
return ((rate & 0xf) + 12);
}
switch (rate) {
/* 11g */
case 12: return 4;
case 18: return 5;
case 24: return 6;
case 36: return 7;
case 48: return 8;
case 72: return 9;
case 96: return 10;
case 108: return 11;
/* 11b */
case 2: return 0;
case 4: return 1;
case 11: return 2;
case 22: return 3;
default: return RTWN_RIDX_UNKNOWN;
}
}
/* XXX move to net80211 */
static __inline__ uint8_t
rtwn_ctl_mcsrate(const struct ieee80211_rate_table *rt, uint8_t ridx)
{
uint8_t cix, rate;
/* Check if we are using MCS rate. */
KASSERT(ridx >= RTWN_RIDX_MCS(0) && ridx != RTWN_RIDX_UNKNOWN,
("bad mcs rate index %d", ridx));
rate = (ridx - RTWN_RIDX_MCS(0)) | IEEE80211_RATE_MCS;
cix = rt->info[rt->rateCodeToIndex[rate]].ctlRateIndex;
KASSERT(cix != (uint8_t)-1, ("rate %d (%d) has no info", rate, ridx));
return rt->info[cix].dot11Rate;
}
#endif /* IF_RTWN_RIDX_H */

452
sys/dev/rtwn/if_rtwn_rx.c Normal file
View File

@ -0,0 +1,452 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/ethernet.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/if_rtwn_debug.h>
#include <dev/rtwn/if_rtwn_ridx.h>
#include <dev/rtwn/if_rtwn_rx.h>
#include <dev/rtwn/rtl8192c/r92c_reg.h>
#include <dev/rtwn/rtl8192c/r92c_rx_desc.h>
void
rtwn_get_rates(struct rtwn_softc *sc, const struct ieee80211_rateset *rs,
const struct ieee80211_htrateset *rs_ht, uint32_t *rates_p,
int *maxrate_p, int basic_rates)
{
uint32_t rates;
uint8_t ridx;
int i, maxrate;
/* Get rates mask. */
rates = 0;
maxrate = 0;
/* This is for 11bg */
for (i = 0; i < rs->rs_nrates; i++) {
/* Convert 802.11 rate to HW rate index. */
ridx = rate2ridx(IEEE80211_RV(rs->rs_rates[i]));
if (ridx == RTWN_RIDX_UNKNOWN) /* Unknown rate, skip. */
continue;
if (((rs->rs_rates[i] & IEEE80211_RATE_BASIC) != 0) ||
!basic_rates) {
rates |= 1 << ridx;
if (ridx > maxrate)
maxrate = ridx;
}
}
/* If we're doing 11n, enable 11n rates */
if (rs_ht != NULL && !basic_rates) {
for (i = 0; i < rs_ht->rs_nrates; i++) {
if ((rs_ht->rs_rates[i] & 0x7f) > 0xf)
continue;
/* 11n rates start at index 12 */
ridx = RTWN_RIDX_MCS((rs_ht->rs_rates[i]) & 0xf);
rates |= (1 << ridx);
/* Guard against the rate table being oddly ordered */
if (ridx > maxrate)
maxrate = ridx;
}
}
RTWN_DPRINTF(sc, RTWN_DEBUG_RA,
"%s: rates 0x%08X, maxrate %d\n", __func__, rates, maxrate);
if (rates_p != NULL)
*rates_p = rates;
if (maxrate_p != NULL)
*maxrate_p = maxrate;
}
void
rtwn_set_basicrates(struct rtwn_softc *sc, uint32_t rates)
{
RTWN_DPRINTF(sc, RTWN_DEBUG_RA, "%s: rates 0x%08X\n", __func__, rates);
rtwn_setbits_4(sc, R92C_RRSR, R92C_RRSR_RATE_BITMAP_M, rates);
}
static void
rtwn_update_avgrssi(struct rtwn_softc *sc, struct rtwn_node *un, int rate)
{
int pwdb;
/* Convert antenna signal to percentage. */
if (un->last_rssi <= -100 || un->last_rssi >= 20)
pwdb = 0;
else if (un->last_rssi >= 0)
pwdb = 100;
else
pwdb = 100 + un->last_rssi;
if (RTWN_RATE_IS_CCK(rate)) {
/* CCK gain is smaller than OFDM/MCS gain. */
pwdb += 6;
if (pwdb > 100)
pwdb = 100;
if (pwdb <= 14)
pwdb -= 4;
else if (pwdb <= 26)
pwdb -= 8;
else if (pwdb <= 34)
pwdb -= 6;
else if (pwdb <= 42)
pwdb -= 2;
}
if (un->avg_pwdb == -1) /* Init. */
un->avg_pwdb = pwdb;
else if (un->avg_pwdb < pwdb)
un->avg_pwdb = ((un->avg_pwdb * 19 + pwdb) / 20) + 1;
else
un->avg_pwdb = ((un->avg_pwdb * 19 + pwdb) / 20);
RTWN_DPRINTF(sc, RTWN_DEBUG_RSSI,
"MACID %d, PWDB %d, EMA %d\n", un->id, pwdb, un->avg_pwdb);
}
static int8_t
rtwn_get_rssi(struct rtwn_softc *sc, int rate, void *physt)
{
int8_t rssi;
if (RTWN_RATE_IS_CCK(rate))
rssi = rtwn_get_rssi_cck(sc, physt);
else /* OFDM/HT. */
rssi = rtwn_get_rssi_ofdm(sc, physt);
return (rssi);
}
static uint32_t
rtwn_get_tsf_low(struct rtwn_softc *sc, int id)
{
return (rtwn_read_4(sc, R92C_TSFTR(id)));
}
static uint32_t
rtwn_get_tsf_high(struct rtwn_softc *sc, int id)
{
return (rtwn_read_4(sc, R92C_TSFTR(id) + 4));
}
static void
rtwn_get_tsf(struct rtwn_softc *sc, uint64_t *buf, int id)
{
/* NB: we cannot read it at once. */
*buf = rtwn_get_tsf_high(sc, id);
*buf <<= 32;
*buf += rtwn_get_tsf_low(sc, id);
}
struct ieee80211_node *
rtwn_rx_common(struct rtwn_softc *sc, struct mbuf *m, void *desc,
int8_t *rssi)
{
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_node *ni;
struct ieee80211_frame_min *wh;
struct rtwn_node *un;
struct r92c_rx_stat *stat;
uint32_t rxdw0, rxdw3;
int cipher, infosz, pktlen, rate, shift;
stat = desc;
rxdw0 = le32toh(stat->rxdw0);
rxdw3 = le32toh(stat->rxdw3);
cipher = MS(rxdw0, R92C_RXDW0_CIPHER);
infosz = MS(rxdw0, R92C_RXDW0_INFOSZ) * 8;
pktlen = MS(rxdw0, R92C_RXDW0_PKTLEN);
shift = MS(rxdw0, R92C_RXDW0_SHIFT);
rate = MS(rxdw3, R92C_RXDW3_RATE);
wh = (struct ieee80211_frame_min *)(mtodo(m, shift + infosz));
if ((wh->i_fc[1] & IEEE80211_FC1_PROTECTED) &&
cipher != R92C_CAM_ALGO_NONE)
m->m_flags |= M_WEP;
if (pktlen >= sizeof(*wh))
ni = ieee80211_find_rxnode(ic, wh);
else
ni = NULL;
un = RTWN_NODE(ni);
/* Get RSSI from PHY status descriptor if present. */
if (infosz != 0 && (rxdw0 & R92C_RXDW0_PHYST)) {
*rssi = rtwn_get_rssi(sc, rate, mtod(m, void *));
RTWN_DPRINTF(sc, RTWN_DEBUG_RSSI, "%s: rssi %d, ridx %d\n",
__func__, *rssi, rate);
sc->last_rssi = *rssi;
if (un != NULL) {
un->last_rssi = *rssi;
/* Update our average RSSI. */
rtwn_update_avgrssi(sc, un, rate);
}
} else
*rssi = (un != NULL) ? un->last_rssi : sc->last_rssi;
if (ieee80211_radiotap_active(ic)) {
struct rtwn_rx_radiotap_header *tap = &sc->sc_rxtap;
int id = RTWN_VAP_ID_INVALID;
if (ni != NULL)
id = RTWN_VAP(ni->ni_vap)->id;
if (id == RTWN_VAP_ID_INVALID)
id = 0;
tap->wr_flags = rtwn_rx_radiotap_flags(sc, desc);
tap->wr_tsft = rtwn_get_tsf_high(sc, id);
if (le32toh(stat->tsf_low) > rtwn_get_tsf_low(sc, id))
tap->wr_tsft--;
tap->wr_tsft = (uint64_t)htole32(tap->wr_tsft) << 32;
tap->wr_tsft += stat->tsf_low;
/* XXX 20/40? */
/* Map HW rate index to 802.11 rate. */
if (rate < RTWN_RIDX_MCS(0))
tap->wr_rate = ridx2rate[rate];
else /* MCS0~15. */
tap->wr_rate = IEEE80211_RATE_MCS | (rate - 12);
tap->wr_dbm_antsignal = *rssi;
tap->wr_dbm_antnoise = RTWN_NOISE_FLOOR;
}
/* Drop PHY descriptor. */
m_adj(m, infosz + shift);
return (ni);
}
void
rtwn_adhoc_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m, int subtype,
const struct ieee80211_rx_stats *rxs,
int rssi, int nf)
{
struct ieee80211vap *vap = ni->ni_vap;
struct rtwn_softc *sc = vap->iv_ic->ic_softc;
struct rtwn_vap *uvp = RTWN_VAP(vap);
uint64_t ni_tstamp, curr_tstamp;
uvp->recv_mgmt(ni, m, subtype, rxs, rssi, nf);
if (vap->iv_state == IEEE80211_S_RUN &&
(subtype == IEEE80211_FC0_SUBTYPE_BEACON ||
subtype == IEEE80211_FC0_SUBTYPE_PROBE_RESP)) {
ni_tstamp = le64toh(ni->ni_tstamp.tsf);
RTWN_LOCK(sc);
rtwn_get_tsf(sc, &curr_tstamp, uvp->id);
RTWN_UNLOCK(sc);
if (ni_tstamp >= curr_tstamp)
(void) ieee80211_ibss_merge(ni);
}
}
static uint8_t
rtwn_get_multi_pos(const uint8_t maddr[])
{
uint64_t mask = 0x00004d101df481b4;
uint8_t pos = 0x27; /* initial value */
int i, j;
for (i = 0; i < IEEE80211_ADDR_LEN; i++)
for (j = (i == 0) ? 1 : 0; j < 8; j++)
if ((maddr[i] >> j) & 1)
pos ^= (mask >> (i * 8 + j - 1));
pos &= 0x3f;
return (pos);
}
void
rtwn_set_multi(struct rtwn_softc *sc)
{
struct ieee80211com *ic = &sc->sc_ic;
uint32_t mfilt[2];
RTWN_ASSERT_LOCKED(sc);
/* general structure was copied from ath(4). */
if (ic->ic_allmulti == 0) {
struct ieee80211vap *vap;
struct ifnet *ifp;
struct ifmultiaddr *ifma;
/*
* Merge multicast addresses to form the hardware filter.
*/
mfilt[0] = mfilt[1] = 0;
TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
ifp = vap->iv_ifp;
if_maddr_rlock(ifp);
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
caddr_t dl;
uint8_t pos;
dl = LLADDR((struct sockaddr_dl *)
ifma->ifma_addr);
pos = rtwn_get_multi_pos(dl);
mfilt[pos / 32] |= (1 << (pos % 32));
}
if_maddr_runlock(ifp);
}
} else
mfilt[0] = mfilt[1] = ~0;
rtwn_write_4(sc, R92C_MAR + 0, mfilt[0]);
rtwn_write_4(sc, R92C_MAR + 4, mfilt[1]);
RTWN_DPRINTF(sc, RTWN_DEBUG_STATE, "%s: MC filter %08x:%08x\n",
__func__, mfilt[0], mfilt[1]);
}
static void
rtwn_rxfilter_update_mgt(struct rtwn_softc *sc)
{
uint16_t filter;
filter = 0x7f3f;
if (sc->bcn_vaps == 0) { /* STA and/or MONITOR mode vaps */
filter &= ~(
R92C_RXFLTMAP_SUBTYPE(IEEE80211_FC0_SUBTYPE_ASSOC_REQ) |
R92C_RXFLTMAP_SUBTYPE(IEEE80211_FC0_SUBTYPE_REASSOC_REQ) |
R92C_RXFLTMAP_SUBTYPE(IEEE80211_FC0_SUBTYPE_PROBE_REQ));
}
if (sc->ap_vaps == sc->nvaps - sc->mon_vaps) { /* AP vaps only */
filter &= ~(
R92C_RXFLTMAP_SUBTYPE(IEEE80211_FC0_SUBTYPE_ASSOC_RESP) |
R92C_RXFLTMAP_SUBTYPE(IEEE80211_FC0_SUBTYPE_REASSOC_RESP));
}
rtwn_write_2(sc, R92C_RXFLTMAP0, filter);
}
void
rtwn_rxfilter_update(struct rtwn_softc *sc)
{
RTWN_ASSERT_LOCKED(sc);
/* Filter for management frames. */
rtwn_rxfilter_update_mgt(sc);
/* Update Rx filter. */
rtwn_set_promisc(sc);
}
void
rtwn_rxfilter_init(struct rtwn_softc *sc)
{
uint32_t rcr;
RTWN_ASSERT_LOCKED(sc);
/* Setup multicast filter. */
rtwn_set_multi(sc);
/* Reject all control frames. */
rtwn_write_2(sc, R92C_RXFLTMAP1, 0x0000);
/* Reject all data frames. */
rtwn_write_2(sc, R92C_RXFLTMAP2, 0x0000);
rcr = sc->rcr;
rcr |= R92C_RCR_AM | R92C_RCR_AB | R92C_RCR_APM |
R92C_RCR_HTC_LOC_CTRL | R92C_RCR_APP_PHYSTS |
R92C_RCR_APP_ICV | R92C_RCR_APP_MIC;
/* Set Rx filter. */
rtwn_write_4(sc, R92C_RCR, rcr);
/* Update dynamic Rx filter parts. */
rtwn_rxfilter_update(sc);
}
void
rtwn_set_rx_bssid_all(struct rtwn_softc *sc, int enable)
{
if (enable)
rtwn_setbits_4(sc, R92C_RCR, R92C_RCR_CBSSID_BCN, 0);
else
rtwn_setbits_4(sc, R92C_RCR, 0, R92C_RCR_CBSSID_BCN);
}
void
rtwn_set_promisc(struct rtwn_softc *sc)
{
struct ieee80211com *ic = &sc->sc_ic;
uint32_t mask1, mask2;
RTWN_ASSERT_LOCKED(sc);
mask1 = R92C_RCR_ACF | R92C_RCR_ADF | R92C_RCR_AMF | R92C_RCR_AAP;
mask2 = R92C_RCR_APM;
if (sc->vaps_running != 0) {
if (sc->bcn_vaps == 0)
mask2 |= R92C_RCR_CBSSID_BCN;
if (sc->ap_vaps == 0)
mask2 |= R92C_RCR_CBSSID_DATA;
}
if (ic->ic_promisc == 0 && sc->mon_vaps == 0)
rtwn_setbits_4(sc, R92C_RCR, mask1, mask2);
else
rtwn_setbits_4(sc, R92C_RCR, mask2, mask1);
}

38
sys/dev/rtwn/if_rtwn_rx.h Normal file
View File

@ -0,0 +1,38 @@
/*-
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $FreeBSD$
*/
#ifndef IF_RTWN_RX_H
#define IF_RTWN_RX_H
#define RTWN_NOISE_FLOOR -95
void rtwn_get_rates(struct rtwn_softc *, const struct ieee80211_rateset *,
const struct ieee80211_htrateset *, uint32_t *, int *, int);
void rtwn_set_basicrates(struct rtwn_softc *, uint32_t);
struct ieee80211_node * rtwn_rx_common(struct rtwn_softc *, struct mbuf *,
void *, int8_t *);
void rtwn_adhoc_recv_mgmt(struct ieee80211_node *, struct mbuf *, int,
const struct ieee80211_rx_stats *, int, int);
void rtwn_set_multi(struct rtwn_softc *);
void rtwn_rxfilter_update(struct rtwn_softc *);
void rtwn_rxfilter_init(struct rtwn_softc *);
void rtwn_set_rx_bssid_all(struct rtwn_softc *, int);
void rtwn_set_promisc(struct rtwn_softc *);
#endif /* IF_RTWN_RX_H */

122
sys/dev/rtwn/if_rtwn_task.c Normal file
View File

@ -0,0 +1,122 @@
/*-
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/if_rtwn_task.h>
static void
rtwn_cmdq_cb(void *arg, int pending)
{
struct rtwn_softc *sc = arg;
struct rtwn_cmdq *item;
/*
* Device must be powered on (via rtwn_power_on())
* before any command may be sent.
*/
RTWN_LOCK(sc);
if (!(sc->sc_flags & RTWN_RUNNING)) {
RTWN_UNLOCK(sc);
return;
}
RTWN_CMDQ_LOCK(sc);
while (sc->cmdq[sc->cmdq_first].func != NULL) {
item = &sc->cmdq[sc->cmdq_first];
sc->cmdq_first = (sc->cmdq_first + 1) % RTWN_CMDQ_SIZE;
RTWN_CMDQ_UNLOCK(sc);
item->func(sc, &item->data);
RTWN_CMDQ_LOCK(sc);
memset(item, 0, sizeof (*item));
}
RTWN_CMDQ_UNLOCK(sc);
RTWN_UNLOCK(sc);
}
void
rtwn_cmdq_init(struct rtwn_softc *sc)
{
RTWN_CMDQ_LOCK_INIT(sc);
TASK_INIT(&sc->cmdq_task, 0, rtwn_cmdq_cb, sc);
}
void
rtwn_cmdq_destroy(struct rtwn_softc *sc)
{
if (RTWN_CMDQ_LOCK_INITIALIZED(sc))
RTWN_CMDQ_LOCK_DESTROY(sc);
}
int
rtwn_cmd_sleepable(struct rtwn_softc *sc, const void *ptr, size_t len,
CMD_FUNC_PROTO)
{
struct ieee80211com *ic = &sc->sc_ic;
KASSERT(len <= sizeof(union sec_param), ("buffer overflow"));
RTWN_CMDQ_LOCK(sc);
if (sc->sc_detached) {
RTWN_CMDQ_UNLOCK(sc);
return (ESHUTDOWN);
}
if (sc->cmdq[sc->cmdq_last].func != NULL) {
device_printf(sc->sc_dev, "%s: cmdq overflow\n", __func__);
RTWN_CMDQ_UNLOCK(sc);
return (EAGAIN);
}
if (ptr != NULL)
memcpy(&sc->cmdq[sc->cmdq_last].data, ptr, len);
sc->cmdq[sc->cmdq_last].func = func;
sc->cmdq_last = (sc->cmdq_last + 1) % RTWN_CMDQ_SIZE;
RTWN_CMDQ_UNLOCK(sc);
ieee80211_runtask(ic, &sc->cmdq_task);
return (0);
}

View File

@ -0,0 +1,27 @@
/*-
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $FreeBSD$
*/
#ifndef IF_RTWN_TASK_H
#define IF_RTWN_TASK_H
void rtwn_cmdq_init(struct rtwn_softc *);
void rtwn_cmdq_destroy(struct rtwn_softc *);
int rtwn_cmd_sleepable(struct rtwn_softc *, const void *, size_t,
CMD_FUNC_PROTO);
#endif /* IF_RTWN_TASK_H */

346
sys/dev/rtwn/if_rtwn_tx.c Normal file
View File

@ -0,0 +1,346 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <net80211/ieee80211_ratectl.h>
#ifdef IEEE80211_SUPPORT_SUPERG
#include <net80211/ieee80211_superg.h>
#endif
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/if_rtwn_beacon.h>
#include <dev/rtwn/if_rtwn_debug.h>
#include <dev/rtwn/if_rtwn_ridx.h>
#include <dev/rtwn/if_rtwn_tx.h>
void
rtwn_drain_mbufq(struct rtwn_softc *sc)
{
struct mbuf *m;
struct ieee80211_node *ni;
RTWN_ASSERT_LOCKED(sc);
while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
m->m_pkthdr.rcvif = NULL;
ieee80211_free_node(ni);
m_freem(m);
}
}
#ifdef IEEE80211_SUPPORT_SUPERG
void
rtwn_ff_flush_all(struct rtwn_softc *sc, union sec_param *data)
{
struct ieee80211com *ic = &sc->sc_ic;
RTWN_UNLOCK(sc);
ieee80211_ff_flush_all(ic);
RTWN_LOCK(sc);
}
#endif
static uint8_t
rtwn_get_cipher(u_int ic_cipher)
{
uint8_t cipher;
switch (ic_cipher) {
case IEEE80211_CIPHER_NONE:
cipher = RTWN_TXDW1_CIPHER_NONE;
break;
case IEEE80211_CIPHER_WEP:
case IEEE80211_CIPHER_TKIP:
cipher = RTWN_TXDW1_CIPHER_RC4;
break;
case IEEE80211_CIPHER_AES_CCM:
cipher = RTWN_TXDW1_CIPHER_AES;
break;
default:
KASSERT(0, ("%s: unknown cipher %d\n", __func__,
ic_cipher));
return (RTWN_TXDW1_CIPHER_SM4);
}
return (cipher);
}
static int
rtwn_tx_data(struct rtwn_softc *sc, struct ieee80211_node *ni,
struct mbuf *m)
{
const struct ieee80211_txparam *tp;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = ni->ni_vap;
struct ieee80211_key *k = NULL;
struct ieee80211_channel *chan;
struct ieee80211_frame *wh;
struct rtwn_tx_desc_common *txd;
struct rtwn_tx_buf buf;
uint8_t rate, ridx, type;
u_int cipher;
int ismcast, maxretry;
RTWN_ASSERT_LOCKED(sc);
wh = mtod(m, struct ieee80211_frame *);
type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
chan = (ni->ni_chan != IEEE80211_CHAN_ANYC) ?
ni->ni_chan : ic->ic_curchan;
tp = &vap->iv_txparms[ieee80211_chan2mode(chan)];
maxretry = tp->maxretry;
/* Choose a TX rate index. */
if (type == IEEE80211_FC0_TYPE_MGT)
rate = tp->mgmtrate;
else if (ismcast)
rate = tp->mcastrate;
else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
rate = tp->ucastrate;
else if (m->m_flags & M_EAPOL)
rate = tp->mgmtrate;
else {
if (sc->sc_ratectl == RTWN_RATECTL_NET80211) {
/* XXX pass pktlen */
(void) ieee80211_ratectl_rate(ni, NULL, 0);
rate = ni->ni_txrate;
} else {
if (ni->ni_flags & IEEE80211_NODE_HT)
rate = IEEE80211_RATE_MCS | 0x4; /* MCS4 */
else if (ic->ic_curmode != IEEE80211_MODE_11B)
rate = ridx2rate[RTWN_RIDX_OFDM36];
else
rate = ridx2rate[RTWN_RIDX_CCK55];
}
}
ridx = rate2ridx(rate);
cipher = IEEE80211_CIPHER_NONE;
if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
k = ieee80211_crypto_encap(ni, m);
if (k == NULL) {
device_printf(sc->sc_dev,
"ieee80211_crypto_encap returns NULL.\n");
return (ENOBUFS);
}
if (!(k->wk_flags & IEEE80211_KEY_SWCRYPT))
cipher = k->wk_cipher->ic_cipher;
/* in case packet header moved, reset pointer */
wh = mtod(m, struct ieee80211_frame *);
}
/* Fill Tx descriptor. */
txd = (struct rtwn_tx_desc_common *)&buf;
memset(txd, 0, sc->txdesc_len);
txd->txdw1 = htole32(SM(RTWN_TXDW1_CIPHER, rtwn_get_cipher(cipher)));
rtwn_fill_tx_desc(sc, ni, m, txd, ridx, maxretry);
if (ieee80211_radiotap_active_vap(vap)) {
struct rtwn_tx_radiotap_header *tap = &sc->sc_txtap;
tap->wt_flags = rtwn_tx_radiotap_flags(sc, txd);
if (k != NULL)
tap->wt_flags |= IEEE80211_RADIOTAP_F_WEP;
ieee80211_radiotap_tx(vap, m);
}
return (rtwn_tx_start(sc, ni, m, (uint8_t *)txd, type, 0));
}
static int
rtwn_tx_raw(struct rtwn_softc *sc, struct ieee80211_node *ni,
struct mbuf *m, const struct ieee80211_bpf_params *params)
{
struct ieee80211vap *vap = ni->ni_vap;
struct ieee80211_key *k = NULL;
struct ieee80211_frame *wh;
struct rtwn_tx_desc_common *txd;
struct rtwn_tx_buf buf;
uint8_t type;
u_int cipher;
/* Encrypt the frame if need be. */
cipher = IEEE80211_CIPHER_NONE;
if (params->ibp_flags & IEEE80211_BPF_CRYPTO) {
/* Retrieve key for TX. */
k = ieee80211_crypto_encap(ni, m);
if (k == NULL) {
device_printf(sc->sc_dev,
"ieee80211_crypto_encap returns NULL.\n");
return (ENOBUFS);
}
if (!(k->wk_flags & IEEE80211_KEY_SWCRYPT))
cipher = k->wk_cipher->ic_cipher;
}
wh = mtod(m, struct ieee80211_frame *);
type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
/* Fill Tx descriptor. */
txd = (struct rtwn_tx_desc_common *)&buf;
memset(txd, 0, sc->txdesc_len);
txd->txdw1 = htole32(SM(RTWN_TXDW1_CIPHER, rtwn_get_cipher(cipher)));
rtwn_fill_tx_desc_raw(sc, ni, m, txd, params);
if (ieee80211_radiotap_active_vap(vap)) {
struct rtwn_tx_radiotap_header *tap = &sc->sc_txtap;
tap->wt_flags = rtwn_tx_radiotap_flags(sc, txd);
if (k != NULL)
tap->wt_flags |= IEEE80211_RADIOTAP_F_WEP;
ieee80211_radiotap_tx(vap, m);
}
return (rtwn_tx_start(sc, ni, m, (uint8_t *)txd, type, 0));
}
int
rtwn_transmit(struct ieee80211com *ic, struct mbuf *m)
{
struct rtwn_softc *sc = ic->ic_softc;
int error;
RTWN_LOCK(sc);
if ((sc->sc_flags & RTWN_RUNNING) == 0) {
RTWN_UNLOCK(sc);
return (ENXIO);
}
error = mbufq_enqueue(&sc->sc_snd, m);
if (error) {
RTWN_UNLOCK(sc);
return (error);
}
rtwn_start(sc);
RTWN_UNLOCK(sc);
return (0);
}
void
rtwn_start(struct rtwn_softc *sc)
{
struct ieee80211_node *ni;
struct mbuf *m;
RTWN_ASSERT_LOCKED(sc);
while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
if (sc->qfullmsk != 0) {
mbufq_prepend(&sc->sc_snd, m);
break;
}
ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
m->m_pkthdr.rcvif = NULL;
RTWN_DPRINTF(sc, RTWN_DEBUG_XMIT,
"%s: called; m %p, ni %p\n", __func__, m, ni);
if (rtwn_tx_data(sc, ni, m) != 0) {
if_inc_counter(ni->ni_vap->iv_ifp,
IFCOUNTER_OERRORS, 1);
m_freem(m);
#ifdef D4054
ieee80211_tx_watchdog_refresh(ni->ni_ic, -1, 0);
#endif
ieee80211_free_node(ni);
break;
}
}
}
int
rtwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
const struct ieee80211_bpf_params *params)
{
struct ieee80211com *ic = ni->ni_ic;
struct rtwn_softc *sc = ic->ic_softc;
int error;
RTWN_DPRINTF(sc, RTWN_DEBUG_XMIT, "%s: called; m %p, ni %p\n",
__func__, m, ni);
/* prevent management frames from being sent if we're not ready */
RTWN_LOCK(sc);
if (!(sc->sc_flags & RTWN_RUNNING)) {
error = ENETDOWN;
goto end;
}
if (sc->qfullmsk != 0) {
error = ENOBUFS;
goto end;
}
if (params == NULL) {
/*
* Legacy path; interpret frame contents to decide
* precisely how to send the frame.
*/
error = rtwn_tx_data(sc, ni, m);
} else {
/*
* Caller supplied explicit parameters to use in
* sending the frame.
*/
error = rtwn_tx_raw(sc, ni, m, params);
}
end:
if (error != 0) {
if (m->m_flags & M_TXCB)
ieee80211_process_callback(ni, m, 1);
m_freem(m);
}
RTWN_UNLOCK(sc);
return (error);
}

29
sys/dev/rtwn/if_rtwn_tx.h Normal file
View File

@ -0,0 +1,29 @@
/*-
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $FreeBSD$
*/
#ifndef IF_RTWN_TX_H
#define IF_RTWN_TX_H
void rtwn_drain_mbufq(struct rtwn_softc *);
void rtwn_ff_flush_all(struct rtwn_softc *, union sec_param *);
int rtwn_transmit(struct ieee80211com *, struct mbuf *);
void rtwn_start(struct rtwn_softc *);
int rtwn_raw_xmit(struct ieee80211_node *, struct mbuf *,
const struct ieee80211_bpf_params *);
#endif /* IF_RTWN_TX_H */

File diff suppressed because it is too large Load Diff

609
sys/dev/rtwn/if_rtwnvar.h Normal file
View File

@ -0,0 +1,609 @@
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $
* $FreeBSD$
*/
#ifndef IF_RTWNVAR_H
#define IF_RTWNVAR_H
#include "opt_rtwn.h"
#define RTWN_TX_DESC_SIZE 64
#define RTWN_RXBUFSZ (8 * 1024)
#define RTWN_TXBUFSZ (RTWN_TX_DESC_SIZE + IEEE80211_MAX_LEN)
#define RTWN_BCN_MAX_SIZE 512
#define RTWN_CAM_ENTRY_LIMIT 64
#define RTWN_MACID_BC 1 /* Broadcast. */
#define RTWN_MACID_UNDEFINED 0x7fff
#define RTWN_MACID_VALID 0x8000
#define RTWN_MACID_LIMIT 128
#define RTWN_TX_TIMEOUT 5000 /* ms */
#define RTWN_MAX_EPOUT 4
#define RTWN_PORT_COUNT 2
#define RTWN_LED_LINK 0
#define RTWN_LED_DATA 1
struct rtwn_rx_radiotap_header {
struct ieee80211_radiotap_header wr_ihdr;
uint64_t wr_tsft;
uint8_t wr_flags;
uint8_t wr_rate;
uint16_t wr_chan_freq;
uint16_t wr_chan_flags;
int8_t wr_dbm_antsignal;
int8_t wr_dbm_antnoise;
} __packed __aligned(8);
#define RTWN_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 rtwn_tx_radiotap_header {
struct ieee80211_radiotap_header wt_ihdr;
uint8_t wt_flags;
uint16_t wt_chan_freq;
uint16_t wt_chan_flags;
} __packed __aligned(8);
#define RTWN_TX_RADIOTAP_PRESENT \
(1 << IEEE80211_RADIOTAP_FLAGS | \
1 << IEEE80211_RADIOTAP_CHANNEL)
struct rtwn_tx_buf {
uint8_t txd[RTWN_TX_DESC_SIZE];
} __attribute__((aligned(4)));
struct rtwn_softc;
union sec_param {
struct ieee80211_key key;
int macid;
};
#define CMD_FUNC_PROTO void (*func)(struct rtwn_softc *, \
union sec_param *)
struct rtwn_cmdq {
union sec_param data;
CMD_FUNC_PROTO;
};
#define RTWN_CMDQ_SIZE 16
struct rtwn_node {
struct ieee80211_node ni; /* must be the first */
int id;
int8_t last_rssi;
int avg_pwdb;
};
#define RTWN_NODE(ni) ((struct rtwn_node *)(ni))
struct rtwn_vap {
struct ieee80211vap vap;
int id;
#define RTWN_VAP_ID_INVALID -1
int curr_mode;
struct rtwn_tx_buf bcn_desc;
struct mbuf *bcn_mbuf;
struct callout tsf_sync_adhoc;
struct task tsf_sync_adhoc_task;
const struct ieee80211_key *keys[IEEE80211_WEP_NKID];
int (*newstate)(struct ieee80211vap *,
enum ieee80211_state, int);
void (*recv_mgmt)(struct ieee80211_node *,
struct mbuf *, int,
const struct ieee80211_rx_stats *,
int, int);
};
#define RTWN_VAP(vap) ((struct rtwn_vap *)(vap))
/*
* Rx data types.
*/
enum {
RTWN_RX_DATA,
RTWN_RX_TX_REPORT,
RTWN_RX_OTHER
};
/*
* Firmware reset reasons.
*/
enum {
RTWN_FW_RESET_DOWNLOAD,
RTWN_FW_RESET_CHECKSUM,
RTWN_FW_RESET_SHUTDOWN
};
/*
* Rate control algorithm selection.
*/
enum {
RTWN_RATECTL_NONE,
RTWN_RATECTL_NET80211,
RTWN_RATECTL_FW,
RTWN_RATECTL_MAX
};
/*
* Control h/w crypto usage.
*/
enum {
RTWN_CRYPTO_SW,
RTWN_CRYPTO_PAIR,
RTWN_CRYPTO_FULL,
RTWN_CRYPTO_MAX,
};
struct rtwn_softc {
struct ieee80211com sc_ic;
struct mbufq sc_snd;
device_t sc_dev;
#if 1
int sc_ht40;
#endif
uint32_t sc_debug;
int sc_hwcrypto;
int sc_ratectl_sysctl;
int sc_ratectl;
uint8_t sc_detached;
uint8_t sc_flags;
/* Device flags */
#define RTWN_FLAG_CCK_HIPWR 0x01
#define RTWN_FLAG_EXT_HDR 0x02
#define RTWN_FLAG_CAM_FIXED 0x04
/* Driver state */
#define RTWN_STARTED 0x08
#define RTWN_RUNNING 0x10
#define RTWN_FW_LOADED 0x20
#define RTWN_TEMP_MEASURED 0x40
#define RTWN_CHIP_HAS_BCNQ1(_sc) \
((_sc)->bcn_status_reg[0] != (_sc)->bcn_status_reg[1])
void *sc_priv;
const char *name;
int sc_ant;
int8_t last_rssi;
uint8_t thcal_temp;
int cur_bcnq_id;
int nvaps;
int ap_vaps;
int bcn_vaps;
int mon_vaps;
int vaps_running;
int monvaps_running;
uint16_t next_rom_addr;
uint8_t keys_bmap[roundup2(RTWN_CAM_ENTRY_LIMIT, NBBY)];
struct rtwn_vap *vaps[RTWN_PORT_COUNT];
struct ieee80211_node *node_list[RTWN_MACID_LIMIT];
struct mtx nt_mtx;
struct callout sc_calib_to;
struct callout sc_pwrmode_init;
#ifndef D4054
struct callout sc_watchdog_to;
int sc_tx_timer;
#endif
struct mtx sc_mtx;
struct rtwn_cmdq cmdq[RTWN_CMDQ_SIZE];
struct mtx cmdq_mtx;
struct task cmdq_task;
uint8_t cmdq_first;
uint8_t cmdq_last;
struct wmeParams cap_wmeParams[WME_NUM_AC];
struct rtwn_rx_radiotap_header sc_rxtap;
struct rtwn_tx_radiotap_header sc_txtap;
int ntxchains;
int nrxchains;
int ledlink;
uint8_t thermal_meter;
int sc_tx_n_active;
uint8_t qfullmsk;
/* Firmware-specific */
const char *fwname;
uint16_t fwver;
uint16_t fwsig;
int fwcur;
void (*sc_node_free)(struct ieee80211_node *);
void (*sc_scan_curchan)(struct ieee80211_scan_state *,
unsigned long);
/* Interface-specific. */
int (*sc_write_1)(struct rtwn_softc *, uint16_t,
uint8_t);
int (*sc_write_2)(struct rtwn_softc *, uint16_t,
uint16_t);
int (*sc_write_4)(struct rtwn_softc *, uint16_t,
uint32_t);
uint8_t (*sc_read_1)(struct rtwn_softc *, uint16_t);
uint16_t (*sc_read_2)(struct rtwn_softc *, uint16_t);
uint32_t (*sc_read_4)(struct rtwn_softc *, uint16_t);
/* XXX eliminate */
void (*sc_delay)(struct rtwn_softc *, int);
int (*sc_tx_start)(struct rtwn_softc *,
struct ieee80211_node *, struct mbuf *, uint8_t *,
uint8_t, int);
void (*sc_start_xfers)(struct rtwn_softc *);
void (*sc_reset_lists)(struct rtwn_softc *,
struct ieee80211vap *);
void (*sc_abort_xfers)(struct rtwn_softc *);
int (*sc_fw_write_block)(struct rtwn_softc *,
const uint8_t *, uint16_t, int);
uint16_t (*sc_get_qmap)(struct rtwn_softc *);
void (*sc_set_desc_addr)(struct rtwn_softc *);
void (*sc_drop_incorrect_tx)(struct rtwn_softc *);
/* Device-specific. */
uint32_t (*sc_rf_read)(struct rtwn_softc *, int, uint8_t);
void (*sc_rf_write)(struct rtwn_softc *, int, uint8_t,
uint32_t);
int (*sc_check_condition)(struct rtwn_softc *,
const uint8_t[]);
void (*sc_efuse_postread)(struct rtwn_softc *);
void (*sc_parse_rom)(struct rtwn_softc *, uint8_t *);
void (*sc_set_led)(struct rtwn_softc *, int, int);
int (*sc_power_on)(struct rtwn_softc *);
void (*sc_power_off)(struct rtwn_softc *);
#ifndef RTWN_WITHOUT_UCODE
void (*sc_fw_reset)(struct rtwn_softc *, int);
void (*sc_fw_download_enable)(struct rtwn_softc *, int);
#endif
int (*sc_set_page_size)(struct rtwn_softc *);
void (*sc_lc_calib)(struct rtwn_softc *);
void (*sc_iq_calib)(struct rtwn_softc *);
void (*sc_read_chipid_vendor)(struct rtwn_softc *,
uint32_t);
void (*sc_adj_devcaps)(struct rtwn_softc *);
void (*sc_vap_preattach)(struct rtwn_softc *,
struct ieee80211vap *);
void (*sc_postattach)(struct rtwn_softc *);
void (*sc_detach_private)(struct rtwn_softc *);
void (*sc_fill_tx_desc)(struct rtwn_softc *,
struct ieee80211_node *, struct mbuf *,
void *, uint8_t, int);
void (*sc_fill_tx_desc_raw)(struct rtwn_softc *,
struct ieee80211_node *, struct mbuf *,
void *, const struct ieee80211_bpf_params *);
void (*sc_fill_tx_desc_null)(struct rtwn_softc *,
void *, int, int, int);
void (*sc_dump_tx_desc)(struct rtwn_softc *, const void *);
uint8_t (*sc_tx_radiotap_flags)(const void *);
uint8_t (*sc_rx_radiotap_flags)(const void *);
void (*sc_beacon_init)(struct rtwn_softc *, void *, int);
void (*sc_beacon_enable)(struct rtwn_softc *, int, int);
void (*sc_beacon_set_rate)(void *, int);
void (*sc_beacon_select)(struct rtwn_softc *, int);
void (*sc_set_chan)(struct rtwn_softc *,
struct ieee80211_channel *);
void (*sc_set_media_status)(struct rtwn_softc *, int);
#ifndef RTWN_WITHOUT_UCODE
int (*sc_set_rsvd_page)(struct rtwn_softc *, int, int,
int);
int (*sc_set_pwrmode)(struct rtwn_softc *,
struct ieee80211vap *, int);
void (*sc_set_rssi)(struct rtwn_softc *);
#endif
int8_t (*sc_get_rssi_cck)(struct rtwn_softc *, void *);
int8_t (*sc_get_rssi_ofdm)(struct rtwn_softc *, void *);
int (*sc_classify_intr)(struct rtwn_softc *, void *, int);
void (*sc_handle_tx_report)(struct rtwn_softc *, uint8_t *,
int);
void (*sc_handle_c2h_report)(struct rtwn_softc *,
uint8_t *, int);
int (*sc_check_frame)(struct rtwn_softc *, struct mbuf *);
void (*sc_temp_measure)(struct rtwn_softc *);
uint8_t (*sc_temp_read)(struct rtwn_softc *);
void (*sc_init_tx_agg)(struct rtwn_softc *);
void (*sc_init_rx_agg)(struct rtwn_softc *);
void (*sc_init_intr)(struct rtwn_softc *);
void (*sc_init_ampdu)(struct rtwn_softc *);
void (*sc_init_edca)(struct rtwn_softc *);
void (*sc_init_bb)(struct rtwn_softc *);
void (*sc_init_rf)(struct rtwn_softc *);
void (*sc_init_antsel)(struct rtwn_softc *);
void (*sc_post_init)(struct rtwn_softc *);
int (*sc_init_bcnq1_boundary)(struct rtwn_softc *);
const uint8_t *chan_list_5ghz[3];
int chan_num_5ghz[3];
const struct rtwn_mac_prog *mac_prog;
int mac_size;
const struct rtwn_bb_prog *bb_prog;
int bb_size;
const struct rtwn_agc_prog *agc_prog;
int agc_size;
const struct rtwn_rf_prog *rf_prog;
int page_count;
int pktbuf_count;
int ackto;
int npubqpages;
int nhqpages;
int nnqpages;
int nlqpages;
int page_size;
int txdesc_len;
int efuse_maxlen;
int efuse_maplen;
uint16_t rx_dma_size;
int macid_limit;
int cam_entry_limit;
int fwsize_limit;
int temp_delta;
uint16_t bcn_status_reg[RTWN_PORT_COUNT];
uint32_t rcr; /* Rx filter */
};
MALLOC_DECLARE(M_RTWN_PRIV);
#define RTWN_LOCK(sc) mtx_lock(&(sc)->sc_mtx)
#define RTWN_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx)
#define RTWN_ASSERT_LOCKED(sc) mtx_assert(&(sc)->sc_mtx, MA_OWNED)
#define RTWN_CMDQ_LOCK_INIT(sc) \
mtx_init(&(sc)->cmdq_mtx, "cmdq lock", NULL, MTX_DEF)
#define RTWN_CMDQ_LOCK(sc) mtx_lock(&(sc)->cmdq_mtx)
#define RTWN_CMDQ_UNLOCK(sc) mtx_unlock(&(sc)->cmdq_mtx)
#define RTWN_CMDQ_LOCK_INITIALIZED(sc) mtx_initialized(&(sc)->cmdq_mtx)
#define RTWN_CMDQ_LOCK_DESTROY(sc) mtx_destroy(&(sc)->cmdq_mtx)
#define RTWN_NT_LOCK_INIT(sc) \
mtx_init(&(sc)->nt_mtx, "node table lock", NULL, MTX_DEF)
#define RTWN_NT_LOCK(sc) mtx_lock(&(sc)->nt_mtx)
#define RTWN_NT_UNLOCK(sc) mtx_unlock(&(sc)->nt_mtx)
#define RTWN_NT_LOCK_INITIALIZED(sc) mtx_initialized(&(sc)->nt_mtx)
#define RTWN_NT_LOCK_DESTROY(sc) mtx_destroy(&(sc)->nt_mtx)
void rtwn_sysctlattach(struct rtwn_softc *);
int rtwn_attach(struct rtwn_softc *);
void rtwn_detach(struct rtwn_softc *);
void rtwn_resume(struct rtwn_softc *);
void rtwn_suspend(struct rtwn_softc *);
/* Interface-specific. */
#define rtwn_write_1(_sc, _addr, _val) \
(((_sc)->sc_write_1)((_sc), (_addr), (_val)))
#define rtwn_write_2(_sc, _addr, _val) \
(((_sc)->sc_write_2)((_sc), (_addr), (_val)))
#define rtwn_write_4(_sc, _addr, _val) \
(((_sc)->sc_write_4)((_sc), (_addr), (_val)))
#define rtwn_read_1(_sc, _addr) \
(((_sc)->sc_read_1)((_sc), (_addr)))
#define rtwn_read_2(_sc, _addr) \
(((_sc)->sc_read_2)((_sc), (_addr)))
#define rtwn_read_4(_sc, _addr) \
(((_sc)->sc_read_4)((_sc), (_addr)))
#define rtwn_delay(_sc, _usec) \
(((_sc)->sc_delay)((_sc), (_usec)))
#define rtwn_tx_start(_sc, _ni, _m, _desc, _type, _id) \
(((_sc)->sc_tx_start)((_sc), (_ni), (_m), (_desc), (_type), (_id)))
#define rtwn_start_xfers(_sc) \
(((_sc)->sc_start_xfers)((_sc)))
#define rtwn_reset_lists(_sc, _vap) \
(((_sc)->sc_reset_lists)((_sc), (_vap)))
#define rtwn_abort_xfers(_sc) \
(((_sc)->sc_abort_xfers)((_sc)))
#define rtwn_fw_write_block(_sc, _buf, _reg, _len) \
(((_sc)->sc_fw_write_block)((_sc), (_buf), (_reg), (_len)))
#define rtwn_get_qmap(_sc) \
(((_sc)->sc_get_qmap)((_sc)))
#define rtwn_set_desc_addr(_sc) \
(((_sc)->sc_set_desc_addr)((_sc)))
#define rtwn_drop_incorrect_tx(_sc) \
(((_sc)->sc_drop_incorrect_tx)((_sc)))
/* Aliases. */
#define rtwn_bb_write rtwn_write_4
#define rtwn_bb_read rtwn_read_4
#define rtwn_bb_setbits rtwn_setbits_4
/* Device-specific. */
#define rtwn_rf_read(_sc, _chain, _addr) \
(((_sc)->sc_rf_read)((_sc), (_chain), (_addr)))
#define rtwn_rf_write(_sc, _chain, _addr, _val) \
(((_sc)->sc_rf_write)((_sc), (_chain), (_addr), (_val)))
#define rtwn_check_condition(_sc, _cond) \
(((_sc)->sc_check_condition)((_sc), (_cond)))
#define rtwn_efuse_postread(_sc) \
(((_sc)->sc_efuse_postread)((_sc)))
#define rtwn_parse_rom(_sc, _rom) \
(((_sc)->sc_parse_rom)((_sc), (_rom)))
#define rtwn_set_led(_sc, _led, _on) \
(((_sc)->sc_set_led)((_sc), (_led), (_on)))
#define rtwn_get_rssi_cck(_sc, _physt) \
(((_sc)->sc_get_rssi_cck)((_sc), (_physt)))
#define rtwn_get_rssi_ofdm(_sc, _physt) \
(((_sc)->sc_get_rssi_ofdm)((_sc), (_physt)))
#define rtwn_power_on(_sc) \
(((_sc)->sc_power_on)((_sc)))
#define rtwn_power_off(_sc) \
(((_sc)->sc_power_off)((_sc)))
#ifndef RTWN_WITHOUT_UCODE
#define rtwn_fw_reset(_sc, _reason) \
(((_sc)->sc_fw_reset)((_sc), (_reason)))
#define rtwn_fw_download_enable(_sc, _enable) \
(((_sc)->sc_fw_download_enable)((_sc), (_enable)))
#endif
#define rtwn_set_page_size(_sc) \
(((_sc)->sc_set_page_size)((_sc)))
#define rtwn_lc_calib(_sc) \
(((_sc)->sc_lc_calib)((_sc)))
#define rtwn_iq_calib(_sc) \
(((_sc)->sc_iq_calib)((_sc)))
#define rtwn_read_chipid_vendor(_sc, _reg) \
(((_sc)->sc_read_chipid_vendor)((_sc), (_reg)))
#define rtwn_adj_devcaps(_sc) \
(((_sc)->sc_adj_devcaps)((_sc)))
#define rtwn_vap_preattach(_sc, _vap) \
(((_sc)->sc_vap_preattach)((_sc), (_vap)))
#define rtwn_postattach(_sc) \
(((_sc)->sc_postattach)((_sc)))
#define rtwn_detach_private(_sc) \
(((_sc)->sc_detach_private)((_sc)))
#define rtwn_fill_tx_desc(_sc, _ni, _m, \
_buf, _ridx, _maxretry) \
(((_sc)->sc_fill_tx_desc)((_sc), (_ni), \
(_m), (_buf), (_ridx), (_maxretry)))
#define rtwn_fill_tx_desc_raw(_sc, _ni, _m, \
_buf, _params) \
(((_sc)->sc_fill_tx_desc_raw)((_sc), (_ni), \
(_m), (_buf), (_params)))
#define rtwn_fill_tx_desc_null(_sc, _buf, _11b, _qos, _id) \
(((_sc)->sc_fill_tx_desc_null)((_sc), \
(_buf), (_11b), (_qos), (_id)))
#define rtwn_dump_tx_desc(_sc, _desc) \
(((_sc)->sc_dump_tx_desc)((_sc), (_desc)))
#define rtwn_tx_radiotap_flags(_sc, _buf) \
(((_sc)->sc_tx_radiotap_flags)((_buf)))
#define rtwn_rx_radiotap_flags(_sc, _buf) \
(((_sc)->sc_rx_radiotap_flags)((_buf)))
#define rtwn_set_chan(_sc, _c) \
(((_sc)->sc_set_chan)((_sc), (_c)))
#ifndef RTWN_WITHOUT_UCODE
#define rtwn_set_rsvd_page(_sc, _resp, _null, _qos_null) \
(((_sc)->sc_set_rsvd_page)((_sc), \
(_resp), (_null), (_qos_null)))
#define rtwn_set_pwrmode(_sc, _vap, _off) \
(((_sc)->sc_set_pwrmode)((_sc), (_vap), (_off)))
#define rtwn_set_rssi(_sc) \
(((_sc)->sc_set_rssi)((_sc)))
#endif
#define rtwn_classify_intr(_sc, _buf, _len) \
(((_sc)->sc_classify_intr)((_sc), (_buf), (_len)))
#define rtwn_handle_tx_report(_sc, _buf, _len) \
(((_sc)->sc_handle_tx_report)((_sc), (_buf), (_len)))
#define rtwn_handle_c2h_report(_sc, _buf, _len) \
(((_sc)->sc_handle_c2h_report)((_sc), (_buf), (_len)))
#define rtwn_check_frame(_sc, _m) \
(((_sc)->sc_check_frame)((_sc), (_m)))
#define rtwn_beacon_init(_sc, _buf, _id) \
(((_sc)->sc_beacon_init)((_sc), (_buf), (_id)))
#define rtwn_beacon_enable(_sc, _id, _enable) \
(((_sc)->sc_beacon_enable)((_sc), (_id), (_enable)))
#define rtwn_beacon_set_rate(_sc, _buf, _is5ghz) \
(((_sc)->sc_beacon_set_rate)((_buf), (_is5ghz)))
#define rtwn_beacon_select(_sc, _id) \
(((_sc)->sc_beacon_select)((_sc), (_id)))
#define rtwn_temp_measure(_sc) \
(((_sc)->sc_temp_measure)((_sc)))
#define rtwn_temp_read(_sc) \
(((_sc)->sc_temp_read)((_sc)))
#define rtwn_init_tx_agg(_sc) \
(((_sc)->sc_init_tx_agg)((_sc)))
#define rtwn_init_rx_agg(_sc) \
(((_sc)->sc_init_rx_agg)((_sc)))
#define rtwn_init_intr(_sc) \
(((_sc)->sc_init_intr)((_sc)))
#define rtwn_init_ampdu(_sc) \
(((_sc)->sc_init_ampdu)((_sc)))
#define rtwn_init_edca(_sc) \
(((_sc)->sc_init_edca)((_sc)))
#define rtwn_init_bb(_sc) \
(((_sc)->sc_init_bb)((_sc)))
#define rtwn_init_rf(_sc) \
(((_sc)->sc_init_rf)((_sc)))
#define rtwn_init_antsel(_sc) \
(((_sc)->sc_init_antsel)((_sc)))
#define rtwn_post_init(_sc) \
(((_sc)->sc_post_init)((_sc)))
#define rtwn_init_bcnq1_boundary(_sc) \
(((_sc)->sc_init_bcnq1_boundary)((_sc)))
/*
* Methods to access subfields in registers.
*/
static __inline int
rtwn_setbits_1(struct rtwn_softc *sc, uint16_t addr, uint8_t clr,
uint8_t set)
{
return (rtwn_write_1(sc, addr,
(rtwn_read_1(sc, addr) & ~clr) | set));
}
static __inline int
rtwn_setbits_1_shift(struct rtwn_softc *sc, uint16_t addr, uint32_t clr,
uint32_t set, int shift)
{
return (rtwn_setbits_1(sc, addr + shift, clr >> shift * NBBY,
set >> shift * NBBY));
}
static __inline int
rtwn_setbits_2(struct rtwn_softc *sc, uint16_t addr, uint16_t clr,
uint16_t set)
{
return (rtwn_write_2(sc, addr,
(rtwn_read_2(sc, addr) & ~clr) | set));
}
static __inline int
rtwn_setbits_4(struct rtwn_softc *sc, uint16_t addr, uint32_t clr,
uint32_t set)
{
return (rtwn_write_4(sc, addr,
(rtwn_read_4(sc, addr) & ~clr) | set));
}
static __inline void
rtwn_rf_setbits(struct rtwn_softc *sc, int chain, uint8_t addr,
uint32_t clr, uint32_t set)
{
rtwn_rf_write(sc, chain, addr,
(rtwn_rf_read(sc, chain, addr) & ~clr) | set);
}
#endif /* IF_RTWNVAR_H */

View File

@ -0,0 +1,687 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/sysctl.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <sys/kdb.h>
#include <machine/bus.h>
#include <machine/resource.h>
#include <sys/rman.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/if_rtwn_nop.h>
#include <dev/rtwn/if_rtwn_debug.h>
#include <dev/rtwn/pci/rtwn_pci_var.h>
#include <dev/rtwn/pci/rtwn_pci_attach.h>
#include <dev/rtwn/pci/rtwn_pci_reg.h>
#include <dev/rtwn/pci/rtwn_pci_rx.h>
#include <dev/rtwn/pci/rtwn_pci_tx.h>
#include <dev/rtwn/rtl8192c/pci/r92ce_reg.h>
#include <dev/rtwn/rtl8192c/pci/r92ce_rx_desc.h>
static device_probe_t rtwn_pci_probe;
static device_attach_t rtwn_pci_attach;
static device_detach_t rtwn_pci_detach;
static device_shutdown_t rtwn_pci_shutdown;
static device_suspend_t rtwn_pci_suspend;
static device_resume_t rtwn_pci_resume;
static int rtwn_pci_alloc_rx_list(struct rtwn_softc *);
static void rtwn_pci_reset_rx_list(struct rtwn_softc *);
static void rtwn_pci_free_rx_list(struct rtwn_softc *);
static int rtwn_pci_alloc_tx_list(struct rtwn_softc *, int);
static void rtwn_pci_reset_tx_list(struct rtwn_softc *,
struct ieee80211vap *, int);
static void rtwn_pci_free_tx_list(struct rtwn_softc *, int);
static void rtwn_pci_reset_lists(struct rtwn_softc *,
struct ieee80211vap *);
static int rtwn_pci_fw_write_block(struct rtwn_softc *,
const uint8_t *, uint16_t, int);
static uint16_t rtwn_pci_get_qmap(struct rtwn_softc *);
static void rtwn_pci_set_desc_addr(struct rtwn_softc *);
static void rtwn_pci_attach_methods(struct rtwn_softc *);
static int matched_chip = RTWN_CHIP_MAX_PCI;
static int
rtwn_pci_probe(device_t dev)
{
const struct rtwn_pci_ident *ident;
for (ident = rtwn_pci_ident_table; ident->name != NULL; ident++) {
if (pci_get_vendor(dev) == ident->vendor &&
pci_get_device(dev) == ident->device) {
matched_chip = ident->chip;
device_set_desc(dev, ident->name);
return (BUS_PROBE_DEFAULT);
}
}
return (ENXIO);
}
static int
rtwn_pci_alloc_rx_list(struct rtwn_softc *sc)
{
struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
struct rtwn_rx_ring *rx_ring = &pc->rx_ring;
struct rtwn_rx_data *rx_data;
bus_size_t size;
int i, error;
/* Allocate Rx descriptors. */
size = sizeof(struct r92ce_rx_stat) * RTWN_PCI_RX_LIST_COUNT;
error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 1, 0,
BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
size, 1, size, 0, NULL, NULL, &rx_ring->desc_dmat);
if (error != 0) {
device_printf(sc->sc_dev, "could not create rx desc DMA tag\n");
goto fail;
}
error = bus_dmamem_alloc(rx_ring->desc_dmat, (void **)&rx_ring->desc,
BUS_DMA_NOWAIT | BUS_DMA_ZERO | BUS_DMA_COHERENT,
&rx_ring->desc_map);
if (error != 0) {
device_printf(sc->sc_dev, "could not allocate rx desc\n");
goto fail;
}
error = bus_dmamap_load(rx_ring->desc_dmat, rx_ring->desc_map,
rx_ring->desc, size, rtwn_pci_dma_map_addr, &rx_ring->paddr, 0);
if (error != 0) {
device_printf(sc->sc_dev, "could not load rx desc DMA map\n");
goto fail;
}
bus_dmamap_sync(rx_ring->desc_dmat, rx_ring->desc_map,
BUS_DMASYNC_PREWRITE);
/* Create RX buffer DMA tag. */
error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 1, 0,
BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES,
1, MCLBYTES, 0, NULL, NULL, &rx_ring->data_dmat);
if (error != 0) {
device_printf(sc->sc_dev, "could not create rx buf DMA tag\n");
goto fail;
}
/* Allocate Rx buffers. */
for (i = 0; i < RTWN_PCI_RX_LIST_COUNT; i++) {
rx_data = &rx_ring->rx_data[i];
error = bus_dmamap_create(rx_ring->data_dmat, 0, &rx_data->map);
if (error != 0) {
device_printf(sc->sc_dev,
"could not create rx buf DMA map\n");
goto fail;
}
rx_data->m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
if (rx_data->m == NULL) {
device_printf(sc->sc_dev,
"could not allocate rx mbuf\n");
error = ENOMEM;
goto fail;
}
error = bus_dmamap_load(rx_ring->data_dmat, rx_data->map,
mtod(rx_data->m, void *), MCLBYTES, rtwn_pci_dma_map_addr,
&rx_data->paddr, BUS_DMA_NOWAIT);
if (error != 0) {
device_printf(sc->sc_dev,
"could not load rx buf DMA map");
goto fail;
}
rtwn_pci_setup_rx_desc(pc, &rx_ring->desc[i], rx_data->paddr,
MCLBYTES, i);
}
rx_ring->cur = 0;
return (0);
fail:
rtwn_pci_free_rx_list(sc);
return (error);
}
static void
rtwn_pci_reset_rx_list(struct rtwn_softc *sc)
{
struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
struct rtwn_rx_ring *rx_ring = &pc->rx_ring;
struct rtwn_rx_data *rx_data;
int i;
for (i = 0; i < RTWN_PCI_RX_LIST_COUNT; i++) {
rx_data = &rx_ring->rx_data[i];
rtwn_pci_setup_rx_desc(pc, &rx_ring->desc[i],
rx_data->paddr, MCLBYTES, i);
}
rx_ring->cur = 0;
}
static void
rtwn_pci_free_rx_list(struct rtwn_softc *sc)
{
struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
struct rtwn_rx_ring *rx_ring = &pc->rx_ring;
struct rtwn_rx_data *rx_data;
int i;
if (rx_ring->desc_dmat != NULL) {
if (rx_ring->desc != NULL) {
bus_dmamap_sync(rx_ring->desc_dmat,
rx_ring->desc_map,
BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
bus_dmamap_unload(rx_ring->desc_dmat,
rx_ring->desc_map);
bus_dmamem_free(rx_ring->desc_dmat, rx_ring->desc,
rx_ring->desc_map);
rx_ring->desc = NULL;
}
bus_dma_tag_destroy(rx_ring->desc_dmat);
rx_ring->desc_dmat = NULL;
}
for (i = 0; i < RTWN_PCI_RX_LIST_COUNT; i++) {
rx_data = &rx_ring->rx_data[i];
if (rx_data->m != NULL) {
bus_dmamap_sync(rx_ring->data_dmat,
rx_data->map, BUS_DMASYNC_POSTREAD);
bus_dmamap_unload(rx_ring->data_dmat, rx_data->map);
m_freem(rx_data->m);
rx_data->m = NULL;
}
bus_dmamap_destroy(rx_ring->data_dmat, rx_data->map);
rx_data->map = NULL;
}
if (rx_ring->data_dmat != NULL) {
bus_dma_tag_destroy(rx_ring->data_dmat);
rx_ring->data_dmat = NULL;
}
}
static int
rtwn_pci_alloc_tx_list(struct rtwn_softc *sc, int qid)
{
struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
struct rtwn_tx_ring *tx_ring = &pc->tx_ring[qid];
bus_size_t size;
int i, error;
size = sc->txdesc_len * RTWN_PCI_TX_LIST_COUNT;
error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), PAGE_SIZE, 0,
BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
size, 1, size, 0, NULL, NULL, &tx_ring->desc_dmat);
if (error != 0) {
device_printf(sc->sc_dev, "could not create tx ring DMA tag\n");
goto fail;
}
error = bus_dmamem_alloc(tx_ring->desc_dmat, &tx_ring->desc,
BUS_DMA_NOWAIT | BUS_DMA_ZERO, &tx_ring->desc_map);
if (error != 0) {
device_printf(sc->sc_dev, "can't map tx ring DMA memory\n");
goto fail;
}
error = bus_dmamap_load(tx_ring->desc_dmat, tx_ring->desc_map,
tx_ring->desc, size, rtwn_pci_dma_map_addr, &tx_ring->paddr,
BUS_DMA_NOWAIT);
if (error != 0) {
device_printf(sc->sc_dev, "could not load desc DMA map\n");
goto fail;
}
bus_dmamap_sync(tx_ring->desc_dmat, tx_ring->desc_map,
BUS_DMASYNC_PREWRITE);
error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 1, 0,
BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES,
1, MCLBYTES, 0, NULL, NULL, &tx_ring->data_dmat);
if (error != 0) {
device_printf(sc->sc_dev, "could not create tx buf DMA tag\n");
goto fail;
}
for (i = 0; i < RTWN_PCI_TX_LIST_COUNT; i++) {
struct rtwn_tx_data *tx_data = &tx_ring->tx_data[i];
void *tx_desc = (uint8_t *)tx_ring->desc + sc->txdesc_len * i;
uint32_t next_desc_addr = tx_ring->paddr +
sc->txdesc_len * ((i + 1) % RTWN_PCI_TX_LIST_COUNT);
rtwn_pci_setup_tx_desc(pc, tx_desc, next_desc_addr);
error = bus_dmamap_create(tx_ring->data_dmat, 0, &tx_data->map);
if (error != 0) {
device_printf(sc->sc_dev,
"could not create tx buf DMA map\n");
return (error);
}
tx_data->m = NULL;
tx_data->ni = NULL;
}
return (0);
fail:
rtwn_pci_free_tx_list(sc, qid);
return (error);
}
static void
rtwn_pci_reset_tx_list(struct rtwn_softc *sc, struct ieee80211vap *vap,
int qid)
{
struct rtwn_vap *uvp = RTWN_VAP(vap);
struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
struct rtwn_tx_ring *tx_ring = &pc->tx_ring[qid];
int i, id;
id = (uvp != NULL ? uvp->id : RTWN_VAP_ID_INVALID);
for (i = 0; i < RTWN_PCI_TX_LIST_COUNT; i++) {
struct rtwn_tx_data *tx_data = &tx_ring->tx_data[i];
if (vap == NULL || (tx_data->ni == NULL &&
(tx_data->id == id || id == RTWN_VAP_ID_INVALID)) ||
(tx_data->ni != NULL && tx_data->ni->ni_vap == vap)) {
void *tx_desc =
(uint8_t *)tx_ring->desc + sc->txdesc_len * i;
rtwn_pci_copy_tx_desc(pc, tx_desc, NULL);
if (tx_data->m != NULL) {
bus_dmamap_sync(tx_ring->data_dmat,
tx_data->map, BUS_DMASYNC_POSTWRITE);
bus_dmamap_unload(tx_ring->data_dmat,
tx_data->map);
m_freem(tx_data->m);
tx_data->m = NULL;
}
if (tx_data->ni != NULL) {
ieee80211_free_node(tx_data->ni);
tx_data->ni = NULL;
}
}
}
bus_dmamap_sync(tx_ring->desc_dmat, tx_ring->desc_map,
BUS_DMASYNC_POSTWRITE);
sc->qfullmsk &= ~(1 << qid);
tx_ring->queued = 0;
tx_ring->last = tx_ring->cur = 0;
}
static void
rtwn_pci_free_tx_list(struct rtwn_softc *sc, int qid)
{
struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
struct rtwn_tx_ring *tx_ring = &pc->tx_ring[qid];
struct rtwn_tx_data *tx_data;
int i;
if (tx_ring->desc_dmat != NULL) {
if (tx_ring->desc != NULL) {
bus_dmamap_sync(tx_ring->desc_dmat,
tx_ring->desc_map, BUS_DMASYNC_POSTWRITE);
bus_dmamap_unload(tx_ring->desc_dmat,
tx_ring->desc_map);
bus_dmamem_free(tx_ring->desc_dmat, tx_ring->desc,
tx_ring->desc_map);
}
bus_dma_tag_destroy(tx_ring->desc_dmat);
}
for (i = 0; i < RTWN_PCI_TX_LIST_COUNT; i++) {
tx_data = &tx_ring->tx_data[i];
if (tx_data->m != NULL) {
bus_dmamap_sync(tx_ring->data_dmat, tx_data->map,
BUS_DMASYNC_POSTWRITE);
bus_dmamap_unload(tx_ring->data_dmat, tx_data->map);
m_freem(tx_data->m);
tx_data->m = NULL;
}
}
if (tx_ring->data_dmat != NULL) {
bus_dma_tag_destroy(tx_ring->data_dmat);
tx_ring->data_dmat = NULL;
}
sc->qfullmsk &= ~(1 << qid);
tx_ring->queued = 0;
tx_ring->last = tx_ring->cur = 0;
}
static void
rtwn_pci_reset_lists(struct rtwn_softc *sc, struct ieee80211vap *vap)
{
int i;
for (i = 0; i < RTWN_PCI_NTXQUEUES; i++)
rtwn_pci_reset_tx_list(sc, vap, i);
if (vap == NULL) {
sc->qfullmsk = 0;
rtwn_pci_reset_rx_list(sc);
}
}
static int
rtwn_pci_fw_write_block(struct rtwn_softc *sc, const uint8_t *buf,
uint16_t reg, int mlen)
{
int i;
for (i = 0; i < mlen; i++)
rtwn_pci_write_1(sc, reg++, buf[i]);
/* NB: cannot fail */
return (0);
}
static uint16_t
rtwn_pci_get_qmap(struct rtwn_softc *sc)
{
struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
KASSERT(pc->pc_qmap != 0, ("%s: qmap is not set!\n", __func__));
return (pc->pc_qmap);
}
static void
rtwn_pci_set_desc_addr(struct rtwn_softc *sc)
{
struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
RTWN_DPRINTF(sc, RTWN_DEBUG_RESET, "%s: addresses:\n"
"bk: %08jX, be: %08jX, vi: %08jX, vo: %08jX\n"
"bcn: %08jX, mgt: %08jX, high: %08jX, rx: %08jX\n",
__func__, (uintmax_t)pc->tx_ring[RTWN_PCI_BK_QUEUE].paddr,
(uintmax_t)pc->tx_ring[RTWN_PCI_BE_QUEUE].paddr,
(uintmax_t)pc->tx_ring[RTWN_PCI_VI_QUEUE].paddr,
(uintmax_t)pc->tx_ring[RTWN_PCI_VO_QUEUE].paddr,
(uintmax_t)pc->tx_ring[RTWN_PCI_BEACON_QUEUE].paddr,
(uintmax_t)pc->tx_ring[RTWN_PCI_MGNT_QUEUE].paddr,
(uintmax_t)pc->tx_ring[RTWN_PCI_HIGH_QUEUE].paddr,
(uintmax_t)pc->rx_ring.paddr);
/* Set Tx Configuration Register. */
rtwn_pci_write_4(sc, R92C_TCR, pc->tcr);
/* Configure Tx DMA. */
rtwn_pci_write_4(sc, R92C_BKQ_DESA,
pc->tx_ring[RTWN_PCI_BK_QUEUE].paddr);
rtwn_pci_write_4(sc, R92C_BEQ_DESA,
pc->tx_ring[RTWN_PCI_BE_QUEUE].paddr);
rtwn_pci_write_4(sc, R92C_VIQ_DESA,
pc->tx_ring[RTWN_PCI_VI_QUEUE].paddr);
rtwn_pci_write_4(sc, R92C_VOQ_DESA,
pc->tx_ring[RTWN_PCI_VO_QUEUE].paddr);
rtwn_pci_write_4(sc, R92C_BCNQ_DESA,
pc->tx_ring[RTWN_PCI_BEACON_QUEUE].paddr);
rtwn_pci_write_4(sc, R92C_MGQ_DESA,
pc->tx_ring[RTWN_PCI_MGNT_QUEUE].paddr);
rtwn_pci_write_4(sc, R92C_HQ_DESA,
pc->tx_ring[RTWN_PCI_HIGH_QUEUE].paddr);
/* Configure Rx DMA. */
rtwn_pci_write_4(sc, R92C_RX_DESA, pc->rx_ring.paddr);
}
static void
rtwn_pci_attach_methods(struct rtwn_softc *sc)
{
sc->sc_write_1 = rtwn_pci_write_1;
sc->sc_write_2 = rtwn_pci_write_2;
sc->sc_write_4 = rtwn_pci_write_4;
sc->sc_read_1 = rtwn_pci_read_1;
sc->sc_read_2 = rtwn_pci_read_2;
sc->sc_read_4 = rtwn_pci_read_4;
sc->sc_delay = rtwn_pci_delay;
sc->sc_tx_start = rtwn_pci_tx_start;
sc->sc_reset_lists = rtwn_pci_reset_lists;
sc->sc_abort_xfers = rtwn_nop_softc;
sc->sc_fw_write_block = rtwn_pci_fw_write_block;
sc->sc_get_qmap = rtwn_pci_get_qmap;
sc->sc_set_desc_addr = rtwn_pci_set_desc_addr;
sc->sc_drop_incorrect_tx = rtwn_nop_softc;
}
static int
rtwn_pci_attach(device_t dev)
{
struct rtwn_pci_softc *pc = device_get_softc(dev);
struct rtwn_softc *sc = &pc->pc_sc;
struct ieee80211com *ic = &sc->sc_ic;
uint32_t lcsr;
int cap_off, i, error, rid;
if (matched_chip >= RTWN_CHIP_MAX_PCI)
return (ENXIO);
/*
* Get the offset of the PCI Express Capability Structure in PCI
* Configuration Space.
*/
error = pci_find_cap(dev, PCIY_EXPRESS, &cap_off);
if (error != 0) {
device_printf(dev, "PCIe capability structure not found!\n");
return (error);
}
/* Enable bus-mastering. */
pci_enable_busmaster(dev);
rid = PCIR_BAR(2);
pc->mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
RF_ACTIVE);
if (pc->mem == NULL) {
device_printf(dev, "can't map mem space\n");
return (ENOMEM);
}
pc->pc_st = rman_get_bustag(pc->mem);
pc->pc_sh = rman_get_bushandle(pc->mem);
/* Install interrupt handler. */
rid = 1;
if (pci_alloc_msi(dev, &rid) == 0)
rid = 1;
else
rid = 0;
pc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE |
(rid != 0 ? 0 : RF_SHAREABLE));
if (pc->irq == NULL) {
device_printf(dev, "can't map interrupt\n");
goto detach;
}
/* Disable PCIe Active State Power Management (ASPM). */
lcsr = pci_read_config(dev, cap_off + PCIER_LINK_CTL, 4);
lcsr &= ~PCIEM_LINK_CTL_ASPMC;
pci_write_config(dev, cap_off + PCIER_LINK_CTL, lcsr, 4);
sc->sc_dev = dev;
ic->ic_name = device_get_nameunit(dev);
/* Need to be initialized early. */
rtwn_sysctlattach(sc);
mtx_init(&sc->sc_mtx, ic->ic_name, MTX_NETWORK_LOCK, MTX_DEF);
rtwn_pci_attach_methods(sc);
/* XXX something similar to USB_GET_DRIVER_INFO() */
rtwn_pci_attach_private(pc, matched_chip);
/* Allocate Tx/Rx buffers. */
error = rtwn_pci_alloc_rx_list(sc);
if (error != 0) {
device_printf(dev,
"could not allocate Rx buffers, error %d\n",
error);
goto detach;
}
for (i = 0; i < RTWN_PCI_NTXQUEUES; i++) {
error = rtwn_pci_alloc_tx_list(sc, i);
if (error != 0) {
device_printf(dev,
"could not allocate Tx buffers, error %d\n",
error);
goto detach;
}
}
/* Generic attach. */
error = rtwn_attach(sc);
if (error != 0)
goto detach;
/*
* Hook our interrupt after all initialization is complete.
*/
error = bus_setup_intr(dev, pc->irq, INTR_TYPE_NET | INTR_MPSAFE,
NULL, rtwn_pci_intr, sc, &pc->pc_ih);
if (error != 0) {
device_printf(dev, "can't establish interrupt, error %d\n",
error);
goto detach;
}
return (0);
detach:
rtwn_pci_detach(dev); /* failure */
return (ENXIO);
}
static int
rtwn_pci_detach(device_t dev)
{
struct rtwn_pci_softc *pc = device_get_softc(dev);
struct rtwn_softc *sc = &pc->pc_sc;
int i;
/* Generic detach. */
rtwn_detach(sc);
/* Uninstall interrupt handler. */
if (pc->irq != NULL) {
bus_teardown_intr(dev, pc->irq, pc->pc_ih);
bus_release_resource(dev, SYS_RES_IRQ, rman_get_rid(pc->irq),
pc->irq);
pci_release_msi(dev);
}
/* Free Tx/Rx buffers. */
for (i = 0; i < RTWN_PCI_NTXQUEUES; i++)
rtwn_pci_free_tx_list(sc, i);
rtwn_pci_free_rx_list(sc);
if (pc->mem != NULL)
bus_release_resource(dev, SYS_RES_MEMORY,
rman_get_rid(pc->mem), pc->mem);
rtwn_detach_private(sc);
mtx_destroy(&sc->sc_mtx);
return (0);
}
static int
rtwn_pci_shutdown(device_t self)
{
struct rtwn_pci_softc *pc = device_get_softc(self);
ieee80211_stop_all(&pc->pc_sc.sc_ic);
return (0);
}
static int
rtwn_pci_suspend(device_t self)
{
struct rtwn_pci_softc *pc = device_get_softc(self);
rtwn_suspend(&pc->pc_sc);
return (0);
}
static int
rtwn_pci_resume(device_t self)
{
struct rtwn_pci_softc *pc = device_get_softc(self);
rtwn_resume(&pc->pc_sc);
return (0);
}
static device_method_t rtwn_pci_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, rtwn_pci_probe),
DEVMETHOD(device_attach, rtwn_pci_attach),
DEVMETHOD(device_detach, rtwn_pci_detach),
DEVMETHOD(device_shutdown, rtwn_pci_shutdown),
DEVMETHOD(device_suspend, rtwn_pci_suspend),
DEVMETHOD(device_resume, rtwn_pci_resume),
DEVMETHOD_END
};
static driver_t rtwn_pci_driver = {
"rtwn",
rtwn_pci_methods,
sizeof(struct rtwn_pci_softc)
};
static devclass_t rtwn_pci_devclass;
DRIVER_MODULE(rtwn_pci, pci, rtwn_pci_driver, rtwn_pci_devclass, NULL, NULL);
MODULE_VERSION(rtwn_pci, 1);
MODULE_DEPEND(rtwn_pci, pci, 1, 1, 1);
MODULE_DEPEND(rtwn_pci, wlan, 1, 1, 1);
MODULE_DEPEND(rtwn_pci, rtwn, 2, 2, 2);

View File

@ -0,0 +1,48 @@
/*-
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $FreeBSD$
*/
void r92ce_attach(struct rtwn_pci_softc *);
enum {
RTWN_CHIP_RTL8192CE,
RTWN_CHIP_MAX_PCI
};
struct rtwn_pci_ident {
uint16_t vendor;
uint16_t device;
const char *name;
int chip;
};
static const struct rtwn_pci_ident rtwn_pci_ident_table[] = {
{ 0x10ec, 0x8176, "Realtek RTL8188CE", RTWN_CHIP_RTL8192CE },
{ 0, 0, NULL, RTWN_CHIP_MAX_PCI }
};
typedef void (*chip_pci_attach)(struct rtwn_pci_softc *);
static const chip_pci_attach rtwn_chip_pci_attach[RTWN_CHIP_MAX_PCI] = {
[RTWN_CHIP_RTL8192CE] = r92ce_attach
};
static __inline void
rtwn_pci_attach_private(struct rtwn_pci_softc *pc, int chip)
{
rtwn_chip_pci_attach[chip](pc);
}

View File

@ -0,0 +1,123 @@
/* $OpenBSD: if_rtwn.c,v 1.6 2015/08/28 00:03:53 deraadt Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2015 Stefan Sperling <stsp@openbsd.org>
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <machine/bus.h>
#include <machine/resource.h>
#include <sys/rman.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/pci/rtwn_pci_var.h>
#include <dev/rtwn/pci/rtwn_pci_reg.h>
int
rtwn_pci_write_1(struct rtwn_softc *sc, uint16_t addr, uint8_t val)
{
struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
bus_space_write_1(pc->pc_st, pc->pc_sh, addr, val);
return (0);
}
int
rtwn_pci_write_2(struct rtwn_softc *sc, uint16_t addr, uint16_t val)
{
struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
val = htole16(val);
bus_space_write_2(pc->pc_st, pc->pc_sh, addr, val);
return (0);
}
int
rtwn_pci_write_4(struct rtwn_softc *sc, uint16_t addr, uint32_t val)
{
struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
val = htole32(val);
bus_space_write_4(pc->pc_st, pc->pc_sh, addr, val);
return (0);
}
uint8_t
rtwn_pci_read_1(struct rtwn_softc *sc, uint16_t addr)
{
struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
return (bus_space_read_1(pc->pc_st, pc->pc_sh, addr));
}
uint16_t
rtwn_pci_read_2(struct rtwn_softc *sc, uint16_t addr)
{
struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
uint16_t val;
val = bus_space_read_2(pc->pc_st, pc->pc_sh, addr);
return le16toh(val);
}
uint32_t
rtwn_pci_read_4(struct rtwn_softc *sc, uint16_t addr)
{
struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
uint32_t val;
val = bus_space_read_4(pc->pc_st, pc->pc_sh, addr);
return le32toh(val);
}
void
rtwn_pci_delay(struct rtwn_softc *sc, int usec)
{
if (usec < 1000)
DELAY(usec);
else {
(void) mtx_sleep(sc, &sc->sc_mtx, 0, "rtwn_pci",
MAX(msecs_to_ticks(usec / 1000), 1));
}
}

View File

@ -0,0 +1,30 @@
/*-
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $FreeBSD$
*/
#ifndef RTWN_PCI_REG_H
#define RTWN_PCI_REG_H
int rtwn_pci_write_1(struct rtwn_softc *, uint16_t, uint8_t);
int rtwn_pci_write_2(struct rtwn_softc *, uint16_t, uint16_t);
int rtwn_pci_write_4(struct rtwn_softc *, uint16_t, uint32_t);
uint8_t rtwn_pci_read_1(struct rtwn_softc *, uint16_t);
uint16_t rtwn_pci_read_2(struct rtwn_softc *, uint16_t);
uint32_t rtwn_pci_read_4(struct rtwn_softc *, uint16_t);
void rtwn_pci_delay(struct rtwn_softc *, int);
#endif /* RTWN_PCI_REG_H */

View File

@ -0,0 +1,293 @@
/* $OpenBSD: if_rtwn.c,v 1.6 2015/08/28 00:03:53 deraadt Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2015 Stefan Sperling <stsp@openbsd.org>
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <machine/bus.h>
#include <machine/resource.h>
#include <sys/rman.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/if_rtwn_debug.h>
#include <dev/rtwn/if_rtwn_rx.h>
#include <dev/rtwn/if_rtwn_tx.h>
#include <dev/rtwn/pci/rtwn_pci_var.h>
#include <dev/rtwn/pci/rtwn_pci_rx.h>
#include <dev/rtwn/rtl8192c/pci/r92ce_rx_desc.h>
void
rtwn_pci_dma_map_addr(void *arg, bus_dma_segment_t *segs, int nsegs,
int error)
{
if (error != 0)
return;
KASSERT(nsegs == 1, ("too many DMA segments, %d should be 1", nsegs));
*(bus_addr_t *)arg = segs[0].ds_addr;
}
void
rtwn_pci_setup_rx_desc(struct rtwn_pci_softc *pc, struct r92ce_rx_stat *desc,
bus_addr_t addr, size_t len, int idx)
{
memset(desc, 0, sizeof(*desc));
desc->rxdw0 = htole32(SM(R92C_RXDW0_PKTLEN, len) |
((idx == RTWN_PCI_RX_LIST_COUNT - 1) ? R92C_RXDW0_EOR : 0));
desc->rxbufaddr = htole32(addr);
bus_space_barrier(pc->pc_st, pc->pc_sh, 0, pc->pc_mapsize,
BUS_SPACE_BARRIER_WRITE);
desc->rxdw0 |= htole32(R92C_RXDW0_OWN);
}
static void
rtwn_pci_rx_frame(struct rtwn_softc *sc, struct r92ce_rx_stat *rx_desc,
int desc_idx)
{
struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
struct rtwn_rx_ring *ring = &pc->rx_ring;
struct rtwn_rx_data *rx_data = &ring->rx_data[desc_idx];
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_node *ni;
uint32_t rxdw0;
struct mbuf *m, *m1;
int8_t rssi = 0, nf;
int infosz, pktlen, shift, error;
/* Dump Rx descriptor. */
RTWN_DPRINTF(sc, RTWN_DEBUG_RECV_DESC,
"%s: dw: 0 %08X, 1 %08X, 2 %08X, 3 %08X, 4 %08X, tsfl %08X, "
"addr: %08X (64: %08X)\n",
__func__, le32toh(rx_desc->rxdw0), le32toh(rx_desc->rxdw1),
le32toh(rx_desc->rxdw2), le32toh(rx_desc->rxdw3),
le32toh(rx_desc->rxdw4), le32toh(rx_desc->tsf_low),
le32toh(rx_desc->rxbufaddr), le32toh(rx_desc->rxbufaddr64));
rxdw0 = le32toh(rx_desc->rxdw0);
if (__predict_false(rxdw0 & (R92C_RXDW0_CRCERR | R92C_RXDW0_ICVERR))) {
/*
* This should not happen since we setup our Rx filter
* to not receive these frames.
*/
RTWN_DPRINTF(sc, RTWN_DEBUG_RECV,
"%s: RX flags error (%s)\n", __func__,
rxdw0 & R92C_RXDW0_CRCERR ? "CRC" : "ICV");
goto fail;
}
pktlen = MS(rxdw0, R92C_RXDW0_PKTLEN);
if (__predict_false(pktlen < sizeof(struct ieee80211_frame_ack) ||
pktlen > MCLBYTES)) {
RTWN_DPRINTF(sc, RTWN_DEBUG_RECV,
"%s: frame is too short/long: %d\n", __func__, pktlen);
goto fail;
}
infosz = MS(rxdw0, R92C_RXDW0_INFOSZ) * 8;
shift = MS(rxdw0, R92C_RXDW0_SHIFT);
m1 = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
if (__predict_false(m1 == NULL)) {
device_printf(sc->sc_dev, "%s: could not allocate RX mbuf\n",
__func__);
goto fail;
}
bus_dmamap_sync(ring->data_dmat, rx_data->map, BUS_DMASYNC_POSTREAD);
bus_dmamap_unload(ring->data_dmat, rx_data->map);
error = bus_dmamap_load(ring->data_dmat, rx_data->map, mtod(m1, void *),
MCLBYTES, rtwn_pci_dma_map_addr, &rx_data->paddr, 0);
if (error != 0) {
m_freem(m1);
error = bus_dmamap_load(ring->data_dmat, rx_data->map,
mtod(rx_data->m, void *), MCLBYTES, rtwn_pci_dma_map_addr,
&rx_data->paddr, BUS_DMA_NOWAIT);
if (error != 0)
panic("%s: could not load old RX mbuf",
device_get_name(sc->sc_dev));
/* Physical address may have changed. */
rtwn_pci_setup_rx_desc(pc, rx_desc, rx_data->paddr, MCLBYTES,
desc_idx);
goto fail;
}
/* Finalize mbuf. */
m = rx_data->m;
rx_data->m = m1;
m->m_pkthdr.len = m->m_len = pktlen + infosz + shift;
nf = RTWN_NOISE_FLOOR;
ni = rtwn_rx_common(sc, m, rx_desc, &rssi);
RTWN_DPRINTF(sc, RTWN_DEBUG_RECV,
"%s: Rx frame len %d, infosz %d, shift %d, rssi %d\n",
__func__, pktlen, infosz, shift, rssi);
/* Update RX descriptor. */
rtwn_pci_setup_rx_desc(pc, rx_desc, rx_data->paddr, MCLBYTES,
desc_idx);
/* Send the frame to the 802.11 layer. */
RTWN_UNLOCK(sc);
if (ni != NULL) {
(void)ieee80211_input(ni, m, rssi - nf, nf);
/* Node is no longer needed. */
ieee80211_free_node(ni);
} else
(void)ieee80211_input_all(ic, m, rssi - nf, nf);
RTWN_LOCK(sc);
return;
fail:
counter_u64_add(ic->ic_ierrors, 1);
}
static void
rtwn_pci_tx_done(struct rtwn_softc *sc, int qid)
{
struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
struct rtwn_tx_ring *ring = &pc->tx_ring[qid];
struct rtwn_tx_desc_common *desc;
struct rtwn_tx_data *data;
RTWN_DPRINTF(sc, RTWN_DEBUG_INTR, "%s: qid %d, last %d, cur %d\n",
__func__, qid, ring->last, ring->cur);
bus_dmamap_sync(ring->desc_dmat, ring->desc_map, BUS_DMASYNC_POSTREAD);
while(ring->last != ring->cur) {
data = &ring->tx_data[ring->last];
desc = (struct rtwn_tx_desc_common *)
((uint8_t *)ring->desc + sc->txdesc_len * ring->last);
KASSERT(data->m != NULL, ("no mbuf"));
if (desc->flags0 & RTWN_FLAGS0_OWN)
break;
/* Unmap and free mbuf. */
bus_dmamap_sync(ring->data_dmat, data->map,
BUS_DMASYNC_POSTWRITE);
bus_dmamap_unload(ring->data_dmat, data->map);
if (data->ni != NULL) { /* not a beacon frame */
ieee80211_tx_complete(data->ni, data->m, 0);
data->ni = NULL;
ring->queued--;
} else
m_freem(data->m);
data->m = NULL;
ring->last = (ring->last + 1) % RTWN_PCI_TX_LIST_COUNT;
#ifndef D4054
if (ring->queued > 0)
sc->sc_tx_timer = 5;
else
sc->sc_tx_timer = 0;
#endif
}
if (ring->queued < (RTWN_PCI_TX_LIST_COUNT - 1))
sc->qfullmsk &= ~(1 << qid);
rtwn_start(sc);
}
static void
rtwn_pci_rx_done(struct rtwn_softc *sc)
{
struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
struct rtwn_rx_ring *ring = &pc->rx_ring;
bus_dmamap_sync(ring->desc_dmat, ring->desc_map, BUS_DMASYNC_POSTREAD);
for (;;) {
struct r92ce_rx_stat *rx_desc = &ring->desc[ring->cur];
if (le32toh(rx_desc->rxdw0) & R92C_RXDW0_OWN)
break;
rtwn_pci_rx_frame(sc, rx_desc, ring->cur);
if (!(sc->sc_flags & RTWN_RUNNING))
return;
ring->cur = (ring->cur + 1) % RTWN_PCI_RX_LIST_COUNT;
}
}
void
rtwn_pci_intr(void *arg)
{
struct rtwn_softc *sc = arg;
struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
int i, status, tx_rings;
RTWN_LOCK(sc);
status = rtwn_classify_intr(sc, &tx_rings, 0);
RTWN_DPRINTF(sc, RTWN_DEBUG_INTR, "%s: status %08X, tx_rings %08X\n",
__func__, status, tx_rings);
if (status == 0 && tx_rings == 0) {
RTWN_UNLOCK(sc);
return;
}
if (status & RTWN_PCI_INTR_RX)
rtwn_pci_rx_done(sc);
if (tx_rings != 0)
for (i = 0; i < RTWN_PCI_NTXQUEUES; i++)
if (tx_rings & (1 << i))
rtwn_pci_tx_done(sc, i);
if (sc->sc_flags & RTWN_RUNNING)
rtwn_pci_enable_intr(pc);
RTWN_UNLOCK(sc);
}

View File

@ -0,0 +1,27 @@
/*-
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $FreeBSD$
*/
#ifndef RTWN_PCI_RX_H
#define RTWN_PCI_RX_H
void rtwn_pci_dma_map_addr(void *, bus_dma_segment_t *, int, int);
void rtwn_pci_setup_rx_desc(struct rtwn_pci_softc *,
struct r92ce_rx_stat *, bus_addr_t, size_t, int);
void rtwn_pci_intr(void *);
#endif /* RTWN_PCI_RX_H */

View File

@ -0,0 +1,195 @@
/* $OpenBSD: if_rtwn.c,v 1.6 2015/08/28 00:03:53 deraadt Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2015 Stefan Sperling <stsp@openbsd.org>
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <machine/bus.h>
#include <machine/resource.h>
#include <sys/rman.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/if_rtwn_debug.h>
#include <dev/rtwn/pci/rtwn_pci_var.h>
#include <dev/rtwn/pci/rtwn_pci_tx.h>
#include <dev/rtwn/rtl8192c/pci/r92ce_reg.h>
static int
rtwn_pci_tx_start_common(struct rtwn_softc *sc, struct ieee80211_node *ni,
struct mbuf *m, uint8_t *tx_desc, uint8_t type, int id)
{
struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
struct rtwn_tx_ring *ring;
struct rtwn_tx_data *data;
struct rtwn_tx_desc_common *txd;
bus_dma_segment_t segs[1];
uint8_t qid;
int nsegs, error;
RTWN_ASSERT_LOCKED(sc);
switch (type) {
case IEEE80211_FC0_TYPE_CTL:
case IEEE80211_FC0_TYPE_MGT:
qid = RTWN_PCI_VO_QUEUE;
break;
default:
qid = M_WME_GETAC(m);
break;
}
if (ni == NULL) /* beacon frame */
qid = RTWN_PCI_BEACON_QUEUE;
ring = &pc->tx_ring[qid];
data = &ring->tx_data[ring->cur];
if (data->m != NULL) {
RTWN_DPRINTF(sc, RTWN_DEBUG_XMIT,
"%s: ring #%u is full (m %p)\n", __func__, qid, data->m);
return (ENOBUFS);
}
txd = (struct rtwn_tx_desc_common *)
((uint8_t *)ring->desc + sc->txdesc_len * ring->cur);
if (txd->flags0 & RTWN_FLAGS0_OWN) {
device_printf(sc->sc_dev,
"%s: OWN bit is set (tx desc %d, ring %u)!\n",
__func__, ring->cur, qid);
return (ENOBUFS);
}
/* Copy Tx descriptor. */
rtwn_pci_copy_tx_desc(pc, txd, tx_desc);
txd->pktlen = htole16(m->m_pkthdr.len);
txd->offset = sc->txdesc_len;
error = bus_dmamap_load_mbuf_sg(ring->data_dmat, data->map, m, segs,
&nsegs, BUS_DMA_NOWAIT);
if (error != 0 && error != EFBIG) {
device_printf(sc->sc_dev, "can't map mbuf (error %d)\n",
error);
return (error);
}
if (error != 0) {
struct mbuf *mnew;
mnew = m_defrag(m, M_NOWAIT);
if (mnew == NULL) {
device_printf(sc->sc_dev, "can't defragment mbuf\n");
return (ENOBUFS);
}
m = mnew;
error = bus_dmamap_load_mbuf_sg(ring->data_dmat, data->map, m,
segs, &nsegs, BUS_DMA_NOWAIT);
if (error != 0) {
device_printf(sc->sc_dev,
"can't map mbuf (error %d)\n", error);
if (ni != NULL) {
if_inc_counter(ni->ni_vap->iv_ifp,
IFCOUNTER_OERRORS, 1);
ieee80211_free_node(ni);
}
m_freem(m);
return (0); /* XXX */
}
}
rtwn_pci_tx_postsetup(pc, txd, segs);
txd->flags0 |= RTWN_FLAGS0_OWN;
/* Dump Tx descriptor. */
rtwn_dump_tx_desc(sc, txd);
bus_dmamap_sync(ring->desc_dmat, ring->desc_map,
BUS_DMASYNC_POSTWRITE);
bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_POSTWRITE);
data->m = m;
data->ni = ni;
data->id = id;
ring->cur = (ring->cur + 1) % RTWN_PCI_TX_LIST_COUNT;
if (qid != RTWN_PCI_BEACON_QUEUE) {
ring->queued++;
if (ring->queued >= (RTWN_PCI_TX_LIST_COUNT - 1))
sc->qfullmsk |= (1 << qid);
#ifndef D4054
sc->sc_tx_timer = 5;
#endif
}
/* Kick TX. */
rtwn_write_2(sc, R92C_PCIE_CTRL_REG, (1 << qid));
return (0);
}
int
rtwn_pci_tx_start(struct rtwn_softc *sc, struct ieee80211_node *ni,
struct mbuf *m, uint8_t *tx_desc, uint8_t type, int id)
{
int error = 0;
if (ni == NULL) { /* beacon frame */
m = m_dup(m, M_NOWAIT);
if (__predict_false(m == NULL)) {
device_printf(sc->sc_dev,
"%s: could not copy beacon frame\n", __func__);
return (ENOMEM);
}
error = rtwn_pci_tx_start_common(sc, ni, m, tx_desc, type, id);
if (error != 0)
m_freem(m);
} else
error = rtwn_pci_tx_start_common(sc, ni, m, tx_desc, type, id);
return (error);
}

View File

@ -0,0 +1,25 @@
/*-
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $FreeBSD$
*/
#ifndef RTWN_PCI_TX_H
#define RTWN_PCI_TX_H
int rtwn_pci_tx_start(struct rtwn_softc *, struct ieee80211_node *,
struct mbuf *, uint8_t *, uint8_t, int);
#endif /* RTWN_PCI_TX_H */

View File

@ -0,0 +1,141 @@
/* $OpenBSD: if_rtwnreg.h,v 1.3 2015/06/14 08:02:47 stsp Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2015 Stefan Sperling <stsp@openbsd.org>
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $FreeBSD$
*/
#ifndef RTWN_PCI_VAR_H
#define RTWN_PCI_VAR_H
#include <dev/rtwn/rtl8192c/pci/r92ce_rx_desc.h>
#define RTWN_PCI_RX_LIST_COUNT 256
#define RTWN_PCI_TX_LIST_COUNT 256
struct rtwn_rx_data {
bus_dmamap_t map;
struct mbuf *m;
bus_addr_t paddr;
};
struct rtwn_rx_ring {
struct r92ce_rx_stat *desc;
bus_addr_t paddr;
bus_dma_tag_t desc_dmat;
bus_dmamap_t desc_map;
bus_dma_tag_t data_dmat;
bus_dma_segment_t seg;
struct rtwn_rx_data rx_data[RTWN_PCI_RX_LIST_COUNT];
int cur;
};
struct rtwn_tx_data {
bus_dmamap_t map;
struct mbuf *m;
struct ieee80211_node *ni;
uint8_t id;
};
struct rtwn_tx_ring {
bus_addr_t paddr;
bus_dma_tag_t desc_dmat;
bus_dmamap_t desc_map;
bus_dma_tag_t data_dmat;
bus_dma_segment_t seg;
void *desc;
struct rtwn_tx_data tx_data[RTWN_PCI_TX_LIST_COUNT];
int queued;
int cur;
int last;
};
/*
* TX queue indices.
*/
enum {
RTWN_PCI_BK_QUEUE,
RTWN_PCI_BE_QUEUE,
RTWN_PCI_VI_QUEUE,
RTWN_PCI_VO_QUEUE,
RTWN_PCI_BEACON_QUEUE,
RTWN_PCI_TXCMD_QUEUE,
RTWN_PCI_MGNT_QUEUE,
RTWN_PCI_HIGH_QUEUE,
RTWN_PCI_HCCA_QUEUE,
RTWN_PCI_NTXQUEUES
};
/*
* Interrupt events.
*/
enum {
RTWN_PCI_INTR_RX_ERROR = 0x00000001,
RTWN_PCI_INTR_RX_OVERFLOW = 0x00000002,
RTWN_PCI_INTR_RX_DESC_UNAVAIL = 0x00000004,
RTWN_PCI_INTR_RX_DONE = 0x00000008,
RTWN_PCI_INTR_TX_ERROR = 0x00000010,
RTWN_PCI_INTR_TX_OVERFLOW = 0x00000020,
RTWN_PCI_INTR_TX_REPORT = 0x00000040,
RTWN_PCI_INTR_PS_TIMEOUT = 0x00000080
};
/* Shortcuts */
/* Vendor driver treats RX errors like ROK... */
#define RTWN_PCI_INTR_RX \
(RTWN_PCI_INTR_RX_OVERFLOW | RTWN_PCI_INTR_RX_DESC_UNAVAIL | \
RTWN_PCI_INTR_RX_DONE)
struct rtwn_pci_softc {
struct rtwn_softc pc_sc; /* must be the first */
struct resource *irq;
struct resource *mem;
bus_space_tag_t pc_st;
bus_space_handle_t pc_sh;
void *pc_ih;
bus_size_t pc_mapsize;
struct rtwn_rx_ring rx_ring;
struct rtwn_tx_ring tx_ring[RTWN_PCI_NTXQUEUES];
/* must be set by the driver. */
uint16_t pc_qmap;
uint32_t tcr;
void (*pc_setup_tx_desc)(struct rtwn_pci_softc *,
void *, uint32_t);
void (*pc_tx_postsetup)(struct rtwn_pci_softc *,
void *, bus_dma_segment_t *);
void (*pc_copy_tx_desc)(void *, const void *);
void (*pc_enable_intr)(struct rtwn_pci_softc *);
};
#define RTWN_PCI_SOFTC(sc) ((struct rtwn_pci_softc *)(sc))
#define rtwn_pci_setup_tx_desc(_pc, _desc, _addr) \
(((_pc)->pc_setup_tx_desc)((_pc), (_desc), (_addr)))
#define rtwn_pci_tx_postsetup(_pc, _txd, _segs) \
(((_pc)->pc_tx_postsetup)((_pc), (_txd), (_segs)))
#define rtwn_pci_copy_tx_desc(_pc, _dest, _src) \
(((_pc)->pc_copy_tx_desc)((_dest), (_src)))
#define rtwn_pci_enable_intr(_pc) \
(((_pc)->pc_enable_intr)((_pc)))
#endif /* RTWN_PCI_VAR_H */

View File

@ -0,0 +1,94 @@
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $
* $FreeBSD$
*/
#ifndef RTL8188E_H
#define RTL8188E_H
/*
* Global definitions.
*/
#define R88E_PUBQ_NPAGES 142
#define R88E_TXPKTBUF_COUNT 177
#define R88E_TX_PAGE_COUNT 169
#define R88E_MACID_MAX 63
#define R88E_RX_DMA_BUFFER_SIZE 0x2400
#define R88E_INTR_MSG_LEN 60
#define R88E_CALIB_THRESHOLD 4
/*
* Function declarations.
*/
/* r88e_beacon.c */
void r88e_beacon_enable(struct rtwn_softc *, int, int);
/* r88e_calib.c */
void r88e_iq_calib(struct rtwn_softc *);
void r88e_temp_measure(struct rtwn_softc *);
uint8_t r88e_temp_read(struct rtwn_softc *);
/* r88e_chan.c */
void r88e_get_txpower(struct rtwn_softc *, int,
struct ieee80211_channel *, uint16_t[]);
void r88e_set_bw20(struct rtwn_softc *, uint8_t);
void r88e_set_gain(struct rtwn_softc *, uint8_t);
/* r88e_fw.c */
#ifndef RTWN_WITHOUT_UCODE
int r88e_fw_cmd(struct rtwn_softc *, uint8_t, const void *, int);
void r88e_fw_reset(struct rtwn_softc *, int);
void r88e_fw_download_enable(struct rtwn_softc *, int);
#endif
void r88e_macid_enable_link(struct rtwn_softc *, int, int);
void r88e_set_media_status(struct rtwn_softc *, int);
#ifndef RTWN_WITHOUT_UCODE
int r88e_set_rsvd_page(struct rtwn_softc *, int, int, int);
int r88e_set_pwrmode(struct rtwn_softc *, struct ieee80211vap *, int);
#endif
/* r88e_init.c */
void r88e_init_bb(struct rtwn_softc *);
void r88e_init_rf(struct rtwn_softc *);
int r88e_power_on(struct rtwn_softc *);
/* r88e_led.c */
void r88e_set_led(struct rtwn_softc *, int, int);
/* r88e_rf.c */
void r88e_rf_write(struct rtwn_softc *, int, uint8_t, uint32_t);
/* r88e_rom.c */
void r88e_parse_rom(struct rtwn_softc *, uint8_t *);
/* r88e_rx.c */
void r88e_ratectl_tx_complete(struct rtwn_softc *, uint8_t *, int);
void r88e_handle_c2h_report(struct rtwn_softc *, uint8_t *, int);
int8_t r88e_get_rssi_cck(struct rtwn_softc *, void *);
int8_t r88e_get_rssi_ofdm(struct rtwn_softc *, void *);
/* r88e_tx.c */
void r88e_tx_enable_ampdu(void *, int);
void r88e_tx_setup_hwseq(void *);
void r88e_tx_setup_macid(void *, int);
#endif /* RTL8188E_H */

View File

@ -0,0 +1,62 @@
/*-
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/rtl8188e/r88e.h>
#include <dev/rtwn/rtl8188e/r88e_reg.h>
void
r88e_beacon_enable(struct rtwn_softc *sc, int id, int enable)
{
if (enable) {
rtwn_setbits_1(sc, R92C_MBID_NUM, 0, R88E_MBID_TXBCN_RPT(id));
rtwn_setbits_1(sc, R92C_BCN_CTRL(id),
0, R92C_BCN_CTRL_EN_BCN);
} else {
rtwn_setbits_1(sc, R92C_MBID_NUM, R88E_MBID_TXBCN_RPT(id), 0);
rtwn_setbits_1(sc, R92C_BCN_CTRL(id),
R92C_BCN_CTRL_EN_BCN, 0);
}
}

View File

@ -0,0 +1,67 @@
/*-
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/rtl8188e/r88e.h>
#include <dev/rtwn/rtl8188e/r88e_reg.h>
void
r88e_iq_calib(struct rtwn_softc *sc)
{
/* XXX TODO */
}
void
r88e_temp_measure(struct rtwn_softc *sc)
{
rtwn_rf_write(sc, 0, R88E_RF_T_METER, R88E_RF_T_METER_START);
}
uint8_t
r88e_temp_read(struct rtwn_softc *sc)
{
return (MS(rtwn_rf_read(sc, 0, R88E_RF_T_METER),
R88E_RF_T_METER_VAL));
}

View File

@ -0,0 +1,167 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/if_rtwn_debug.h>
#include <dev/rtwn/if_rtwn_ridx.h>
#include <dev/rtwn/rtl8192c/r92c_var.h>
#include <dev/rtwn/rtl8188e/r88e.h>
#include <dev/rtwn/rtl8188e/r88e_priv.h>
#include <dev/rtwn/rtl8188e/r88e_reg.h>
static int
r88e_get_power_group(struct rtwn_softc *sc, struct ieee80211_channel *c)
{
uint8_t chan;
int group;
chan = rtwn_chan2centieee(c);
if (IEEE80211_IS_CHAN_2GHZ(c)) {
if (chan <= 2) group = 0;
else if (chan <= 5) group = 1;
else if (chan <= 8) group = 2;
else if (chan <= 11) group = 3;
else if (chan <= 13) group = 4;
else if (chan <= 14) group = 5;
else {
KASSERT(0, ("wrong 2GHz channel %d!\n", chan));
return (-1);
}
} else {
KASSERT(0, ("wrong channel band (flags %08X)\n", c->ic_flags));
return (-1);
}
return (group);
}
void
r88e_get_txpower(struct rtwn_softc *sc, int chain,
struct ieee80211_channel *c, uint16_t power[RTWN_RIDX_COUNT])
{
struct r92c_softc *rs = sc->sc_priv;
const struct rtwn_r88e_txpwr *rt = rs->rs_txpwr;
const struct rtwn_r88e_txagc *base = rs->rs_txagc;
uint16_t cckpow, ofdmpow, bw20pow, htpow;
int max_mcs, ridx, group;
/* Determine channel group. */
group = r88e_get_power_group(sc, c);
if (group == -1) { /* shouldn't happen */
device_printf(sc->sc_dev, "%s: incorrect channel\n", __func__);
return;
}
/* XXX net80211 regulatory */
max_mcs = RTWN_RIDX_MCS(sc->ntxchains * 8 - 1);
KASSERT(max_mcs <= RTWN_RIDX_COUNT, ("increase ridx limit\n"));
memset(power, 0, max_mcs * sizeof(power[0]));
if (rs->regulatory == 0) {
for (ridx = RTWN_RIDX_CCK1; ridx <= RTWN_RIDX_CCK11; ridx++)
power[ridx] = base->pwr[0][ridx];
}
for (ridx = RTWN_RIDX_OFDM6; ridx < RTWN_RIDX_COUNT; ridx++) {
if (rs->regulatory == 3)
power[ridx] = base->pwr[0][ridx];
else if (rs->regulatory == 1) {
if (!IEEE80211_IS_CHAN_HT40(c))
power[ridx] = base->pwr[group][ridx];
} else if (rs->regulatory != 2)
power[ridx] = base->pwr[0][ridx];
}
/* Compute per-CCK rate Tx power. */
cckpow = rt->cck_tx_pwr[group];
for (ridx = RTWN_RIDX_CCK1; ridx <= RTWN_RIDX_CCK11; ridx++)
power[ridx] += cckpow;
htpow = rt->ht40_tx_pwr[group];
/* Compute per-OFDM rate Tx power. */
ofdmpow = htpow + rt->ofdm_tx_pwr_diff;
for (ridx = RTWN_RIDX_OFDM6; ridx <= RTWN_RIDX_OFDM54; ridx++)
power[ridx] += ofdmpow;
bw20pow = htpow + rt->bw20_tx_pwr_diff;
for (ridx = RTWN_RIDX_MCS(0); ridx <= max_mcs; ridx++)
power[ridx] += bw20pow;
/* Apply max limit. */
for (ridx = RTWN_RIDX_CCK1; ridx <= max_mcs; ridx++) {
if (power[ridx] > R92C_MAX_TX_PWR)
power[ridx] = R92C_MAX_TX_PWR;
}
}
void
r88e_set_bw20(struct rtwn_softc *sc, uint8_t chan)
{
struct r92c_softc *rs = sc->sc_priv;
rtwn_setbits_1(sc, R92C_BWOPMODE, 0, R92C_BWOPMODE_20MHZ);
rtwn_bb_setbits(sc, R92C_FPGA0_RFMOD, R92C_RFMOD_40MHZ, 0);
rtwn_bb_setbits(sc, R92C_FPGA1_RFMOD, R92C_RFMOD_40MHZ, 0);
/* Select 20MHz bandwidth. */
rtwn_rf_write(sc, 0, R92C_RF_CHNLBW,
(rs->rf_chnlbw[0] & ~0xfff) | chan | R88E_RF_CHNLBW_BW20);
}
void
r88e_set_gain(struct rtwn_softc *sc, uint8_t gain)
{
rtwn_bb_setbits(sc, R92C_OFDM0_AGCCORE1(0),
R92C_OFDM0_AGCCORE1_GAIN_M, gain);
}

View File

@ -0,0 +1,225 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/if_rtwn_debug.h>
#include <dev/rtwn/rtl8188e/r88e.h>
#include <dev/rtwn/rtl8188e/r88e_reg.h>
#include <dev/rtwn/rtl8188e/r88e_fw_cmd.h>
#ifndef RTWN_WITHOUT_UCODE
int
r88e_fw_cmd(struct rtwn_softc *sc, uint8_t id, const void *buf, int len)
{
struct r88e_fw_cmd cmd;
int ntries, error;
if (!(sc->sc_flags & RTWN_FW_LOADED)) {
RTWN_DPRINTF(sc, RTWN_DEBUG_FIRMWARE, "%s: firmware "
"was not loaded; command (id %d) will be discarded\n",
__func__, id);
return (0);
}
/* Wait for current FW box to be empty. */
for (ntries = 0; ntries < 50; ntries++) {
if (!(rtwn_read_1(sc, R92C_HMETFR) & (1 << sc->fwcur)))
break;
rtwn_delay(sc, 2000);
}
if (ntries == 100) {
device_printf(sc->sc_dev,
"could not send firmware command\n");
return (ETIMEDOUT);
}
memset(&cmd, 0, sizeof(cmd));
cmd.id = id;
KASSERT(len <= sizeof(cmd.msg),
("%s: firmware command too long (%d > %zu)\n",
__func__, len, sizeof(cmd.msg)));
memcpy(cmd.msg, buf, len);
/* Write the first word last since that will trigger the FW. */
if (len > 3) {
error = rtwn_write_4(sc, R88E_HMEBOX_EXT(sc->fwcur),
*(uint32_t *)((uint8_t *)&cmd + 4));
if (error != 0)
return (error);
}
error = rtwn_write_4(sc, R92C_HMEBOX(sc->fwcur), *(uint32_t *)&cmd);
if (error != 0)
return (error);
sc->fwcur = (sc->fwcur + 1) % R92C_H2C_NBOX;
return (0);
}
void
r88e_fw_reset(struct rtwn_softc *sc, int reason)
{
uint16_t reg;
reg = rtwn_read_2(sc, R92C_SYS_FUNC_EN);
rtwn_write_2(sc, R92C_SYS_FUNC_EN, reg & ~R92C_SYS_FUNC_EN_CPUEN);
rtwn_write_2(sc, R92C_SYS_FUNC_EN, reg | R92C_SYS_FUNC_EN_CPUEN);
}
void
r88e_fw_download_enable(struct rtwn_softc *sc, int enable)
{
if (enable) {
/* MCU firmware download enable. */
rtwn_setbits_1(sc, R92C_MCUFWDL, 0, R92C_MCUFWDL_EN);
/* 8051 reset. */
rtwn_setbits_1_shift(sc, R92C_MCUFWDL, R92C_MCUFWDL_ROM_DLEN,
0, 2);
} else {
/* MCU download disable. */
rtwn_setbits_1(sc, R92C_MCUFWDL, R92C_MCUFWDL_EN, 0);
/* Reserved for f/w extension. */
rtwn_write_1(sc, R92C_MCUFWDL + 1, 0);
}
}
#endif
void
r88e_macid_enable_link(struct rtwn_softc *sc, int id, int enable)
{
uint32_t reg;
reg = R88E_MACID_NO_LINK;
if (id > 32)
reg += 4;
if (enable)
rtwn_setbits_4(sc, reg, 1 << (id % 32), 0);
else
rtwn_setbits_4(sc, reg, 0, 1 << (id % 32));
/* XXX max macid for tx reports */
}
void
r88e_set_media_status(struct rtwn_softc *sc, int macid)
{
struct r88e_fw_cmd_msrrpt status;
if (macid & RTWN_MACID_VALID)
status.msrb0 = R88E_MSRRPT_B0_ASSOC;
else
status.msrb0 = R88E_MSRRPT_B0_DISASSOC;
status.macid = (macid & ~RTWN_MACID_VALID);
r88e_macid_enable_link(sc, status.macid,
(macid & RTWN_MACID_VALID) != 0);
#ifndef RTWN_WITHOUT_UCODE
if (r88e_fw_cmd(sc, R88E_CMD_MSR_RPT, &status, sizeof(status)) != 0) {
device_printf(sc->sc_dev, "%s: cannot change media status!\n",
__func__);
}
#endif
}
#ifndef RTWN_WITHOUT_UCODE
int
r88e_set_rsvd_page(struct rtwn_softc *sc, int probe_resp, int null,
int qos_null)
{
struct r88e_fw_cmd_rsvdpage rsvd;
rsvd.probe_resp = probe_resp;
rsvd.ps_poll = 0;
rsvd.null_data = null;
rsvd.null_data_qos = qos_null;
rsvd.null_data_qos_bt = 0;
return (r88e_fw_cmd(sc, R88E_CMD_RSVD_PAGE, &rsvd, sizeof(rsvd)));
}
int
r88e_set_pwrmode(struct rtwn_softc *sc, struct ieee80211vap *vap,
int off)
{
struct r88e_fw_cmd_pwrmode mode;
int error;
if (off && vap->iv_state == IEEE80211_S_RUN &&
(vap->iv_flags & IEEE80211_F_PMGTON)) {
mode.mode = R88E_PWRMODE_LEG;
/*
* TODO: switch to RFOFF state
* (something is missing here - Rx stops with it).
*/
#ifdef RTWN_TODO
mode.pwr_state = R88E_PWRMODE_STATE_RFOFF;
#else
mode.pwr_state = R88E_PWRMODE_STATE_RFON;
#endif
} else {
mode.mode = R88E_PWRMODE_CAM;
mode.pwr_state = R88E_PWRMODE_STATE_ALLON;
}
mode.pwrb1 =
SM(R88E_PWRMODE_B1_SMART_PS, R88E_PWRMODE_B1_LEG_NULLDATA) |
SM(R88E_PWRMODE_B1_RLBM, R88E_PWRMODE_B1_MODE_MIN);
/* XXX ignored */
mode.bcn_pass = 0;
mode.queue_uapsd = 0;
error = r88e_fw_cmd(sc, R88E_CMD_SET_PWRMODE, &mode, sizeof(mode));
if (error != 0) {
device_printf(sc->sc_dev,
"%s: CMD_SET_PWRMODE was not sent, error %d\n",
__func__, error);
}
return (error);
}
#endif

View File

@ -0,0 +1,84 @@
/*-
* Copyright (c) 2015 Kevin Lo <kevlo@FreeBSD.org>
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $
* $FreeBSD$
*/
#ifndef R88E_FW_CMD_H
#define R88E_FW_CMD_H
/*
* Host to firmware commands.
*/
struct r88e_fw_cmd {
uint8_t id;
#define R88E_CMD_RSVD_PAGE 0x00
#define R88E_CMD_MSR_RPT 0x01
#define R88E_CMD_SET_PWRMODE 0x20
uint8_t msg[7];
} __packed __attribute__((aligned(4)));
/* Structure for R88E_CMD_RSVD_PAGE. */
struct r88e_fw_cmd_rsvdpage {
uint8_t probe_resp;
uint8_t ps_poll;
uint8_t null_data;
uint8_t null_data_qos;
uint8_t null_data_qos_bt;
} __packed;
/* Structure for R88E_CMD_MSR_RPT. */
struct r88e_fw_cmd_msrrpt {
uint8_t msrb0;
#define R88E_MSRRPT_B0_DISASSOC 0x00
#define R88E_MSRRPT_B0_ASSOC 0x01
uint8_t macid;
} __packed;
/* Structure for R88E_CMD_SET_PWRMODE. */
struct r88e_fw_cmd_pwrmode {
uint8_t mode;
#define R88E_PWRMODE_CAM 0
#define R88E_PWRMODE_LEG 1
#define R88E_PWRMODE_UAPSD 2
uint8_t pwrb1;
#define R88E_PWRMODE_B1_RLBM_M 0x0f
#define R88E_PWRMODE_B1_RLBM_S 0
#define R88E_PWRMODE_B1_MODE_MIN 0
#define R88E_PWRMODE_B1_MODE_MAX 1
#define R88E_PWRMODE_B1_MODE_DTIM 2
#define R88E_PWRMODE_B1_SMART_PS_M 0xf0
#define R88E_PWRMODE_B1_SMART_PS_S 4
#define R88E_PWRMODE_B1_LEG_PSPOLL0 0
#define R88E_PWRMODE_B1_LEG_PSPOLL1 1
#define R88E_PWRMODE_B1_LEG_NULLDATA 2
#define R88E_PWRMODE_B1_WMM_PSPOLL 0
#define R88E_PWRMODE_B1_WMM_NULLDATA 1
uint8_t bcn_pass;
uint8_t queue_uapsd;
uint8_t pwr_state;
#define R88E_PWRMODE_STATE_RFOFF 0x00
#define R88E_PWRMODE_STATE_RFON 0x04
#define R88E_PWRMODE_STATE_ALLON 0x0c
} __packed;
#endif /* R88E_FW_CMD_H */

View File

@ -0,0 +1,158 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/if_rtwn_debug.h>
#include <dev/rtwn/rtl8192c/r92c.h>
#include <dev/rtwn/rtl8192c/r92c_var.h>
#include <dev/rtwn/rtl8188e/r88e.h>
#include <dev/rtwn/rtl8188e/r88e_reg.h>
static void
r88e_crystalcap_write(struct rtwn_softc *sc)
{
struct r92c_softc *rs = sc->sc_priv;
uint32_t reg;
uint8_t val;
val = rs->crystalcap & 0x3f;
reg = rtwn_bb_read(sc, R92C_AFE_XTAL_CTRL);
rtwn_bb_write(sc, R92C_AFE_XTAL_CTRL,
RW(reg, R92C_AFE_XTAL_CTRL_ADDR, val | val << 6));
}
void
r88e_init_bb(struct rtwn_softc *sc)
{
/* Enable BB and RF. */
rtwn_setbits_2(sc, R92C_SYS_FUNC_EN, 0,
R92C_SYS_FUNC_EN_BBRSTB | R92C_SYS_FUNC_EN_BB_GLB_RST |
R92C_SYS_FUNC_EN_DIO_RF);
rtwn_write_1(sc, R92C_RF_CTRL,
R92C_RF_CTRL_EN | R92C_RF_CTRL_RSTB | R92C_RF_CTRL_SDMRSTB);
rtwn_write_1(sc, R92C_SYS_FUNC_EN,
R92C_SYS_FUNC_EN_USBA | R92C_SYS_FUNC_EN_USBD |
R92C_SYS_FUNC_EN_BB_GLB_RST | R92C_SYS_FUNC_EN_BBRSTB);
r92c_init_bb_common(sc);
rtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(0), 0x69553422);
rtwn_delay(sc, 1);
rtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(0), 0x69553420);
rtwn_delay(sc, 1);
r88e_crystalcap_write(sc);
}
int
r88e_power_on(struct rtwn_softc *sc)
{
#define RTWN_CHK(res) do { \
if (res != 0) \
return (EIO); \
} while(0)
int ntries;
/* Wait for power ready bit. */
for (ntries = 0; ntries < 5000; ntries++) {
if (rtwn_read_4(sc, R92C_APS_FSMCO) & R92C_APS_FSMCO_SUS_HOST)
break;
rtwn_delay(sc, 10);
}
if (ntries == 5000) {
device_printf(sc->sc_dev,
"timeout waiting for chip power up\n");
return (ETIMEDOUT);
}
/* Reset BB. */
RTWN_CHK(rtwn_setbits_1(sc, R92C_SYS_FUNC_EN,
R92C_SYS_FUNC_EN_BBRSTB | R92C_SYS_FUNC_EN_BB_GLB_RST, 0));
RTWN_CHK(rtwn_setbits_1(sc, R92C_AFE_XTAL_CTRL + 2, 0, 0x80));
/* Disable HWPDN. */
RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO,
R92C_APS_FSMCO_APDM_HPDN, 0, 1));
/* Disable WL suspend. */
RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO,
R92C_APS_FSMCO_AFSM_HSUS | R92C_APS_FSMCO_AFSM_PCIE, 0, 1));
RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO,
0, R92C_APS_FSMCO_APFM_ONMAC, 1));
for (ntries = 0; ntries < 5000; ntries++) {
if (!(rtwn_read_2(sc, R92C_APS_FSMCO) &
R92C_APS_FSMCO_APFM_ONMAC))
break;
rtwn_delay(sc, 10);
}
if (ntries == 5000)
return (ETIMEDOUT);
/* Enable LDO normal mode. */
RTWN_CHK(rtwn_setbits_1(sc, R92C_LPLDO_CTRL,
R92C_LPLDO_CTRL_SLEEP, 0));
/* Enable MAC DMA/WMAC/SCHEDULE/SEC blocks. */
RTWN_CHK(rtwn_write_2(sc, R92C_CR, 0));
RTWN_CHK(rtwn_setbits_2(sc, R92C_CR, 0,
R92C_CR_HCI_TXDMA_EN | R92C_CR_TXDMA_EN |
R92C_CR_HCI_RXDMA_EN | R92C_CR_RXDMA_EN |
R92C_CR_PROTOCOL_EN | R92C_CR_SCHEDULE_EN |
((sc->sc_hwcrypto != RTWN_CRYPTO_SW) ? R92C_CR_ENSEC : 0) |
R92C_CR_CALTMR_EN));
return (0);
#undef RTWN_CHK
}

View File

@ -0,0 +1,68 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/rtl8188e/r88e.h>
#include <dev/rtwn/rtl8188e/r88e_reg.h>
void
r88e_set_led(struct rtwn_softc *sc, int led, int on)
{
if (led == RTWN_LED_LINK) {
if (!on) {
rtwn_setbits_1(sc, R92C_LEDCFG2, 0x6f,
R92C_LEDCFG0_DIS);
rtwn_setbits_1(sc, R92C_MAC_PINMUX_CFG, 0x01, 0);
} else
rtwn_setbits_1(sc, R92C_LEDCFG2, 0x0f, 0x60);
sc->ledlink = on; /* Save LED state. */
}
/* XXX led #1? */
}

View File

@ -0,0 +1,273 @@
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $
* $FreeBSD$
*/
#ifndef R88E_PRIV_H
#define R88E_PRIV_H
#include <dev/rtwn/rtl8188e/r88e_rom_defs.h>
/*
* Parsed Tx power (diff) values.
*/
struct rtwn_r88e_txpwr {
uint8_t cck_tx_pwr[R88E_GROUP_2G];
uint8_t ht40_tx_pwr[R88E_GROUP_2G - 1];
int8_t ofdm_tx_pwr_diff;
int8_t bw20_tx_pwr_diff;
};
/*
* MAC initialization values.
*/
static const struct rtwn_mac_prog rtl8188eu_mac[] = {
{ 0x026, 0x41 }, { 0x027, 0x35 }, { 0x040, 0x00 }, { 0x428, 0x0a },
{ 0x429, 0x10 }, { 0x430, 0x00 }, { 0x431, 0x01 }, { 0x432, 0x02 },
{ 0x433, 0x04 }, { 0x434, 0x05 }, { 0x435, 0x06 }, { 0x436, 0x07 },
{ 0x437, 0x08 }, { 0x438, 0x00 }, { 0x439, 0x00 }, { 0x43a, 0x01 },
{ 0x43b, 0x02 }, { 0x43c, 0x04 }, { 0x43d, 0x05 }, { 0x43e, 0x06 },
{ 0x43f, 0x07 }, { 0x440, 0x5d }, { 0x441, 0x01 }, { 0x442, 0x00 },
{ 0x444, 0x15 }, { 0x445, 0xf0 }, { 0x446, 0x0f }, { 0x447, 0x00 },
{ 0x458, 0x41 }, { 0x459, 0xa8 }, { 0x45a, 0x72 }, { 0x45b, 0xb9 },
{ 0x460, 0x66 }, { 0x461, 0x66 }, { 0x480, 0x08 }, { 0x4c8, 0xff },
{ 0x4c9, 0x08 }, { 0x4cc, 0xff }, { 0x4cd, 0xff }, { 0x4ce, 0x01 },
{ 0x4d3, 0x01 }, { 0x500, 0x26 }, { 0x501, 0xa2 }, { 0x502, 0x2f },
{ 0x503, 0x00 }, { 0x504, 0x28 }, { 0x505, 0xa3 }, { 0x506, 0x5e },
{ 0x507, 0x00 }, { 0x508, 0x2b }, { 0x509, 0xa4 }, { 0x50a, 0x5e },
{ 0x50b, 0x00 }, { 0x50c, 0x4f }, { 0x50d, 0xa4 }, { 0x50e, 0x00 },
{ 0x50f, 0x00 }, { 0x512, 0x1c }, { 0x514, 0x0a }, { 0x516, 0x0a },
{ 0x525, 0x4f }, { 0x550, 0x10 }, { 0x551, 0x10 }, { 0x559, 0x02 },
{ 0x55d, 0xff }, { 0x605, 0x30 }, { 0x608, 0x0e }, { 0x609, 0x2a },
{ 0x620, 0xff }, { 0x621, 0xff }, { 0x622, 0xff }, { 0x623, 0xff },
{ 0x624, 0xff }, { 0x625, 0xff }, { 0x626, 0xff }, { 0x627, 0xff },
{ 0x652, 0x20 }, { 0x63c, 0x0a }, { 0x63d, 0x0a }, { 0x63e, 0x0e },
{ 0x63f, 0x0e }, { 0x640, 0x40 }, { 0x66e, 0x05 }, { 0x700, 0x21 },
{ 0x701, 0x43 }, { 0x702, 0x65 }, { 0x703, 0x87 }, { 0x708, 0x21 },
{ 0x709, 0x43 }, { 0x70a, 0x65 }, { 0x70b, 0x87 }
};
/*
* Baseband initialization values.
*/
static const uint16_t rtl8188eu_bb_regs[] = {
0x800, 0x804, 0x808, 0x80c, 0x810, 0x814, 0x818, 0x81c,
0x820, 0x824, 0x828, 0x82c, 0x830, 0x834, 0x838, 0x83c,
0x840, 0x844, 0x848, 0x84c, 0x850, 0x854, 0x858, 0x85c,
0x860, 0x864, 0x868, 0x86c, 0x870, 0x874, 0x878, 0x87c,
0x880, 0x884, 0x888, 0x88c, 0x890, 0x894, 0x898, 0x89c,
0x900, 0x904, 0x908, 0x90c, 0x910, 0x914, 0xa00, 0xa04,
0xa08, 0xa0c, 0xa10, 0xa14, 0xa18, 0xa1c, 0xa20, 0xa24,
0xa28, 0xa2c, 0xa70, 0xa74, 0xa78, 0xa7c, 0xa80, 0xb2c,
0xc00, 0xc04, 0xc08, 0xc0c, 0xc10, 0xc14, 0xc18, 0xc1c,
0xc20, 0xc24, 0xc28, 0xc2c, 0xc30, 0xc34, 0xc38, 0xc3c,
0xc40, 0xc44, 0xc48, 0xc4c, 0xc50, 0xc54, 0xc58, 0xc5c,
0xc60, 0xc64, 0xc68, 0xc6c, 0xc70, 0xc74, 0xc78, 0xc7c,
0xc80, 0xc84, 0xc88, 0xc8c, 0xc90, 0xc94, 0xc98, 0xc9c,
0xca0, 0xca4, 0xca8, 0xcac, 0xcb0, 0xcb4, 0xcb8, 0xcbc,
0xcc0, 0xcc4, 0xcc8, 0xccc, 0xcd0, 0xcd4, 0xcd8, 0xcdc,
0xce0, 0xce4, 0xce8, 0xcec, 0xd00, 0xd04, 0xd08, 0xd0c,
0xd10, 0xd14, 0xd18, 0xd2c, 0xd30, 0xd34, 0xd38, 0xd3c,
0xd40, 0xd44, 0xd48, 0xd4c, 0xd50, 0xd54, 0xd58, 0xd5c,
0xd60, 0xd64, 0xd68, 0xd6c, 0xd70, 0xd74, 0xd78, 0xe00,
0xe04, 0xe08, 0xe10, 0xe14, 0xe18, 0xe1c, 0xe28, 0xe30,
0xe34, 0xe38, 0xe3c, 0xe40, 0xe44, 0xe48, 0xe4c, 0xe50,
0xe54, 0xe58, 0xe5c, 0xe60, 0xe68, 0xe6c, 0xe70, 0xe74,
0xe78, 0xe7c, 0xe80, 0xe84, 0xe88, 0xe8c, 0xed0, 0xed4,
0xed8, 0xedc, 0xee0, 0xee8, 0xeec, 0xf14, 0xf4c, 0xf00
};
static const uint32_t rtl8188eu_bb_vals[] = {
0x80040000, 0x00000003, 0x0000fc00, 0x0000000a, 0x10001331,
0x020c3d10, 0x02200385, 0x00000000, 0x01000100, 0x00390204,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00010000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x569a11a9, 0x01000014, 0x66f60110,
0x061f0649, 0x00000000, 0x27272700, 0x07000760, 0x25004000,
0x00000808, 0x00000000, 0xb0000c1c, 0x00000001, 0x00000000,
0xccc000c0, 0x00000800, 0xfffffffe, 0x40302010, 0x00706050,
0x00000000, 0x00000023, 0x00000000, 0x81121111, 0x00000002,
0x00000201, 0x00d047c8, 0x80ff000c, 0x8c838300, 0x2e7f120f,
0x9500bb78, 0x1114d028, 0x00881117, 0x89140f00, 0x1a1b0000,
0x090e1317, 0x00000204, 0x00d30000, 0x101fbf00, 0x00000007,
0x00000900, 0x225b0606, 0x218075b1, 0x80000000, 0x48071d40,
0x03a05611, 0x000000e4, 0x6c6c6c6c, 0x08800000, 0x40000100,
0x08800000, 0x40000100, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x69e9ac47, 0x469652af, 0x49795994, 0x0a97971c,
0x1f7c403f, 0x000100b7, 0xec020107, 0x007f037f, 0x69553420,
0x43bc0094, 0x00013169, 0x00250492, 0x00000000, 0x7112848b,
0x47c00bff, 0x00000036, 0x2c7f000d, 0x020610db, 0x0000001f,
0x00b91612, 0x390000e4, 0x20f60000, 0x40000100, 0x20200000,
0x00091521, 0x00000000, 0x00121820, 0x00007f7f, 0x00000000,
0x000300a0, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x28000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x64b22427, 0x00766932,
0x00222222, 0x00000000, 0x37644302, 0x2f97d40c, 0x00000740,
0x00020401, 0x0000907f, 0x20010201, 0xa0633333, 0x3333bc43,
0x7a8f5b6f, 0xcc979975, 0x00000000, 0x80608000, 0x00000000,
0x00127353, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x6437140a, 0x00000000, 0x00000282, 0x30032064, 0x4653de68,
0x04518a3c, 0x00002101, 0x2a201c16, 0x1812362e, 0x322c2220,
0x000e3c24, 0x2d2d2d2d, 0x2d2d2d2d, 0x0390272d, 0x2d2d2d2d,
0x2d2d2d2d, 0x2d2d2d2d, 0x2d2d2d2d, 0x00000000, 0x1000dc1f,
0x10008c1f, 0x02140102, 0x681604c2, 0x01007c00, 0x01004800,
0xfb000000, 0x000028d1, 0x1000dc1f, 0x10008c1f, 0x02140102,
0x28160d05, 0x00000008, 0x001b25a4, 0x00c00014, 0x00c00014,
0x01000014, 0x01000014, 0x01000014, 0x01000014, 0x00c00014,
0x01000014, 0x00c00014, 0x00c00014, 0x00c00014, 0x00c00014,
0x00000014, 0x00000014, 0x21555448, 0x01c00014, 0x00000003,
0x00000000, 0x00000300
};
static const struct rtwn_bb_prog rtl8188eu_bb[] = {
{
nitems(rtl8188eu_bb_regs),
rtl8188eu_bb_regs,
rtl8188eu_bb_vals,
{ 0 },
NULL
}
};
static const uint32_t rtl8188eu_agc_vals[] = {
0xfb000001, 0xfb010001, 0xfb020001, 0xfb030001, 0xfb040001,
0xfb050001, 0xfa060001, 0xf9070001, 0xf8080001, 0xf7090001,
0xf60a0001, 0xf50b0001, 0xf40c0001, 0xf30d0001, 0xf20e0001,
0xf10f0001, 0xf0100001, 0xef110001, 0xee120001, 0xed130001,
0xec140001, 0xeb150001, 0xea160001, 0xe9170001, 0xe8180001,
0xe7190001, 0xe61a0001, 0xe51b0001, 0xe41c0001, 0xe31d0001,
0xe21e0001, 0xe11f0001, 0x8a200001, 0x89210001, 0x88220001,
0x87230001, 0x86240001, 0x85250001, 0x84260001, 0x83270001,
0x82280001, 0x6b290001, 0x6a2a0001, 0x692b0001, 0x682c0001,
0x672d0001, 0x662e0001, 0x652f0001, 0x64300001, 0x63310001,
0x62320001, 0x61330001, 0x46340001, 0x45350001, 0x44360001,
0x43370001, 0x42380001, 0x41390001, 0x403a0001, 0x403b0001,
0x403c0001, 0x403d0001, 0x403e0001, 0x403f0001, 0xfb400001,
0xfb410001, 0xfb420001, 0xfb430001, 0xfb440001, 0xfb450001,
0xfb460001, 0xfb470001, 0xfb480001, 0xfa490001, 0xf94a0001,
0xf84B0001, 0xf74c0001, 0xf64d0001, 0xf54e0001, 0xf44f0001,
0xf3500001, 0xf2510001, 0xf1520001, 0xf0530001, 0xef540001,
0xee550001, 0xed560001, 0xec570001, 0xeb580001, 0xea590001,
0xe95a0001, 0xe85b0001, 0xe75c0001, 0xe65d0001, 0xe55e0001,
0xe45f0001, 0xe3600001, 0xe2610001, 0xc3620001, 0xc2630001,
0xc1640001, 0x8b650001, 0x8a660001, 0x89670001, 0x88680001,
0x87690001, 0x866a0001, 0x856b0001, 0x846c0001, 0x676d0001,
0x666e0001, 0x656f0001, 0x64700001, 0x63710001, 0x62720001,
0x61730001, 0x60740001, 0x46750001, 0x45760001, 0x44770001,
0x43780001, 0x42790001, 0x417a0001, 0x407b0001, 0x407c0001,
0x407d0001, 0x407e0001, 0x407f0001
};
static const struct rtwn_agc_prog rtl8188eu_agc[] = {
{
nitems(rtl8188eu_agc_vals),
rtl8188eu_agc_vals,
{ 0 },
NULL
}
};
/*
* RF initialization values.
*/
static const uint8_t rtl8188eu_rf_regs[] = {
0x00, 0x08, 0x18, 0x19, 0x1e, 0x1f, 0x2f, 0x3f, 0x42, 0x57,
0x58, 0x67, 0x83, 0xb0, 0xb1, 0xb2, 0xb4, 0xb6, 0xb7, 0xb8,
0xb9, 0xba, 0xbb, 0xbf, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
0xc8, 0xc9, 0xca, 0xdf, 0xef, 0x51, 0x52, 0x53, 0x56,
0x35, 0x35, 0x35, 0x36, 0x36, 0x36, 0x36, 0xb6, 0x18, 0x5a,
0x19, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34,
0x34, 0x34, 0x00, 0x84, 0x86, 0x87, 0x8e, 0x8f, 0xef, 0x3b,
0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0xef, 0x00, 0x18, 0xfe, 0xfe,
0x1f, 0xfe, 0xfe, 0x1e, 0x1f, 0x00
};
static const uint32_t rtl8188eu_rf_vals[] = {
0x30000, 0x84000, 0x00407, 0x00012, 0x80009, 0x00880, 0x1a060,
0x00000, 0x060c0, 0xd0000, 0xbe180, 0x01552, 0x00000, 0xff8fc,
0x54400, 0xccc19, 0x43003, 0x4953e, 0x1c718, 0x060ff, 0x80001,
0x40000, 0x00400, 0xc0000, 0x02400, 0x00009, 0x40c91, 0x99999,
0x000a3, 0x88820, 0x76c06, 0x00000, 0x80000, 0x00180, 0x001a0,
0x6b27d, 0x7e49d, 0x00073, 0x51ff3, 0x00086, 0x00186,
0x00286, 0x01c25, 0x09c25, 0x11c25, 0x19c25, 0x48538, 0x00c07,
0x4bd00, 0x739d0, 0x0adf3, 0x09df0, 0x08ded, 0x07dea, 0x06de7,
0x054ee, 0x044eb, 0x034e8, 0x0246b, 0x01468, 0x0006d, 0x30159,
0x68200, 0x000ce, 0x48a00, 0x65540, 0x88000, 0x020a0, 0xf02b0,
0xef7b0, 0xd4fb0, 0xcf060, 0xb0090, 0xa0080, 0x90080, 0x8f780,
0x722b0, 0x6f7b0, 0x54fb0, 0x4f060, 0x30090, 0x20080, 0x10080,
0x0f780, 0x000a0, 0x10159, 0x0f407, 0x0c350, 0x0c350, 0x80003,
0x0c350, 0x0c350, 0x00001, 0x80000, 0x33e60
};
static const struct rtwn_rf_prog rtl8188eu_rf[] = {
{
nitems(rtl8188eu_rf_regs),
rtl8188eu_rf_regs,
rtl8188eu_rf_vals,
{ 0 },
NULL
},
{ 0, NULL, NULL, { 0 }, NULL }
};
struct rtwn_r88e_txagc {
uint8_t pwr[R88E_GROUP_2G][20]; /* RTWN_RIDX_MCS(7) + 1 */
};
/*
* Per RF chain/group/rate Tx gain values.
*/
static const struct rtwn_r88e_txagc r88e_txagc[] = {
{ { /* Chain 0. */
{ /* Group 0. */
0x00, 0x00, 0x00, 0x00, /* CCK1~11. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* OFDM6~54. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MCS0~7. */
},
{ /* Group 1. */
0x00, 0x00, 0x00, 0x00, /* CCK1~11. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* OFDM6~54. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MCS0~7. */
},
{ /* Group 2. */
0x00, 0x00, 0x00, 0x00, /* CCK1~11. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* OFDM6~54. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MCS0~7. */
},
{ /* Group 3. */
0x00, 0x00, 0x00, 0x00, /* CCK1~11. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* OFDM6~54. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MCS0~7. */
},
{ /* Group 4. */
0x00, 0x00, 0x00, 0x00, /* CCK1~11. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* OFDM6~54. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MCS0~7. */
},
{ /* Group 5. */
0x00, 0x00, 0x00, 0x00, /* CCK1~11. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* OFDM6~54. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MCS0~7. */
}
} }
};
#endif /* R88E_PRIV_H */

View File

@ -0,0 +1,91 @@
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $
* $FreeBSD$
*/
#ifndef R88E_REG_H
#define R88E_REG_H
#include <dev/rtwn/rtl8192c/r92c_reg.h>
/*
* MAC registers.
*/
/* System Configuration. */
#define R88E_BB_PAD_CTRL 0x064
#define R88E_HIMR 0x0b0
#define R88E_HISR 0x0b4
#define R88E_HIMRE 0x0b8
#define R88E_HISRE 0x0bc
/* MAC General Configuration. */
#define R88E_32K_CTRL 0x194
#define R88E_HMEBOX_EXT(idx) (0x1f0 + (idx) * 4)
/* Protocol Configuration. */
#define R88E_TXPKTBUF_BCNQ1_BDNY 0x457
#define R88E_MACID_NO_LINK 0x484
#define R88E_TX_RPT_CTRL 0x4ec
#define R88E_TX_RPT_MACID_MAX 0x4ed
#define R88E_TX_RPT_TIME 0x4f0
#define R88E_SCH_TXCMD 0x5f8
/* Bits for R88E_HIMR. */
#define R88E_HIMR_CPWM 0x00000100
#define R88E_HIMR_CPWM2 0x00000200
#define R88E_HIMR_TBDER 0x04000000
#define R88E_HIMR_PSTIMEOUT 0x20000000
/* Bits for R88E_HIMRE.*/
#define R88E_HIMRE_RXFOVW 0x00000100
#define R88E_HIMRE_TXFOVW 0x00000200
#define R88E_HIMRE_RXERR 0x00000400
#define R88E_HIMRE_TXERR 0x00000800
/* Bits for R88E_TX_RPT_CTRL. */
#define R88E_TX_RPT1_ENA 0x01
#define R88E_TX_RPT2_ENA 0x02
/* Bits for R92C_MBID_NUM. */
#define R88E_MBID_TXBCN_RPT(id) (0x08 << (id))
/* Bits for R92C_SECCFG. */
#define R88E_SECCFG_CHK_KEYID 0x0100
/*
* Baseband registers.
*/
/* Bits for R92C_LSSI_PARAM(i). */
#define R88E_LSSI_PARAM_ADDR_M 0x0ff00000
#define R88E_LSSI_PARAM_ADDR_S 20
/*
* RF (6052) registers.
*/
#define R88E_RF_T_METER 0x42
/* Bits for R92C_RF_CHNLBW. */
#define R88E_RF_CHNLBW_BW20 0x00c00
/* Bits for R88E_RF_T_METER. */
#define R88E_RF_T_METER_VAL_M 0x0fc00
#define R88E_RF_T_METER_VAL_S 10
#define R88E_RF_T_METER_START 0x30000
#endif /* R88E_REG_H */

View File

@ -0,0 +1,60 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/rtl8188e/r88e.h>
#include <dev/rtwn/rtl8188e/r88e_reg.h>
void
r88e_rf_write(struct rtwn_softc *sc, int chain, uint8_t addr, uint32_t val)
{
rtwn_bb_write(sc, R92C_LSSI_PARAM(chain),
SM(R88E_LSSI_PARAM_ADDR, addr) |
SM(R92C_LSSI_PARAM_DATA, val));
}

View File

@ -0,0 +1,85 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/if_rtwn_debug.h>
#include <dev/rtwn/rtl8192c/r92c_var.h>
#include <dev/rtwn/rtl8188e/r88e.h>
#include <dev/rtwn/rtl8188e/r88e_priv.h>
#include <dev/rtwn/rtl8188e/r88e_rom_image.h>
void
r88e_parse_rom(struct rtwn_softc *sc, uint8_t *buf)
{
struct r92c_softc *rs = sc->sc_priv;
struct rtwn_r88e_txpwr *rt = rs->rs_txpwr;
struct r88e_rom *rom = (struct r88e_rom *)buf;
int i;
rt->bw20_tx_pwr_diff = RTWN_SIGN4TO8(MS(rom->tx_pwr_diff, HIGH_PART));
rt->ofdm_tx_pwr_diff = RTWN_SIGN4TO8(MS(rom->tx_pwr_diff, LOW_PART));
for (i = 0; i < nitems(rom->cck_tx_pwr); i++)
rt->cck_tx_pwr[i] = rom->cck_tx_pwr[i];
for (i = 0; i < nitems(rom->ht40_tx_pwr); i++)
rt->ht40_tx_pwr[i] = rom->ht40_tx_pwr[i];
rs->crystalcap = RTWN_GET_ROM_VAR(rom->crystalcap,
R88E_ROM_CRYSTALCAP_DEF);
rs->regulatory = MS(rom->rf_board_opt, R92C_ROM_RF1_REGULATORY);
rs->board_type =
MS(RTWN_GET_ROM_VAR(rom->rf_board_opt, R92C_BOARD_TYPE_DONGLE),
R92C_ROM_RF1_BOARD_TYPE);
RTWN_DPRINTF(sc, RTWN_DEBUG_ROM, "%s: regulatory type %d\n",
__func__,rs->regulatory);
sc->thermal_meter = rom->thermal_meter;
IEEE80211_ADDR_COPY(sc->sc_ic.ic_macaddr, rom->macaddr);
}

View File

@ -0,0 +1,29 @@
/*-
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $FreeBSD$
*/
#ifndef R88E_ROM_DEFS_H
#define R88E_ROM_DEFS_H
#include <dev/rtwn/rtl8192c/r92c_rom_defs.h>
#define R88E_GROUP_2G 6
#define R88E_EFUSE_MAX_LEN 512
#define R88E_EFUSE_MAP_LEN 512
#endif /* R88E_ROM_DEFS_H */

View File

@ -0,0 +1,60 @@
/*-
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $FreeBSD$
*/
#ifndef R88E_ROM_IMAGE_H
#define R88E_ROM_IMAGE_H
#include <dev/rtwn/rtl8188e/r88e_rom_defs.h>
/*
* RTL8188EU ROM image.
*/
struct r88e_rom {
uint8_t reserved1[16];
uint8_t cck_tx_pwr[R88E_GROUP_2G];
uint8_t ht40_tx_pwr[R88E_GROUP_2G - 1];
uint8_t tx_pwr_diff;
uint8_t reserved2[156];
uint8_t channel_plan;
uint8_t crystalcap;
#define R88E_ROM_CRYSTALCAP_DEF 0x20
uint8_t thermal_meter;
uint8_t reserved3[6];
uint8_t rf_board_opt;
uint8_t rf_feature_opt;
uint8_t rf_bt_opt;
uint8_t version;
uint8_t customer_id;
uint8_t reserved4[3];
uint8_t rf_ant_opt;
uint8_t reserved5[6];
uint16_t vid;
uint16_t pid;
uint8_t usb_opt;
uint8_t reserved6[2];
uint8_t macaddr[IEEE80211_ADDR_LEN];
uint8_t reserved7[2];
uint8_t string[33]; /* "realtek 802.11n NIC" */
uint8_t reserved8[256];
} __packed;
_Static_assert(sizeof(struct r88e_rom) == R88E_EFUSE_MAP_LEN,
"R88E_EFUSE_MAP_LEN must be equal to sizeof(struct r88e_rom)!");
#endif /* R88E_ROM_IMAGE_H */

View File

@ -0,0 +1,211 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <net80211/ieee80211_ratectl.h>
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/if_rtwn_debug.h>
#include <dev/rtwn/if_rtwn_ridx.h>
#include <dev/rtwn/rtl8188e/r88e.h>
#include <dev/rtwn/rtl8188e/r88e_rx_desc.h>
void
r88e_ratectl_tx_complete(struct rtwn_softc *sc, uint8_t *buf, int len)
{
#if __FreeBSD_version >= 1200012
struct ieee80211_ratectl_tx_status txs;
#endif
struct r88e_tx_rpt_ccx *rpt;
struct ieee80211_node *ni;
uint8_t macid;
int ntries;
/* Skip Rx descriptor. */
buf += sizeof(struct r92c_rx_stat);
len -= sizeof(struct r92c_rx_stat);
rpt = (struct r88e_tx_rpt_ccx *)buf;
if (len != sizeof(*rpt)) {
RTWN_DPRINTF(sc, RTWN_DEBUG_INTR,
"%s: wrong report size (%d, must be %zu)\n",
__func__, len, sizeof(*rpt));
return;
}
RTWN_DPRINTF(sc, RTWN_DEBUG_INTR,
"%s: ccx report dump: 0: %02X, 1: %02X, 2: %02X, queue time: "
"low %02X, high %02X, final ridx: %02X, 6: %02X, 7: %02X\n",
__func__, rpt->rptb0, rpt->rptb1, rpt->rptb2, rpt->queue_time_low,
rpt->queue_time_high, rpt->final_rate, rpt->rptb6, rpt->rptb7);
macid = MS(rpt->rptb1, R88E_RPTB1_MACID);
if (macid > sc->macid_limit) {
device_printf(sc->sc_dev,
"macid %u is too big; increase MACID_MAX limit\n",
macid);
return;
}
ntries = MS(rpt->rptb2, R88E_RPTB2_RETRY_CNT);
ni = sc->node_list[macid];
if (ni != NULL) {
RTWN_DPRINTF(sc, RTWN_DEBUG_INTR, "%s: frame for macid %u was"
"%s sent (%d retries)\n", __func__, macid,
(rpt->rptb1 & R88E_RPTB1_PKT_OK) ? "" : " not",
ntries);
#if __FreeBSD_version >= 1200012
txs.flags = IEEE80211_RATECTL_STATUS_LONG_RETRY |
IEEE80211_RATECTL_STATUS_FINAL_RATE;
txs.long_retries = ntries;
if (rpt->final_rate > RTWN_RIDX_OFDM54) { /* MCS */
txs.final_rate =
(rpt->final_rate - 12) | IEEE80211_RATE_MCS;
} else
txs.final_rate = ridx2rate[rpt->final_rate];
if (rpt->rptb1 & R88E_RPTB1_PKT_OK)
txs.status = IEEE80211_RATECTL_TX_SUCCESS;
else if (rpt->rptb2 & R88E_RPTB2_RETRY_OVER)
txs.status = IEEE80211_RATECTL_TX_FAIL_LONG;
else if (rpt->rptb2 & R88E_RPTB2_LIFE_EXPIRE)
txs.status = IEEE80211_RATECTL_TX_FAIL_EXPIRED;
else
txs.status = IEEE80211_RATECTL_TX_FAIL_UNSPECIFIED;
ieee80211_ratectl_tx_complete(ni, &txs);
#else
struct ieee80211vap *vap = ni->ni_vap;
if (rpt->rptb1 & R88E_RPTB1_PKT_OK) {
ieee80211_ratectl_tx_complete(vap, ni,
IEEE80211_RATECTL_TX_SUCCESS, &ntries, NULL);
} else {
ieee80211_ratectl_tx_complete(vap, ni,
IEEE80211_RATECTL_TX_FAILURE, &ntries, NULL);
}
#endif
} else {
RTWN_DPRINTF(sc, RTWN_DEBUG_INTR, "%s: macid %u, ni is NULL\n",
__func__, macid);
}
}
void
r88e_handle_c2h_report(struct rtwn_softc *sc, uint8_t *buf, int len)
{
/* Skip Rx descriptor. */
buf += sizeof(struct r92c_rx_stat);
len -= sizeof(struct r92c_rx_stat);
if (len != R88E_INTR_MSG_LEN) {
RTWN_DPRINTF(sc, RTWN_DEBUG_INTR,
"%s: wrong interrupt message size (%d, must be %d)\n",
__func__, len, R88E_INTR_MSG_LEN);
return;
}
/* XXX TODO */
}
int8_t
r88e_get_rssi_cck(struct rtwn_softc *sc, void *physt)
{
struct r88e_rx_phystat *phy = (struct r88e_rx_phystat *)physt;
int8_t lna_idx, vga_idx, rssi;
lna_idx = (phy->agc_rpt & 0xe0) >> 5;
vga_idx = (phy->agc_rpt & 0x1f);
rssi = 6 - 2 * vga_idx;
switch (lna_idx) {
case 7:
if (vga_idx > 27)
rssi = -100 + 6;
else
rssi += -100 + 2 * 27;
break;
case 6:
rssi += -48 + 2 * 2;
break;
case 5:
rssi += -42 + 2 * 7;
break;
case 4:
rssi += -36 + 2 * 7;
break;
case 3:
rssi += -24 + 2 * 7;
break;
case 2:
rssi += -6 + 2 * 5;
if (sc->sc_flags & RTWN_FLAG_CCK_HIPWR)
rssi -= 6;
break;
case 1:
rssi += 8;
break;
case 0:
rssi += 14;
break;
}
return (rssi);
}
int8_t
r88e_get_rssi_ofdm(struct rtwn_softc *sc, void *physt)
{
struct r88e_rx_phystat *phy = (struct r88e_rx_phystat *)physt;
int rssi;
/* Get average RSSI. */
rssi = ((phy->sig_qual >> 1) & 0x7f) - 110;
return (rssi);
}

View File

@ -0,0 +1,100 @@
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $
* $FreeBSD$
*/
#ifndef R88E_RX_DESC_H
#define R88E_RX_DESC_H
#include <dev/rtwn/rtl8192c/r92c_rx_desc.h>
/* Rx MAC descriptor defines (chip-specific). */
/* Rx dword 3 */
#define R88E_RXDW3_RPT_M 0x0000c000
#define R88E_RXDW3_RPT_S 14
#define R88E_RXDW3_RPT_RX 0
#define R88E_RXDW3_RPT_TX1 1
#define R88E_RXDW3_RPT_TX2 2
#define R88E_RXDW3_RPT_HIS 3
/* Rx PHY descriptor. */
struct r88e_rx_phystat {
uint8_t path_agc[2];
uint8_t chan;
uint8_t reserved1;
uint8_t sig_qual;
uint8_t agc_rpt;
uint8_t rpt_b;
uint8_t reserved2;
uint8_t noise_power;
uint8_t path_cfotail[2];
uint8_t pcts_mask[2];
uint8_t stream_rxevm[2];
uint8_t path_rxsnr[2];
uint8_t noise_power_db_lsb;
uint8_t reserved3[3];
uint8_t stream_csi[2];
uint8_t stream_target_csi[2];
uint8_t sig_evm;
} __packed;
/* Tx report (type 1). */
struct r88e_tx_rpt_ccx {
uint8_t rptb0;
#define R88E_RPTB6_PKT_NUM_M 0x0e
#define R88E_RPTB6_PKT_NUM_S 1
#define R88E_RPTB0_INT_CCX 0x80
uint8_t rptb1;
#define R88E_RPTB1_MACID_M 0x3f
#define R88E_RPTB1_MACID_S 0
#define R88E_RPTB1_PKT_OK 0x40
#define R88E_RPTB1_BMC 0x80
uint8_t rptb2;
#define R88E_RPTB2_RETRY_CNT_M 0x3f
#define R88E_RPTB2_RETRY_CNT_S 0
#define R88E_RPTB2_LIFE_EXPIRE 0x40
#define R88E_RPTB2_RETRY_OVER 0x80
uint8_t queue_time_low;
uint8_t queue_time_high;
uint8_t final_rate;
uint8_t rptb6;
#define R88E_RPTB6_QSEL_M 0xf0
#define R88E_RPTB6_QSEL_S 4
uint8_t rptb7;
} __packed;
/* Interrupt message format. */
/* XXX recheck */
struct r88e_intr_msg {
uint8_t c2h_id;
uint8_t c2h_seq;
uint8_t c2h_evt;
uint8_t reserved1[13];
uint8_t cpwm1;
uint8_t reserved2[3];
uint8_t cpwm2;
uint8_t reserved3[27];
uint32_t hisr;
uint32_t hisr_ex;
};
#endif /* R88E_RX_DESC_H */

View File

@ -0,0 +1,79 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/rtl8188e/r88e.h>
#include <dev/rtwn/rtl8188e/r88e_tx_desc.h>
void
r88e_tx_enable_ampdu(void *buf, int enable)
{
struct r92c_tx_desc *txd = (struct r92c_tx_desc *)buf;
if (enable)
txd->txdw2 |= htole32(R88E_TXDW2_AGGEN);
else
txd->txdw2 |= htole32(R88E_TXDW2_AGGBK);
}
void
r88e_tx_setup_hwseq(void *buf)
{
struct r92c_tx_desc *txd = (struct r92c_tx_desc *)buf;
txd->txdseq |= htole16(R88E_TXDSEQ_HWSEQ_EN);
}
void
r88e_tx_setup_macid(void *buf, int id)
{
struct r92c_tx_desc *txd = (struct r92c_tx_desc *)buf;
txd->txdw1 |= htole32(SM(R88E_TXDW1_MACID, id));
}

View File

@ -0,0 +1,38 @@
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $
* $FreeBSD$
*/
#ifndef R88E_TX_DESC_H
#define R88E_TX_DESC_H
#include <dev/rtwn/rtl8192c/r92c_tx_desc.h>
/* Tx MAC descriptor defines (chip-specific). */
/* Tx dword 1. */
#define R88E_TXDW1_MACID_M 0x0000003f
#define R88E_TXDW1_MACID_S 0
/* Tx dword 2. */
#define R88E_TXDW2_AGGEN 0x00001000
#define R88E_TXDW2_AGGBK 0x00010000
/* Tx dword 3. */
#define R88E_TXDSEQ_HWSEQ_EN 0x8000
#endif /* R88E_TX_DESC_H */

View File

@ -0,0 +1,39 @@
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $
* $FreeBSD$
*/
#ifndef RTL8188EU_H
#define RTL8188EU_H
#include <dev/rtwn/rtl8188e/r88e.h>
/*
* Function declarations.
*/
/* r88eu_init.c */
void r88eu_power_off(struct rtwn_softc *);
void r88eu_init_intr(struct rtwn_softc *);
void r88eu_init_rx_agg(struct rtwn_softc *);
void r88eu_post_init(struct rtwn_softc *);
/* r88eu_rx.c */
int r88eu_classify_intr(struct rtwn_softc *, void *, int);
#endif /* RTL8188EU_H */

View File

@ -0,0 +1,216 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/if_rtwn_nop.h>
#include <dev/rtwn/usb/rtwn_usb_var.h>
#include <dev/rtwn/rtl8192c/r92c_reg.h>
#include <dev/rtwn/rtl8192c/r92c_var.h>
#include <dev/rtwn/rtl8192c/usb/r92cu.h>
#include <dev/rtwn/rtl8192c/usb/r92cu_tx_desc.h>
#include <dev/rtwn/rtl8188e/r88e_priv.h>
#include <dev/rtwn/rtl8188e/usb/r88eu.h>
static struct rtwn_r88e_txpwr r88e_txpwr;
void r88eu_attach(struct rtwn_usb_softc *);
static void
r88e_postattach(struct rtwn_softc *sc)
{
struct r92c_softc *rs = sc->sc_priv;
struct ieee80211com *ic = &sc->sc_ic;
rs->rs_scan_start = ic->ic_scan_start;
ic->ic_scan_start = r92c_scan_start;
rs->rs_scan_end = ic->ic_scan_end;
ic->ic_scan_end = r92c_scan_end;
}
static void
r88eu_attach_private(struct rtwn_softc *sc)
{
struct r92c_softc *rs;
rs = malloc(sizeof(struct r92c_softc), M_RTWN_PRIV, M_WAITOK | M_ZERO);
rs->rs_txpwr = &r88e_txpwr;
rs->rs_txagc = &r88e_txagc;
rs->rs_set_bw20 = r88e_set_bw20;
rs->rs_get_txpower = r88e_get_txpower;
rs->rs_set_gain = r88e_set_gain;
rs->rs_tx_enable_ampdu = r88e_tx_enable_ampdu;
rs->rs_tx_setup_hwseq = r88e_tx_setup_hwseq;
rs->rs_tx_setup_macid = r88e_tx_setup_macid;
rs->rs_set_name = rtwn_nop_softc; /* not used */
rs->rf_read_delay[0] = 10;
rs->rf_read_delay[1] = 100;
rs->rf_read_delay[2] = 10;
sc->sc_priv = rs;
}
static void
r88eu_adj_devcaps(struct rtwn_softc *sc)
{
/* XXX TODO? */
}
void
r88eu_attach(struct rtwn_usb_softc *uc)
{
struct rtwn_softc *sc = &uc->uc_sc;
/* USB part. */
uc->uc_align_rx = r92cu_align_rx;
uc->tx_agg_desc_num = 6;
/* Common part. */
sc->sc_flags = RTWN_FLAG_EXT_HDR;
sc->sc_set_chan = r92c_set_chan;
sc->sc_fill_tx_desc = r92c_fill_tx_desc;
sc->sc_fill_tx_desc_raw = r92c_fill_tx_desc_raw;
sc->sc_fill_tx_desc_null = r92c_fill_tx_desc_null;
sc->sc_dump_tx_desc = r92cu_dump_tx_desc;
sc->sc_tx_radiotap_flags = r92c_tx_radiotap_flags;
sc->sc_rx_radiotap_flags = r92c_rx_radiotap_flags;
sc->sc_get_rssi_cck = r88e_get_rssi_cck;
sc->sc_get_rssi_ofdm = r88e_get_rssi_ofdm;
sc->sc_classify_intr = r88eu_classify_intr;
sc->sc_handle_tx_report = r88e_ratectl_tx_complete;
sc->sc_handle_c2h_report = r88e_handle_c2h_report;
sc->sc_check_frame = rtwn_nop_int_softc_mbuf;
sc->sc_rf_read = r92c_rf_read;
sc->sc_rf_write = r88e_rf_write;
sc->sc_check_condition = r92c_check_condition;
sc->sc_efuse_postread = rtwn_nop_softc;
sc->sc_parse_rom = r88e_parse_rom;
sc->sc_set_led = r88e_set_led;
sc->sc_power_on = r88e_power_on;
sc->sc_power_off = r88eu_power_off;
#ifndef RTWN_WITHOUT_UCODE
sc->sc_fw_reset = r88e_fw_reset;
sc->sc_fw_download_enable = r88e_fw_download_enable;
#endif
sc->sc_set_page_size = r92c_set_page_size;
sc->sc_lc_calib = r92c_lc_calib;
sc->sc_iq_calib = r88e_iq_calib; /* XXX TODO */
sc->sc_read_chipid_vendor = rtwn_nop_softc_uint32;
sc->sc_adj_devcaps = r88eu_adj_devcaps;
sc->sc_vap_preattach = rtwn_nop_softc_vap;
sc->sc_postattach = r88e_postattach;
sc->sc_detach_private = r92c_detach_private;
sc->sc_set_media_status = r88e_set_media_status;
#ifndef RTWN_WITHOUT_UCODE
sc->sc_set_rsvd_page = r88e_set_rsvd_page;
sc->sc_set_pwrmode = r88e_set_pwrmode;
sc->sc_set_rssi = rtwn_nop_softc; /* XXX TODO? */
#endif
sc->sc_beacon_init = r92c_beacon_init;
sc->sc_beacon_enable = r88e_beacon_enable;
sc->sc_beacon_set_rate = rtwn_nop_void_int;
sc->sc_beacon_select = rtwn_nop_softc_int;
sc->sc_temp_measure = r88e_temp_measure;
sc->sc_temp_read = r88e_temp_read;
sc->sc_init_tx_agg = r92cu_init_tx_agg;
sc->sc_init_rx_agg = r88eu_init_rx_agg;
sc->sc_init_ampdu = rtwn_nop_softc;
sc->sc_init_intr = r88eu_init_intr;
sc->sc_init_edca = r92c_init_edca;
sc->sc_init_bb = r88e_init_bb;
sc->sc_init_rf = r92c_init_rf_common;
sc->sc_init_antsel = rtwn_nop_softc;
sc->sc_post_init = r88eu_post_init;
sc->sc_init_bcnq1_boundary = rtwn_nop_int_softc;
sc->mac_prog = &rtl8188eu_mac[0];
sc->mac_size = nitems(rtl8188eu_mac);
sc->bb_prog = &rtl8188eu_bb[0];
sc->bb_size = nitems(rtl8188eu_bb);
sc->agc_prog = &rtl8188eu_agc[0];
sc->agc_size = nitems(rtl8188eu_agc);
sc->rf_prog = &rtl8188eu_rf[0];
sc->name = "RTL8188EU";
sc->fwname = "rtwn-rtl8188eufw";
sc->fwsig = 0x88e;
sc->page_count = R88E_TX_PAGE_COUNT;
sc->pktbuf_count = R88E_TXPKTBUF_COUNT;
sc->ackto = 0x40;
sc->npubqpages = R88E_PUBQ_NPAGES;
sc->page_size = R92C_TX_PAGE_SIZE;
sc->txdesc_len = sizeof(struct r92cu_tx_desc);
sc->efuse_maxlen = R88E_EFUSE_MAX_LEN;
sc->efuse_maplen = R88E_EFUSE_MAP_LEN;
sc->rx_dma_size = R88E_RX_DMA_BUFFER_SIZE;
sc->macid_limit = R88E_MACID_MAX + 1;
sc->cam_entry_limit = R92C_CAM_ENTRY_COUNT;
sc->fwsize_limit = R92C_MAX_FW_SIZE;
sc->temp_delta = R88E_CALIB_THRESHOLD;
sc->bcn_status_reg[0] = R92C_TDECTRL;
sc->bcn_status_reg[1] = R92C_TDECTRL;
sc->rcr = 0;
sc->ntxchains = 1;
sc->nrxchains = 1;
r88eu_attach_private(sc);
}

View File

@ -0,0 +1,227 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/rtl8192c/r92c.h>
#include <dev/rtwn/rtl8192c/r92c_var.h>
#include <dev/rtwn/rtl8188e/usb/r88eu.h>
#include <dev/rtwn/rtl8188e/usb/r88eu_reg.h>
void
r88eu_power_off(struct rtwn_softc *sc)
{
uint8_t reg;
int error, ntries;
/* Disable any kind of TX reports. */
error = rtwn_setbits_1(sc, R88E_TX_RPT_CTRL,
R88E_TX_RPT1_ENA | R88E_TX_RPT2_ENA, 0);
if (error == ENXIO) /* hardware gone */
return;
/* Stop Rx. */
rtwn_write_1(sc, R92C_CR, 0);
/* Move card to Low Power State. */
/* Block all Tx queues. */
rtwn_write_1(sc, R92C_TXPAUSE, R92C_TX_QUEUE_ALL);
for (ntries = 0; ntries < 10; ntries++) {
/* Should be zero if no packet is transmitting. */
if (rtwn_read_4(sc, R88E_SCH_TXCMD) == 0)
break;
rtwn_delay(sc, 5000);
}
if (ntries == 10) {
device_printf(sc->sc_dev, "%s: failed to block Tx queues\n",
__func__);
return;
}
/* CCK and OFDM are disabled, and clock are gated. */
rtwn_setbits_1(sc, R92C_SYS_FUNC_EN, R92C_SYS_FUNC_EN_BBRSTB, 0);
rtwn_delay(sc, 1);
/* Reset MAC TRX */
rtwn_write_1(sc, R92C_CR,
R92C_CR_HCI_TXDMA_EN | R92C_CR_HCI_RXDMA_EN |
R92C_CR_TXDMA_EN | R92C_CR_RXDMA_EN |
R92C_CR_PROTOCOL_EN | R92C_CR_SCHEDULE_EN);
/* check if removed later */
rtwn_setbits_1_shift(sc, R92C_CR, R92C_CR_ENSEC, 0, 1);
/* Respond TxOK to scheduler */
rtwn_setbits_1(sc, R92C_DUAL_TSF_RST, 0, 0x20);
/* If firmware in ram code, do reset. */
#ifndef RTWN_WITHOUT_UCODE
if (rtwn_read_1(sc, R92C_MCUFWDL) & R92C_MCUFWDL_RDY)
r88e_fw_reset(sc, RTWN_FW_RESET_SHUTDOWN);
#endif
/* Reset MCU ready status. */
rtwn_write_1(sc, R92C_MCUFWDL, 0);
/* Disable 32k. */
rtwn_setbits_1(sc, R88E_32K_CTRL, 0x01, 0);
/* Move card to Disabled state. */
/* Turn off RF. */
rtwn_write_1(sc, R92C_RF_CTRL, 0);
/* LDO Sleep mode. */
rtwn_setbits_1(sc, R92C_LPLDO_CTRL, 0, R92C_LPLDO_CTRL_SLEEP);
/* Turn off MAC by HW state machine */
rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, 0,
R92C_APS_FSMCO_APFM_OFF, 1);
for (ntries = 0; ntries < 10; ntries++) {
/* Wait until it will be disabled. */
if ((rtwn_read_2(sc, R92C_APS_FSMCO) &
R92C_APS_FSMCO_APFM_OFF) == 0)
break;
rtwn_delay(sc, 5000);
}
if (ntries == 10) {
device_printf(sc->sc_dev, "%s: could not turn off MAC\n",
__func__);
return;
}
/* schmit trigger */
rtwn_setbits_1(sc, R92C_AFE_XTAL_CTRL + 2, 0, 0x80);
/* Enable WL suspend. */
rtwn_setbits_1_shift(sc, R92C_APS_FSMCO,
R92C_APS_FSMCO_AFSM_PCIE, R92C_APS_FSMCO_AFSM_HSUS, 1);
/* Enable bandgap mbias in suspend. */
rtwn_write_1(sc, R92C_APS_FSMCO + 3, 0);
/* Clear SIC_EN register. */
rtwn_setbits_1(sc, R92C_GPIO_MUXCFG + 1, 0x10, 0);
/* Set USB suspend enable local register */
rtwn_setbits_1(sc, R92C_USB_SUSPEND, 0, 0x10);
/* Reset MCU IO Wrapper. */
reg = rtwn_read_1(sc, R92C_RSV_CTRL + 1);
rtwn_write_1(sc, R92C_RSV_CTRL + 1, reg & ~0x08);
rtwn_write_1(sc, R92C_RSV_CTRL + 1, reg | 0x08);
/* marked as 'For Power Consumption' code. */
rtwn_write_1(sc, R92C_GPIO_OUT, rtwn_read_1(sc, R92C_GPIO_IN));
rtwn_write_1(sc, R92C_GPIO_IOSEL, 0xff);
rtwn_write_1(sc, R92C_GPIO_IO_SEL,
rtwn_read_1(sc, R92C_GPIO_IO_SEL) << 4);
rtwn_setbits_1(sc, R92C_GPIO_MOD, 0, 0x0f);
/* Set LNA, TRSW, EX_PA Pin to output mode. */
rtwn_write_4(sc, R88E_BB_PAD_CTRL, 0x00080808);
}
void
r88eu_init_intr(struct rtwn_softc *sc)
{
/* TODO: adjust */
rtwn_write_4(sc, R88E_HISR, 0xffffffff);
rtwn_write_4(sc, R88E_HIMR, R88E_HIMR_CPWM | R88E_HIMR_CPWM2 |
R88E_HIMR_TBDER | R88E_HIMR_PSTIMEOUT);
rtwn_write_4(sc, R88E_HIMRE, R88E_HIMRE_RXFOVW |
R88E_HIMRE_TXFOVW | R88E_HIMRE_RXERR | R88E_HIMRE_TXERR);
rtwn_setbits_1(sc, R92C_USB_SPECIAL_OPTION, 0,
R92C_USB_SPECIAL_OPTION_INT_BULK_SEL);
}
void
r88eu_init_rx_agg(struct rtwn_softc *sc)
{
/* XXX merge? */
rtwn_setbits_1(sc, R92C_TRXDMA_CTRL, 0,
R92C_TRXDMA_CTRL_RXDMA_AGG_EN);
/* XXX dehardcode */
rtwn_write_1(sc, R92C_RXDMA_AGG_PG_TH, 48);
rtwn_write_1(sc, R92C_RXDMA_AGG_PG_TH + 1, 4);
}
void
r88eu_post_init(struct rtwn_softc *sc)
{
/* Turn CCK and OFDM blocks on. */
rtwn_bb_setbits(sc, R92C_FPGA0_RFMOD, 0, R92C_RFMOD_CCK_EN);
rtwn_bb_setbits(sc, R92C_FPGA0_RFMOD, 0, R92C_RFMOD_OFDM_EN);
/* Enable per-packet TX report. */
rtwn_setbits_1(sc, R88E_TX_RPT_CTRL, 0, R88E_TX_RPT1_ENA);
/* Disable Tx if MACID is not associated. */
rtwn_write_4(sc, R88E_MACID_NO_LINK, 0xffffffff);
rtwn_write_4(sc, R88E_MACID_NO_LINK + 4, 0xffffffff);
r88e_macid_enable_link(sc, RTWN_MACID_BC, 1);
/* Perform LO and IQ calibrations. */
r88e_iq_calib(sc);
/* Perform LC calibration. */
r92c_lc_calib(sc);
rtwn_write_1(sc, R92C_USB_HRPWM, 0);
if (sc->sc_ratectl_sysctl == RTWN_RATECTL_FW) {
/* No support (yet?) for f/w rate adaptation. */
sc->sc_ratectl = RTWN_RATECTL_NET80211;
} else
sc->sc_ratectl = sc->sc_ratectl_sysctl;
}

View File

@ -0,0 +1,27 @@
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $
* $FreeBSD$
*/
#ifndef R88EU_REG_H
#define R88EU_REG_H
#include <dev/rtwn/rtl8192c/usb/r92cu_reg.h>
#include <dev/rtwn/rtl8188e/r88e_reg.h>
#endif /* R88EU_REG_H */

View File

@ -0,0 +1,74 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/if_rtwn_debug.h>
#include <dev/rtwn/rtl8188e/r88e_rx_desc.h>
#include <dev/rtwn/rtl8188e/usb/r88eu.h>
int
r88eu_classify_intr(struct rtwn_softc *sc, void *buf, int len)
{
struct r92c_rx_stat *stat = buf;
int report_sel = MS(le32toh(stat->rxdw3), R88E_RXDW3_RPT);
switch (report_sel) {
case R88E_RXDW3_RPT_RX:
return (RTWN_RX_DATA);
case R88E_RXDW3_RPT_TX1: /* per-packet Tx report */
case R88E_RXDW3_RPT_TX2: /* periodical Tx report */
return (RTWN_RX_TX_REPORT);
case R88E_RXDW3_RPT_HIS:
return (RTWN_RX_OTHER);
default: /* shut up the compiler */
return (RTWN_RX_DATA);
}
}

View File

@ -0,0 +1,74 @@
/* $OpenBSD: if_rtwnreg.h,v 1.3 2015/06/14 08:02:47 stsp Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2015 Stefan Sperling <stsp@openbsd.org>
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $FreeBSD$
*/
#ifndef RTL8192CE_H
#define RTL8192CE_H
#include <dev/rtwn/rtl8192c/r92c.h>
/*
* Global definitions.
*/
#define R92CE_PUBQ_NPAGES 176
#define R92CE_HPQ_NPAGES 41
#define R92CE_LPQ_NPAGES 28
#define R92CE_TX_PAGE_COUNT \
(R92CE_PUBQ_NPAGES + R92CE_HPQ_NPAGES + R92CE_LPQ_NPAGES)
/*
* Function declarations.
*/
/* r92ce_calib.c */
void r92ce_iq_calib(struct rtwn_softc *);
/* r92ce_fw.c */
#ifndef RTWN_WITHOUT_UCODE
void r92ce_fw_reset(struct rtwn_softc *, int);
#endif
/* r92ce_init.c */
void r92ce_init_intr(struct rtwn_softc *);
void r92ce_init_edca(struct rtwn_softc *);
void r92ce_init_bb(struct rtwn_softc *);
int r92ce_power_on(struct rtwn_softc *);
void r92ce_power_off(struct rtwn_softc *);
void r92ce_init_ampdu(struct rtwn_softc *);
void r92ce_post_init(struct rtwn_softc *);
/* r92ce_led.c */
void r92ce_set_led(struct rtwn_softc *, int, int);
/* r92ce_rx.c */
int r92ce_classify_intr(struct rtwn_softc *, void *, int);
void r92ce_enable_intr(struct rtwn_pci_softc *);
void r92ce_start_xfers(struct rtwn_softc *);
/* r92ce_tx.c */
void r92ce_setup_tx_desc(struct rtwn_pci_softc *, void *, uint32_t);
void r92ce_tx_postsetup(struct rtwn_pci_softc *, void *,
bus_dma_segment_t[]);
void r92ce_copy_tx_desc(void *, const void *);
void r92ce_dump_tx_desc(struct rtwn_softc *, const void *);
#endif /* RTL8192CE_H */

View File

@ -0,0 +1,263 @@
/* $OpenBSD: if_rtwn.c,v 1.6 2015/08/28 00:03:53 deraadt Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2015 Stefan Sperling <stsp@openbsd.org>
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <machine/bus.h>
#include <machine/resource.h>
#include <sys/rman.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/if_rtwn_nop.h>
#include <dev/rtwn/pci/rtwn_pci_var.h>
#include <dev/rtwn/rtl8192c/r92c_var.h>
#include <dev/rtwn/rtl8192c/pci/r92ce.h>
#include <dev/rtwn/rtl8192c/pci/r92ce_priv.h>
#include <dev/rtwn/rtl8192c/pci/r92ce_reg.h>
#include <dev/rtwn/rtl8192c/pci/r92ce_tx_desc.h>
static struct rtwn_r92c_txpwr r92c_txpwr;
void r92ce_attach(struct rtwn_pci_softc *);
static void
r92ce_postattach(struct rtwn_softc *sc)
{
struct r92c_softc *rs = sc->sc_priv;
struct ieee80211com *ic = &sc->sc_ic;
if (!(rs->chip & R92C_CHIP_92C) &&
rs->board_type == R92C_BOARD_TYPE_HIGHPA)
rs->rs_txagc = &rtl8188ru_txagc[0];
else
rs->rs_txagc = &rtl8192cu_txagc[0];
if ((rs->chip & (R92C_CHIP_UMC_A_CUT | R92C_CHIP_92C)) ==
R92C_CHIP_UMC_A_CUT)
sc->fwname = "rtwn-rtl8192cfwE";
else
sc->fwname = "rtwn-rtl8192cfwE_B";
sc->fwsig = 0x88c;
rs->rs_scan_start = ic->ic_scan_start;
ic->ic_scan_start = r92c_scan_start;
rs->rs_scan_end = ic->ic_scan_end;
ic->ic_scan_end = r92c_scan_end;
}
static void
r92ce_set_name(struct rtwn_softc *sc)
{
struct r92c_softc *rs = sc->sc_priv;
if (rs->chip & R92C_CHIP_92C)
sc->name = "RTL8192CE";
else
sc->name = "RTL8188CE";
}
static void
r92ce_attach_private(struct rtwn_softc *sc)
{
struct r92c_softc *rs;
rs = malloc(sizeof(struct r92c_softc), M_RTWN_PRIV, M_WAITOK | M_ZERO);
rs->rs_txpwr = &r92c_txpwr;
rs->rs_set_bw20 = r92c_set_bw20;
rs->rs_get_txpower = r92c_get_txpower;
rs->rs_set_gain = r92c_set_gain;
rs->rs_tx_enable_ampdu = r92c_tx_enable_ampdu;
rs->rs_tx_setup_hwseq = r92c_tx_setup_hwseq;
rs->rs_tx_setup_macid = r92c_tx_setup_macid;
rs->rs_set_name = r92ce_set_name;
/* XXX TODO: test with net80211 ratectl! */
#ifndef RTWN_WITHOUT_UCODE
rs->rs_c2h_timeout = hz;
callout_init_mtx(&rs->rs_c2h_report, &sc->sc_mtx, 0);
#endif
rs->rf_read_delay[0] = 1000;
rs->rf_read_delay[1] = 1000;
rs->rf_read_delay[2] = 1000;
sc->sc_priv = rs;
}
static void
r92ce_adj_devcaps(struct rtwn_softc *sc)
{
struct ieee80211com *ic = &sc->sc_ic;
/* XXX TODO: test everything that removed here before enabling. */
/* XX do NOT enable PMGT until RSVD_PAGE command will not be fixed. */
ic->ic_caps &= ~(
IEEE80211_C_IBSS /* check beaconing / tsf */
| IEEE80211_C_HOSTAP /* the same */
| IEEE80211_C_PMGT /* check null frame / device usability */
| IEEE80211_C_SWAMSDUTX
| IEEE80211_C_FF
);
ic->ic_htcaps = 0;
}
void
r92ce_attach(struct rtwn_pci_softc *pc)
{
struct rtwn_softc *sc = &pc->pc_sc;
/* PCIe part. */
pc->pc_setup_tx_desc = r92ce_setup_tx_desc;
pc->pc_tx_postsetup = r92ce_tx_postsetup;
pc->pc_copy_tx_desc = r92ce_copy_tx_desc;
pc->pc_enable_intr = r92ce_enable_intr;
pc->pc_qmap = 0xf771;
pc->tcr =
R92C_TCR_CFENDFORM | (1 << 12) | (1 << 13);
/* Common part. */
/* RTL8192C* cannot use pairwise keys from first 4 slots */
sc->sc_flags = RTWN_FLAG_CAM_FIXED;
sc->sc_start_xfers = r92ce_start_xfers;
sc->sc_set_chan = r92c_set_chan;
sc->sc_fill_tx_desc = r92c_fill_tx_desc;
sc->sc_fill_tx_desc_raw = r92c_fill_tx_desc_raw;
sc->sc_fill_tx_desc_null = r92c_fill_tx_desc_null; /* XXX recheck */
sc->sc_dump_tx_desc = r92ce_dump_tx_desc;
sc->sc_tx_radiotap_flags = r92c_tx_radiotap_flags;
sc->sc_rx_radiotap_flags = r92c_rx_radiotap_flags;
sc->sc_get_rssi_cck = r92c_get_rssi_cck;
sc->sc_get_rssi_ofdm = r92c_get_rssi_ofdm;
sc->sc_classify_intr = r92ce_classify_intr;
sc->sc_handle_tx_report = rtwn_nop_softc_uint8_int;
sc->sc_handle_c2h_report = rtwn_nop_softc_uint8_int;
sc->sc_check_frame = rtwn_nop_int_softc_mbuf;
sc->sc_rf_read = r92c_rf_read;
sc->sc_rf_write = r92c_rf_write;
sc->sc_check_condition = r92c_check_condition;
sc->sc_efuse_postread = r92c_efuse_postread;
sc->sc_parse_rom = r92c_parse_rom;
sc->sc_set_led = r92ce_set_led;
sc->sc_power_on = r92ce_power_on;
sc->sc_power_off = r92ce_power_off;
#ifndef RTWN_WITHOUT_UCODE
sc->sc_fw_reset = r92ce_fw_reset;
sc->sc_fw_download_enable = r92c_fw_download_enable;
#endif
sc->sc_set_page_size = r92c_set_page_size;
sc->sc_lc_calib = r92c_lc_calib;
sc->sc_iq_calib = r92ce_iq_calib;
sc->sc_read_chipid_vendor = r92c_read_chipid_vendor;
sc->sc_adj_devcaps = r92ce_adj_devcaps;
sc->sc_vap_preattach = rtwn_nop_softc_vap;
sc->sc_postattach = r92ce_postattach;
sc->sc_detach_private = r92c_detach_private;
sc->sc_set_media_status = r92c_joinbss_rpt;
#ifndef RTWN_WITHOUT_UCODE
sc->sc_set_rsvd_page = r92c_set_rsvd_page;
sc->sc_set_pwrmode = r92c_set_pwrmode;
sc->sc_set_rssi = r92c_set_rssi;
#endif
sc->sc_beacon_init = r92c_beacon_init;
sc->sc_beacon_enable = r92c_beacon_enable;
sc->sc_beacon_set_rate = rtwn_nop_void_int;
sc->sc_beacon_select = rtwn_nop_softc_int;
sc->sc_temp_measure = r92c_temp_measure;
sc->sc_temp_read = r92c_temp_read;
sc->sc_init_tx_agg = rtwn_nop_softc;
sc->sc_init_rx_agg = rtwn_nop_softc;
sc->sc_init_ampdu = r92ce_init_ampdu;
sc->sc_init_intr = r92ce_init_intr;
sc->sc_init_edca = r92ce_init_edca;
sc->sc_init_bb = r92ce_init_bb;
sc->sc_init_rf = r92c_init_rf;
sc->sc_init_antsel = rtwn_nop_softc;
sc->sc_post_init = r92ce_post_init;
sc->sc_init_bcnq1_boundary = rtwn_nop_int_softc;
sc->mac_prog = &rtl8192ce_mac[0];
sc->mac_size = nitems(rtl8192ce_mac);
sc->bb_prog = &rtl8192ce_bb[0];
sc->bb_size = nitems(rtl8192ce_bb);
sc->agc_prog = &rtl8192ce_agc[0];
sc->agc_size = nitems(rtl8192ce_agc);
sc->rf_prog = &rtl8192c_rf[0];
sc->page_count = R92CE_TX_PAGE_COUNT;
sc->pktbuf_count = R92C_TXPKTBUF_COUNT;
sc->ackto = 0x40;
sc->npubqpages = R92CE_PUBQ_NPAGES;
sc->nhqpages = R92CE_HPQ_NPAGES;
sc->nnqpages = 0;
sc->nlqpages = R92CE_LPQ_NPAGES;
sc->page_size = R92C_TX_PAGE_SIZE;
sc->txdesc_len = sizeof(struct r92ce_tx_desc);
sc->efuse_maxlen = R92C_EFUSE_MAX_LEN;
sc->efuse_maplen = R92C_EFUSE_MAP_LEN;
sc->rx_dma_size = R92C_RX_DMA_BUFFER_SIZE;
sc->macid_limit = R92C_MACID_MAX + 1;
sc->cam_entry_limit = R92C_CAM_ENTRY_COUNT;
sc->fwsize_limit = R92C_MAX_FW_SIZE;
sc->temp_delta = R92C_CALIB_THRESHOLD;
sc->bcn_status_reg[0] = R92C_TDECTRL;
sc->bcn_status_reg[1] = R92C_TDECTRL;
sc->rcr = 0;
r92ce_attach_private(sc);
}

View File

@ -0,0 +1,386 @@
/* $OpenBSD: if_rtwn.c,v 1.6 2015/08/28 00:03:53 deraadt Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2015 Stefan Sperling <stsp@openbsd.org>
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <machine/bus.h>
#include <machine/resource.h>
#include <sys/rman.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/if_rtwn_debug.h>
#include <dev/rtwn/pci/rtwn_pci_var.h>
#include <dev/rtwn/rtl8192c/pci/r92ce.h>
#include <dev/rtwn/rtl8192c/pci/r92ce_reg.h>
/* Registers to save and restore during IQ calibration. */
struct r92ce_iq_cal_reg_vals {
uint32_t adda[16];
uint8_t txpause;
uint8_t bcn_ctrl[2];
uint32_t gpio_muxcfg;
uint32_t ofdm0_trxpathena;
uint32_t ofdm0_trmuxpar;
uint32_t fpga0_rfifacesw1;
};
/* XXX 92CU? */
static int
r92ce_iq_calib_chain(struct rtwn_softc *sc, int chain, uint16_t tx[2],
uint16_t rx[2])
{
uint32_t status;
int offset = chain * 0x20;
if (chain == 0) { /* IQ calibration for chain 0. */
/* IQ calibration settings for chain 0. */
rtwn_bb_write(sc, 0xe30, 0x10008c1f);
rtwn_bb_write(sc, 0xe34, 0x10008c1f);
rtwn_bb_write(sc, 0xe38, 0x82140102);
if (sc->ntxchains > 1) {
rtwn_bb_write(sc, 0xe3c, 0x28160202); /* 2T */
/* IQ calibration settings for chain 1. */
rtwn_bb_write(sc, 0xe50, 0x10008c22);
rtwn_bb_write(sc, 0xe54, 0x10008c22);
rtwn_bb_write(sc, 0xe58, 0x82140102);
rtwn_bb_write(sc, 0xe5c, 0x28160202);
} else
rtwn_bb_write(sc, 0xe3c, 0x28160502); /* 1T */
/* LO calibration settings. */
rtwn_bb_write(sc, 0xe4c, 0x001028d1);
/* We're doing LO and IQ calibration in one shot. */
rtwn_bb_write(sc, 0xe48, 0xf9000000);
rtwn_bb_write(sc, 0xe48, 0xf8000000);
} else { /* IQ calibration for chain 1. */
/* We're doing LO and IQ calibration in one shot. */
rtwn_bb_write(sc, 0xe60, 0x00000002);
rtwn_bb_write(sc, 0xe60, 0x00000000);
}
/* Give LO and IQ calibrations the time to complete. */
rtwn_delay(sc, 1000);
/* Read IQ calibration status. */
status = rtwn_bb_read(sc, 0xeac);
if (status & (1 << (28 + chain * 3)))
return (0); /* Tx failed. */
/* Read Tx IQ calibration results. */
tx[0] = (rtwn_bb_read(sc, 0xe94 + offset) >> 16) & 0x3ff;
tx[1] = (rtwn_bb_read(sc, 0xe9c + offset) >> 16) & 0x3ff;
if (tx[0] == 0x142 || tx[1] == 0x042)
return (0); /* Tx failed. */
if (status & (1 << (27 + chain * 3)))
return (1); /* Rx failed. */
/* Read Rx IQ calibration results. */
rx[0] = (rtwn_bb_read(sc, 0xea4 + offset) >> 16) & 0x3ff;
rx[1] = (rtwn_bb_read(sc, 0xeac + offset) >> 16) & 0x3ff;
if (rx[0] == 0x132 || rx[1] == 0x036)
return (1); /* Rx failed. */
return (3); /* Both Tx and Rx succeeded. */
}
static void
r92ce_iq_calib_run(struct rtwn_softc *sc, int n, uint16_t tx[2][2],
uint16_t rx[2][2], struct r92ce_iq_cal_reg_vals *vals)
{
/* Registers to save and restore during IQ calibration. */
static const uint16_t reg_adda[16] = {
0x85c, 0xe6c, 0xe70, 0xe74,
0xe78, 0xe7c, 0xe80, 0xe84,
0xe88, 0xe8c, 0xed0, 0xed4,
0xed8, 0xedc, 0xee0, 0xeec
};
int i, chain;
uint32_t hssi_param1;
if (n == 0) {
for (i = 0; i < nitems(reg_adda); i++)
vals->adda[i] = rtwn_bb_read(sc, reg_adda[i]);
vals->txpause = rtwn_read_1(sc, R92C_TXPAUSE);
vals->bcn_ctrl[0] = rtwn_read_1(sc, R92C_BCN_CTRL(0));
vals->bcn_ctrl[1] = rtwn_read_1(sc, R92C_BCN_CTRL(1));
vals->gpio_muxcfg = rtwn_read_4(sc, R92C_GPIO_MUXCFG);
}
if (sc->ntxchains == 1) {
rtwn_bb_write(sc, reg_adda[0], 0x0b1b25a0);
for (i = 1; i < nitems(reg_adda); i++)
rtwn_bb_write(sc, reg_adda[i], 0x0bdb25a0);
} else {
for (i = 0; i < nitems(reg_adda); i++)
rtwn_bb_write(sc, reg_adda[i], 0x04db25a4);
}
hssi_param1 = rtwn_bb_read(sc, R92C_HSSI_PARAM1(0));
if (!(hssi_param1 & R92C_HSSI_PARAM1_PI)) {
rtwn_bb_write(sc, R92C_HSSI_PARAM1(0),
hssi_param1 | R92C_HSSI_PARAM1_PI);
rtwn_bb_write(sc, R92C_HSSI_PARAM1(1),
hssi_param1 | R92C_HSSI_PARAM1_PI);
}
if (n == 0) {
vals->ofdm0_trxpathena =
rtwn_bb_read(sc, R92C_OFDM0_TRXPATHENA);
vals->ofdm0_trmuxpar = rtwn_bb_read(sc, R92C_OFDM0_TRMUXPAR);
vals->fpga0_rfifacesw1 =
rtwn_bb_read(sc, R92C_FPGA0_RFIFACESW(1));
}
rtwn_bb_write(sc, R92C_OFDM0_TRXPATHENA, 0x03a05600);
rtwn_bb_write(sc, R92C_OFDM0_TRMUXPAR, 0x000800e4);
rtwn_bb_write(sc, R92C_FPGA0_RFIFACESW(1), 0x22204000);
if (sc->ntxchains > 1) {
rtwn_bb_write(sc, R92C_LSSI_PARAM(0), 0x00010000);
rtwn_bb_write(sc, R92C_LSSI_PARAM(1), 0x00010000);
}
rtwn_write_1(sc, R92C_TXPAUSE,
R92C_TX_QUEUE_AC | R92C_TX_QUEUE_MGT | R92C_TX_QUEUE_HIGH);
rtwn_write_1(sc, R92C_BCN_CTRL(0),
vals->bcn_ctrl[0] & ~R92C_BCN_CTRL_EN_BCN);
rtwn_write_1(sc, R92C_BCN_CTRL(1),
vals->bcn_ctrl[1] & ~R92C_BCN_CTRL_EN_BCN);
rtwn_write_1(sc, R92C_GPIO_MUXCFG,
vals->gpio_muxcfg & ~R92C_GPIO_MUXCFG_ENBT);
rtwn_bb_write(sc, 0x0b68, 0x00080000);
if (sc->ntxchains > 1)
rtwn_bb_write(sc, 0x0b6c, 0x00080000);
rtwn_bb_write(sc, 0x0e28, 0x80800000);
rtwn_bb_write(sc, 0x0e40, 0x01007c00);
rtwn_bb_write(sc, 0x0e44, 0x01004800);
rtwn_bb_write(sc, 0x0b68, 0x00080000);
for (chain = 0; chain < sc->ntxchains; chain++) {
if (chain > 0) {
/* Put chain 0 on standby. */
rtwn_bb_write(sc, 0x0e28, 0x00);
rtwn_bb_write(sc, R92C_LSSI_PARAM(0), 0x00010000);
rtwn_bb_write(sc, 0x0e28, 0x80800000);
/* Enable chain 1. */
for (i = 0; i < nitems(reg_adda); i++)
rtwn_bb_write(sc, reg_adda[i], 0x0b1b25a4);
}
/* Run IQ calibration twice. */
for (i = 0; i < 2; i++) {
int ret;
ret = r92ce_iq_calib_chain(sc, chain,
tx[chain], rx[chain]);
if (ret == 0) {
RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB,
"%s: chain %d: Tx failed.\n",
__func__, chain);
tx[chain][0] = 0xff;
tx[chain][1] = 0xff;
rx[chain][0] = 0xff;
rx[chain][1] = 0xff;
} else if (ret == 1) {
RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB,
"%s: chain %d: Rx failed.\n",
__func__, chain);
rx[chain][0] = 0xff;
rx[chain][1] = 0xff;
} else if (ret == 3) {
RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB,
"%s: chain %d: Both Tx and Rx "
"succeeded.\n", __func__, chain);
}
}
RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB,
"%s: results for run %d chain %d: tx[0] 0x%x, "
"tx[1] 0x%x, rx[0] 0x%x, rx[1] 0x%x\n", __func__, n, chain,
tx[chain][0], tx[chain][1], rx[chain][0], rx[chain][1]);
}
rtwn_bb_write(sc, R92C_OFDM0_TRXPATHENA,
vals->ofdm0_trxpathena);
rtwn_bb_write(sc, R92C_FPGA0_RFIFACESW(1),
vals->fpga0_rfifacesw1);
rtwn_bb_write(sc, R92C_OFDM0_TRMUXPAR, vals->ofdm0_trmuxpar);
rtwn_bb_write(sc, 0x0e28, 0x00);
rtwn_bb_write(sc, R92C_LSSI_PARAM(0), 0x00032ed3);
if (sc->ntxchains > 1)
rtwn_bb_write(sc, R92C_LSSI_PARAM(1), 0x00032ed3);
if (n != 0) {
if (!(hssi_param1 & R92C_HSSI_PARAM1_PI)) {
rtwn_bb_write(sc, R92C_HSSI_PARAM1(0), hssi_param1);
rtwn_bb_write(sc, R92C_HSSI_PARAM1(1), hssi_param1);
}
for (i = 0; i < nitems(reg_adda); i++)
rtwn_bb_write(sc, reg_adda[i], vals->adda[i]);
rtwn_write_1(sc, R92C_TXPAUSE, vals->txpause);
rtwn_write_1(sc, R92C_BCN_CTRL(0), vals->bcn_ctrl[0]);
rtwn_write_1(sc, R92C_BCN_CTRL(1), vals->bcn_ctrl[1]);
rtwn_write_4(sc, R92C_GPIO_MUXCFG, vals->gpio_muxcfg);
}
}
#define RTWN_IQ_CAL_MAX_TOLERANCE 5
static int
r92ce_iq_calib_compare_results(struct rtwn_softc *sc, uint16_t tx1[2][2],
uint16_t rx1[2][2], uint16_t tx2[2][2], uint16_t rx2[2][2])
{
int chain, i, tx_ok[2], rx_ok[2];
tx_ok[0] = tx_ok[1] = rx_ok[0] = rx_ok[1] = 0;
for (chain = 0; chain < sc->ntxchains; chain++) {
for (i = 0; i < 2; i++) {
if (tx1[chain][i] == 0xff || tx2[chain][i] == 0xff ||
rx1[chain][i] == 0xff || rx2[chain][i] == 0xff)
continue;
tx_ok[chain] = (abs(tx1[chain][i] - tx2[chain][i]) <=
RTWN_IQ_CAL_MAX_TOLERANCE);
rx_ok[chain] = (abs(rx1[chain][i] - rx2[chain][i]) <=
RTWN_IQ_CAL_MAX_TOLERANCE);
}
}
if (sc->ntxchains > 1)
return (tx_ok[0] && tx_ok[1] && rx_ok[0] && rx_ok[1]);
else
return (tx_ok[0] && rx_ok[0]);
}
#undef RTWN_IQ_CAL_MAX_TOLERANCE
static void
r92ce_iq_calib_write_results(struct rtwn_softc *sc, uint16_t tx[2],
uint16_t rx[2], int chain)
{
uint32_t reg, val, x;
long y, tx_c;
if (tx[0] == 0xff || tx[1] == 0xff)
return;
reg = rtwn_bb_read(sc, R92C_OFDM0_TXIQIMBALANCE(chain));
val = ((reg >> 22) & 0x3ff);
x = tx[0];
if (x & 0x00000200)
x |= 0xfffffc00;
reg = (((x * val) >> 8) & 0x3ff);
rtwn_bb_setbits(sc, R92C_OFDM0_TXIQIMBALANCE(chain), 0x3ff, reg);
rtwn_bb_setbits(sc, R92C_OFDM0_ECCATHRESHOLD, 0x80000000,
((x * val) & 0x80) << 24);
y = tx[1];
if (y & 0x00000200)
y |= 0xfffffc00;
tx_c = (y * val) >> 8;
rtwn_bb_setbits(sc, R92C_OFDM0_TXAFE(chain), 0xf0000000,
(tx_c & 0x3c0) << 22);
rtwn_bb_setbits(sc, R92C_OFDM0_TXIQIMBALANCE(chain), 0x003f0000,
(tx_c & 0x3f) << 16);
rtwn_bb_setbits(sc, R92C_OFDM0_ECCATHRESHOLD, 0x20000000,
((y * val) & 0x80) << 22);
if (rx[0] == 0xff || rx[1] == 0xff)
return;
rtwn_bb_setbits(sc, R92C_OFDM0_RXIQIMBALANCE(chain), 0x3ff,
rx[0] & 0x3ff);
rtwn_bb_setbits(sc, R92C_OFDM0_RXIQIMBALANCE(chain), 0xfc00,
(rx[1] & 0x3f) << 10);
if (chain == 0) {
rtwn_bb_setbits(sc, R92C_OFDM0_RXIQEXTANTA, 0xf0000000,
(rx[1] & 0x3c0) << 22);
} else {
rtwn_bb_setbits(sc, R92C_OFDM0_AGCRSSITABLE, 0xf000,
(rx[1] & 0x3c0) << 6);
}
}
#define RTWN_IQ_CAL_NRUN 3
void
r92ce_iq_calib(struct rtwn_softc *sc)
{
struct r92ce_iq_cal_reg_vals vals;
uint16_t tx[RTWN_IQ_CAL_NRUN][2][2], rx[RTWN_IQ_CAL_NRUN][2][2];
int n, valid;
valid = 0;
for (n = 0; n < RTWN_IQ_CAL_NRUN; n++) {
r92ce_iq_calib_run(sc, n, tx[n], rx[n], &vals);
if (n == 0)
continue;
/* Valid results remain stable after consecutive runs. */
valid = r92ce_iq_calib_compare_results(sc, tx[n - 1],
rx[n - 1], tx[n], rx[n]);
if (valid)
break;
}
if (valid) {
r92ce_iq_calib_write_results(sc, tx[n][0], rx[n][0], 0);
if (sc->ntxchains > 1)
r92ce_iq_calib_write_results(sc, tx[n][1], rx[n][1], 1);
}
}
#undef RTWN_IQ_CAL_NRUN

View File

@ -0,0 +1,74 @@
/* $OpenBSD: if_rtwn.c,v 1.6 2015/08/28 00:03:53 deraadt Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2015 Stefan Sperling <stsp@openbsd.org>
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <machine/bus.h>
#include <machine/resource.h>
#include <sys/rman.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/pci/rtwn_pci_var.h>
#include <dev/rtwn/rtl8192c/pci/r92ce.h>
#ifndef RTWN_WITHOUT_UCODE
void
r92ce_fw_reset(struct rtwn_softc *sc, int reason)
{
if (reason == RTWN_FW_RESET_CHECKSUM)
return;
r92c_fw_reset(sc, reason);
/*
* We must sleep for one second to let the firmware settle.
* Accessing registers too early will hang the whole system.
*/
rtwn_delay(sc, 1000 * 1000);
}
#endif

View File

@ -0,0 +1,327 @@
/* $OpenBSD: if_rtwn.c,v 1.6 2015/08/28 00:03:53 deraadt Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2015 Stefan Sperling <stsp@openbsd.org>
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <machine/bus.h>
#include <machine/resource.h>
#include <sys/rman.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/pci/rtwn_pci_var.h>
#include <dev/rtwn/rtl8192c/r92c_var.h>
#include <dev/rtwn/rtl8192c/pci/r92ce.h>
#include <dev/rtwn/rtl8192c/pci/r92ce_reg.h>
void
r92ce_init_intr(struct rtwn_softc *sc)
{
/* Disable interrupts. */
rtwn_write_4(sc, R92C_HISR, 0x00000000);
rtwn_write_4(sc, R92C_HIMR, 0x00000000);
}
void
r92ce_init_edca(struct rtwn_softc *sc)
{
/* SIFS */
rtwn_write_2(sc, R92C_SPEC_SIFS, 0x1010);
rtwn_write_2(sc, R92C_MAC_SPEC_SIFS, 0x1010);
rtwn_write_2(sc, R92C_SIFS_CCK, 0x1010);
rtwn_write_2(sc, R92C_SIFS_OFDM, 0x0e0e);
/* TXOP */
rtwn_write_4(sc, R92C_EDCA_BE_PARAM, 0x005ea42b);
rtwn_write_4(sc, R92C_EDCA_BK_PARAM, 0x0000a44f);
rtwn_write_4(sc, R92C_EDCA_VI_PARAM, 0x005e4322);
rtwn_write_4(sc, R92C_EDCA_VO_PARAM, 0x002f3222);
}
void
r92ce_init_bb(struct rtwn_softc *sc)
{
/* Enable BB and RF. */
rtwn_setbits_2(sc, R92C_SYS_FUNC_EN, 0,
R92C_SYS_FUNC_EN_BBRSTB | R92C_SYS_FUNC_EN_BB_GLB_RST |
R92C_SYS_FUNC_EN_DIO_RF);
rtwn_write_2(sc, R92C_AFE_PLL_CTRL, 0xdb83);
rtwn_write_1(sc, R92C_RF_CTRL,
R92C_RF_CTRL_EN | R92C_RF_CTRL_RSTB | R92C_RF_CTRL_SDMRSTB);
rtwn_write_1(sc, R92C_SYS_FUNC_EN,
R92C_SYS_FUNC_EN_DIO_PCIE | R92C_SYS_FUNC_EN_PCIEA |
R92C_SYS_FUNC_EN_PPLL | R92C_SYS_FUNC_EN_BB_GLB_RST |
R92C_SYS_FUNC_EN_BBRSTB);
rtwn_write_1(sc, R92C_AFE_XTAL_CTRL + 1, 0x80);
rtwn_setbits_4(sc, R92C_LEDCFG0, 0, 0x00800000);
r92c_init_bb_common(sc);
if (rtwn_bb_read(sc, R92C_HSSI_PARAM2(0)) &
R92C_HSSI_PARAM2_CCK_HIPWR)
sc->sc_flags |= RTWN_FLAG_CCK_HIPWR;
}
int
r92ce_power_on(struct rtwn_softc *sc)
{
struct r92c_softc *rs = sc->sc_priv;
uint32_t reg;
int ntries;
/* Wait for autoload done bit. */
for (ntries = 0; ntries < 1000; ntries++) {
if (rtwn_read_1(sc, R92C_APS_FSMCO) & R92C_APS_FSMCO_PFM_ALDN)
break;
DELAY(5);
}
if (ntries == 1000) {
device_printf(sc->sc_dev,
"timeout waiting for chip autoload\n");
return (ETIMEDOUT);
}
/* Unlock ISO/CLK/Power control register. */
rtwn_write_1(sc, R92C_RSV_CTRL, 0);
if (rs->board_type != R92C_BOARD_TYPE_DONGLE) {
/* bt coex */
rtwn_setbits_4(sc, R92C_APS_FSMCO, 0,
R92C_APS_FSMCO_SOP_ABG |
R92C_APS_FSMCO_SOP_AMB |
R92C_APS_FSMCO_XOP_BTCK);
}
/* Move SPS into PWM mode. */
rtwn_write_1(sc, R92C_SPS0_CTRL, 0x2b);
/* Set low byte to 0x0f, leave others unchanged. */
rtwn_write_1(sc, R92C_AFE_XTAL_CTRL, 0x0f);
/* TODO: check if we need this for 8188CE */
if (rs->board_type != R92C_BOARD_TYPE_DONGLE) {
/* bt coex */
/* XXX magic from linux */
rtwn_setbits_4(sc, R92C_AFE_XTAL_CTRL, 0x024800, 0);
}
rtwn_setbits_2(sc, R92C_SYS_ISO_CTRL, 0xff00,
R92C_SYS_ISO_CTRL_PWC_EV12V | R92C_SYS_ISO_CTRL_DIOR);
DELAY(200);
/* TODO: linux does additional btcoex stuff here */
/* Auto enable WLAN. */
rtwn_setbits_2(sc, R92C_APS_FSMCO, 0, R92C_APS_FSMCO_APFM_ONMAC);
for (ntries = 0; ntries < 1000; ntries++) {
if (!(rtwn_read_2(sc, R92C_APS_FSMCO) &
R92C_APS_FSMCO_APFM_ONMAC))
break;
DELAY(5);
}
if (ntries == 1000) {
device_printf(sc->sc_dev, "timeout waiting for MAC auto ON\n");
return (ETIMEDOUT);
}
/* Enable radio, GPIO and LED functions. */
rtwn_write_2(sc, R92C_APS_FSMCO,
R92C_APS_FSMCO_AFSM_PCIE |
R92C_APS_FSMCO_PDN_EN |
R92C_APS_FSMCO_PFM_ALDN);
/* Release RF digital isolation. */
rtwn_setbits_2(sc, R92C_SYS_ISO_CTRL, R92C_SYS_ISO_CTRL_DIOR, 0);
if (rs->chip & R92C_CHIP_92C)
rtwn_write_1(sc, R92C_PCIE_CTRL_REG + 3, 0x77);
else
rtwn_write_1(sc, R92C_PCIE_CTRL_REG + 3, 0x22);
rtwn_write_4(sc, R92C_INT_MIG, 0);
if (rs->board_type != R92C_BOARD_TYPE_DONGLE) {
/* bt coex */
/* XXX magic from linux */
rtwn_setbits_1(sc, R92C_AFE_XTAL_CTRL + 2, 0x02, 0);
}
rtwn_setbits_1(sc, R92C_GPIO_MUXCFG, R92C_GPIO_MUXCFG_RFKILL, 0);
reg = rtwn_read_1(sc, R92C_GPIO_IO_SEL);
if (!(reg & R92C_GPIO_IO_SEL_RFKILL)) {
device_printf(sc->sc_dev,
"radio is disabled by hardware switch\n");
/* XXX how driver will know when radio will be enabled? */
return (EPERM);
}
/* Initialize MAC. */
rtwn_setbits_1(sc, R92C_APSD_CTRL, R92C_APSD_CTRL_OFF, 0);
for (ntries = 0; ntries < 200; ntries++) {
if (!(rtwn_read_1(sc, R92C_APSD_CTRL) &
R92C_APSD_CTRL_OFF_STATUS))
break;
DELAY(500);
}
if (ntries == 200) {
device_printf(sc->sc_dev,
"timeout waiting for MAC initialization\n");
return (ETIMEDOUT);
}
/* Enable MAC DMA/WMAC/SCHEDULE/SEC blocks. */
rtwn_setbits_2(sc, R92C_CR, 0,
R92C_CR_HCI_TXDMA_EN | R92C_CR_HCI_RXDMA_EN |
R92C_CR_TXDMA_EN | R92C_CR_RXDMA_EN | R92C_CR_PROTOCOL_EN |
R92C_CR_SCHEDULE_EN | R92C_CR_MACTXEN | R92C_CR_MACRXEN |
((sc->sc_hwcrypto != RTWN_CRYPTO_SW) ? R92C_CR_ENSEC : 0));
rtwn_write_4(sc, R92C_MCUTST_1, 0x0);
return (0);
}
void
r92ce_power_off(struct rtwn_softc *sc)
{
#ifndef RTWN_WITHOUT_UCODE
struct r92c_softc *rs = sc->sc_priv;
/* Deinit C2H event handler. */
callout_stop(&rs->rs_c2h_report);
rs->rs_c2h_paused = 0;
rs->rs_c2h_pending = 0;
rs->rs_c2h_timeout = hz;
#endif
/* Stop hardware. */
/* Disable interrupts. */
rtwn_write_4(sc, R92C_HISR, 0);
rtwn_write_4(sc, R92C_HIMR, 0);
/* Stop hardware. */
rtwn_write_1(sc, R92C_TXPAUSE, R92C_TX_QUEUE_ALL);
/* Turn off RF. */
rtwn_write_1(sc, R92C_RF_CTRL, 0);
/* Reset BB state machine */
rtwn_setbits_1(sc, R92C_SYS_FUNC_EN, 0, R92C_SYS_FUNC_EN_BB_GLB_RST);
rtwn_setbits_1(sc, R92C_SYS_FUNC_EN, R92C_SYS_FUNC_EN_BB_GLB_RST, 0);
/* Disable MAC DMA/WMAC/SCHEDULE/SEC blocks. */
rtwn_setbits_2(sc, R92C_CR,
R92C_CR_HCI_TXDMA_EN | R92C_CR_HCI_RXDMA_EN |
R92C_CR_TXDMA_EN | R92C_CR_RXDMA_EN | R92C_CR_PROTOCOL_EN |
R92C_CR_SCHEDULE_EN | R92C_CR_MACTXEN | R92C_CR_MACRXEN |
R92C_CR_ENSEC,
0);
/* If firmware in ram code, do reset. */
#ifndef RTWN_WITHOUT_UCODE
if (rtwn_read_1(sc, R92C_MCUFWDL) & R92C_MCUFWDL_RAM_DL_SEL)
r92ce_fw_reset(sc, RTWN_FW_RESET_SHUTDOWN);
#endif
/* TODO: linux does additional btcoex stuff here */
rtwn_write_2(sc, R92C_AFE_PLL_CTRL, 0x80); /* linux magic number */
rtwn_write_1(sc, R92C_SPS0_CTRL, 0x23); /* ditto */
rtwn_write_1(sc, R92C_AFE_XTAL_CTRL, 0x0e); /* different with btcoex */
rtwn_write_1(sc, R92C_RSV_CTRL, 0x0e);
rtwn_write_1(sc, R92C_APS_FSMCO, R92C_APS_FSMCO_PDN_EN);
}
void
r92ce_init_ampdu(struct rtwn_softc *sc)
{
/* Setup AMPDU aggregation. */
rtwn_write_4(sc, R92C_AGGLEN_LMT, 0x99997631); /* MCS7~0 */
rtwn_write_1(sc, R92C_AGGR_BREAK_TIME, 0x16);
}
void
r92ce_post_init(struct rtwn_softc *sc)
{
rtwn_write_2(sc, R92C_FWHW_TXQ_CTRL,
0x1f00 | R92C_FWHW_TXQ_CTRL_AMPDU_RTY_NEW);
rtwn_write_1(sc, R92C_BCN_MAX_ERR, 0xff);
/* Perform LO and IQ calibrations. */
r92ce_iq_calib(sc);
/* Perform LC calibration. */
r92c_lc_calib(sc);
r92c_pa_bias_init(sc);
/* Fix for lower temperature. */
rtwn_write_1(sc, 0x15, 0xe9);
#ifndef RTWN_WITHOUT_UCODE
if (sc->sc_flags & RTWN_FW_LOADED) {
struct r92c_softc *rs = sc->sc_priv;
if (sc->sc_ratectl_sysctl == RTWN_RATECTL_FW) {
/* XXX TODO: fix (see comment in r92cu_init.c) */
sc->sc_ratectl = RTWN_RATECTL_NET80211;
} else
sc->sc_ratectl = sc->sc_ratectl_sysctl;
/* Start C2H event handling. */
callout_reset(&rs->rs_c2h_report, rs->rs_c2h_timeout,
r92c_handle_c2h_report, sc);
} else
#endif
sc->sc_ratectl = RTWN_RATECTL_NONE;
}

View File

@ -0,0 +1,67 @@
/* $OpenBSD: if_rtwn.c,v 1.6 2015/08/28 00:03:53 deraadt Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2015 Stefan Sperling <stsp@openbsd.org>
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <machine/bus.h>
#include <machine/resource.h>
#include <sys/rman.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/pci/rtwn_pci_var.h>
#include <dev/rtwn/rtl8192c/pci/r92ce.h>
#include <dev/rtwn/rtl8192c/pci/r92ce_reg.h>
void
r92ce_set_led(struct rtwn_softc *sc, int led, int on)
{
if (led == RTWN_LED_LINK) {
rtwn_setbits_1(sc, R92C_LEDCFG2, 0x0f,
on ? R92C_LEDCFG2_EN : R92C_LEDCFG2_DIS);
sc->ledlink = on; /* Save LED state. */
}
}

View File

@ -0,0 +1,182 @@
/* $OpenBSD: if_rtwnreg.h,v 1.3 2015/06/14 08:02:47 stsp Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2015 Stefan Sperling <stsp@openbsd.org>
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $FreeBSD$
*/
#ifndef R92CE_PRIV_H
#define R92CE_PRIV_H
#include <dev/rtwn/rtl8192c/r92c_priv.h>
/*
* MAC initialization values.
*/
static const struct rtwn_mac_prog rtl8192ce_mac[] = {
{ 0x420, 0x80 }, { 0x423, 0x00 }, { 0x430, 0x00 }, { 0x431, 0x00 },
{ 0x432, 0x00 }, { 0x433, 0x01 }, { 0x434, 0x04 }, { 0x435, 0x05 },
{ 0x436, 0x06 }, { 0x437, 0x07 }, { 0x438, 0x00 }, { 0x439, 0x00 },
{ 0x43a, 0x00 }, { 0x43b, 0x01 }, { 0x43c, 0x04 }, { 0x43d, 0x05 },
{ 0x43e, 0x06 }, { 0x43f, 0x07 }, { 0x440, 0x5d }, { 0x441, 0x01 },
{ 0x442, 0x00 }, { 0x444, 0x15 }, { 0x445, 0xf0 }, { 0x446, 0x0f },
{ 0x447, 0x00 }, { 0x458, 0x41 }, { 0x459, 0xa8 }, { 0x45a, 0x72 },
{ 0x45b, 0xb9 }, { 0x460, 0x88 }, { 0x461, 0x88 }, { 0x462, 0x06 },
{ 0x463, 0x03 }, { 0x4c8, 0x04 }, { 0x4c9, 0x08 }, { 0x4cc, 0x02 },
{ 0x4cd, 0x28 }, { 0x4ce, 0x01 }, { 0x500, 0x26 }, { 0x501, 0xa2 },
{ 0x502, 0x2f }, { 0x503, 0x00 }, { 0x504, 0x28 }, { 0x505, 0xa3 },
{ 0x506, 0x5e }, { 0x507, 0x00 }, { 0x508, 0x2b }, { 0x509, 0xa4 },
{ 0x50a, 0x5e }, { 0x50b, 0x00 }, { 0x50c, 0x4f }, { 0x50d, 0xa4 },
{ 0x50e, 0x00 }, { 0x50f, 0x00 }, { 0x512, 0x1c }, { 0x514, 0x0a },
{ 0x515, 0x10 }, { 0x516, 0x0a }, { 0x517, 0x10 }, { 0x51a, 0x16 },
{ 0x524, 0x0f }, { 0x525, 0x4f }, { 0x546, 0x20 }, { 0x547, 0x00 },
{ 0x559, 0x02 }, { 0x55a, 0x02 }, { 0x55d, 0xff }, { 0x605, 0x30 },
{ 0x608, 0x0e }, { 0x609, 0x2a }, { 0x652, 0x20 }, { 0x63c, 0x0a },
{ 0x63d, 0x0e }, { 0x700, 0x21 }, { 0x701, 0x43 }, { 0x702, 0x65 },
{ 0x703, 0x87 }, { 0x708, 0x21 }, { 0x709, 0x43 }, { 0x70a, 0x65 },
{ 0x70b, 0x87 }
};
/*
* Baseband initialization values.
*/
static const uint16_t rtl8192ce_bb_regs0[] = {
0x024, 0x028, 0x800, 0x804, 0x808, 0x80c, 0x810, 0x814, 0x818,
0x81c, 0x820, 0x824, 0x828, 0x82c, 0x830, 0x834, 0x838, 0x83c,
0x840, 0x844, 0x848, 0x84c, 0x850, 0x854, 0x858, 0x85c, 0x860,
0x864, 0x868, 0x86c, 0x870, 0x874, 0x878, 0x87c, 0x880, 0x884,
0x888, 0x88c, 0x890, 0x894, 0x898, 0x89c, 0x900, 0x904, 0x908,
0x90c, 0xa00, 0xa04, 0xa08, 0xa0c, 0xa10, 0xa14, 0xa18, 0xa1c,
0xa20, 0xa24, 0xa28, 0xa2c, 0xa70, 0xa74, 0xc00, 0xc04
}, rtl8192ce_bb_regs1[] = {
0xc08, 0xc0c, 0xc10, 0xc14, 0xc18, 0xc1c, 0xc20, 0xc24, 0xc28,
0xc2c, 0xc30, 0xc34, 0xc38, 0xc3c, 0xc40, 0xc44, 0xc48, 0xc4c,
0xc50, 0xc54, 0xc58, 0xc5c, 0xc60, 0xc64, 0xc68, 0xc6c, 0xc70,
0xc74, 0xc78, 0xc7c, 0xc80, 0xc84, 0xc88, 0xc8c, 0xc90, 0xc94,
0xc98, 0xc9c, 0xca0, 0xca4, 0xca8, 0xcac, 0xcb0, 0xcb4, 0xcb8,
0xcbc, 0xcc0, 0xcc4, 0xcc8, 0xccc, 0xcd0, 0xcd4, 0xcd8, 0xcdc,
0xce0, 0xce4, 0xce8, 0xcec, 0xd00
};
static const uint32_t rtl8192ce_bb_vals0_2t[] = {
0x0011800f, 0x00ffdb83, 0x80040002, 0x00000003, 0x0000fc00,
0x0000000a, 0x10005388, 0x020c3d10, 0x02200385, 0x00000000,
0x01000100, 0x00390004, 0x01000100, 0x00390004, 0x27272727,
0x27272727, 0x27272727, 0x27272727, 0x00010000, 0x00010000,
0x27272727, 0x27272727, 0x00000000, 0x00000000, 0x569a569a,
0x0c1b25a4, 0x66e60230, 0x061f0130, 0x27272727, 0x2b2b2b27,
0x07000700, 0x22184000, 0x08080808, 0x00000000, 0xc0083070,
0x000004d5, 0x00000000, 0xcc0000c0, 0x00000800, 0xfffffffe,
0x40302010, 0x00706050, 0x00000000, 0x00000023, 0x00000000,
0x81121313, 0x00d047c8, 0x80ff000c, 0x8c838300, 0x2e68120f,
0x9500bb78, 0x11144028, 0x00881117, 0x89140f00, 0x1a1b0000,
0x090e1317, 0x00000204, 0x00d30000, 0x101fbf00, 0x00000007,
0x48071d40, 0x03a05633
}, rtl8192ce_bb_vals0_1t[] = {
0x0011800f, 0x00ffdb83, 0x80040000, 0x00000001, 0x0000fc00,
0x0000000a, 0x10005388, 0x020c3d10, 0x02200385, 0x00000000,
0x01000100, 0x00390004, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00010000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x569a569a,
0x001b25a4, 0x66e60230, 0x061f0130, 0x00000000, 0x32323200,
0x07000700, 0x22004000, 0x00000808, 0x00000000, 0xc0083070,
0x000004d5, 0x00000000, 0xccc000c0, 0x00000800, 0xfffffffe,
0x40302010, 0x00706050, 0x00000000, 0x00000023, 0x00000000,
0x81121111, 0x00d047c8, 0x80ff000c, 0x8c838300, 0x2e68120f,
0x9500bb78, 0x11144028, 0x00881117, 0x89140f00, 0x1a1b0000,
0x090e1317, 0x00000204, 0x00d30000, 0x101fbf00, 0x00000007,
0x48071d40, 0x03a05611
}, rtl8192ce_bb_vals1[] = {
0x000000e4, 0x6c6c6c6c, 0x08800000, 0x40000100, 0x08800000,
0x40000100, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x69e9ac44, 0x469652cf, 0x49795994, 0x0a97971c, 0x1f7c403f,
0x000100b7, 0xec020107, 0x007f037f, 0x69543420, 0x43bc0094,
0x69543420, 0x433c0094, 0x00000000, 0x5116848b, 0x47c00bff,
0x00000036, 0x2c7f000d, 0x018610db, 0x0000001f, 0x00b91612,
0x40000100, 0x20f60000, 0x40000100, 0x20200000, 0x00121820,
0x00000000, 0x00121820, 0x00007f7f, 0x00000000, 0x00000080,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x28000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x64b22427, 0x00766932, 0x00222222,
0x00000000, 0x37644302, 0x2f97d40c, 0x00080740
}, rtl8192ce_bb_vals4_1t[] = {
0x00000010, 0x001b25a4, 0x631b25a0, 0x631b25a0, 0x081b25a0,
0x081b25a0, 0x081b25a0, 0x081b25a0, 0x631b25a0, 0x081b25a0,
0x631b25a0, 0x631b25a0, 0x631b25a0, 0x631b25a0, 0x001b25a0,
0x001b25a0, 0x6b1b25a0, 0x00000003, 0x00000000, 0x00000300
};
static const struct rtwn_bb_prog rtl8192ce_bb[] = {
{
nitems(rtl8192ce_bb_regs0),
rtl8192ce_bb_regs0,
rtl8192ce_bb_vals0_2t,
{ R92C_COND_RTL8192C },
&(const struct rtwn_bb_prog){
nitems(rtl8192ce_bb_regs0),
rtl8192ce_bb_regs0,
rtl8192ce_bb_vals0_1t,
{ 0 },
NULL
}
},
{
nitems(rtl8192ce_bb_regs1),
rtl8192ce_bb_regs1,
rtl8192ce_bb_vals1,
{ 0 },
NULL
},
{
nitems(rtl8192c_bb_regs3),
rtl8192c_bb_regs3,
rtl8192c_bb_vals3_92ce_92cu,
{ R92C_COND_RTL8192C },
&(const struct rtwn_bb_prog){
nitems(rtl8192c_bb_regs3),
rtl8192c_bb_regs3,
rtl8192c_bb_vals3_88cu_88ru,
{ 0 },
NULL
}
},
{
nitems(rtl8192c_bb_regs4),
rtl8192c_bb_regs4,
rtl8192c_bb_vals4,
{ 0 },
NULL
},
{
nitems(rtl8192c_bb_regs5),
rtl8192c_bb_regs5,
rtl8192c_bb_vals5_92ce_92cu,
{ R92C_COND_RTL8192C },
&(const struct rtwn_bb_prog){
nitems(rtl8192c_bb_regs5),
rtl8192c_bb_regs5,
rtl8192ce_bb_vals4_1t,
{ 0 },
NULL
}
}
};
#endif /* R92CE_PRIV_H */

View File

@ -0,0 +1,103 @@
/* $OpenBSD: if_rtwnreg.h,v 1.3 2015/06/14 08:02:47 stsp Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2015 Stefan Sperling <stsp@openbsd.org>
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $FreeBSD$
*/
#ifndef R92CE_REG_H
#define R92CE_REG_H
#include <dev/rtwn/rtl8192c/r92c_reg.h>
/*
* MAC registers.
*/
/* System Configuration. */
#define R92C_PCIE_MIO_INTF 0x0e4
#define R92C_PCIE_MIO_INTD 0x0e8
/* PCIe Configuration. */
#define R92C_PCIE_CTRL_REG 0x300
#define R92C_INT_MIG 0x304
#define R92C_BCNQ_DESA 0x308
#define R92C_HQ_DESA 0x310
#define R92C_MGQ_DESA 0x318
#define R92C_VOQ_DESA 0x320
#define R92C_VIQ_DESA 0x328
#define R92C_BEQ_DESA 0x330
#define R92C_BKQ_DESA 0x338
#define R92C_RX_DESA 0x340
#define R92C_DBI 0x348
#define R92C_MDIO 0x354
#define R92C_DBG_SEL 0x360
#define R92C_PCIE_HRPWM 0x361
#define R92C_PCIE_HCPWM 0x363
#define R92C_UART_CTRL 0x364
#define R92C_UART_TX_DES 0x370
#define R92C_UART_RX_DES 0x378
/* Bits for R92C_GPIO_MUXCFG. */
#define R92C_GPIO_MUXCFG_RFKILL 0x0008
/* Bits for R92C_GPIO_IO_SEL. */
#define R92C_GPIO_IO_SEL_RFKILL 0x0008
/* Bits for R92C_LEDCFG2. */
#define R92C_LEDCFG2_EN 0x60
#define R92C_LEDCFG2_DIS 0x68
/* Bits for R92C_HIMR. */
#define R92C_IMR_ROK 0x00000001 /* receive DMA OK */
#define R92C_IMR_VODOK 0x00000002 /* AC_VO DMA OK */
#define R92C_IMR_VIDOK 0x00000004 /* AC_VI DMA OK */
#define R92C_IMR_BEDOK 0x00000008 /* AC_BE DMA OK */
#define R92C_IMR_BKDOK 0x00000010 /* AC_BK DMA OK */
#define R92C_IMR_TXBDER 0x00000020 /* beacon transmit error */
#define R92C_IMR_MGNTDOK 0x00000040 /* management queue DMA OK */
#define R92C_IMR_TBDOK 0x00000080 /* beacon transmit OK */
#define R92C_IMR_HIGHDOK 0x00000100 /* high queue DMA OK */
#define R92C_IMR_BDOK 0x00000200 /* beacon queue DMA OK */
#define R92C_IMR_ATIMEND 0x00000400 /* ATIM window end interrupt */
#define R92C_IMR_RDU 0x00000800 /* Rx descriptor unavailable */
#define R92C_IMR_RXFOVW 0x00001000 /* receive FIFO overflow */
#define R92C_IMR_BCNINT 0x00002000 /* beacon DMA interrupt 0 */
#define R92C_IMR_PSTIMEOUT 0x00004000 /* powersave timeout */
#define R92C_IMR_TXFOVW 0x00008000 /* transmit FIFO overflow */
#define R92C_IMR_TIMEOUT1 0x00010000 /* timeout interrupt 1 */
#define R92C_IMR_TIMEOUT2 0x00020000 /* timeout interrupt 2 */
#define R92C_IMR_BCNDOK1 0x00040000 /* beacon queue DMA OK (1) */
#define R92C_IMR_BCNDOK2 0x00080000 /* beacon queue DMA OK (2) */
#define R92C_IMR_BCNDOK3 0x00100000 /* beacon queue DMA OK (3) */
#define R92C_IMR_BCNDOK4 0x00200000 /* beacon queue DMA OK (4) */
#define R92C_IMR_BCNDOK5 0x00400000 /* beacon queue DMA OK (5) */
#define R92C_IMR_BCNDOK6 0x00800000 /* beacon queue DMA OK (6) */
#define R92C_IMR_BCNDOK7 0x01000000 /* beacon queue DMA OK (7) */
#define R92C_IMR_BCNDOK8 0x02000000 /* beacon queue DMA OK (8) */
#define R92C_IMR_BCNDMAINT1 0x04000000 /* beacon DMA interrupt 1 */
#define R92C_IMR_BCNDMAINT2 0x08000000 /* beacon DMA interrupt 2 */
#define R92C_IMR_BCNDMAINT3 0x10000000 /* beacon DMA interrupt 3 */
#define R92C_IMR_BCNDMAINT4 0x20000000 /* beacon DMA interrupt 4 */
#define R92C_IMR_BCNDMAINT5 0x40000000 /* beacon DMA interrupt 5 */
#define R92C_IMR_BCNDMAINT6 0x80000000 /* beacon DMA interrupt 6 */
/* Shortcut. */
#define R92C_IBSS_INT_MASK \
(R92C_IMR_BCNINT | R92C_IMR_TBDOK | R92C_IMR_TBDER)
#endif /* R92CE_REG_H */

View File

@ -0,0 +1,132 @@
/* $OpenBSD: if_rtwn.c,v 1.6 2015/08/28 00:03:53 deraadt Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2015 Stefan Sperling <stsp@openbsd.org>
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <machine/bus.h>
#include <machine/resource.h>
#include <sys/rman.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/if_rtwn_debug.h>
#include <dev/rtwn/pci/rtwn_pci_var.h>
#include <dev/rtwn/rtl8192c/pci/r92ce.h>
#include <dev/rtwn/rtl8192c/pci/r92ce_reg.h>
int
r92ce_classify_intr(struct rtwn_softc *sc, void *arg, int len __unused)
{
uint32_t status;
int *rings = arg;
int ret;
*rings = 0;
status = rtwn_read_4(sc, R92C_HISR);
RTWN_DPRINTF(sc, RTWN_DEBUG_INTR, "%s: HISR %08X, HISRE %04X\n",
__func__, status, rtwn_read_2(sc, R92C_HISRE));
if (status == 0 || status == 0xffffffff)
return (0);
/* Disable interrupts. */
rtwn_write_4(sc, R92C_HIMR, 0);
/* Ack interrupts. */
rtwn_write_4(sc, R92C_HISR, status);
if (status & R92C_IMR_BDOK)
*rings |= (1 << RTWN_PCI_BEACON_QUEUE);
if (status & R92C_IMR_HIGHDOK)
*rings |= (1 << RTWN_PCI_HIGH_QUEUE);
if (status & R92C_IMR_MGNTDOK)
*rings |= (1 << RTWN_PCI_MGNT_QUEUE);
if (status & R92C_IMR_BKDOK)
*rings |= (1 << RTWN_PCI_BK_QUEUE);
if (status & R92C_IMR_BEDOK)
*rings |= (1 << RTWN_PCI_BE_QUEUE);
if (status & R92C_IMR_VIDOK)
*rings |= (1 << RTWN_PCI_VI_QUEUE);
if (status & R92C_IMR_VODOK)
*rings |= (1 << RTWN_PCI_VO_QUEUE);
ret = 0;
if (status & R92C_IMR_RXFOVW)
ret |= RTWN_PCI_INTR_RX_OVERFLOW;
if (status & R92C_IMR_RDU)
ret |= RTWN_PCI_INTR_RX_DESC_UNAVAIL;
if (status & R92C_IMR_ROK)
ret |= RTWN_PCI_INTR_RX_DONE;
if (status & R92C_IMR_TXFOVW)
ret |= RTWN_PCI_INTR_TX_OVERFLOW;
if (status & R92C_IMR_PSTIMEOUT)
ret |= RTWN_PCI_INTR_PS_TIMEOUT;
return (ret);
}
#define R92C_INT_ENABLE (R92C_IMR_ROK | R92C_IMR_VODOK | R92C_IMR_VIDOK | \
R92C_IMR_BEDOK | R92C_IMR_BKDOK | R92C_IMR_MGNTDOK | \
R92C_IMR_HIGHDOK | R92C_IMR_BDOK | R92C_IMR_RDU | \
R92C_IMR_RXFOVW)
void
r92ce_enable_intr(struct rtwn_pci_softc *pc)
{
struct rtwn_softc *sc = &pc->pc_sc;
/* Enable interrupts. */
rtwn_write_4(sc, R92C_HIMR, R92C_INT_ENABLE);
}
void
r92ce_start_xfers(struct rtwn_softc *sc)
{
/* Clear pending interrupts. */
rtwn_write_4(sc, R92C_HISR, 0xffffffff);
/* Enable interrupts. */
rtwn_write_4(sc, R92C_HIMR, R92C_INT_ENABLE);
}
#undef R92C_INT_ENABLE

View File

@ -0,0 +1,41 @@
/* $OpenBSD: if_rtwnreg.h,v 1.3 2015/06/14 08:02:47 stsp Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2015 Stefan Sperling <stsp@openbsd.org>
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $FreeBSD$
*/
#ifndef R92CE_RX_DESC_H
#define R92CE_RX_DESC_H
#include <dev/rtwn/rtl8192c/r92c_rx_desc.h>
/* Rx MAC descriptor (PCIe). */
struct r92ce_rx_stat {
uint32_t rxdw0;
uint32_t rxdw1;
uint32_t rxdw2;
uint32_t rxdw3;
uint32_t rxdw4;
uint32_t tsf_low;
uint32_t rxbufaddr;
uint32_t rxbufaddr64;
} __packed __attribute__((aligned(4)));
#endif /* R92CE_RX_DESC_H */

View File

@ -0,0 +1,115 @@
/* $OpenBSD: if_rtwn.c,v 1.6 2015/08/28 00:03:53 deraadt Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2015 Stefan Sperling <stsp@openbsd.org>
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <machine/bus.h>
#include <machine/resource.h>
#include <sys/rman.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/if_rtwn_debug.h>
#include <dev/rtwn/pci/rtwn_pci_var.h>
#include <dev/rtwn/rtl8192c/pci/r92ce.h>
#include <dev/rtwn/rtl8192c/pci/r92ce_tx_desc.h>
void
r92ce_setup_tx_desc(struct rtwn_pci_softc *pc, void *desc,
uint32_t next_desc_addr)
{
struct r92ce_tx_desc *txd = desc;
/* setup tx desc */
txd->nextdescaddr = htole32(next_desc_addr);
}
void
r92ce_tx_postsetup(struct rtwn_pci_softc *pc, void *desc,
bus_dma_segment_t segs[])
{
struct r92ce_tx_desc *txd = desc;
txd->txbufaddr = htole32(segs[0].ds_addr);
txd->txbufsize = txd->pktlen;
bus_space_barrier(pc->pc_st, pc->pc_sh, 0, pc->pc_mapsize,
BUS_SPACE_BARRIER_WRITE);
}
void
r92ce_copy_tx_desc(void *dest, const void *src)
{
struct r92ce_tx_desc *txd = dest;
size_t len = sizeof(struct r92c_tx_desc) +
sizeof(txd->txbufsize) + sizeof(txd->pad);
if (src != NULL)
memcpy(dest, src, len);
else
memset(dest, 0, len);
}
void
r92ce_dump_tx_desc(struct rtwn_softc *sc, const void *desc)
{
#ifdef RTWN_DEBUG
const struct r92ce_tx_desc *txd = desc;
RTWN_DPRINTF(sc, RTWN_DEBUG_XMIT_DESC,
"%s: len %d, off %d, flags0 %02X, dw: 1 %08X, 2 %08X, 3 %04X "
"(seq %04X), 4 %08X, 5 %08X, 6 %08X, size %04X, pad %04X, "
"addr: %08X (64: %08X), next: %08X (64: %08X), "
"rsvd: %08X %08X %08X %08X\n",
__func__, le16toh(txd->pktlen), txd->offset, txd->flags0,
le32toh(txd->txdw1), le32toh(txd->txdw2), le16toh(txd->txdw3),
le16toh(txd->txdseq), le32toh(txd->txdw4), le32toh(txd->txdw5),
le32toh(txd->txdw6), le16toh(txd->txbufsize), le16toh(txd->pad),
le32toh(txd->txbufaddr), le32toh(txd->txbufaddr64),
le32toh(txd->nextdescaddr), le32toh(txd->nextdescaddr64),
le32toh(txd->reserved[0]), le32toh(txd->reserved[1]),
le32toh(txd->reserved[2]), le32toh(txd->reserved[3]));
#endif
}

View File

@ -0,0 +1,55 @@
/* $OpenBSD: if_rtwnreg.h,v 1.3 2015/06/14 08:02:47 stsp Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2015 Stefan Sperling <stsp@openbsd.org>
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $FreeBSD$
*/
#ifndef R92CE_TX_DESC_H
#define R92CE_TX_DESC_H
#include <dev/rtwn/rtl8192c/r92c_tx_desc.h>
/* Tx MAC descriptor (PCIe). */
struct r92ce_tx_desc {
uint16_t pktlen;
uint8_t offset;
uint8_t flags0;
uint32_t txdw1;
uint32_t txdw2;
uint16_t txdw3;
uint16_t txdseq;
uint32_t txdw4;
uint32_t txdw5;
uint32_t txdw6;
uint16_t txbufsize;
uint16_t pad;
uint32_t txbufaddr;
uint32_t txbufaddr64;
uint32_t nextdescaddr;
uint32_t nextdescaddr64;
uint32_t reserved[4];
} __packed __attribute__((aligned(4)));
#endif /* R92CE_TX_DESC_H */

View File

@ -0,0 +1,115 @@
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $
* $FreeBSD$
*/
#ifndef RTL8192C_H
#define RTL8192C_H
/*
* Global definitions.
*/
#define R92C_TXPKTBUF_COUNT 256
#define R92C_TX_PAGE_SIZE 128
#define R92C_RX_DMA_BUFFER_SIZE 0x2800
#define R92C_MAX_FW_SIZE 0x4000
#define R92C_MACID_MAX 31
#define R92C_CAM_ENTRY_COUNT 32
#define R92C_CALIB_THRESHOLD 2
/*
* Function declarations.
*/
/* r92c_attach.c */
void r92c_detach_private(struct rtwn_softc *);
void r92c_read_chipid_vendor(struct rtwn_softc *, uint32_t);
/* r92c_beacon.c */
void r92c_beacon_init(struct rtwn_softc *, void *, int);
void r92c_beacon_enable(struct rtwn_softc *, int, int);
/* r92c_calib.c */
void r92c_iq_calib(struct rtwn_softc *);
void r92c_lc_calib(struct rtwn_softc *);
void r92c_temp_measure(struct rtwn_softc *);
uint8_t r92c_temp_read(struct rtwn_softc *);
/* r92c_chan.c */
void r92c_get_txpower(struct rtwn_softc *, int,
struct ieee80211_channel *, uint16_t[]);
void r92c_set_bw20(struct rtwn_softc *, uint8_t);
void r92c_set_chan(struct rtwn_softc *, struct ieee80211_channel *);
void r92c_set_gain(struct rtwn_softc *, uint8_t);
void r92c_scan_start(struct ieee80211com *);
void r92c_scan_end(struct ieee80211com *);
/* r92c_fw.c */
#ifndef RTWN_WITHOUT_UCODE
void r92c_fw_reset(struct rtwn_softc *, int);
void r92c_fw_download_enable(struct rtwn_softc *, int);
#endif
void r92c_joinbss_rpt(struct rtwn_softc *, int);
#ifndef RTWN_WITHOUT_UCODE
int r92c_set_rsvd_page(struct rtwn_softc *, int, int, int);
int r92c_set_pwrmode(struct rtwn_softc *, struct ieee80211vap *, int);
void r92c_set_rssi(struct rtwn_softc *);
void r92c_handle_c2h_report(void *);
#endif
/* r92c_init.c */
int r92c_check_condition(struct rtwn_softc *, const uint8_t[]);
int r92c_set_page_size(struct rtwn_softc *);
void r92c_init_bb_common(struct rtwn_softc *);
int r92c_init_rf_chain(struct rtwn_softc *,
const struct rtwn_rf_prog *, int);
void r92c_init_rf_common(struct rtwn_softc *);
void r92c_init_rf(struct rtwn_softc *);
void r92c_init_edca(struct rtwn_softc *);
void r92c_init_ampdu(struct rtwn_softc *);
void r92c_init_antsel(struct rtwn_softc *);
void r92c_pa_bias_init(struct rtwn_softc *);
/* r92c_rf.c */
uint32_t r92c_rf_read(struct rtwn_softc *, int, uint8_t);
void r92c_rf_write(struct rtwn_softc *, int, uint8_t, uint32_t);
/* r92c_rom.c */
void r92c_efuse_postread(struct rtwn_softc *);
void r92c_parse_rom(struct rtwn_softc *, uint8_t *);
/* r92c_rx.c */
int8_t r92c_get_rssi_cck(struct rtwn_softc *, void *);
int8_t r92c_get_rssi_ofdm(struct rtwn_softc *, void *);
uint8_t r92c_rx_radiotap_flags(const void *);
/* r92c_tx.c */
void r92c_tx_enable_ampdu(void *, int);
void r92c_tx_setup_hwseq(void *);
void r92c_tx_setup_macid(void *, int);
void r92c_fill_tx_desc(struct rtwn_softc *, struct ieee80211_node *,
struct mbuf *, void *, uint8_t, int);
void r92c_fill_tx_desc_raw(struct rtwn_softc *, struct ieee80211_node *,
struct mbuf *, void *, const struct ieee80211_bpf_params *);
void r92c_fill_tx_desc_null(struct rtwn_softc *, void *, int, int, int);
uint8_t r92c_tx_radiotap_flags(const void *);
#endif /* RTL8192C_H */

View File

@ -0,0 +1,80 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/rtl8192c/r92c.h>
#include <dev/rtwn/rtl8192c/r92c_reg.h>
#include <dev/rtwn/rtl8192c/r92c_var.h>
void
r92c_detach_private(struct rtwn_softc *sc)
{
struct r92c_softc *rs = sc->sc_priv;
free(rs, M_RTWN_PRIV);
}
void
r92c_read_chipid_vendor(struct rtwn_softc *sc, uint32_t reg_sys_cfg)
{
struct r92c_softc *rs = sc->sc_priv;
if (reg_sys_cfg & R92C_SYS_CFG_TYPE_92C) {
rs->chip |= R92C_CHIP_92C;
/* Check if it is a castrated 8192C. */
if (MS(rtwn_read_4(sc, R92C_HPON_FSM),
R92C_HPON_FSM_CHIP_BONDING_ID) ==
R92C_HPON_FSM_CHIP_BONDING_ID_92C_1T2R)
rs->chip |= R92C_CHIP_92C_1T2R;
}
if (reg_sys_cfg & R92C_SYS_CFG_VENDOR_UMC) {
if (MS(reg_sys_cfg, R92C_SYS_CFG_CHIP_VER_RTL) == 0)
rs->chip |= R92C_CHIP_UMC_A_CUT;
}
}

View File

@ -0,0 +1,85 @@
/*-
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwn_ridx.h>
#include <dev/rtwn/rtl8192c/r92c.h>
#include <dev/rtwn/rtl8192c/r92c_var.h>
#include <dev/rtwn/rtl8192c/r92c_reg.h>
#include <dev/rtwn/rtl8192c/r92c_tx_desc.h>
void
r92c_beacon_init(struct rtwn_softc *sc, void *buf, int id)
{
struct r92c_tx_desc *txd = (struct r92c_tx_desc *)buf;
/*
* NB: there is no need to setup HWSEQ_EN bit;
* QSEL_BEACON already implies it.
*/
txd->flags0 |= R92C_FLAGS0_BMCAST | R92C_FLAGS0_FSG | R92C_FLAGS0_LSG;
txd->txdw1 |= htole32(
SM(R92C_TXDW1_QSEL, R92C_TXDW1_QSEL_BEACON) |
SM(R92C_TXDW1_RAID, R92C_RAID_11B));
rtwn_r92c_tx_setup_macid(sc, buf, id);
txd->txdw4 |= htole32(R92C_TXDW4_DRVRATE);
txd->txdw4 |= htole32(SM(R92C_TXDW4_SEQ_SEL, id));
txd->txdw5 |= htole32(SM(R92C_TXDW5_DATARATE, RTWN_RIDX_CCK1));
}
void
r92c_beacon_enable(struct rtwn_softc *sc, int id, int enable)
{
if (enable) {
rtwn_setbits_1(sc, R92C_BCN_CTRL(id),
0, R92C_BCN_CTRL_EN_BCN);
} else {
rtwn_setbits_1(sc, R92C_BCN_CTRL(id),
R92C_BCN_CTRL_EN_BCN, 0);
}
}

View File

@ -0,0 +1,113 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/rtl8192c/r92c.h>
#include <dev/rtwn/rtl8192c/r92c_reg.h>
void
r92c_iq_calib(struct rtwn_softc *sc)
{
/* XXX TODO */
}
void
r92c_lc_calib(struct rtwn_softc *sc)
{
uint32_t rf_ac[2];
uint8_t txmode;
int i;
txmode = rtwn_read_1(sc, R92C_OFDM1_LSTF + 3);
if ((txmode & 0x70) != 0) {
/* Disable all continuous Tx. */
rtwn_write_1(sc, R92C_OFDM1_LSTF + 3, txmode & ~0x70);
/* Set RF mode to standby mode. */
for (i = 0; i < sc->nrxchains; i++) {
rf_ac[i] = rtwn_rf_read(sc, i, R92C_RF_AC);
rtwn_rf_write(sc, i, R92C_RF_AC,
RW(rf_ac[i], R92C_RF_AC_MODE,
R92C_RF_AC_MODE_STANDBY));
}
} else {
/* Block all Tx queues. */
rtwn_write_1(sc, R92C_TXPAUSE, R92C_TX_QUEUE_ALL);
}
/* Start calibration. */
rtwn_rf_setbits(sc, 0, R92C_RF_CHNLBW, 0, R92C_RF_CHNLBW_LCSTART);
/* Give calibration the time to complete. */
rtwn_delay(sc, 100000); /* 100ms */
/* Restore configuration. */
if ((txmode & 0x70) != 0) {
/* Restore Tx mode. */
rtwn_write_1(sc, R92C_OFDM1_LSTF + 3, txmode);
/* Restore RF mode. */
for (i = 0; i < sc->nrxchains; i++)
rtwn_rf_write(sc, i, R92C_RF_AC, rf_ac[i]);
} else {
/* Unblock all Tx queues. */
rtwn_write_1(sc, R92C_TXPAUSE, 0x00);
}
}
void
r92c_temp_measure(struct rtwn_softc *sc)
{
rtwn_rf_write(sc, 0, R92C_RF_T_METER, R92C_RF_T_METER_START);
}
uint8_t
r92c_temp_read(struct rtwn_softc *sc)
{
return (MS(rtwn_rf_read(sc, 0, R92C_RF_T_METER),
R92C_RF_T_METER_VAL));
}

View File

@ -0,0 +1,351 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/if_rtwn_debug.h>
#include <dev/rtwn/if_rtwn_ridx.h>
#include <dev/rtwn/rtl8192c/r92c.h>
#include <dev/rtwn/rtl8192c/r92c_priv.h>
#include <dev/rtwn/rtl8192c/r92c_reg.h>
#include <dev/rtwn/rtl8192c/r92c_var.h>
static int
r92c_get_power_group(struct rtwn_softc *sc, struct ieee80211_channel *c)
{
uint8_t chan;
int group;
chan = rtwn_chan2centieee(c);
if (IEEE80211_IS_CHAN_2GHZ(c)) {
if (chan <= 3) group = 0;
else if (chan <= 9) group = 1;
else if (chan <= 14) group = 2;
else {
KASSERT(0, ("wrong 2GHz channel %d!\n", chan));
return (-1);
}
} else {
KASSERT(0, ("wrong channel band (flags %08X)\n", c->ic_flags));
return (-1);
}
return (group);
}
/* XXX recheck */
void
r92c_get_txpower(struct rtwn_softc *sc, int chain,
struct ieee80211_channel *c, uint16_t power[RTWN_RIDX_COUNT])
{
struct r92c_softc *rs = sc->sc_priv;
struct rtwn_r92c_txpwr *rt = rs->rs_txpwr;
const struct rtwn_r92c_txagc *base = rs->rs_txagc;
uint8_t ofdmpow, htpow, diff, max;
int max_mcs, ridx, group;
/* Determine channel group. */
group = r92c_get_power_group(sc, c);
if (group == -1) { /* shouldn't happen */
device_printf(sc->sc_dev, "%s: incorrect channel\n", __func__);
return;
}
/* XXX net80211 regulatory */
max_mcs = RTWN_RIDX_MCS(sc->ntxchains * 8 - 1);
KASSERT(max_mcs <= RTWN_RIDX_COUNT, ("increase ridx limit\n"));
memset(power, 0, max_mcs * sizeof(power[0]));
if (rs->regulatory == 0) {
for (ridx = RTWN_RIDX_CCK1; ridx <= RTWN_RIDX_CCK11; ridx++)
power[ridx] = base[chain].pwr[0][ridx];
}
for (ridx = RTWN_RIDX_OFDM6; ridx < RTWN_RIDX_COUNT; ridx++) {
if (rs->regulatory == 3) {
power[ridx] = base[chain].pwr[0][ridx];
/* Apply vendor limits. */
if (IEEE80211_IS_CHAN_HT40(c))
max = rt->ht40_max_pwr[chain][group];
else
max = rt->ht20_max_pwr[chain][group];
if (power[ridx] > max)
power[ridx] = max;
} else if (rs->regulatory == 1) {
if (!IEEE80211_IS_CHAN_HT40(c))
power[ridx] = base[chain].pwr[group][ridx];
} else if (rs->regulatory != 2)
power[ridx] = base[chain].pwr[0][ridx];
}
/* Compute per-CCK rate Tx power. */
for (ridx = RTWN_RIDX_CCK1; ridx <= RTWN_RIDX_CCK11; ridx++)
power[ridx] += rt->cck_tx_pwr[chain][group];
htpow = rt->ht40_1s_tx_pwr[chain][group];
if (sc->ntxchains > 1) {
/* Apply reduction for 2 spatial streams. */
diff = rt->ht40_2s_tx_pwr_diff[chain][group];
htpow = (htpow > diff) ? htpow - diff : 0;
}
/* Compute per-OFDM rate Tx power. */
diff = rt->ofdm_tx_pwr_diff[chain][group];
ofdmpow = htpow + diff; /* HT->OFDM correction. */
for (ridx = RTWN_RIDX_OFDM6; ridx <= RTWN_RIDX_OFDM54; ridx++)
power[ridx] += ofdmpow;
/* Compute per-MCS Tx power. */
if (!IEEE80211_IS_CHAN_HT40(c)) {
diff = rt->ht20_tx_pwr_diff[chain][group];
htpow += diff; /* HT40->HT20 correction. */
}
for (ridx = RTWN_RIDX_MCS(0); ridx <= max_mcs; ridx++)
power[ridx] += htpow;
/* Apply max limit. */
for (ridx = RTWN_RIDX_CCK1; ridx <= max_mcs; ridx++) {
if (power[ridx] > R92C_MAX_TX_PWR)
power[ridx] = R92C_MAX_TX_PWR;
}
}
static void
r92c_write_txpower(struct rtwn_softc *sc, int chain,
uint16_t power[RTWN_RIDX_COUNT])
{
uint32_t reg;
/* Write per-CCK rate Tx power. */
if (chain == 0) {
reg = rtwn_bb_read(sc, R92C_TXAGC_A_CCK1_MCS32);
reg = RW(reg, R92C_TXAGC_A_CCK1, power[RTWN_RIDX_CCK1]);
rtwn_bb_write(sc, R92C_TXAGC_A_CCK1_MCS32, reg);
reg = rtwn_bb_read(sc, R92C_TXAGC_B_CCK11_A_CCK2_11);
reg = RW(reg, R92C_TXAGC_A_CCK2, power[RTWN_RIDX_CCK2]);
reg = RW(reg, R92C_TXAGC_A_CCK55, power[RTWN_RIDX_CCK55]);
reg = RW(reg, R92C_TXAGC_A_CCK11, power[RTWN_RIDX_CCK11]);
rtwn_bb_write(sc, R92C_TXAGC_B_CCK11_A_CCK2_11, reg);
} else {
reg = rtwn_bb_read(sc, R92C_TXAGC_B_CCK1_55_MCS32);
reg = RW(reg, R92C_TXAGC_B_CCK1, power[RTWN_RIDX_CCK1]);
reg = RW(reg, R92C_TXAGC_B_CCK2, power[RTWN_RIDX_CCK2]);
reg = RW(reg, R92C_TXAGC_B_CCK55, power[RTWN_RIDX_CCK55]);
rtwn_bb_write(sc, R92C_TXAGC_B_CCK1_55_MCS32, reg);
reg = rtwn_bb_read(sc, R92C_TXAGC_B_CCK11_A_CCK2_11);
reg = RW(reg, R92C_TXAGC_B_CCK11, power[RTWN_RIDX_CCK11]);
rtwn_bb_write(sc, R92C_TXAGC_B_CCK11_A_CCK2_11, reg);
}
/* Write per-OFDM rate Tx power. */
rtwn_bb_write(sc, R92C_TXAGC_RATE18_06(chain),
SM(R92C_TXAGC_RATE06, power[RTWN_RIDX_OFDM6]) |
SM(R92C_TXAGC_RATE09, power[RTWN_RIDX_OFDM9]) |
SM(R92C_TXAGC_RATE12, power[RTWN_RIDX_OFDM12]) |
SM(R92C_TXAGC_RATE18, power[RTWN_RIDX_OFDM18]));
rtwn_bb_write(sc, R92C_TXAGC_RATE54_24(chain),
SM(R92C_TXAGC_RATE24, power[RTWN_RIDX_OFDM24]) |
SM(R92C_TXAGC_RATE36, power[RTWN_RIDX_OFDM36]) |
SM(R92C_TXAGC_RATE48, power[RTWN_RIDX_OFDM48]) |
SM(R92C_TXAGC_RATE54, power[RTWN_RIDX_OFDM54]));
/* Write per-MCS Tx power. */
rtwn_bb_write(sc, R92C_TXAGC_MCS03_MCS00(chain),
SM(R92C_TXAGC_MCS00, power[RTWN_RIDX_MCS(0)]) |
SM(R92C_TXAGC_MCS01, power[RTWN_RIDX_MCS(1)]) |
SM(R92C_TXAGC_MCS02, power[RTWN_RIDX_MCS(2)]) |
SM(R92C_TXAGC_MCS03, power[RTWN_RIDX_MCS(3)]));
rtwn_bb_write(sc, R92C_TXAGC_MCS07_MCS04(chain),
SM(R92C_TXAGC_MCS04, power[RTWN_RIDX_MCS(4)]) |
SM(R92C_TXAGC_MCS05, power[RTWN_RIDX_MCS(5)]) |
SM(R92C_TXAGC_MCS06, power[RTWN_RIDX_MCS(6)]) |
SM(R92C_TXAGC_MCS07, power[RTWN_RIDX_MCS(7)]));
if (sc->ntxchains >= 2) {
rtwn_bb_write(sc, R92C_TXAGC_MCS11_MCS08(chain),
SM(R92C_TXAGC_MCS08, power[RTWN_RIDX_MCS(8)]) |
SM(R92C_TXAGC_MCS09, power[RTWN_RIDX_MCS(9)]) |
SM(R92C_TXAGC_MCS10, power[RTWN_RIDX_MCS(10)]) |
SM(R92C_TXAGC_MCS11, power[RTWN_RIDX_MCS(11)]));
rtwn_bb_write(sc, R92C_TXAGC_MCS15_MCS12(chain),
SM(R92C_TXAGC_MCS12, power[RTWN_RIDX_MCS(12)]) |
SM(R92C_TXAGC_MCS13, power[RTWN_RIDX_MCS(13)]) |
SM(R92C_TXAGC_MCS14, power[RTWN_RIDX_MCS(14)]) |
SM(R92C_TXAGC_MCS15, power[RTWN_RIDX_MCS(15)]));
}
}
static void
r92c_set_txpower(struct rtwn_softc *sc, struct ieee80211_channel *c)
{
uint16_t power[RTWN_RIDX_COUNT];
int i;
for (i = 0; i < sc->ntxchains; i++) {
/* Compute per-rate Tx power values. */
rtwn_r92c_get_txpower(sc, i, c, power);
#ifdef RTWN_DEBUG
if (sc->sc_debug & RTWN_DEBUG_TXPWR) {
int ridx;
/* Dump per-rate Tx power values. */
printf("Tx power for chain %d:\n", i);
for (ridx = RTWN_RIDX_CCK1;
ridx < RTWN_RIDX_COUNT;
ridx++)
printf("Rate %d = %u\n", ridx, power[ridx]);
}
#endif
/* Write per-rate Tx power values to hardware. */
r92c_write_txpower(sc, i, power);
}
}
static void
r92c_set_bw40(struct rtwn_softc *sc, uint8_t chan, int prichlo)
{
struct r92c_softc *rs = sc->sc_priv;
rtwn_setbits_1(sc, R92C_BWOPMODE, R92C_BWOPMODE_20MHZ, 0);
rtwn_setbits_1(sc, R92C_RRSR + 2, 0x6f, (prichlo ? 1 : 2) << 5);
rtwn_bb_setbits(sc, R92C_FPGA0_RFMOD, 0, R92C_RFMOD_40MHZ);
rtwn_bb_setbits(sc, R92C_FPGA1_RFMOD, 0, R92C_RFMOD_40MHZ);
/* Set CCK side band. */
rtwn_bb_setbits(sc, R92C_CCK0_SYSTEM, 0x10,
(prichlo ? 0 : 1) << 4);
rtwn_bb_setbits(sc, R92C_OFDM1_LSTF, 0x0c00,
(prichlo ? 1 : 2) << 10);
rtwn_bb_setbits(sc, R92C_FPGA0_ANAPARAM2,
R92C_FPGA0_ANAPARAM2_CBW20, 0);
rtwn_bb_setbits(sc, 0x818, 0x0c000000, (prichlo ? 2 : 1) << 26);
/* Select 40MHz bandwidth. */
rtwn_rf_write(sc, 0, R92C_RF_CHNLBW,
(rs->rf_chnlbw[0] & ~0xfff) | chan);
}
void
r92c_set_bw20(struct rtwn_softc *sc, uint8_t chan)
{
struct r92c_softc *rs = sc->sc_priv;
rtwn_setbits_1(sc, R92C_BWOPMODE, 0, R92C_BWOPMODE_20MHZ);
rtwn_bb_setbits(sc, R92C_FPGA0_RFMOD, R92C_RFMOD_40MHZ, 0);
rtwn_bb_setbits(sc, R92C_FPGA1_RFMOD, R92C_RFMOD_40MHZ, 0);
rtwn_bb_setbits(sc, R92C_FPGA0_ANAPARAM2, 0,
R92C_FPGA0_ANAPARAM2_CBW20);
/* Select 20MHz bandwidth. */
rtwn_rf_write(sc, 0, R92C_RF_CHNLBW,
(rs->rf_chnlbw[0] & ~0xfff) | chan | R92C_RF_CHNLBW_BW20);
}
void
r92c_set_chan(struct rtwn_softc *sc, struct ieee80211_channel *c)
{
struct r92c_softc *rs = sc->sc_priv;
u_int chan;
int i;
chan = rtwn_chan2centieee(c);
/* Set Tx power for this new channel. */
r92c_set_txpower(sc, c);
for (i = 0; i < sc->nrxchains; i++) {
rtwn_rf_write(sc, i, R92C_RF_CHNLBW,
RW(rs->rf_chnlbw[i], R92C_RF_CHNLBW_CHNL, chan));
}
if (IEEE80211_IS_CHAN_HT40(c))
r92c_set_bw40(sc, chan, IEEE80211_IS_CHAN_HT40U(c));
else
rtwn_r92c_set_bw20(sc, chan);
}
void
r92c_set_gain(struct rtwn_softc *sc, uint8_t gain)
{
rtwn_bb_setbits(sc, R92C_OFDM0_AGCCORE1(0),
R92C_OFDM0_AGCCORE1_GAIN_M, gain);
rtwn_bb_setbits(sc, R92C_OFDM0_AGCCORE1(1),
R92C_OFDM0_AGCCORE1_GAIN_M, gain);
}
void
r92c_scan_start(struct ieee80211com *ic)
{
struct rtwn_softc *sc = ic->ic_softc;
struct r92c_softc *rs = sc->sc_priv;
RTWN_LOCK(sc);
/* Set gain for scanning. */
rtwn_r92c_set_gain(sc, 0x20);
RTWN_UNLOCK(sc);
rs->rs_scan_start(ic);
}
void
r92c_scan_end(struct ieee80211com *ic)
{
struct rtwn_softc *sc = ic->ic_softc;
struct r92c_softc *rs = sc->sc_priv;
RTWN_LOCK(sc);
/* Set gain under link. */
rtwn_r92c_set_gain(sc, 0x32);
RTWN_UNLOCK(sc);
rs->rs_scan_end(ic);
}

View File

@ -0,0 +1,520 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <net80211/ieee80211_ratectl.h>
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/if_rtwn_debug.h>
#include <dev/rtwn/if_rtwn_ridx.h>
#include <dev/rtwn/if_rtwn_rx.h>
#include <dev/rtwn/if_rtwn_task.h>
#include <dev/rtwn/if_rtwn_tx.h>
#include <dev/rtwn/rtl8192c/r92c.h>
#include <dev/rtwn/rtl8192c/r92c_reg.h>
#include <dev/rtwn/rtl8192c/r92c_var.h>
#include <dev/rtwn/rtl8192c/r92c_fw_cmd.h>
#include <dev/rtwn/rtl8192c/r92c_tx_desc.h>
#ifndef RTWN_WITHOUT_UCODE
static int
r92c_fw_cmd(struct rtwn_softc *sc, uint8_t id, const void *buf, int len)
{
struct r92c_fw_cmd cmd;
int ntries, error;
KASSERT(len <= sizeof(cmd.msg),
("%s: firmware command too long (%d > %zu)\n",
__func__, len, sizeof(cmd.msg)));
if (!(sc->sc_flags & RTWN_FW_LOADED)) {
RTWN_DPRINTF(sc, RTWN_DEBUG_FIRMWARE, "%s: firmware "
"was not loaded; command (id %u) will be discarded\n",
__func__, id);
return (0);
}
/* Wait for current FW box to be empty. */
for (ntries = 0; ntries < 50; ntries++) {
if (!(rtwn_read_1(sc, R92C_HMETFR) & (1 << sc->fwcur)))
break;
rtwn_delay(sc, 2000);
}
if (ntries == 100) {
device_printf(sc->sc_dev,
"could not send firmware command\n");
return (ETIMEDOUT);
}
memset(&cmd, 0, sizeof(cmd));
cmd.id = id;
if (len > 3) {
/* Ext command: [id : byte2 : byte3 : byte4 : byte0 : byte1] */
cmd.id |= R92C_CMD_FLAG_EXT;
memcpy(cmd.msg, (const uint8_t *)buf + 2, len - 2);
memcpy(cmd.msg + 3, buf, 2);
} else
memcpy(cmd.msg, buf, len);
/* Write the first word last since that will trigger the FW. */
if (len > 3) {
error = rtwn_write_2(sc, R92C_HMEBOX_EXT(sc->fwcur),
*(uint16_t *)((uint8_t *)&cmd + 4));
if (error != 0)
return (error);
}
error = rtwn_write_4(sc, R92C_HMEBOX(sc->fwcur),
*(uint32_t *)&cmd);
if (error != 0)
return (error);
sc->fwcur = (sc->fwcur + 1) % R92C_H2C_NBOX;
return (0);
}
void
r92c_fw_reset(struct rtwn_softc *sc, int reason)
{
int ntries;
if (reason == RTWN_FW_RESET_CHECKSUM)
return;
/* Tell 8051 to reset itself. */
rtwn_write_1(sc, R92C_HMETFR + 3, 0x20);
/* Wait until 8051 resets by itself. */
for (ntries = 0; ntries < 100; ntries++) {
if ((rtwn_read_2(sc, R92C_SYS_FUNC_EN) &
R92C_SYS_FUNC_EN_CPUEN) == 0)
return;
rtwn_delay(sc, 50);
}
/* Force 8051 reset. */
rtwn_setbits_1_shift(sc, R92C_SYS_FUNC_EN,
R92C_SYS_FUNC_EN_CPUEN, 0, 1);
}
void
r92c_fw_download_enable(struct rtwn_softc *sc, int enable)
{
if (enable) {
/* 8051 enable. */
rtwn_setbits_1_shift(sc, R92C_SYS_FUNC_EN, 0,
R92C_SYS_FUNC_EN_CPUEN, 1);
/* MCU firmware download enable. */
rtwn_setbits_1(sc, R92C_MCUFWDL, 0, R92C_MCUFWDL_EN);
/* 8051 reset. */
rtwn_setbits_1_shift(sc, R92C_MCUFWDL, R92C_MCUFWDL_ROM_DLEN,
0, 2);
} else {
/* MCU download disable. */
rtwn_setbits_1(sc, R92C_MCUFWDL, R92C_MCUFWDL_EN, 0);
/* Reserved for f/w extension. */
rtwn_write_1(sc, R92C_MCUFWDL + 1, 0);
}
}
#endif
/*
* Initialize firmware rate adaptation.
*/
#ifndef RTWN_WITHOUT_UCODE
static int
r92c_send_ra_cmd(struct rtwn_softc *sc, int macid, uint32_t rates,
int maxrate)
{
struct r92c_fw_cmd_macid_cfg cmd;
uint8_t mode;
int error = 0;
/* XXX should be called directly from iv_newstate() for MACID_BC */
/* XXX joinbss, not send_ra_cmd() */
#ifdef RTWN_TODO
/* NB: group addressed frames are done at 11bg rates for now */
if (ic->ic_curmode == IEEE80211_MODE_11B)
mode = R92C_RAID_11B;
else
mode = R92C_RAID_11BG;
/* XXX misleading 'mode' value here for unicast frames */
RTWN_DPRINTF(sc, RTWN_DEBUG_RA,
"%s: mode 0x%x, rates 0x%08x, basicrates 0x%08x\n", __func__,
mode, rates, basicrates);
/* Set rates mask for group addressed frames. */
cmd.macid = RTWN_MACID_BC | R92C_CMD_MACID_VALID;
cmd.mask = htole32(mode << 28 | basicrates);
error = rtwn_fw_cmd(sc, R92C_CMD_MACID_CONFIG, &cmd, sizeof(cmd));
if (error != 0) {
device_printf(sc->sc_dev,
"could not set RA mask for broadcast station\n");
return (error);
}
#endif
/* Set rates mask for unicast frames. */
if (maxrate >= RTWN_RIDX_MCS(0))
mode = R92C_RAID_11GN;
else if (maxrate >= RTWN_RIDX_OFDM6)
mode = R92C_RAID_11BG;
else
mode = R92C_RAID_11B;
cmd.macid = macid | R92C_CMD_MACID_VALID;
cmd.mask = htole32(mode << 28 | rates);
error = r92c_fw_cmd(sc, R92C_CMD_MACID_CONFIG, &cmd, sizeof(cmd));
if (error != 0) {
device_printf(sc->sc_dev,
"%s: could not set RA mask for %d station\n",
__func__, macid);
return (error);
}
return (0);
}
#endif
static void
r92c_init_ra(struct rtwn_softc *sc, int macid)
{
struct ieee80211_htrateset *rs_ht;
struct ieee80211_node *ni;
uint32_t rates;
int maxrate;
RTWN_NT_LOCK(sc);
if (sc->node_list[macid] == NULL) {
RTWN_DPRINTF(sc, RTWN_DEBUG_RA, "%s: macid %d, ni is NULL\n",
__func__, macid);
RTWN_NT_UNLOCK(sc);
return;
}
ni = ieee80211_ref_node(sc->node_list[macid]);
if (ni->ni_flags & IEEE80211_NODE_HT)
rs_ht = &ni->ni_htrates;
else
rs_ht = NULL;
/* XXX MACID_BC */
rtwn_get_rates(sc, &ni->ni_rates, rs_ht, &rates, &maxrate, 0);
RTWN_NT_UNLOCK(sc);
#ifndef RTWN_WITHOUT_UCODE
if (sc->sc_ratectl == RTWN_RATECTL_FW) {
r92c_send_ra_cmd(sc, macid, rates, maxrate);
}
#endif
rtwn_write_1(sc, R92C_INIDATA_RATE_SEL(macid), maxrate);
ieee80211_free_node(ni);
}
void
r92c_joinbss_rpt(struct rtwn_softc *sc, int macid)
{
#ifndef RTWN_WITHOUT_UCODE
struct r92c_softc *rs = sc->sc_priv;
struct ieee80211vap *vap;
struct r92c_fw_cmd_joinbss_rpt cmd;
if (sc->vaps[0] == NULL) /* XXX fix */
goto end;
vap = &sc->vaps[0]->vap;
if ((vap->iv_state == IEEE80211_S_RUN) ^
!(rs->rs_flags & R92C_FLAG_ASSOCIATED))
goto end;
if (rs->rs_flags & R92C_FLAG_ASSOCIATED) {
cmd.mstatus = R92C_MSTATUS_DISASSOC;
rs->rs_flags &= ~R92C_FLAG_ASSOCIATED;
} else {
cmd.mstatus = R92C_MSTATUS_ASSOC;
rs->rs_flags |= R92C_FLAG_ASSOCIATED;
}
if (r92c_fw_cmd(sc, R92C_CMD_JOINBSS_RPT, &cmd, sizeof(cmd)) != 0) {
device_printf(sc->sc_dev, "%s: cannot change media status!\n",
__func__);
}
end:
#endif
/* TODO: init rates for RTWN_MACID_BC. */
if (macid & RTWN_MACID_VALID)
r92c_init_ra(sc, macid & ~RTWN_MACID_VALID);
}
#ifndef RTWN_WITHOUT_UCODE
int
r92c_set_rsvd_page(struct rtwn_softc *sc, int probe_resp, int null,
int qos_null)
{
struct r92c_fw_cmd_rsvdpage rsvd;
rsvd.probe_resp = probe_resp;
rsvd.ps_poll = 0;
rsvd.null_data = null;
return (r92c_fw_cmd(sc, R92C_CMD_RSVD_PAGE, &rsvd, sizeof(rsvd)));
}
int
r92c_set_pwrmode(struct rtwn_softc *sc, struct ieee80211vap *vap,
int off)
{
struct r92c_fw_cmd_pwrmode mode;
int error;
/* XXX dm_RF_saving */
if (off && vap->iv_state == IEEE80211_S_RUN &&
(vap->iv_flags & IEEE80211_F_PMGTON))
mode.mode = R92C_PWRMODE_MIN;
else
mode.mode = R92C_PWRMODE_CAM;
mode.smart_ps = R92C_PWRMODE_SMARTPS_NULLDATA;
mode.bcn_pass = 1; /* XXX */
error = r92c_fw_cmd(sc, R92C_CMD_SET_PWRMODE, &mode, sizeof(mode));
if (error != 0) {
device_printf(sc->sc_dev,
"%s: CMD_SET_PWRMODE was not sent, error %d\n",
__func__, error);
}
return (error);
}
void
r92c_set_rssi(struct rtwn_softc *sc)
{
struct ieee80211_node *ni;
struct rtwn_node *rn;
struct r92c_fw_cmd_rssi cmd;
int i;
cmd.reserved = 0;
RTWN_NT_LOCK(sc);
for (i = 0; i < sc->macid_limit; i++) {
/* XXX optimize? */
ni = sc->node_list[i];
if (ni == NULL)
continue;
rn = RTWN_NODE(ni);
cmd.macid = i;
cmd.pwdb = rn->avg_pwdb;
RTWN_DPRINTF(sc, RTWN_DEBUG_RSSI,
"%s: sending RSSI command (macid %d, rssi %d)\n",
__func__, i, rn->avg_pwdb);
RTWN_NT_UNLOCK(sc);
r92c_fw_cmd(sc, R92C_CMD_RSSI_SETTING, &cmd, sizeof(cmd));
RTWN_NT_LOCK(sc);
}
RTWN_NT_UNLOCK(sc);
}
static void
r92c_ratectl_tx_complete(struct rtwn_softc *sc, uint8_t *buf, int len)
{
#if __FreeBSD_version >= 1200012
struct ieee80211_ratectl_tx_status txs;
#endif
struct r92c_c2h_tx_rpt *rpt;
struct ieee80211_node *ni;
uint8_t macid;
int ntries;
if (sc->sc_ratectl != RTWN_RATECTL_NET80211) {
/* shouldn't happen */
device_printf(sc->sc_dev, "%s called while ratectl = %d!\n",
__func__, sc->sc_ratectl);
return;
}
rpt = (struct r92c_c2h_tx_rpt *)buf;
if (len != sizeof(*rpt)) {
device_printf(sc->sc_dev,
"%s: wrong report size (%d, must be %zu)\n",
__func__, len, sizeof(*rpt));
return;
}
RTWN_DPRINTF(sc, RTWN_DEBUG_INTR,
"%s: ccx report dump: 0: %02X, 1: %02X, queue time: "
"low %02X, high %02X, 4: %02X, 5: %02X, 6: %02X, 7: %02X\n",
__func__, rpt->rptb0, rpt->rptb1, rpt->queue_time_low,
rpt->queue_time_high, rpt->rptb4, rpt->rptb5, rpt->rptb6,
rpt->rptb7);
macid = MS(rpt->rptb5, R92C_RPTB5_MACID);
if (macid > sc->macid_limit) {
device_printf(sc->sc_dev,
"macid %u is too big; increase MACID_MAX limit\n",
macid);
return;
}
ntries = MS(rpt->rptb0, R92C_RPTB0_RETRY_CNT);
RTWN_NT_LOCK(sc);
ni = sc->node_list[macid];
if (ni != NULL) {
RTWN_DPRINTF(sc, RTWN_DEBUG_INTR, "%s: frame for macid %u was"
"%s sent (%d retries)\n", __func__, macid,
(rpt->rptb7 & R92C_RPTB7_PKT_OK) ? "" : " not",
ntries);
#if __FreeBSD_version >= 1200012
txs.flags = IEEE80211_RATECTL_STATUS_LONG_RETRY;
txs.long_retries = ntries;
if (rpt->rptb7 & R92C_RPTB7_PKT_OK)
txs.status = IEEE80211_RATECTL_TX_SUCCESS;
else if (rpt->rptb6 & R92C_RPTB6_RETRY_OVER)
txs.status = IEEE80211_RATECTL_TX_FAIL_LONG; /* XXX */
else if (rpt->rptb6 & R92C_RPTB6_LIFE_EXPIRE)
txs.status = IEEE80211_RATECTL_TX_FAIL_EXPIRED;
else
txs.status = IEEE80211_RATECTL_TX_FAIL_UNSPECIFIED;
ieee80211_ratectl_tx_complete(ni, &txs);
#else
struct ieee80211vap *vap = ni->ni_vap;
if (rpt->rptb7 & R92C_RPTB7_PKT_OK) {
ieee80211_ratectl_tx_complete(vap, ni,
IEEE80211_RATECTL_TX_SUCCESS, &ntries, NULL);
} else {
ieee80211_ratectl_tx_complete(vap, ni,
IEEE80211_RATECTL_TX_FAILURE, &ntries, NULL);
}
#endif
} else {
RTWN_DPRINTF(sc, RTWN_DEBUG_INTR, "%s: macid %u, ni is NULL\n",
__func__, macid);
}
RTWN_NT_UNLOCK(sc);
#ifdef IEEE80211_SUPPORT_SUPERG
if (sc->sc_tx_n_active > 0 && --sc->sc_tx_n_active <= 1)
rtwn_cmd_sleepable(sc, NULL, 0, rtwn_ff_flush_all);
#endif
}
static void
r92c_handle_c2h_task(struct rtwn_softc *sc, union sec_param *data)
{
const uint16_t off = R92C_C2H_EVT_MSG + sizeof(struct r92c_c2h_evt);
struct r92c_softc *rs = sc->sc_priv;
uint16_t buf[R92C_C2H_MSG_MAX_LEN / 2 + 1];
uint8_t id, len, status;
int i;
/* Do not reschedule the task if device is not running. */
if (!(sc->sc_flags & RTWN_RUNNING))
return;
/* Read current status. */
status = rtwn_read_1(sc, R92C_C2H_EVT_CLEAR);
if (status == R92C_C2H_EVT_HOST_CLOSE)
goto end; /* nothing to do */
else if (status == R92C_C2H_EVT_FW_CLOSE) {
len = rtwn_read_1(sc, R92C_C2H_EVT_MSG);
id = MS(len, R92C_C2H_EVTB0_ID);
len = MS(len, R92C_C2H_EVTB0_LEN);
memset(buf, 0, sizeof(buf));
/* Try to optimize event reads. */
for (i = 0; i < len; i += 2)
buf[i / 2] = rtwn_read_2(sc, off + i);
KASSERT(i < sizeof(buf), ("%s: buffer overrun (%d >= %zu)!",
__func__, i, sizeof(buf)));
switch (id) {
case R92C_C2H_EVT_TX_REPORT:
r92c_ratectl_tx_complete(sc, (uint8_t *)buf, len);
break;
default:
device_printf(sc->sc_dev,
"%s: C2H report %u (len %u) was not handled\n",
__func__, id, len);
break;
}
}
/* Prepare for next event. */
rtwn_write_1(sc, R92C_C2H_EVT_CLEAR, R92C_C2H_EVT_HOST_CLOSE);
end:
/* Adjust timeout for next call. */
if (rs->rs_c2h_pending != 0) {
rs->rs_c2h_pending = 0;
rs->rs_c2h_paused = 0;
} else
rs->rs_c2h_paused++;
if (rs->rs_c2h_paused > R92C_TX_PAUSED_THRESHOLD)
rs->rs_c2h_timeout = hz;
else
rs->rs_c2h_timeout = MAX(hz / 100, 1);
/* Reschedule the task. */
callout_reset(&rs->rs_c2h_report, rs->rs_c2h_timeout,
r92c_handle_c2h_report, sc);
}
void
r92c_handle_c2h_report(void *arg)
{
struct rtwn_softc *sc = arg;
rtwn_cmd_sleepable(sc, NULL, 0, r92c_handle_c2h_task);
}
#endif /* RTWN_WITHOUT_UCODE */

View File

@ -0,0 +1,148 @@
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $
* $FreeBSD$
*/
#ifndef R92C_FW_CMD_H
#define R92C_FW_CMD_H
/*
* Host to firmware commands.
*/
struct r92c_fw_cmd {
uint8_t id;
#define R92C_CMD_SET_PWRMODE 1
#define R92C_CMD_JOINBSS_RPT 2
#define R92C_CMD_RSVD_PAGE 3
#define R92C_CMD_RSSI_SETTING 5
#define R92C_CMD_MACID_CONFIG 6
#define R92C_CMD_FLAG_EXT 0x80
uint8_t msg[5];
} __packed __attribute__((aligned(4)));
/* Structure for R92C_CMD_JOINBSS_RPT. */
struct r92c_fw_cmd_joinbss_rpt {
uint8_t mstatus;
#define R92C_MSTATUS_DISASSOC 0x00
#define R92C_MSTATUS_ASSOC 0x01
} __packed;
/* Structure for R92C_CMD_SET_PWRMODE. */
struct r92c_fw_cmd_pwrmode {
uint8_t mode;
#define R92C_PWRMODE_CAM 0
#define R92C_PWRMODE_MIN 1
#define R92C_PWRMODE_MAX 2
#define R92C_PWRMODE_DTIM 3
#define R92C_PWRMODE_UAPSD_WMM 5
#define R92C_PWRMODE_UAPSD 6
#define R92C_PWRMODE_IBSS 7
uint8_t smart_ps;
/* XXX undocumented */
#define R92C_PWRMODE_SMARTPS_NULLDATA 2
uint8_t bcn_pass; /* unit: beacon interval */
} __packed;
/* Structure for R92C_CMD_RSVD_PAGE. */
struct r92c_fw_cmd_rsvdpage {
uint8_t probe_resp;
uint8_t ps_poll;
uint8_t null_data;
} __packed;
/* Structure for R92C_CMD_RSSI_SETTING. */
struct r92c_fw_cmd_rssi {
uint8_t macid;
uint8_t reserved;
uint8_t pwdb;
} __packed;
/* Structure for R92C_CMD_MACID_CONFIG. */
struct r92c_fw_cmd_macid_cfg {
uint32_t mask;
uint8_t macid;
#define R92C_CMD_MACID_VALID 0x80
} __packed;
/*
* C2H event structure.
*/
/* Bigger value is used to prevent buffer overrun. */
#define R92C_C2H_MSG_MAX_LEN 16
struct r92c_c2h_evt {
uint8_t evtb0;
#define R92C_C2H_EVTB0_ID_M 0x0f
#define R92C_C2H_EVTB0_ID_S 0
#define R92C_C2H_EVTB0_LEN_M 0xf0
#define R92C_C2H_EVTB0_LEN_S 4
uint8_t seq;
/* Followed by payload (see below). */
} __packed;
/*
* C2H event types.
*/
#define R92C_C2H_EVT_DEBUG 0
#define R92C_C2H_EVT_TX_REPORT 3
#define R92C_C2H_EVT_EXT_RA_RPT 6
/* Structure for R92C_C2H_EVT_TX_REPORT event. */
struct r92c_c2h_tx_rpt {
uint8_t rptb0;
#define R92C_RPTB0_RETRY_CNT_M 0x3f
#define R92C_RPTB0_RETRY_CNT_S 0
uint8_t rptb1; /* XXX junk */
#define R92C_RPTB1_RTS_RETRY_CNT_M 0x3f
#define R92C_RPTB1_RTS_RETRY_CNT_S 0
uint8_t queue_time_low;
uint8_t queue_time_high;
uint8_t rptb4;
#define R92C_RPTB4_MISSED_PKT_NUM_M 0x1f
#define R92C_RPTB4_MISSED_PKT_NUM_S 0
uint8_t rptb5;
#define R92C_RPTB5_MACID_M 0x1f
#define R92C_RPTB5_MACID_S 0
#define R92C_RPTB5_DES1_FRAGSSN_M 0xe0
#define R92C_RPTB5_DES1_FRAGSSN_S 5
uint8_t rptb6;
#define R92C_RPTB6_RPT_PKT_NUM_M 0x1f
#define R92C_RPTB6_RPT_PKT_NUM_S 0
#define R92C_RPTB6_PKT_DROP 0x20
#define R92C_RPTB6_LIFE_EXPIRE 0x40
#define R92C_RPTB6_RETRY_OVER 0x80
uint8_t rptb7;
#define R92C_RPTB7_EDCA_M 0x0f
#define R92C_RPTB7_EDCA_S 0
#define R92C_RPTB7_BMC 0x20
#define R92C_RPTB7_PKT_OK 0x40
#define R92C_RPTB7_INT_CCX 0x80
} __packed;
#endif /* R92C_FW_CMD_H */

View File

@ -0,0 +1,322 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/if_rtwn_debug.h>
#include <dev/rtwn/rtl8192c/r92c.h>
#include <dev/rtwn/rtl8192c/r92c_priv.h>
#include <dev/rtwn/rtl8192c/r92c_reg.h>
#include <dev/rtwn/rtl8192c/r92c_var.h>
int
r92c_check_condition(struct rtwn_softc *sc, const uint8_t cond[])
{
struct r92c_softc *rs = sc->sc_priv;
uint8_t mask;
int i;
if (cond[0] == 0)
return (1);
RTWN_DPRINTF(sc, RTWN_DEBUG_RESET,
"%s: condition byte 0: %02X; chip %02X, board %02X\n",
__func__, cond[0], rs->chip, rs->board_type);
if (!(rs->chip & R92C_CHIP_92C)) {
if (rs->board_type == R92C_BOARD_TYPE_HIGHPA)
mask = R92C_COND_RTL8188RU;
else if (rs->board_type == R92C_BOARD_TYPE_MINICARD)
mask = R92C_COND_RTL8188CE;
else
mask = R92C_COND_RTL8188CU;
} else {
if (rs->board_type == R92C_BOARD_TYPE_MINICARD)
mask = R92C_COND_RTL8192CE;
else
mask = R92C_COND_RTL8192CU;
}
for (i = 0; i < RTWN_MAX_CONDITIONS && cond[i] != 0; i++)
if ((cond[i] & mask) == mask)
return (1);
return (0);
}
int
r92c_set_page_size(struct rtwn_softc *sc)
{
return (rtwn_write_1(sc, R92C_PBP, SM(R92C_PBP_PSRX, R92C_PBP_128) |
SM(R92C_PBP_PSTX, R92C_PBP_128)) == 0);
}
void
r92c_init_bb_common(struct rtwn_softc *sc)
{
struct r92c_softc *rs = sc->sc_priv;
int i, j;
/* Write BB initialization values. */
for (i = 0; i < sc->bb_size; i++) {
const struct rtwn_bb_prog *bb_prog = &sc->bb_prog[i];
while (!rtwn_check_condition(sc, bb_prog->cond)) {
KASSERT(bb_prog->next != NULL,
("%s: wrong condition value (i %d)\n",
__func__, i));
bb_prog = bb_prog->next;
}
for (j = 0; j < bb_prog->count; j++) {
RTWN_DPRINTF(sc, RTWN_DEBUG_RESET,
"BB: reg 0x%03x, val 0x%08x\n",
bb_prog->reg[j], bb_prog->val[j]);
rtwn_bb_write(sc, bb_prog->reg[j], bb_prog->val[j]);
rtwn_delay(sc, 1);
}
}
if (rs->chip & R92C_CHIP_92C_1T2R) {
/* 8192C 1T only configuration. */
rtwn_bb_setbits(sc, R92C_FPGA0_TXINFO, 0x03, 0x02);
rtwn_bb_setbits(sc, R92C_FPGA1_TXINFO, 0x300033, 0x200022);
rtwn_bb_setbits(sc, R92C_CCK0_AFESETTING, 0xff000000,
0x45000000);
rtwn_bb_setbits(sc, R92C_OFDM0_TRXPATHENA, 0xff, 0x23);
rtwn_bb_setbits(sc, R92C_OFDM0_AGCPARAM1, 0x30, 0x10);
rtwn_bb_setbits(sc, 0xe74, 0x0c000000, 0x08000000);
rtwn_bb_setbits(sc, 0xe78, 0x0c000000, 0x08000000);
rtwn_bb_setbits(sc, 0xe7c, 0x0c000000, 0x08000000);
rtwn_bb_setbits(sc, 0xe80, 0x0c000000, 0x08000000);
rtwn_bb_setbits(sc, 0xe88, 0x0c000000, 0x08000000);
}
/* Write AGC values. */
for (i = 0; i < sc->agc_size; i++) {
const struct rtwn_agc_prog *agc_prog = &sc->agc_prog[i];
while (!rtwn_check_condition(sc, agc_prog->cond)) {
KASSERT(agc_prog->next != NULL,
("%s: wrong condition value (2) (i %d)\n",
__func__, i));
agc_prog = agc_prog->next;
}
for (j = 0; j < agc_prog->count; j++) {
RTWN_DPRINTF(sc, RTWN_DEBUG_RESET,
"AGC: val 0x%08x\n", agc_prog->val[j]);
rtwn_bb_write(sc, R92C_OFDM0_AGCRSSITABLE,
agc_prog->val[j]);
rtwn_delay(sc, 1);
}
}
}
int
r92c_init_rf_chain(struct rtwn_softc *sc,
const struct rtwn_rf_prog *rf_prog, int chain)
{
int i, j;
RTWN_DPRINTF(sc, RTWN_DEBUG_RESET, "%s: chain %d\n",
__func__, chain);
for (i = 0; rf_prog[i].reg != NULL; i++) {
const struct rtwn_rf_prog *prog = &rf_prog[i];
while (!rtwn_check_condition(sc, prog->cond)) {
KASSERT(prog->next != NULL,
("%s: wrong condition value (i %d)\n",
__func__, i));
prog = prog->next;
}
for (j = 0; j < prog->count; j++) {
RTWN_DPRINTF(sc, RTWN_DEBUG_RESET,
"RF: reg 0x%02x, val 0x%05x\n",
prog->reg[j], prog->val[j]);
/*
* These are fake RF registers offsets that
* indicate a delay is required.
*/
/* NB: we are using 'value' to store required delay. */
if (prog->reg[j] > 0xf8) {
rtwn_delay(sc, prog->val[j]);
continue;
}
rtwn_rf_write(sc, chain, prog->reg[j], prog->val[j]);
rtwn_delay(sc, 1);
}
}
return (i);
}
void
r92c_init_rf_common(struct rtwn_softc *sc)
{
struct r92c_softc *rs = sc->sc_priv;
uint32_t reg, type;
int i, chain, idx, off;
for (chain = 0, i = 0; chain < sc->nrxchains; chain++, i++) {
/* Save RF_ENV control type. */
idx = chain / 2;
off = (chain % 2) * 16;
reg = rtwn_bb_read(sc, R92C_FPGA0_RFIFACESW(idx));
type = (reg >> off) & 0x10;
/* Set RF_ENV enable. */
rtwn_bb_setbits(sc, R92C_FPGA0_RFIFACEOE(chain),
0, 0x100000);
rtwn_delay(sc, 1);
/* Set RF_ENV output high. */
rtwn_bb_setbits(sc, R92C_FPGA0_RFIFACEOE(chain),
0, 0x10);
rtwn_delay(sc, 1);
/* Set address and data lengths of RF registers. */
rtwn_bb_setbits(sc, R92C_HSSI_PARAM2(chain),
R92C_HSSI_PARAM2_ADDR_LENGTH, 0);
rtwn_delay(sc, 1);
rtwn_bb_setbits(sc, R92C_HSSI_PARAM2(chain),
R92C_HSSI_PARAM2_DATA_LENGTH, 0);
rtwn_delay(sc, 1);
/* Write RF initialization values for this chain. */
i += r92c_init_rf_chain(sc, &sc->rf_prog[i], chain);
/* Restore RF_ENV control type. */
rtwn_bb_setbits(sc, R92C_FPGA0_RFIFACESW(idx),
0x10 << off, type << off);
/* Cache RF register CHNLBW. */
rs->rf_chnlbw[chain] = rtwn_rf_read(sc, chain,
R92C_RF_CHNLBW);
}
}
void
r92c_init_rf(struct rtwn_softc *sc)
{
struct r92c_softc *rs = sc->sc_priv;
r92c_init_rf_common(sc);
if ((rs->chip & (R92C_CHIP_UMC_A_CUT | R92C_CHIP_92C)) ==
R92C_CHIP_UMC_A_CUT) {
rtwn_rf_write(sc, 0, R92C_RF_RX_G1, 0x30255);
rtwn_rf_write(sc, 0, R92C_RF_RX_G2, 0x50a00);
}
/* Turn CCK and OFDM blocks on. */
rtwn_bb_setbits(sc, R92C_FPGA0_RFMOD, 0, R92C_RFMOD_CCK_EN);
rtwn_bb_setbits(sc, R92C_FPGA0_RFMOD, 0, R92C_RFMOD_OFDM_EN);
}
void
r92c_init_edca(struct rtwn_softc *sc)
{
/* SIFS */
rtwn_write_2(sc, R92C_SPEC_SIFS, 0x100a);
rtwn_write_2(sc, R92C_MAC_SPEC_SIFS, 0x100a);
rtwn_write_2(sc, R92C_SIFS_CCK, 0x100a);
rtwn_write_2(sc, R92C_SIFS_OFDM, 0x100a);
/* TXOP */
rtwn_write_4(sc, R92C_EDCA_BE_PARAM, 0x005ea42b);
rtwn_write_4(sc, R92C_EDCA_BK_PARAM, 0x0000a44f);
rtwn_write_4(sc, R92C_EDCA_VI_PARAM, 0x005ea324);
rtwn_write_4(sc, R92C_EDCA_VO_PARAM, 0x002fa226);
}
void
r92c_init_ampdu(struct rtwn_softc *sc)
{
/* Setup AMPDU aggregation. */
rtwn_write_4(sc, R92C_AGGLEN_LMT, 0x99997631); /* MCS7~0 */
rtwn_write_1(sc, R92C_AGGR_BREAK_TIME, 0x16);
rtwn_write_2(sc, R92C_MAX_AGGR_NUM, 0x0708);
}
void
r92c_init_antsel(struct rtwn_softc *sc)
{
uint32_t reg;
if (sc->ntxchains != 1 || sc->nrxchains != 1)
return;
rtwn_setbits_1(sc, R92C_LEDCFG2, 0, 0x80);
rtwn_bb_setbits(sc, R92C_FPGA0_RFPARAM(0), 0, 0x2000);
reg = rtwn_bb_read(sc, R92C_FPGA0_RFIFACEOE(0));
sc->sc_ant = MS(reg, R92C_FPGA0_RFIFACEOE0_ANT); /* XXX */
}
void
r92c_pa_bias_init(struct rtwn_softc *sc)
{
struct r92c_softc *rs = sc->sc_priv;
int i;
for (i = 0; i < sc->nrxchains; i++) {
if (rs->pa_setting & (1 << i))
continue;
r92c_rf_write(sc, i, R92C_RF_IPA, 0x0f406);
r92c_rf_write(sc, i, R92C_RF_IPA, 0x4f406);
r92c_rf_write(sc, i, R92C_RF_IPA, 0x8f406);
r92c_rf_write(sc, i, R92C_RF_IPA, 0xcf406);
}
if (!(rs->pa_setting & 0x10))
rtwn_setbits_1(sc, 0x16, 0xf0, 0x90);
}

Some files were not shown because too many files have changed in this diff Show More