Add support for the Realtek RTL8192EU chipset.

Committed over the D-Link DWA-131 rev E1 on amd64 with WPA.

Reviewed by:	avos
This commit is contained in:
Kevin Lo 2017-01-24 02:35:38 +00:00
parent 83988d944b
commit 60b9567d16
43 changed files with 3097 additions and 76 deletions

View File

@ -2737,7 +2737,7 @@ nomatch 32 {
match "bus" "uhub[0-9]+";
match "mode" "host";
match "vendor" "0x0bda";
match "product" "(0x8176|0x8177|0x8178|0x8179|0x817a|0x817b|0x817c|0x817d|0x817e|0x817f)";
match "product" "(0x8176|0x8177|0x8178|0x8178|0x8179|0x817a|0x817b|0x817c|0x817d|0x817e|0x817f)";
action "kldload -n if_rtwn_usb";
};
@ -2753,7 +2753,7 @@ nomatch 32 {
match "bus" "uhub[0-9]+";
match "mode" "host";
match "vendor" "0x0bda";
match "product" "(0x818a|0x8191)";
match "product" "(0x818a|0x818b|0x8191)";
action "kldload -n if_rtwn_usb";
};
@ -3793,7 +3793,7 @@ nomatch 32 {
match "bus" "uhub[0-9]+";
match "mode" "host";
match "vendor" "0x1199";
match "product" "(0x68aa|0x68c0|0x9041)";
match "product" "(0x68aa|0x68c0|0x9041|0x9071)";
action "kldload -n u3g";
};
@ -3905,7 +3905,7 @@ nomatch 32 {
match "bus" "uhub[0-9]+";
match "mode" "host";
match "vendor" "0x12d1";
match "product" "(0x1573|0x1803|0x1c05|0x1c0b)";
match "product" "(0x1573|0x15c1|0x1803|0x1c05|0x1c0b)";
action "kldload -n u3g";
};
@ -5025,7 +5025,7 @@ nomatch 32 {
match "bus" "uhub[0-9]+";
match "mode" "host";
match "vendor" "0x2001";
match "product" "(0x3307|0x3308|0x3309|0x330a|0x330d|0x330f|0x3310|0x3314|0x3315|0x3316|0x3318)";
match "product" "(0x3307|0x3308|0x3309|0x330a|0x330d|0x330f|0x3310|0x3314|0x3315|0x3316|0x3318|0x3319)";
action "kldload -n if_rtwn_usb";
};
@ -5297,7 +5297,7 @@ nomatch 32 {
match "bus" "uhub[0-9]+";
match "mode" "host";
match "vendor" "0x2357";
match "product" "0x0101";
match "product" "(0x0101|0x0108|0x0109)";
action "kldload -n if_rtwn_usb";
};
@ -5889,5 +5889,5 @@ nomatch 32 {
action "kldload -n umass";
};
# 2743 USB entries processed
# 2751 USB entries processed

View File

@ -18,7 +18,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd October 17, 2016
.Dd January 24, 2017
.Dt RTWN 4
.Os
.Sh NAME
@ -52,9 +52,9 @@ if_rtwn_usb_load="YES"
The
.Nm
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.
the Realtek RTL8192C, RTL8188E, RTL8192E, 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
To enable use for PCI/PCIe systems, see the rtwn_pci(4) driver;
for USB devices, use the rtwn_usb(4) driver.
@ -98,6 +98,7 @@ when an interface is brought up:
.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-rtl8192eufw.ko
.It Pa /boot/kernel/rtwn-rtl8812aufw.ko
.It Pa /boot/kernel/rtwn-rtl8821aufw.ko
.El

View File

@ -29,7 +29,7 @@
.\"
.\" $FreeBSD$
.\"/
.Dd January 6, 2017
.Dd January 24, 2017
.Dt RTWN_USB 4
.Os
.Sh NAME
@ -56,7 +56,7 @@ driver.
.Sh HARDWARE
The
.Nm
driver supports Realtek RTL8188CU/RTL8188RU/RTL8188EU/RTL8192CU/RTL8812AU/RTL8821AU
driver supports Realtek RTL8188CU/RTL8188RU/RTL8188EU/RTL8192CU/RTL8192EU/RTL8812AU/RTL8821AU
based USB wireless network adapters, including:
.Pp
.Bl -column -compact "Belkin F7D1102 Surf Wireless Micro" "Bus"
@ -70,6 +70,7 @@ based USB wireless network adapters, including:
.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-131 rev E1" 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
@ -94,7 +95,10 @@ based USB wireless network adapters, including:
.It "TP-LINK TL-WN723N v3" Ta USB 2.0
.It "TP-LINK TL-WN725N v2" Ta USB 2.0
.It "TP-LINK TL-WN821N v4" Ta USB 2.0
.It "TP-LINK TL-WN821N v5" Ta USB 2.0
.It "TP-LINK TL-WN822N v4" Ta USB 2.0
.It "TP-LINK TL-WN823N v1" Ta USB 2.0
.It "TP-LINK TL-WN823N v2" Ta USB 2.0
.It "TRENDnet TEW-805UB" Ta USB 3.0
.It "ZyXEL NWD6605" Ta USB 3.0
.El

View File

@ -23,7 +23,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd October 28, 2015
.Dd January 24, 2017
.Dt RTWNFW 4
.Os
.Sh NAME
@ -46,6 +46,7 @@ of the following:
.Cd "device rtwn-rtl8192cfwE"
.Cd "device rtwn-rtl8192cfwT"
.Cd "device rtwn-rtl8192cfwU"
.Cd "device rtwn-rtl8192eufw"
.Cd "device rtwn-rtl8812aufw"
.Cd "device rtwn-rtl8821aufw"
.Ed
@ -59,6 +60,7 @@ rtwn-rtl8192cfwE_B_load="YES"
rtwn-rtl8192cfwE_load="YES"
rtwn-rtl8192cfwT_load="YES"
rtwn-rtl8192cfwU_load="YES"
rtwn-rtl8192eufw_load="YES"
rtwn-rtl8812aufw_load="YES"
rtwn-rtl8821aufw_load="YES"
.Ed
@ -66,8 +68,8 @@ rtwn-rtl8821aufw_load="YES"
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.
RTL8188CE-VAU, RTL8188EUS, RTL8188RU, RTL8192CU, RTL8192EU, RTL8812AU and
RTL8821AU chip based USB WiFi adapters.
They may be
statically linked into the kernel, or loaded as a modules.
.Pp

View File

@ -2674,6 +2674,7 @@ 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_llt.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
@ -2690,6 +2691,16 @@ 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
# RTL8192E
dev/rtwn/rtl8192e/r92e_chan.c optional rtwn
dev/rtwn/rtl8192e/r92e_fw.c optional rtwn
dev/rtwn/rtl8192e/r92e_init.c optional rtwn
dev/rtwn/rtl8192e/r92e_led.c optional rtwn
dev/rtwn/rtl8192e/r92e_rf.c optional rtwn
dev/rtwn/rtl8192e/r92e_rom.c optional rtwn
dev/rtwn/rtl8192e/r92e_rx.c optional rtwn
dev/rtwn/rtl8192e/usb/r92eu_attach.c optional rtwn_usb
dev/rtwn/rtl8192e/usb/r92eu_init.c optional rtwn_usb
# RTL8812A
dev/rtwn/rtl8812a/r12a_beacon.c optional rtwn
dev/rtwn/rtl8812a/r12a_calib.c optional rtwn
@ -2788,6 +2799,20 @@ rtwn-rtl8192cfwU.fw optional rtwn-rtl8192cfwU | rtwnfw \
compile-with "${NORMAL_FW}" \
no-obj no-implicit-rule \
clean "rtwn-rtl8192cfwU.fw"
rtwn-rtl8192eufw.c optional rtwn-rtl8192eufw | rtwnfw \
compile-with "${AWK} -f $S/tools/fw_stub.awk rtwn-rtl8192eufw.fw:rtwn-rtl8192eufw:111 -mrtwn-rtl8192eufw -c${.TARGET}" \
no-implicit-rule before-depend local \
clean "rtwn-rtl8192eufw.c"
rtwn-rtl8192eufw.fwo optional rtwn-rtl8192eufw | rtwnfw \
dependency "rtwn-rtl8192eufw.fw" \
compile-with "${NORMAL_FWO}" \
no-implicit-rule \
clean "rtwn-rtl8192eufw.fwo"
rtwn-rtl8192eufw.fw optional rtwn-rtl8192eufw | rtwnfw \
dependency "$S/contrib/dev/rtwn/rtwn-rtl8192eufw.fw.uu" \
compile-with "${NORMAL_FW}" \
no-obj no-implicit-rule \
clean "rtwn-rtl8192eufw.fw"
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 \

View File

@ -0,0 +1,711 @@
begin 644 rtwn-rtl8192eufw.fw.uu
MX9(0`!,````#,1%`*GP``+@0```````````````````"24T"7_4`````````
M`````````F`Y``````````````````)P*```````````````````````````
M`````````````E_V```````":$@```````)OZ@WP_P\````-\`\`````#?#_
M#P````WP#P`````0\/\/````$/`/`````/4/``````#P#P``````#0``````
M`!#P__\````0\#\`````"@@#`P`$"0<#`P`$"`8#`@`$"`4#`0`$#0H'!0`(
M#`H'!``("PH&!0`("PH%`P`("PH#`@`(%!(,!``0%!()!``0)"(<$@`@)"(8
M#``@)"(4!@`@)"(/!``@)"$*!``@(R$,!``@(Q\*!``@(A\/!``@(1\6#``@
M,2\@%``P,2\8$``P,2P8#``P,2H4#``P,2@4```P,204```P,1X4```P`@("
M!0($!0<'!P@*`0($!@<*"PT"`P0'"`L-#P4%!P<("PT/!04'!P@+#0\!`@,&
M!PH+#`T.`@,$!P@+#`T.$`4%!P<("PT/#P\%!0<'"`L-#P\/!`0$!0<'"0D,
M#A`2!`4&!PL-$1,$!08'"PT1$PD)"0D,#A$3"0D)"0P.$1,$"`D*#`X0$A,4
M!`@*#`X0$1,4%@D)"0D,#A$3$Q,)"0D)#`X1$Q,3````````````)"8J````
M'R$E)R@`````(R8H*@`````C)B@J`````",F*"H`````("4G*2DJ`````"`E
M)RDI*@`````C)B@J*BH````?(R8H*BHJ````!`````0````(````$````!@`
M```D````,````$@```!@````D````,````#8````/````&0```!X````H```
M`/````%````!D````>````"@````\````4````&0```"6````R````9````'
MT````,@```$8```!X````M````/H```$L```!D````?0````R````1@```'@
M```"T````^@```2P```&0```!]`````\````9````'@```"@````\````4``
M``&0```!X```!+````E@````R````1@```'@```"T````^@```?0```+N```
M$X@``!=P```?0````,@```$8```!X````M````/H```$L```!D````?0```'
MT```!]````#(```!&````>````+0```#Z```!+````9````'T```!]````?0
M``(``@`$``@`#``2`!@`)``P`$@`8`!L`!X`,@`\`%``>`"@`,@`\`!0`'@`
MH`#(`2P!D`.$!10`9`",`/`!:`'T`E@#(`/H`&0`C`#P`6@!]`)8`R`#Z``>
M`#(`/`!0`'@`H`#(`/`"6`2P`&0`C`#P`6@!]`/H!=P)Q`NX#Z``9`",`/`!
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
#`*FO
`
end

View File

@ -121,9 +121,6 @@ static int rtwn_run(struct rtwn_softc *,
static void rtwn_watchdog(void *);
#endif
static void rtwn_parent(struct ieee80211com *);
static int rtwn_llt_write(struct rtwn_softc *, uint32_t,
uint32_t);
static int rtwn_llt_init(struct rtwn_softc *);
static int rtwn_dma_init(struct rtwn_softc *);
static int rtwn_mac_init(struct rtwn_softc *);
static void rtwn_mrr_init(struct rtwn_softc *);
@ -1383,54 +1380,6 @@ rtwn_parent(struct ieee80211com *ic)
rtwn_stop(sc);
}
static int
rtwn_llt_write(struct rtwn_softc *sc, uint32_t addr, uint32_t data)
{
int ntries, error;
error = rtwn_write_4(sc, R92C_LLT_INIT,
SM(R92C_LLT_INIT_OP, R92C_LLT_INIT_OP_WRITE) |
SM(R92C_LLT_INIT_ADDR, addr) |
SM(R92C_LLT_INIT_DATA, data));
if (error != 0)
return (error);
/* Wait for write operation to complete. */
for (ntries = 0; ntries < 20; ntries++) {
if (MS(rtwn_read_4(sc, R92C_LLT_INIT), R92C_LLT_INIT_OP) ==
R92C_LLT_INIT_OP_NO_ACTIVE)
return (0);
rtwn_delay(sc, 10);
}
return (ETIMEDOUT);
}
static int
rtwn_llt_init(struct rtwn_softc *sc)
{
int i, error;
/* Reserve pages [0; page_count]. */
for (i = 0; i < sc->page_count; i++) {
if ((error = rtwn_llt_write(sc, i, i + 1)) != 0)
return (error);
}
/* NB: 0xff indicates end-of-list. */
if ((error = rtwn_llt_write(sc, i, 0xff)) != 0)
return (error);
/*
* Use pages [page_count + 1; pktbuf_count - 1]
* as ring buffer.
*/
for (++i; i < sc->pktbuf_count - 1; i++) {
if ((error = rtwn_llt_write(sc, i, i + 1)) != 0)
return (error);
}
/* Make the last page point to the beginning of the ring buffer. */
error = rtwn_llt_write(sc, i, sc->page_count + 1);
return (error);
}
static int
rtwn_dma_init(struct rtwn_softc *sc)
{

View File

@ -308,6 +308,7 @@ struct rtwn_softc {
void (*sc_fw_reset)(struct rtwn_softc *, int);
void (*sc_fw_download_enable)(struct rtwn_softc *, int);
#endif
int (*sc_llt_init)(struct rtwn_softc *);
int (*sc_set_page_size)(struct rtwn_softc *);
void (*sc_lc_calib)(struct rtwn_softc *);
void (*sc_iq_calib)(struct rtwn_softc *);
@ -472,8 +473,8 @@ void rtwn_suspend(struct rtwn_softc *);
/* Aliases. */
#define rtwn_bb_write rtwn_write_4
#define rtwn_bb_read rtwn_read_4
#define rtwn_bb_setbits rtwn_setbits_4
#define rtwn_bb_read rtwn_read_4
#define rtwn_bb_setbits rtwn_setbits_4
/* Device-specific. */
#define rtwn_rf_read(_sc, _chain, _addr) \
@ -504,6 +505,8 @@ void rtwn_suspend(struct rtwn_softc *);
#define rtwn_fw_download_enable(_sc, _enable) \
(((_sc)->sc_fw_download_enable)((_sc), (_enable)))
#endif
#define rtwn_llt_init(_sc) \
(((_sc)->sc_llt_init)((_sc)))
#define rtwn_set_page_size(_sc) \
(((_sc)->sc_set_page_size)((_sc)))
#define rtwn_lc_calib(_sc) \

View File

@ -146,6 +146,7 @@ r88eu_attach(struct rtwn_usb_softc *uc)
sc->sc_fw_reset = r88e_fw_reset;
sc->sc_fw_download_enable = r88e_fw_download_enable;
#endif
sc->sc_llt_init = r92c_llt_init;
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 */

View File

@ -191,6 +191,7 @@ r92ce_attach(struct rtwn_pci_softc *pc)
sc->sc_fw_reset = r92ce_fw_reset;
sc->sc_fw_download_enable = r92c_fw_download_enable;
#endif
sc->sc_llt_init = r92c_llt_init;
sc->sc_set_page_size = r92c_set_page_size;
sc->sc_lc_calib = r92c_lc_calib;
sc->sc_iq_calib = r92ce_iq_calib;

View File

@ -77,6 +77,7 @@ void r92c_handle_c2h_report(void *);
/* r92c_init.c */
int r92c_check_condition(struct rtwn_softc *, const uint8_t[]);
int r92c_llt_init(struct rtwn_softc *);
int r92c_set_page_size(struct rtwn_softc *);
void r92c_init_bb_common(struct rtwn_softc *);
int r92c_init_rf_chain(struct rtwn_softc *,
@ -87,6 +88,9 @@ void r92c_init_ampdu(struct rtwn_softc *);
void r92c_init_antsel(struct rtwn_softc *);
void r92c_pa_bias_init(struct rtwn_softc *);
/* r92c_llt.c */
int r92c_llt_write(struct rtwn_softc *, uint32_t, uint32_t);
/* 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);

View File

@ -89,6 +89,32 @@ r92c_check_condition(struct rtwn_softc *sc, const uint8_t cond[])
return (0);
}
int
r92c_llt_init(struct rtwn_softc *sc)
{
int i, error;
/* Reserve pages [0; page_count]. */
for (i = 0; i < sc->page_count; i++) {
if ((error = r92c_llt_write(sc, i, i + 1)) != 0)
return (error);
}
/* NB: 0xff indicates end-of-list. */
if ((error = r92c_llt_write(sc, i, 0xff)) != 0)
return (error);
/*
* Use pages [page_count + 1; pktbuf_count - 1]
* as ring buffer.
*/
for (++i; i < sc->pktbuf_count - 1; i++) {
if ((error = r92c_llt_write(sc, i, i + 1)) != 0)
return (error);
}
/* Make the last page point to the beginning of the ring buffer. */
error = r92c_llt_write(sc, i, sc->page_count + 1);
return (error);
}
int
r92c_set_page_size(struct rtwn_softc *sc)
{

View File

@ -0,0 +1,73 @@
/* $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_reg.h>
#include <dev/rtwn/rtl8192c/r92c_var.h>
int
r92c_llt_write(struct rtwn_softc *sc, uint32_t addr, uint32_t data)
{
int ntries, error;
error = rtwn_write_4(sc, R92C_LLT_INIT,
SM(R92C_LLT_INIT_OP, R92C_LLT_INIT_OP_WRITE) |
SM(R92C_LLT_INIT_ADDR, addr) |
SM(R92C_LLT_INIT_DATA, data));
if (error != 0)
return (error);
/* Wait for write operation to complete. */
for (ntries = 0; ntries < 20; ntries++) {
if (MS(rtwn_read_4(sc, R92C_LLT_INIT), R92C_LLT_INIT_OP) ==
R92C_LLT_INIT_OP_NO_ACTIVE)
return (0);
rtwn_delay(sc, 10);
}
return (ETIMEDOUT);
}

View File

@ -66,6 +66,7 @@
#define R92C_HSIMR 0x058
#define R92C_HSISR 0x05c
#define R92C_MULTI_FUNC_CTRL 0x068
#define R92C_LDO_SWR_CTRL 0x07c
#define R92C_MCUFWDL 0x080
#define R92C_HMEBOX_EXT(idx) (0x088 + (idx) * 2)
#define R92C_EFUSE_ACCESS 0x0cf
@ -115,6 +116,7 @@
#define R92C_TXDMA_OFFSET_CHK 0x20c
#define R92C_TXDMA_STATUS 0x210
#define R92C_RQPN_NPQ 0x214
#define R92C_AUTO_LLT 0x224
/* Rx DMA Configuration. */
#define R92C_RXDMA_AGG_PG_TH 0x280
#define R92C_RXPKT_NUM 0x284
@ -297,6 +299,16 @@
#define R92C_SYS_CLKR_SYS_EN 0x00001000
#define R92C_SYS_CLKR_RING_EN 0x00002000
/* Bits for R92C_RSV_CTRL. */
#define R92C_RSV_CTRL_WLOCK_ALL 0x01
#define R92C_RSV_CTRL_WLOCK_00 0x02
#define R92C_RSV_CTRL_WLOCK_04 0x04
#define R92C_RSV_CTRL_WLOCK_08 0x08
#define R92C_RSV_CTRL_WLOCK_40 0x10
#define R92C_RSV_CTRL_R_DIS_PRST_0 0x20
#define R92C_RSV_CTRL_R_DIS_PRST_1 0x40
#define R92C_RSV_CTRL_LOCK_ALL_EN 0x80
/* Bits for R92C_RF_CTRL. */
#define R92C_RF_CTRL_EN 0x01
#define R92C_RF_CTRL_RSTB 0x02
@ -339,6 +351,9 @@
/* Bits for R92C_LEDCFG0. */
#define R92C_LEDCFG0_DIS 0x08
/* Bits for R92C_LEDCFG1. */
#define R92C_LEDCFG1_DIS 0x80
/* Bits for R92C_MULTI_FUNC_CTRL. */
#define R92C_MULTI_BT_FUNC_EN 0x00040000
@ -477,6 +492,9 @@
/* Bits for R92C_TXDMA_OFFSET_CHK. */
#define R92C_TXDMA_OFFSET_DROP_DATA_EN 0x00000200
/* Bits for R92C_AUTO_LLT. */
#define R92C_AUTO_LLT_INIT 0x00010000
/* Bits for R92C_FWHW_TXQ_CTRL. */
#define R92C_FWHW_TXQ_CTRL_AMPDU_RTY_NEW 0x80
#define R92C_FWHW_TXQ_CTRL_REAL_BEACON 0x400000
@ -683,6 +701,7 @@
#define R92C_OFDM0_TXIQIMBALANCE(chain) (0xc80 + (chain) * 8)
#define R92C_OFDM0_TXAFE(chain) (0xc94 + (chain) * 8)
#define R92C_OFDM0_RXIQEXTANTA 0xca0
#define R92C_OFDM0_TXPSEUDONOISEWGT 0xce4
#define R92C_OFDM1_LSTF 0xd00
/* Bits for R92C_FPGA[01]_RFMOD. */
@ -802,6 +821,9 @@
#define R92C_LSSI_READBACK_DATA_M 0x000fffff
#define R92C_LSSI_READBACK_DATA_S 0
/* Bits for R92C_CCK0_SYSTEM. */
#define R92C_CCK0_SYSTEM_CCK_SIDEBAND 0x00000010
/* Bits for R92C_OFDM0_AGCCORE1(i). */
#define R92C_OFDM0_AGCCORE1_GAIN_M 0x0000007f
#define R92C_OFDM0_AGCCORE1_GAIN_S 0

View File

@ -184,6 +184,7 @@ r92cu_attach(struct rtwn_usb_softc *uc)
sc->sc_fw_reset = r92c_fw_reset;
sc->sc_fw_download_enable = r92c_fw_download_enable;
#endif
sc->sc_llt_init = r92c_llt_init;
sc->sc_set_page_size = r92c_set_page_size;
sc->sc_lc_calib = r92c_lc_calib;
sc->sc_iq_calib = r92c_iq_calib; /* XXX TODO */

View File

@ -0,0 +1,82 @@
/*-
* Copyright (c) 2017 Kevin Lo <kevlo@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.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef RTL8192E_H
#define RTL8192E_H
/*
* Global definitions.
*/
#define R92E_PUBQ_NPAGES 222
#define R92E_TX_PAGE_COUNT 243
#define R92E_TX_PAGE_SIZE 256
#define R92E_RX_DMA_BUFFER_SIZE 0x3d00
#define R92E_MAX_FW_SIZE 0x8000
/*
* Function declarations.
*/
/* r92e_attach.c */
void r92e_detach_private(struct rtwn_softc *);
/* r92e_chan.c */
void r92e_set_chan(struct rtwn_softc *, struct ieee80211_channel *);
/* r92e_fw.c */
#ifndef RTWN_WITHOUT_UCODE
void r92e_fw_reset(struct rtwn_softc *, int);
void r92e_set_media_status(struct rtwn_softc *, int);
int r92e_set_pwrmode(struct rtwn_softc *, struct ieee80211vap *, int);
#endif
/* r92e_init.c */
int r92e_llt_init(struct rtwn_softc *);
void r92e_init_bb(struct rtwn_softc *);
void r92e_init_rf(struct rtwn_softc *);
int r92e_power_on(struct rtwn_softc *);
void r92e_power_off(struct rtwn_softc *);
/* r92e_led.c */
void r92e_set_led(struct rtwn_softc *, int, int);
/* r92e_rf.c */
uint32_t r92e_rf_read(struct rtwn_softc *, int, uint8_t);
void r92e_rf_write(struct rtwn_softc *, int, uint8_t, uint32_t);
/* r92e_rom.c */
void r92e_parse_rom_common(struct rtwn_softc *, uint8_t *);
void r92e_parse_rom(struct rtwn_softc *, uint8_t *);
/* r92e_rx.c */
void r92e_handle_c2h_report(struct rtwn_softc *, uint8_t *, int);
int8_t r92e_get_rssi_cck(struct rtwn_softc *, void *);
#endif /* RTL8192E_H */

View File

@ -0,0 +1,294 @@
/*-
* Copyright (c) 2017 Kevin Lo <kevlo@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.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#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/if_rtwn_rx.h>
#include <dev/rtwn/rtl8192e/r92e.h>
#include <dev/rtwn/rtl8192e/r92e_reg.h>
#include <dev/rtwn/rtl8192e/r92e_var.h>
static int
r92e_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 <= 14) group = 4;
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);
}
static void
r92e_get_txpower(struct rtwn_softc *sc, int chain, struct ieee80211_channel *c,
uint8_t power[RTWN_RIDX_COUNT])
{
struct r92e_softc *rs = sc->sc_priv;
int i, ridx, group, max_mcs;
/* Determine channel group. */
group = r92e_get_power_group(sc, c);
if (group == -1) { /* shouldn't happen */
device_printf(sc->sc_dev, "%s: incorrect channel\n", __func__);
return;
}
max_mcs = RTWN_RIDX_MCS(sc->ntxchains * 8 - 1);
/* XXX regulatory */
/* XXX net80211 regulatory */
for (ridx = RTWN_RIDX_CCK1; ridx <= RTWN_RIDX_CCK11; ridx++)
power[ridx] = rs->cck_tx_pwr[chain][group];
for (ridx = RTWN_RIDX_OFDM6; ridx <= max_mcs; ridx++)
power[ridx] = rs->ht40_tx_pwr_2g[chain][group];
for (ridx = RTWN_RIDX_OFDM6; ridx <= RTWN_RIDX_OFDM54; ridx++)
power[ridx] += rs->ofdm_tx_pwr_diff_2g[chain][0];
for (i = 0; i < sc->ntxchains; i++) {
uint8_t min_mcs;
uint8_t pwr_diff;
if (IEEE80211_IS_CHAN_HT40(c))
pwr_diff = rs->bw40_tx_pwr_diff_2g[chain][i];
else
pwr_diff = rs->bw20_tx_pwr_diff_2g[chain][i];
min_mcs = RTWN_RIDX_MCS(i * 8);
for (ridx = min_mcs; ridx <= max_mcs; ridx++)
power[ridx] += pwr_diff;
}
/* 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;
}
#ifdef RTWN_DEBUG
if (sc->sc_debug & RTWN_DEBUG_TXPWR) {
/* Dump per-rate Tx power values. */
printf("Tx power for chain %d:\n", chain);
for (ridx = RTWN_RIDX_CCK1; ridx < RTWN_RIDX_COUNT; ridx++)
printf("Rate %d = %u\n", ridx, power[ridx]);
}
#endif
}
static void
r92e_write_txpower(struct rtwn_softc *sc, int chain,
uint8_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
r92e_set_txpower(struct rtwn_softc *sc, struct ieee80211_channel *c)
{
uint8_t power[RTWN_RIDX_COUNT];
int i;
for (i = 0; i < sc->ntxchains; i++) {
memset(power, 0, sizeof(power));
/* Compute per-rate Tx power values. */
r92e_get_txpower(sc, i, c, power);
/* Write per-rate Tx power values to hardware. */
r92e_write_txpower(sc, i, power);
}
}
static void
r92e_set_bw40(struct rtwn_softc *sc, uint8_t chan, int prichlo)
{
int i;
rtwn_setbits_2(sc, R92C_WMAC_TRXPTCL_CTL, 0x100, 0x80);
rtwn_write_1(sc, R12A_DATA_SEC,
prichlo ? R12A_DATA_SEC_PRIM_DOWN_20 : R12A_DATA_SEC_PRIM_UP_20);
rtwn_bb_setbits(sc, R92C_FPGA0_RFMOD, 0, R92C_RFMOD_40MHZ);
rtwn_bb_setbits(sc, R92C_FPGA1_RFMOD, 0, R92C_RFMOD_40MHZ);
/* Select 40MHz bandwidth. */
for (i = 0; i < sc->nrxchains; i++)
rtwn_rf_setbits(sc, i, R92C_RF_CHNLBW,
R88E_RF_CHNLBW_BW20, 0x400);
/* Set CCK side band. */
rtwn_bb_setbits(sc, R92C_CCK0_SYSTEM,
R92C_CCK0_SYSTEM_CCK_SIDEBAND, (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);
}
static void
r92e_set_bw20(struct rtwn_softc *sc, uint8_t chan)
{
int i;
rtwn_setbits_2(sc, R92C_WMAC_TRXPTCL_CTL, 0x180, 0);
rtwn_write_1(sc, R12A_DATA_SEC, R12A_DATA_SEC_NO_EXT);
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. */
for (i = 0; i < sc->nrxchains; i++)
rtwn_rf_setbits(sc, i, R92C_RF_CHNLBW,
R88E_RF_CHNLBW_BW20, 0xc00);
rtwn_bb_setbits(sc, R92C_OFDM0_TXPSEUDONOISEWGT, 0xc0000000, 0);
}
void
r92e_set_chan(struct rtwn_softc *sc, struct ieee80211_channel *c)
{
struct r92e_softc *rs = sc->sc_priv;
u_int chan;
int i;
chan = rtwn_chan2centieee(c);
for (i = 0; i < sc->nrxchains; i++) {
rtwn_rf_write(sc, i, R92C_RF_CHNLBW,
RW(rs->rf_chnlbw[0], R92C_RF_CHNLBW_CHNL, chan));
}
if (IEEE80211_IS_CHAN_HT40(c))
r92e_set_bw40(sc, chan, IEEE80211_IS_CHAN_HT40U(c));
else
r92e_set_bw20(sc, chan);
/* Set Tx power for this new channel. */
r92e_set_txpower(sc, c);
}

View File

@ -0,0 +1,137 @@
/*-
* Copyright (c) 2017 Kevin Lo <kevlo@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.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#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/rtl8812a/r12a_fw_cmd.h>
#include <dev/rtwn/rtl8192e/r92e.h>
#ifndef RTWN_WITHOUT_UCODE
void
r92e_fw_reset(struct rtwn_softc *sc, int reason)
{
/* Reset MCU IO wrapper. */
rtwn_setbits_1(sc, R92C_RSV_CTRL + 1, 0x01, 0);
rtwn_setbits_1_shift(sc, R92C_SYS_FUNC_EN,
R92C_SYS_FUNC_EN_CPUEN, 0, 1);
/* Enable MCU IO wrapper. */
rtwn_setbits_1(sc, R92C_RSV_CTRL + 1, 0, 0x01);
rtwn_setbits_1_shift(sc, R92C_SYS_FUNC_EN,
0, R92C_SYS_FUNC_EN_CPUEN, 1);
}
void
r92e_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);
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__);
}
}
int
r92e_set_pwrmode(struct rtwn_softc *sc, struct ieee80211vap *vap, int off)
{
struct r12a_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;
mode.pwrb5 = 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,385 @@
/*-
* Copyright (c) 2017 Kevin Lo <kevlo@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.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#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/rtl8192e/r92e.h>
#include <dev/rtwn/rtl8192e/r92e_reg.h>
#include <dev/rtwn/rtl8192e/r92e_priv.h>
#include <dev/rtwn/rtl8192e/r92e_var.h>
int
r92e_llt_init(struct rtwn_softc *sc)
{
int ntries, error;
error = rtwn_setbits_4(sc, R92C_AUTO_LLT, 0, R92C_AUTO_LLT_INIT);
if (error != 0)
return (error);
for (ntries = 0; ntries < 1000; ntries++) {
if (!(rtwn_read_4(sc, R92C_AUTO_LLT) & R92C_AUTO_LLT_INIT))
return (0);
rtwn_delay(sc, 1);
}
return (ETIMEDOUT);
}
static void
r92e_crystalcap_write(struct rtwn_softc *sc)
{
struct r92e_softc *rs = sc->sc_priv;
uint32_t reg;
uint8_t val;
val = rs->crystalcap & 0x3f;
reg = rtwn_bb_read(sc, R92E_AFE_XTAL_CTRL);
rtwn_bb_write(sc, R92E_AFE_XTAL_CTRL,
RW(reg, R92E_AFE_XTAL_CTRL_ADDR, val | val << 6));
rtwn_bb_write(sc, R92C_AFE_XTAL_CTRL, 0x000f81fb);
}
void
r92e_init_bb(struct rtwn_softc *sc)
{
int i, j;
rtwn_setbits_2(sc, R92C_SYS_FUNC_EN, 0,
R92C_SYS_FUNC_EN_USBA | R92C_SYS_FUNC_EN_USBD);
/* 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);
/* PathA RF Power On. */
rtwn_write_1(sc, R92C_RF_CTRL,
R92C_RF_CTRL_EN | R92C_RF_CTRL_RSTB | R92C_RF_CTRL_SDMRSTB);
/* 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);
}
}
/* 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);
}
}
if (rtwn_bb_read(sc, R92C_HSSI_PARAM2(0)) & R92C_HSSI_PARAM2_CCK_HIPWR)
sc->sc_flags |= RTWN_FLAG_CCK_HIPWR;
rtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(0), 0x00040022);
rtwn_delay(sc, 1);
rtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(0), 0x00040020);
rtwn_delay(sc, 1);
r92e_crystalcap_write(sc);
}
void
r92e_init_rf(struct rtwn_softc *sc)
{
struct r92e_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);
/* Cache RF register CHNLBW. */
rs->rf_chnlbw[chain] = rtwn_rf_read(sc, chain, R92C_RF_CHNLBW);
}
/* 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);
}
static void
r92e_adj_crystal(struct rtwn_softc *sc)
{
rtwn_setbits_1(sc, R92C_AFE_PLL_CTRL, R92C_AFE_PLL_CTRL_FREF_SEL, 0);
rtwn_setbits_4(sc, R92E_APE_PLL_CTRL_EXT, 0x00000380, 0);
rtwn_setbits_1(sc, R92C_AFE_PLL_CTRL, 0x40, 0);
rtwn_setbits_4(sc, R92E_APE_PLL_CTRL_EXT, 0x00200000, 0);
}
int
r92e_power_on(struct rtwn_softc *sc)
{
#define RTWN_CHK(res) do { \
if (res != 0) \
return (EIO); \
} while(0)
int ntries;
if (rtwn_read_4(sc, R92C_SYS_CFG) & R92C_SYS_CFG_TRP_BT_EN)
RTWN_CHK(rtwn_write_1(sc, R92C_LDO_SWR_CTRL, 0xc3));
else {
RTWN_CHK(rtwn_setbits_4(sc, R92E_LDOV12_CTRL, 0x00100000,
0x00500000));
RTWN_CHK(rtwn_write_1(sc, R92C_LDO_SWR_CTRL, 0x83));
}
r92e_adj_crystal(sc);
/* Enable WL suspend. */
RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO,
R92C_APS_FSMCO_AFSM_HSUS | R92C_APS_FSMCO_AFSM_PCIE, 0, 1));
/* Disable HWPDN, SW LPS and WL suspend. */
RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO,
R92C_APS_FSMCO_APFM_RSM | R92C_APS_FSMCO_AFSM_HSUS |
R92C_APS_FSMCO_AFSM_PCIE | R92C_APS_FSMCO_APDM_HPDN, 0, 1));
/* 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);
}
/* Release WLON reset. */
RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, 0,
R92C_APS_FSMCO_RDY_MACON, 2));
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 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);
}
void
r92e_power_off(struct rtwn_softc *sc)
{
int error, ntries;
/* Stop Rx. */
error = rtwn_write_1(sc, R92C_CR, 0);
if (error == ENXIO) /* hardware gone */
return;
/* Move card to Low Power state. */
/* Block all Tx queues. */
rtwn_write_1(sc, R92C_TXPAUSE, R92C_TX_QUEUE_ALL);
for (ntries = 0; ntries < 5000; ntries++) {
/* Should be zero if no packet is transmitting. */
if (rtwn_read_4(sc, R88E_SCH_TXCMD) == 0)
break;
rtwn_delay(sc, 10);
}
if (ntries == 5000) {
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 whole BB. */
rtwn_setbits_1(sc, R92C_SYS_FUNC_EN, R92C_SYS_FUNC_EN_BB_GLB_RST, 0);
/* Reset MAC TRX. */
rtwn_write_1(sc, R92C_CR,
R92C_CR_HCI_TXDMA_EN | R92C_CR_HCI_RXDMA_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, R92C_DUAL_TSF_RST_TXOK);
/* Reset MCU. */
rtwn_write_1(sc, R92C_MCUFWDL, 0);
#ifndef RTWN_WITHOUT_UCODE
/* Reset MCU IO wrapper. */
rtwn_setbits_1(sc, R92C_RSV_CTRL + 1, 0x01, 0);
rtwn_setbits_1_shift(sc, R92C_SYS_FUNC_EN,
R92C_SYS_FUNC_EN_CPUEN, 0, 1);
/* Enable MCU IO wrapper. */
rtwn_setbits_1(sc, R92C_RSV_CTRL + 1, 0, 0x01);
#endif
/* Move card to Disabled state. */
/* Turn off RF. */
rtwn_write_1(sc, R92C_RF_CTRL, 0);
/* Switch DPDT_SEL_P output. */
rtwn_setbits_1(sc, R92C_LEDCFG2, 0x80, 0);
/* 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 < 5000; 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, 10);
}
if (ntries == 5000) {
device_printf(sc->sc_dev, "%s: could not turn off MAC\n",
__func__);
return;
}
/* SOP option to disable BG/MB. */
rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, 0xff,
R92C_APS_FSMCO_SOP_RCK, 3);
/* Unlock small LDO Register. */
rtwn_setbits_1(sc, 0xcc, 0, 0x4);
/* Disable small LDO. */
rtwn_setbits_1(sc, R92C_SPS0_CTRL, 0x1, 0);
/* Enable WL suspend. */
rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, R92C_APS_FSMCO_AFSM_PCIE,
R92C_APS_FSMCO_AFSM_HSUS, 1);
/* Enable SW LPS. */
rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, 0,
R92C_APS_FSMCO_APFM_RSM, 1);
}

View File

@ -0,0 +1,69 @@
/*-
* Copyright (c) 2017 Kevin Lo <kevlo@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.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#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/rtl8192e/r92e.h>
#include <dev/rtwn/rtl8192e/r92e_reg.h>
void
r92e_set_led(struct rtwn_softc *sc, int led, int on)
{
if (led == RTWN_LED_LINK) {
if (!on)
rtwn_setbits_1(sc, R92C_LEDCFG1, 0, R92C_LEDCFG1_DIS);
else
rtwn_setbits_1(sc, R92C_LEDCFG1, R92C_LEDCFG1_DIS, 0);
sc->ledlink = on; /* Save LED state. */
}
}

View File

@ -0,0 +1,262 @@
/*-
* Copyright (c) 2017 Kevin Lo <kevlo@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.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef R92E_PRIV_H
#define R92E_PRIV_H
/*
* MAC initialization values.
*/
static const struct rtwn_mac_prog rtl8192eu_mac[] = {
{ 0x011, 0xeb }, { 0x012, 0x07 }, { 0x014, 0x75 }, { 0x303, 0xa7 },
{ 0x428, 0x0a }, { 0x429, 0x10 }, { 0x430, 0x00 }, { 0x431, 0x00 },
{ 0x432, 0x00 }, { 0x433, 0x01 }, { 0x434, 0x04 }, { 0x435, 0x05 },
{ 0x436, 0x07 }, { 0x437, 0x08 }, { 0x43c, 0x04 }, { 0x43d, 0x05 },
{ 0x43e, 0x07 }, { 0x43f, 0x08 }, { 0x440, 0x5d }, { 0x441, 0x01 },
{ 0x442, 0x00 }, { 0x444, 0x10 }, { 0x445, 0x00 }, { 0x446, 0x00 },
{ 0x447, 0x00 }, { 0x448, 0x00 }, { 0x449, 0xf0 }, { 0x44a, 0x0f },
{ 0x44b, 0x3e }, { 0x44c, 0x10 }, { 0x44d, 0x00 }, { 0x44e, 0x00 },
{ 0x44f, 0x00 }, { 0x450, 0x00 }, { 0x451, 0xf0 }, { 0x452, 0x0f },
{ 0x453, 0x00 }, { 0x456, 0x5e }, { 0x460, 0x66 }, { 0x461, 0x66 },
{ 0x4c8, 0xff }, { 0x4c9, 0x08 }, { 0x4cc, 0xff }, { 0x4cd, 0xff },
{ 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 }, { 0x516, 0x0a },
{ 0x525, 0x4f }, { 0x540, 0x12 }, { 0x541, 0x64 }, { 0x550, 0x10 },
{ 0x551, 0x10 }, { 0x559, 0x02 }, { 0x55c, 0x50 }, { 0x55d, 0xff },
{ 0x605, 0x30 }, { 0x608, 0x0e }, { 0x609, 0x2a }, { 0x620, 0xff },
{ 0x621, 0xff }, { 0x622, 0xff }, { 0x623, 0xff }, { 0x624, 0xff },
{ 0x625, 0xff }, { 0x626, 0xff }, { 0x627, 0xff }, { 0x638, 0x50 },
{ 0x63c, 0x0a }, { 0x63d, 0x0a }, { 0x63e, 0x0e }, { 0x63f, 0x0e },
{ 0x640, 0x40 }, { 0x642, 0x40 }, { 0x643, 0x00 }, { 0x652, 0xc8 },
{ 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 rtl8192eu_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, 0x900, 0x904, 0x908, 0x90c, 0x910, 0x914,
0x918, 0x91c, 0x924, 0x928, 0x92c, 0x930, 0x934, 0x938, 0x93c,
0x940, 0x944, 0x94c, 0xa00, 0xa04, 0xa08, 0xa0c, 0xa10, 0xa14,
0xa18, 0xa1c, 0xa20, 0xa24, 0xa28, 0xa2c, 0xa70, 0xa74, 0xa78,
0xa7c, 0xa80, 0xb38, 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, 0xd1c, 0xd2c,
0xd30, 0xd34, 0xd38, 0xd3c, 0xd40, 0xd44, 0xd48, 0xd4c, 0xd50,
0xd54, 0xd58, 0xd5c, 0xd60, 0xd64, 0xd68, 0xd6c, 0xd70, 0xd74,
0xd78, 0xd80, 0xd84, 0xd88, 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, 0xeec, 0xee4, 0xee8, 0xf14, 0xf4c,
0xf00
};
static const uint32_t rtl8192eu_bb_vals[] = {
0x80040000, 0x00000003, 0x0000fc00, 0x0000000a, 0x10001331,
0x020c3d10, 0x02220385, 0x00000000, 0x01000100, 0x00390204,
0x01000100, 0x00390204, 0x32323232, 0x30303030, 0x30303030,
0x30303030, 0x00010000, 0x00010000, 0x28282828, 0x28282828,
0x00000000, 0x00000000, 0x009a009a, 0x01000014, 0x66f60000,
0x061f0000, 0x30303030, 0x30303030, 0x00000000, 0x55004200,
0x08080808, 0x00000000, 0xb0000c1c, 0x00000001, 0x00000000,
0xcc0000c0, 0x00000800, 0xfffffffe, 0x40302010, 0x00000000,
0x00000023, 0x00000000, 0x81121313, 0x806c0001, 0x00000001,
0x00000000, 0x00010000, 0x00000001, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000008, 0x00d0c7c8, 0x81ff000c, 0x8c838300,
0x2e68120f, 0x95009b78, 0x1114d028, 0x00881117, 0x89140f00,
0x1a1b0000, 0x090e1317, 0x00000204, 0x00d30000, 0x101fff00,
0x00000007, 0x00000900, 0x225b0606, 0x218075b1, 0x00000000,
0x48071d40, 0x03a05633, 0x000000e4, 0x6c6c6c6c, 0x08800000,
0x40000100, 0x08800000, 0x40000100, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x69e9ac47, 0x469652af, 0x49795994,
0x0a97971c, 0x1f7c403f, 0x000100b7, 0xec020107, 0x007f037f,
0x00340020, 0x0080801f, 0x00000020, 0x00248492, 0x00000000,
0x7112848b, 0x47c00bff, 0x00000036, 0x00000600, 0x02013169,
0x0000001f, 0x00b91612, 0x40000100, 0x21f60000, 0x40000100,
0xa0e40000, 0x00121820, 0x00000000, 0x00121820, 0x00007f7f,
0x00000000, 0x000300a0, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x28000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x64b22427,
0x00766932, 0x00222222, 0x00040000, 0x77644302, 0x2f97d40c,
0x00080740, 0x00020403, 0x0000907f, 0x20010201, 0xa0633333,
0x3333bc43, 0x7a8f5b6b, 0x0000007f, 0xcc979975, 0x00000000,
0x80608000, 0x00000000, 0x00127353, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x6437140a, 0x00000000, 0x00000282,
0x30032064, 0x4653de68, 0x04518a3c, 0x00002101, 0x2a201c16,
0x1812362e, 0x322c2220, 0x000e3c24, 0x01081008, 0x00000800,
0xf0b50000, 0x30303030, 0x30303030, 0x03903030, 0x30303030,
0x30303030, 0x30303030, 0x30303030, 0x00000000, 0x1000dc1f,
0x10008c1f, 0x02140102, 0x681604c2, 0x01007c00, 0x01004800,
0xfb000000, 0x000028d1, 0x1000dc1f, 0x10008c1f, 0x02140102,
0x28160d05, 0x00000008, 0x0fc05656, 0x03c09696, 0x03c09696,
0x0c005656, 0x0c005656, 0x0c005656, 0x0c005656, 0x03c09696,
0x0c005656, 0x03c09696, 0x03c09696, 0x03c09696, 0x03c09696,
0x0000d6d6, 0x0000d6d6, 0x0fc01616, 0xb0000c1c, 0x00000001,
0x00000003, 0x00000000, 0x00000300
};
static const struct rtwn_bb_prog rtl8192eu_bb[] = {
{
nitems(rtl8192eu_bb_regs),
rtl8192eu_bb_regs,
rtl8192eu_bb_vals,
{ 0 },
NULL
}
};
static const uint32_t rtl8192eu_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, 0xc81a0001, 0xc71b0001, 0xc61c0001, 0x071d0001,
0x061e0001, 0x051f0001, 0x04200001, 0x03210001, 0xaa220001,
0xa9230001, 0xa8240001, 0xa7250001, 0xa6260001, 0x85270001,
0x84280001, 0x83290001, 0x252a0001, 0x242b0001, 0x232c0001,
0x222d0001, 0x672e0001, 0x662f0001, 0x65300001, 0x64310001,
0x63320001, 0x62330001, 0x61340001, 0x45350001, 0x44360001,
0x43370001, 0x42380001, 0x41390001, 0x403a0001, 0x403b0001,
0x403c0001, 0x403d0001, 0x403e0001, 0x403f0001, 0xfb400001,
0xfb410001, 0xfb420001, 0xfb430001, 0xfb440001, 0xfb450001,
0xfa460001, 0xf9470001, 0xf8480001, 0xf7490001, 0xf64a0001,
0xf54b0001, 0xf44c0001, 0xf34d0001, 0xf24e0001, 0xf14f0001,
0xf0500001, 0xef510001, 0xee520001, 0xed530001, 0xec540001,
0xeb550001, 0xea560001, 0xe9570001, 0xe8580001, 0xe7590001,
0xe65a0001, 0xe55b0001, 0xe45c0001, 0xe35d0001, 0xe25e0001,
0xe15f0001, 0x8a600001, 0x89610001, 0x88620001, 0x87630001,
0x86640001, 0x85650001, 0x84660001, 0x83670001, 0x82680001,
0x6b690001, 0x6a6a0001, 0x696b0001, 0x686c0001, 0x676d0001,
0x666e0001, 0x656f0001, 0x64700001, 0x63710001, 0x62720001,
0x61730001, 0x49740001, 0x48750001, 0x47760001, 0x46770001,
0x45780001, 0x44790001, 0x437a0001, 0x427b0001, 0x417c0001,
0x407d0001, 0x407e0001, 0x407f0001
};
static const struct rtwn_agc_prog rtl8192eu_agc[] = {
{
nitems(rtl8192eu_agc_vals),
rtl8192eu_agc_vals,
{ 0 },
NULL
}
};
/*
* RF initialization values.
*/
static const uint8_t rtl8192eu_rf0_regs[] = {
0x7f, 0x81, 0x00, 0x08, 0x18, 0x19, 0x1b, 0x1e, 0x1f, 0x2f, 0x3f,
0x42, 0x57, 0x58, 0x67, 0x83, 0xb0, 0xb1, 0xb2, 0xb4, 0xb5, 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, 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,
0x18, 0x1e, 0x1f, 0x00
}, rtl8192eu_rf1_regs[] = {
0x7f, 0x81, 0x00, 0x08, 0x18, 0x19, 0x1b, 0x1e, 0x1f, 0x2f, 0x3f,
0x42, 0x57, 0x58, 0x67, 0x7f, 0x81, 0x83, 0xdf, 0xef, 0x51, 0x52,
0x53, 0x56, 0x35, 0x35, 0x35, 0x36, 0x36, 0x36, 0x36, 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, 0x1e, 0x1f, 0x00
};
static const uint32_t rtl8192eu_rf0_vals[] = {
0x00082, 0x3fc00, 0x30000, 0x08400, 0x00407, 0x00012, 0x00064,
0x80009, 0x00880, 0x1a060, 0x00000, 0x060c0, 0xd0000, 0xbe180,
0x01552, 0x00000, 0xff9f1, 0x55418, 0x8cc00, 0x43083, 0x08166,
0x0803e, 0x1c69f, 0x0407f, 0x80001, 0x40001, 0x00400, 0xc0000,
0x02400, 0x00009, 0x40c91, 0x99999, 0x000a3, 0x88820, 0x76c06,
0x00000, 0x80000, 0x00180, 0x001a0, 0x69545, 0x7e45e, 0x00071,
0x51ff3, 0x000a8, 0x001e2, 0x002a8, 0x01c24, 0x09c24, 0x11c24,
0x19c24, 0x00c07, 0x48000, 0x739d0, 0x0add7, 0x09dd4, 0x08dd1,
0x07dce, 0x06dcb, 0x05dc8, 0x04dc5, 0x034cc, 0x0244f, 0x0144c,
0x00014, 0x30159, 0x68180, 0x0014e, 0x48e00, 0x65540, 0x88000,
0x020a0, 0xf02b0, 0xef7b0, 0xd4fb0, 0xcf060, 0xb0090, 0xa0080,
0x90080, 0x8f780, 0x78730, 0x60fb0, 0x5ffa0, 0x40620, 0x37090,
0x20080, 0x1f060, 0x0ffb0, 0x000a0, 0x0fc07, 0x00001, 0x80000,
0x33e70
}, rtl8192eu_rf1_vals[] = {
0x00082, 0x3fc00, 0x30000, 0x08400, 0x00407, 0x00012, 0x00064,
0x80009, 0x00880, 0x1a060, 0x00000, 0x060c0, 0xd0000, 0xbe180,
0x01552, 0x00082, 0x3f000, 0x00000, 0x00180, 0x001a0, 0x69545,
0x7e42e, 0x00071, 0x51ff3, 0x000a8, 0x001e0, 0x002a8, 0x01ca8,
0x09c24, 0x11c24, 0x19c24, 0x00c07, 0x48000, 0x739d0, 0x0add7,
0x09dd4, 0x08dd1, 0x07dce, 0x06dcb, 0x05dc8, 0x04dc5, 0x034cc,
0x0244f, 0x0144c, 0x00014, 0x30159, 0x68180, 0x000ce, 0x48a00,
0x65540, 0x88000, 0x020a0, 0xf02b0, 0xef7b0, 0xd4fb0, 0xcf060,
0xb0090, 0xa0080, 0x90080, 0x8f780, 0x78730, 0x60fb0, 0x5ffa0,
0x40620, 0x37090, 0x20080, 0x1f060, 0x0ffb0, 0x000a0, 0x10159,
0x00001, 0x80000, 0x33e70
};
static const struct rtwn_rf_prog rtl8192eu_rf[] = {
/* RF chain 0. */
{
nitems(rtl8192eu_rf0_regs),
rtl8192eu_rf0_regs,
rtl8192eu_rf0_vals,
{ 0 },
NULL
},
{ 0, NULL, NULL, { 0 }, NULL },
/* RF chain 1. */
{
nitems(rtl8192eu_rf1_regs),
rtl8192eu_rf1_regs,
rtl8192eu_rf1_vals,
{ 0 },
NULL
},
{ 0, NULL, NULL, { 0 }, NULL }
};
#endif /* R92E_PRIV_H */

View File

@ -0,0 +1,47 @@
/*-
* Copyright (c) 2017 Kevin Lo <kevlo@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.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef R92E_REG_H
#define R92E_REG_H
#include <dev/rtwn/rtl8188e/r88e_reg.h>
#include <dev/rtwn/rtl8812a/r12a_reg.h>
/*
* MAC registers.
*/
/* System Configuration. */
#define R92E_LDOV12_CTRL 0x014
#define R92E_AFE_XTAL_CTRL 0x02c
#define R92E_APE_PLL_CTRL_EXT 0x078
/* Bits for R92E_AFE_XTAL_CTRL. */
#define R92E_AFE_XTAL_CTRL_ADDR_M 0x00fff000
#define R92E_AFE_XTAL_CTRL_ADDR_S 12
#endif /* R92E_REG_H */

View File

@ -0,0 +1,88 @@
/*-
* Copyright (c) 2017 Kevin Lo <kevlo@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.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#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/rtl8192e/r92e.h>
#include <dev/rtwn/rtl8192e/r92e_reg.h>
uint32_t
r92e_rf_read(struct rtwn_softc *sc, int chain, uint8_t addr)
{
uint32_t val;
val = rtwn_bb_read(sc, R92C_HSSI_PARAM2(chain));
rtwn_bb_write(sc, R92C_HSSI_PARAM2(chain),
RW(val, R92C_HSSI_PARAM2_READ_ADDR, addr) &
~R92C_HSSI_PARAM2_READ_EDGE);
rtwn_bb_setbits(sc, R92C_HSSI_PARAM2(0), R92C_HSSI_PARAM2_READ_EDGE, 0);
rtwn_bb_setbits(sc, R92C_HSSI_PARAM2(0), 0, R92C_HSSI_PARAM2_READ_EDGE);
rtwn_delay(sc, 20);
if (rtwn_bb_read(sc, R92C_HSSI_PARAM1(chain)) & R92C_HSSI_PARAM1_PI)
val = rtwn_bb_read(sc, R92C_HSPI_READBACK(chain));
else
val = rtwn_bb_read(sc, R92C_LSSI_READBACK(chain));
return (MS(val, R92C_LSSI_READBACK_DATA));
}
void
r92e_rf_write(struct rtwn_softc *sc, int chain, uint8_t addr, uint32_t val)
{
rtwn_bb_setbits(sc, 0x818, 0x20000, 0);
rtwn_bb_write(sc, R92C_LSSI_PARAM(chain),
SM(R88E_LSSI_PARAM_ADDR, addr) | SM(R92C_LSSI_PARAM_DATA, val));
rtwn_bb_setbits(sc, 0x818, 0, 0x20000);
}

View File

@ -0,0 +1,144 @@
/*-
* Copyright (c) 2017 Kevin Lo <kevlo@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.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#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/rtl8192e/r92e.h>
#include <dev/rtwn/rtl8192e/r92e_var.h>
#include <dev/rtwn/rtl8192e/r92e_rom_image.h>
void
r92e_parse_rom(struct rtwn_softc *sc, uint8_t *buf)
{
struct r92e_softc *rs = sc->sc_priv;
struct r92e_rom *rom = (struct r92e_rom *)buf;
uint8_t pwr_diff;
int i, j, k;
sc->thermal_meter = rom->thermal_meter;
rs->crystalcap = RTWN_GET_ROM_VAR(rom->crystalcap,
R92E_ROM_CRYSTALCAP_DEF);
for (i = 0; i < sc->ntxchains; i++) {
struct r92e_tx_pwr_2g *pwr_2g = &rom->tx_pwr[i].pwr_2g;
struct r92e_tx_pwr_diff_2g *pwr_diff_2g =
&rom->tx_pwr[i].pwr_diff_2g;
for (j = 0; j < R92E_GROUP_2G - 1; j++) {
rs->cck_tx_pwr[i][j] =
RTWN_GET_ROM_VAR(pwr_2g->cck[j],
R92E_DEF_TX_PWR_2G);
rs->ht40_tx_pwr_2g[i][j] =
RTWN_GET_ROM_VAR(pwr_2g->ht40[j],
R92E_DEF_TX_PWR_2G);
}
rs->cck_tx_pwr[i][j] = RTWN_GET_ROM_VAR(pwr_2g->cck[j],
R92E_DEF_TX_PWR_2G);
rs->cck_tx_pwr_diff_2g[i][0] = 0;
rs->ofdm_tx_pwr_diff_2g[i][0] = RTWN_SIGN4TO8(
MS(pwr_diff_2g->ht20_ofdm, LOW_PART));
rs->bw20_tx_pwr_diff_2g[i][0] = RTWN_SIGN4TO8(
MS(pwr_diff_2g->ht20_ofdm, HIGH_PART));
rs->bw40_tx_pwr_diff_2g[i][0] = 0;
pwr_diff = RTWN_GET_ROM_VAR(pwr_diff_2g->ht20_ofdm,
R92E_DEF_TX_PWR_HT20_DIFF);
if (pwr_diff != R92E_DEF_TX_PWR_HT20_DIFF) {
rs->ofdm_tx_pwr_diff_2g[i][0] = RTWN_SIGN4TO8(
MS(pwr_diff_2g->ht20_ofdm, LOW_PART));
rs->bw20_tx_pwr_diff_2g[i][0] = RTWN_SIGN4TO8(
MS(pwr_diff_2g->ht20_ofdm, HIGH_PART));
} else {
rs->ofdm_tx_pwr_diff_2g[i][0] =
rs->bw20_tx_pwr_diff_2g[i][0] = pwr_diff;
}
for (j = 1, k = 0; k < nitems(pwr_diff_2g->diff123); j++, k++) {
pwr_diff = RTWN_GET_ROM_VAR(
pwr_diff_2g->diff123[k].ofdm_cck,
R92E_DEF_TX_PWR_DIFF);
if (pwr_diff != R92E_DEF_TX_PWR_DIFF) {
rs->cck_tx_pwr_diff_2g[i][j] = RTWN_SIGN4TO8(
MS(pwr_diff_2g->diff123[k].ofdm_cck,
LOW_PART));
rs->ofdm_tx_pwr_diff_2g[i][j] = RTWN_SIGN4TO8(
MS(pwr_diff_2g->diff123[k].ofdm_cck,
HIGH_PART));
} else {
rs->cck_tx_pwr_diff_2g[i][j] =
rs->ofdm_tx_pwr_diff_2g[i][j] = pwr_diff;
}
pwr_diff = RTWN_GET_ROM_VAR(
pwr_diff_2g->diff123[k].ht40_ht20,
R92E_DEF_TX_PWR_DIFF);
if (pwr_diff != R92E_DEF_TX_PWR_DIFF) {
rs->bw20_tx_pwr_diff_2g[i][j] = RTWN_SIGN4TO8(
MS(pwr_diff_2g->diff123[k].ht40_ht20,
LOW_PART));
rs->bw40_tx_pwr_diff_2g[i][j] = RTWN_SIGN4TO8(
MS(pwr_diff_2g->diff123[k].ht40_ht20,
HIGH_PART));
} else {
rs->bw20_tx_pwr_diff_2g[i][j] =
rs->bw40_tx_pwr_diff_2g[i][j] = pwr_diff;
}
}
}
rs->regulatory = MS(rom->rf_board_opt, R92C_ROM_RF1_REGULATORY);
/* Read MAC address. */
IEEE80211_ADDR_COPY(sc->sc_ic.ic_macaddr, rom->macaddr);
}

View File

@ -0,0 +1,42 @@
/*-
* Copyright (c) 2017 Kevin Lo <kevlo@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.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef R92E_ROM_DEFS_H
#define R92E_ROM_DEFS_H
#include <dev/rtwn/rtl8192c/r92c_rom_defs.h>
#define R92E_GROUP_2G 6
#define R92E_MAX_TX_COUNT 4
#define R92E_MAX_RF_PATH 4
#define R92E_EFUSE_MAX_LEN 512
#define R92E_EFUSE_MAP_LEN 512
#endif /* R92E_ROM_DEFS_H */

View File

@ -0,0 +1,87 @@
/*-
* Copyright (c) 2017 Kevin Lo <kevlo@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 R92E_ROM_IMAGE_H
#define R92E_ROM_IMAGE_H
#include <dev/rtwn/rtl8192e/r92e_rom_defs.h>
#define R92E_DEF_TX_PWR_2G 0x2d
#define R92E_DEF_TX_PWR_HT20_DIFF 0x02
#define R92E_DEF_TX_PWR_DIFF 0xfe
struct r92e_tx_pwr_2g {
uint8_t cck[R92E_GROUP_2G];
uint8_t ht40[R92E_GROUP_2G - 1];
} __packed;
struct r92e_tx_pwr_diff_2g {
uint8_t ht20_ofdm;
struct {
uint8_t ht40_ht20;
uint8_t ofdm_cck;
} __packed diff123[R92E_MAX_TX_COUNT - 1];
} __packed;
struct r92e_tx_pwr {
struct r92e_tx_pwr_2g pwr_2g;
struct r92e_tx_pwr_diff_2g pwr_diff_2g;
uint8_t reserved[24];
} __packed;
/*
* RTL8192EU ROM image.
*/
struct r92e_rom {
uint8_t reserved1[16];
struct r92e_tx_pwr tx_pwr[R92E_MAX_RF_PATH];
uint8_t channel_plan;
uint8_t crystalcap;
#define R92E_ROM_CRYSTALCAP_DEF 0x20
uint8_t thermal_meter;
uint8_t iqk_lck;
uint8_t pa_type;
uint8_t lna_type_2g;
uint8_t reserved2;
uint8_t lna_type_5g;
uint8_t reserved3;
uint8_t rf_board_opt;
uint8_t rf_feature_opt;
uint8_t rf_bt_opt;
uint8_t version;
uint8_t customer_id;
uint8_t tx_bbswing_2g;
uint8_t tx_bbswing_5g;
uint8_t tx_pwr_calib_rate;
uint8_t rf_ant_opt;
uint8_t rfe_option;
uint8_t reserved4[5];
uint16_t vid;
uint16_t pid;
uint8_t reserved5[3];
uint8_t macaddr[IEEE80211_ADDR_LEN];
uint8_t reserved6[2];
uint8_t string[7]; /* "Realtek" */
uint8_t reserved7[282];
} __packed;
_Static_assert(sizeof(struct r92e_rom) == R92E_EFUSE_MAP_LEN,
"R92E_EFUSE_MAP_LEN must be equal to sizeof(struct r92e_rom)!");
#endif /* R92E_ROM_IMAGE_H */

View File

@ -0,0 +1,97 @@
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2014, 2017 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/rtl8192e/r92e.h>
#include <dev/rtwn/rtl8192c/r92c_rx_desc.h>
#include <dev/rtwn/rtl8812a/r12a_fw_cmd.h>
#ifndef RTWN_WITHOUT_UCODE
void
r92e_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 < 2) {
device_printf(sc->sc_dev, "C2H report too short (len %d)\n",
len);
return;
}
len -= 2;
switch (buf[0]) { /* command id */
case R12A_C2H_TX_REPORT:
/* NOTREACHED */
KASSERT(0, ("use handle_tx_report() instead of %s\n",
__func__));
break;
}
}
#else
void
r92e_handle_c2h_report(struct rtwn_softc *sc, uint8_t *buf, int len)
{
/* Should not happen. */
device_printf(sc->sc_dev, "%s: called\n", __func__);
}
#endif
int8_t
r92e_get_rssi_cck(struct rtwn_softc *sc, void *physt)
{
return (10 + r88e_get_rssi_cck(sc, physt));
}

View File

@ -0,0 +1,54 @@
/*-
* Copyright (c) 2017 Kevin Lo <kevlo@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.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef R92E_VAR_H
#define R92E_VAR_H
#include <dev/rtwn/rtl8192e/r92e_rom_defs.h>
struct r92e_softc {
uint8_t chip;
uint8_t rs_flags;
uint8_t regulatory;
uint8_t crystalcap;
int8_t cck_tx_pwr[R92E_MAX_RF_PATH][R92E_GROUP_2G];
int8_t ht40_tx_pwr_2g[R92E_MAX_RF_PATH][R92E_GROUP_2G];
int8_t cck_tx_pwr_diff_2g[R92E_MAX_RF_PATH][R92E_MAX_TX_COUNT];
int8_t ofdm_tx_pwr_diff_2g[R92E_MAX_RF_PATH][R92E_MAX_TX_COUNT];
int8_t bw20_tx_pwr_diff_2g[R92E_MAX_RF_PATH][R92E_MAX_TX_COUNT];
int8_t bw40_tx_pwr_diff_2g[R92E_MAX_RF_PATH][R92E_MAX_TX_COUNT];
int ac_usb_dma_size;
int ac_usb_dma_time;
uint32_t rf_chnlbw[R92E_MAX_RF_PATH];
};
#endif /* R92E_VAR_H */

View File

@ -0,0 +1,43 @@
/*-
* Copyright (c) 2017 Kevin Lo <kevlo@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.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef RTL8192EU_H
#define RTL8192EU_H
#include <dev/rtwn/rtl8812a/r12a.h>
#include <dev/rtwn/rtl8192e/r92e.h>
/*
* Function declarations.
*/
/* r92eu_init.c */
void r92eu_init_rx_agg(struct rtwn_softc *);
void r92eu_post_init(struct rtwn_softc *);
#endif /* RTL8192EU_H */

View File

@ -0,0 +1,202 @@
/*-
* Copyright (c) 2017 Kevin Lo <kevlo@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/usb/usb.h>
#include <dev/usb/usbdi.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/usb/r92cu.h>
#include <dev/rtwn/rtl8188e/r88e.h>
#include <dev/rtwn/rtl8192e/r92e_priv.h>
#include <dev/rtwn/rtl8192e/r92e_reg.h>
#include <dev/rtwn/rtl8192e/r92e_var.h>
#include <dev/rtwn/rtl8192e/usb/r92eu.h>
#include <dev/rtwn/rtl8812a/usb/r12au.h>
#include <dev/rtwn/rtl8812a/usb/r12au_tx_desc.h>
#include <dev/rtwn/rtl8821a/usb/r21au.h>
#include <dev/rtwn/rtl8821a/r21a_reg.h>
void r92eu_attach(struct rtwn_usb_softc *);
static void
r92eu_attach_private(struct rtwn_softc *sc)
{
struct r92e_softc *rs;
rs = malloc(sizeof(struct r92e_softc), M_RTWN_PRIV, M_WAITOK | M_ZERO);
rs->ac_usb_dma_size = 0x06;
rs->ac_usb_dma_time = 0x20;
sc->sc_priv = rs;
}
void
r92e_detach_private(struct rtwn_softc *sc)
{
struct r92e_softc *rs = sc->sc_priv;
free(rs, M_RTWN_PRIV);
}
static void
r92eu_adj_devcaps(struct rtwn_softc *sc)
{
/* XXX TODO? */
}
void
r92eu_attach(struct rtwn_usb_softc *uc)
{
struct rtwn_softc *sc = &uc->uc_sc;
/* USB part. */
uc->uc_align_rx = r12au_align_rx;
uc->tx_agg_desc_num = 3;
/* Common part. */
sc->sc_flags = RTWN_FLAG_EXT_HDR;
sc->sc_set_chan = r92e_set_chan;
sc->sc_fill_tx_desc = r12a_fill_tx_desc;
sc->sc_fill_tx_desc_raw = r12a_fill_tx_desc_raw;
sc->sc_fill_tx_desc_null = r12a_fill_tx_desc_null;
sc->sc_dump_tx_desc = r12au_dump_tx_desc;
sc->sc_tx_radiotap_flags = r12a_tx_radiotap_flags;
sc->sc_rx_radiotap_flags = r12a_rx_radiotap_flags;
sc->sc_get_rx_stats = r12a_get_rx_stats;
sc->sc_get_rssi_cck = r92e_get_rssi_cck;
sc->sc_get_rssi_ofdm = r88e_get_rssi_ofdm;
sc->sc_classify_intr = r12au_classify_intr;
sc->sc_handle_tx_report = r12a_ratectl_tx_complete;
sc->sc_handle_c2h_report = r92e_handle_c2h_report;
sc->sc_check_frame = rtwn_nop_int_softc_mbuf;
sc->sc_rf_read = r92e_rf_read;
sc->sc_rf_write = r92e_rf_write;
sc->sc_check_condition = r92c_check_condition;
sc->sc_efuse_postread = rtwn_nop_softc;
sc->sc_parse_rom = r92e_parse_rom;
sc->sc_set_led = r92e_set_led;
sc->sc_power_on = r92e_power_on;
sc->sc_power_off = r92e_power_off;
#ifndef RTWN_WITHOUT_UCODE
sc->sc_fw_reset = r92e_fw_reset;
sc->sc_fw_download_enable = r12a_fw_download_enable;
#endif
sc->sc_llt_init = r92e_llt_init;
sc->sc_set_page_size = rtwn_nop_int_softc;
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 = r92eu_adj_devcaps;
sc->sc_vap_preattach = rtwn_nop_softc_vap;
sc->sc_postattach = rtwn_nop_softc;
sc->sc_detach_private = r92e_detach_private;
sc->sc_set_media_status = r92e_set_media_status;
#ifndef RTWN_WITHOUT_UCODE
sc->sc_set_rsvd_page = r88e_set_rsvd_page;
sc->sc_set_pwrmode = r92e_set_pwrmode;
sc->sc_set_rssi = rtwn_nop_softc; /* XXX TODO? */
#endif
sc->sc_beacon_init = r12a_beacon_init;
sc->sc_beacon_enable = r92c_beacon_enable;
sc->sc_beacon_set_rate = rtwn_nop_void_int;
sc->sc_beacon_select = r21a_beacon_select;
sc->sc_temp_measure = r88e_temp_measure;
sc->sc_temp_read = r88e_temp_read;
sc->sc_init_tx_agg = r21au_init_tx_agg;
sc->sc_init_rx_agg = r92eu_init_rx_agg;
sc->sc_init_ampdu = rtwn_nop_softc;
sc->sc_init_intr = r12a_init_intr;
sc->sc_init_edca = r92c_init_edca;
sc->sc_init_bb = r92e_init_bb;
sc->sc_init_rf = r92e_init_rf;
sc->sc_init_antsel = rtwn_nop_softc;
sc->sc_post_init = r92eu_post_init;
sc->sc_init_bcnq1_boundary = rtwn_nop_int_softc;
sc->mac_prog = &rtl8192eu_mac[0];
sc->mac_size = nitems(rtl8192eu_mac);
sc->bb_prog = &rtl8192eu_bb[0];
sc->bb_size = nitems(rtl8192eu_bb);
sc->agc_prog = &rtl8192eu_agc[0];
sc->agc_size = nitems(rtl8192eu_agc);
sc->rf_prog = &rtl8192eu_rf[0];
sc->name = "RTL8192EU";
sc->fwname = "rtwn-rtl8192eufw";
sc->fwsig = 0x92e;
sc->page_count = R92E_TX_PAGE_COUNT;
sc->pktbuf_count = 0; /* Unused */
sc->ackto = 0x40;
sc->npubqpages = R92E_PUBQ_NPAGES;
sc->page_size = R92E_TX_PAGE_SIZE;
sc->txdesc_len = sizeof(struct r12au_tx_desc);
sc->efuse_maxlen = R92E_EFUSE_MAX_LEN;
sc->efuse_maplen = R92E_EFUSE_MAP_LEN;
sc->rx_dma_size = R92E_RX_DMA_BUFFER_SIZE;
sc->macid_limit = R12A_MACID_MAX + 1;
sc->cam_entry_limit = R12A_CAM_ENTRY_COUNT;
sc->fwsize_limit = R92E_MAX_FW_SIZE;
sc->temp_delta = R88E_CALIB_THRESHOLD;
sc->bcn_status_reg[0] = R92C_TDECTRL;
sc->bcn_status_reg[1] = R21A_DWBCN1_CTRL;
sc->rcr = 0;
sc->ntxchains = 2;
sc->nrxchains = 2;
r92eu_attach_private(sc);
}

View File

@ -0,0 +1,96 @@
/*-
* Copyright (c) 2017 Kevin Lo <kevlo@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.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#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/rtl8192e/r92e_var.h>
#include <dev/rtwn/rtl8192e/usb/r92eu.h>
#include <dev/rtwn/rtl8192e/usb/r92eu_reg.h>
void
r92eu_init_rx_agg(struct rtwn_softc *sc)
{
struct r92e_softc *rs = sc->sc_priv;
/* Rx aggregation (USB). */
rtwn_setbits_1(sc, R12A_RXDMA_PRO, 0x20, 0x1e);
rtwn_write_4(sc, R92C_RXDMA_AGG_PG_TH,
rs->ac_usb_dma_size | (rs->ac_usb_dma_time << 8));
rtwn_setbits_1(sc, R92C_TRXDMA_CTRL, 0,
R92C_TRXDMA_CTRL_RXDMA_AGG_EN);
}
void
r92eu_post_init(struct rtwn_softc *sc)
{
/* Setup RTS BW (equal to data BW). */
rtwn_setbits_1(sc, R92C_QUEUE_CTRL, 0x08, 0);
/* Reset USB mode switch setting. */
rtwn_write_1(sc, R92C_ACLK_MON, 0);
rtwn_write_1(sc, R92C_USB_HRPWM, 0);
#ifndef RTWN_WITHOUT_UCODE
if (sc->sc_flags & RTWN_FW_LOADED) {
if (sc->sc_ratectl_sysctl == RTWN_RATECTL_FW) {
/* TODO: implement */
sc->sc_ratectl = RTWN_RATECTL_NET80211;
} else
sc->sc_ratectl = sc->sc_ratectl_sysctl;
} else
#endif
sc->sc_ratectl = RTWN_RATECTL_NONE;
}

View File

@ -0,0 +1,36 @@
/*-
* Copyright (c) 2017 Kevin Lo <kevlo@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.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef R92EU_REG_H
#define R92EU_REG_H
#include <dev/rtwn/rtl8188e/usb/r88eu_reg.h>
#include <dev/rtwn/rtl8192e/r92e_reg.h>
#include <dev/rtwn/rtl8812a/r12a_reg.h>
#endif /* R92EU_REG_H */

View File

@ -77,6 +77,8 @@ r12a_beacon_init(struct rtwn_softc *sc, void *buf, int id)
txd->txdw3 = htole32(R12A_TXDW3_DRVRATE);
txd->txdw3 |= htole32(SM(R12A_TXDW3_SEQ_SEL, id));
txd->txdw4 = htole32(SM(R12A_TXDW4_DATARATE, RTWN_RIDX_CCK1));
txd->txdw6 = htole32(SM(R21A_TXDW6_MBSSID, id));
}

View File

@ -68,14 +68,14 @@ void
r12a_fw_reset(struct rtwn_softc *sc, int reason)
{
/* Reset MCU IO wrapper. */
rtwn_setbits_1(sc, R92C_RSV_CTRL, 0x02, 0);
rtwn_setbits_1(sc, R92C_RSV_CTRL, R92C_RSV_CTRL_WLOCK_00, 0);
rtwn_setbits_1(sc, R92C_RSV_CTRL + 1, 0x08, 0);
rtwn_setbits_1_shift(sc, R92C_SYS_FUNC_EN,
R92C_SYS_FUNC_EN_CPUEN, 0, 1);
/* Enable MCU IO wrapper. */
rtwn_setbits_1(sc, R92C_RSV_CTRL, 0x02, 0);
rtwn_setbits_1(sc, R92C_RSV_CTRL, R92C_RSV_CTRL_WLOCK_00, 0);
rtwn_setbits_1(sc, R92C_RSV_CTRL + 1, 0, 0x08);
rtwn_setbits_1_shift(sc, R92C_SYS_FUNC_EN,

View File

@ -215,6 +215,7 @@ r12au_attach(struct rtwn_usb_softc *uc)
sc->sc_fw_reset = r12a_fw_reset;
sc->sc_fw_download_enable = r12a_fw_download_enable;
#endif
sc->sc_llt_init = r92c_llt_init;
sc->sc_set_page_size = r12a_set_page_size;
sc->sc_lc_calib = r12a_lc_calib;
sc->sc_iq_calib = r12a_iq_calib;

View File

@ -174,7 +174,7 @@ r21a_power_on(struct rtwn_softc *sc)
R92C_CR_CALTMR_EN));
if (rtwn_read_4(sc, R92C_SYS_CFG) & R92C_SYS_CFG_TRP_BT_EN)
RTWN_CHK(rtwn_setbits_1(sc, 0x07C, 0, 0x40));
RTWN_CHK(rtwn_setbits_1(sc, R92C_LDO_SWR_CTRL, 0, 0x40));
return (0);
#undef RTWN_CHK

View File

@ -201,6 +201,7 @@ r21au_attach(struct rtwn_usb_softc *uc)
sc->sc_fw_reset = r21a_fw_reset;
sc->sc_fw_download_enable = r12a_fw_download_enable;
#endif
sc->sc_llt_init = r92c_llt_init;
sc->sc_set_page_size = rtwn_nop_int_softc;
sc->sc_lc_calib = rtwn_nop_softc; /* XXX not used */
sc->sc_iq_calib = r12a_iq_calib;

View File

@ -21,12 +21,14 @@
*/
void r92cu_attach(struct rtwn_usb_softc *);
void r92eu_attach(struct rtwn_usb_softc *);
void r88eu_attach(struct rtwn_usb_softc *);
void r12au_attach(struct rtwn_usb_softc *);
void r21au_attach(struct rtwn_usb_softc *);
enum {
RTWN_CHIP_RTL8192CU,
RTWN_CHIP_RTL8192EU,
RTWN_CHIP_RTL8188EU,
RTWN_CHIP_RTL8812AU,
RTWN_CHIP_RTL8821AU,
@ -101,6 +103,15 @@ static const STRUCT_USB_HOST_ID rtwn_devs[] = {
RTWN_RTL8192CU_DEV(ZYXEL, RTL8192CU),
#undef RTWN_RTL8192CU_DEV
/* RTL8192EU */
#define RTWN_RTL8192EU_DEV(v,p) \
{ USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, RTWN_CHIP_RTL8192EU) }
RTWN_RTL8192EU_DEV(DLINK, DWA131E1),
RTWN_RTL8192EU_DEV(REALTEK, RTL8192EU),
RTWN_RTL8192EU_DEV(TPLINK, WN822NV4),
RTWN_RTL8192EU_DEV(TPLINK, WN823NV2),
#undef RTWN_RTL8192EU_DEV
/* RTL8188EU */
#define RTWN_RTL8188EU_DEV(v,p) \
{ USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, RTWN_CHIP_RTL8188EU) }
@ -148,6 +159,7 @@ typedef void (*chip_usb_attach)(struct rtwn_usb_softc *);
static const chip_usb_attach rtwn_chip_usb_attach[RTWN_CHIP_MAX_USB] = {
[RTWN_CHIP_RTL8192CU] = r92cu_attach,
[RTWN_CHIP_RTL8192EU] = r92eu_attach,
[RTWN_CHIP_RTL8188EU] = r88eu_attach,
[RTWN_CHIP_RTL8812AU] = r12au_attach,
[RTWN_CHIP_RTL8821AU] = r21au_attach

View File

@ -3815,6 +3815,7 @@ product REALTEK DUMMY 0x0000 Dummy product
product REALTEK USB20CRW 0x0158 USB20CRW Card Reader
product REALTEK RTL8188ETV 0x0179 RTL8188ETV
product REALTEK RTL8188CTV 0x018a RTL8188CTV
product REALTEK RTL8188RU_2 0x317f RTL8188RU
product REALTEK USBKR100 0x8150 USBKR100 USB Ethernet
product REALTEK RTL8152 0x8152 RTL8152 USB Ethernet
product REALTEK RTL8153 0x8153 RTL8153 USB Ethernet
@ -3831,6 +3832,7 @@ product REALTEK RTL8188CU_1 0x817a RTL8188CU
product REALTEK RTL8188CU_2 0x817b RTL8188CU
product REALTEK RTL8187 0x8187 RTL8187 Wireless Adapter
product REALTEK RTL8187B_0 0x8189 RTL8187B Wireless Adapter
product REALTEK RTL8192EU 0x818b RTL8192EU
product REALTEK RTL8188CU_3 0x8191 RTL8188CU
product REALTEK RTL8196EU 0x8196 RTL8196EU
product REALTEK RTL8187B_1 0x8197 RTL8187B Wireless Adapter
@ -3844,7 +3846,7 @@ product REALTEK RTL8188RU_1 0x817d RTL8188RU
product REALTEK RTL8188RU_3 0x817f RTL8188RU
product REALTEK RTL8712 0x8712 RTL8712
product REALTEK RTL8713 0x8712 RTL8713
product REALTEK RTL8188RU_2 0x317f RTL8188RU
product REALTEK RTL8723BU 0xb720 RTL8723BU
product REALTEK RTL8192SU 0xc512 RTL8192SU
/* RedOctane products */
@ -4484,6 +4486,7 @@ product TOSHIBA TRANSMEMORY 0x6545 USB ThumbDrive
/* TP-Link products */
product TPLINK T4U 0x0101 Archer T4U
product TPLINK WN822NV4 0x0108 TL-WN822N v4
product TPLINK WN823NV2 0x0109 TL-WN823N v2
/* Trek Technology products */

View File

@ -16,7 +16,7 @@ SRCS = if_rtwn.c if_rtwn_tx.c if_rtwn_rx.c if_rtwn_beacon.c \
.PATH: ${.CURDIR}/../../dev/rtwn/rtl8192c
SRCS += r92c_attach.c r92c_beacon.c r92c_calib.c r92c_chan.c r92c_fw.c \
r92c_init.c r92c_rf.c r92c_rom.c r92c_rx.c r92c_tx.c \
r92c_init.c r92c_llt.c r92c_rf.c r92c_rom.c r92c_rx.c r92c_tx.c \
r92c.h r92c_priv.h r92c_reg.h r92c_var.h r92c_rom_defs.h \
r92c_rom_image.h r92c_fw_cmd.h r92c_rx_desc.h r92c_tx_desc.h
@ -26,6 +26,11 @@ SRCS += r88e_beacon.c r88e_calib.c r88e_chan.c r88e_fw.c r88e_init.c \
r88e_priv.h r88e_reg.h r88e_rom_defs.h r88e_rom_image.h \
r88e_fw_cmd.h r88e_rx_desc.h r88e_tx_desc.h
.PATH: ${.CURDIR}/../../dev/rtwn/rtl8192e
SRCS += r92e_chan.c r92e_fw.c r92e_init.c r92e_led.c r92e_rf.c \
r92e_rom.c r92e_rx.c r92e.h r92e_priv.h r92e_reg.h \
r92e_rom_image.h r92e_rom_defs.h
.PATH: ${.CURDIR}/../../dev/rtwn/rtl8812a
SRCS += r12a_beacon.c r12a_calib.c r12a_caps.c r12a_chan.c r12a_fw.c \
r12a_init.c r12a_led.c r12a_rf.c r12a_rom.c r12a_rx.c r12a_tx.c \

View File

@ -20,6 +20,9 @@ SRCS += r88eu_attach.c r88eu_init.c r88eu_rx.c \
SRCS += r92cu_attach.c r92cu_init.c r92cu_led.c r92cu_rx.c r92cu_tx.c \
r92cu.h r92cu_priv.h r92cu_reg.h r92cu_tx_desc.h
.PATH: ${.CURDIR}/../../dev/rtwn/rtl8192e/usb
SRCS += r92eu_attach.c r92eu_init.c r92eu.h r92eu_reg.h
.PATH: ${.CURDIR}/../../dev/rtwn/rtl8812a/usb
SRCS += r12au_attach.c r12au_init.c r12au_rx.c r12au_tx.c \
r12au.h r12au_reg.h r12au_tx_desc.h

View File

@ -1,6 +1,6 @@
# $FreeBSD$
SUBDIR= rtwnrtl8188eu rtwnrtl8192cT rtwnrtl8192cU rtwnrtl8812au rtwnrtl8821au \
rtwnrtl8192cE rtwnrtl8192cEB
SUBDIR= rtwnrtl8188eu rtwnrtl8192cT rtwnrtl8192cU rtwnrtl8192eu rtwnrtl8812au \
rtwnrtl8821au rtwnrtl8192cE rtwnrtl8192cEB
.include <bsd.subdir.mk>

View File

@ -0,0 +1,6 @@
# $FreeBSD$
KMOD= rtwn-rtl8192eufw
IMG= rtwn-rtl8192eufw
.include <bsd.kmod.mk>