rtwn: add support for the RTL8188FTV USB chipset

Add support for the RTL8188FTV chipset to rtwn(4)/rtwn_usb(4).

Differential Revision: https://reviews.freebsd.org/D60875
This commit is contained in:
Mir Saheb Ali authored and Adrian Chadd committed 2026-10-27 19:57:07 -07:00
1 parent 4ab9e73994
commit 2c38dc04d6
39 files changed
+3336 -5

No files matched your search

+4 -1
View File
@@ -19,7 +19,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd September 1, 2026
.Dd October 22, 2026
.Dt RTWN 4
.Os
.Sh NAME
@@ -89,6 +89,8 @@ driver supports USB and PCI devices with the following chipsets:
.It
Realtek 802.11n wireless 8188e (RTL8188E)
.It
Realtek 802.11n wireless 8188f (RTL8188F)
.It
Realtek 802.11n wireless 8192c (RTL8192C)
.It
Realtek 802.11n wireless 8192e (RTL8192E)
@@ -119,6 +121,7 @@ which are loaded when an interface is brought up:
.Bl -tag -width Ds -offset indent -compact
.It Pa /boot/kernel/rtwn-rtl8188eefw.ko
.It Pa /boot/kernel/rtwn-rtl8188eufw.ko
.It Pa /boot/kernel/rtwn-rtl8188fufw.ko
.It Pa /boot/kernel/rtwn-rtl8192cfwE_B.ko
.It Pa /boot/kernel/rtwn-rtl8192cfwE.ko
.It Pa /boot/kernel/rtwn-rtl8192cfwT.ko
+2 -1
View File
@@ -29,7 +29,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
.\" THE POSSIBILITY OF SUCH DAMAGES.
.\"
.Dd September 11, 2026
.Dd October 22, 2026
.Dt RTWN_USB 4
.Os
.Sh NAME
@@ -101,6 +101,7 @@ Realtek RTL 8188/8192/8723/8812 and 8821 chipsets, including:
.It "Realtek RTL8723BU" Ta RTL8723BU Ta USB 2.0
.It "Realtek RTL8192CU" Ta RTL8192CU Ta USB 2.0
.It "Realtek RTL8188CUS" Ta RTL8188CUS Ta USB 2.0
.It "Realtek RTL8188FTV" Ta RTL8188FTV Ta USB 2.0
.It "Sitecom WLA-7100" Ta RTL8812AU Ta USB 3.0
.It "TP-Link Archer T2U Nano" Ta RTL8821AU Ta USB 2.0
.It "TP-Link Archer T2U Plus" Ta RTL8821AU Ta USB 2.0
+3 -1
View File
@@ -41,6 +41,7 @@ of the following:
.Bd -ragged -offset indent
.Cd "device rtwn-rtl8188eefw"
.Cd "device rtwn-rtl8188eufw"
.Cd "device rtwn-rtl8188fufw"
.Cd "device rtwn-rtl8192cfwE_B"
.Cd "device rtwn-rtl8192cfwE"
.Cd "device rtwn-rtl8192cfwT"
@@ -56,6 +57,7 @@ module at boot time, place the following line in
.Bd -literal -offset indent
rtwn-rtl8188eefw_load="YES"
rtwn-rtl8188eufw_load="YES"
rtwn-rtl8188fufw_load="YES"
rtwn-rtl8192cfwE_B_load="YES"
rtwn-rtl8192cfwE_load="YES"
rtwn-rtl8192cfwT_load="YES"
@@ -70,7 +72,7 @@ to firmware sets for the Realtek RTL8188CE chip based PCIe adapters.
rtwn-rtl8188ee module provides access to firmware sets for the
Realtek RTL8188EE chip based PCIe adapters.
Other modules provide access to firmware sets for the Realtek RTL8188CUS,
RTL8188CE-VAU, RTL8188EUS, RTL8188RU, RTL8192CU, RTL8192EU, RTL8812AU and
RTL8188CE-VAU, RTL8188EUS, RTL8188FTV, RTL8188RU, RTL8192CU, RTL8192EU, RTL8812AU and
RTL8821AU chip based USB WiFi adapters.
They may be
statically linked into the kernel, or loaded as a modules.
+11
View File
@@ -2964,6 +2964,17 @@ dev/rtwn/rtl8188e/pci/r88ee_init.c optional rtwn_pci pci
dev/rtwn/rtl8188e/pci/r88ee_rx.c optional rtwn_pci pci
dev/rtwn/rtl8188e/usb/r88eu_attach.c optional rtwn_usb
dev/rtwn/rtl8188e/usb/r88eu_init.c optional rtwn_usb
# RTL8188F
dev/rtwn/rtl8188f/r88f_calib.c optional rtwn
dev/rtwn/rtl8188f/r88f_chan.c optional rtwn
dev/rtwn/rtl8188f/r88f_fw.c optional rtwn
dev/rtwn/rtl8188f/r88f_init.c optional rtwn
dev/rtwn/rtl8188f/r88f_rom.c optional rtwn
dev/rtwn/rtl8188f/r88f_rx.c optional rtwn
dev/rtwn/rtl8188f/usb/r88fu_attach.c optional rtwn_usb
dev/rtwn/rtl8188f/usb/r88fu_init.c optional rtwn_usb
# RTL8192C
dev/rtwn/rtl8192c/r92c_attach.c optional rtwn
dev/rtwn/rtl8192c/r92c_beacon.c optional rtwn
+471
View File
@@ -0,0 +1,471 @@
begin 644 rtwn-rtl8188fufw.fw.uu
M\8@0``0````((A<V_%$"`+PX```````````````````"AWT"R%4`````````
M`````````K4G``````````````````+(IP``````````````````````````
M`````````````LA6```````"PB$```````+(I@``````````````````````
M``````````````````````````````````*(&`**V0*`A@*`B0*I60*C#`*V
M8@*`E0*`F`*`FP*`G@*`H0*`I`*`IP*`J@*`K0*`L`*@/0*`M@*`N0*S&P*X
MS0*X4@*W^0*Q8@*S?`*`S@*`T0*`U`*`UP````*`W0*`X`*`XP*`Y@*`Z0*`
M[`*`[P*`\@*`]0*`^`*`^P*`_@*!`0*!!`*!!P*!"@*!#0*!$`*!$P*!%@*!
M&0````````````````````````````````*_BP+)+0*6[@*8XP*!0`*D:P+-
M\0*!20*!3`*!3P*!4@*!50*!6`*!6P*9^`*!80*!9`+&MP+/Z`+0'0``````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````!7P_P\````5\`\`````!?#_#P````7P#P`````0\/\/````$/`/````
M`/4/``````#P#P``````#0````````H(`P,`!`D'`P,`!`@&`P(`!`@%`P$`
M!`T*!P4`"`P*!P0`"`L*!@4`"`L*!0,`"`L*`P(`"!02#`0`$!02"00`$"0B
M'!(`("0B&`P`("0B%`8`("0B#P0`("0A"@0`(",A#`0`(",?"@0`("(?#P0`
M("$?%@P`(#$O(!0`,#$O&!``,#$L&`P`,#$J%`P`,#$H%```,#$D%```,#$>
M%```,`("`P0$"`D)#`X0$@()"PX-#Q`2``0`!``(`!``(P`M`%``D0##`2<!
M,0%>`(P`R`#<`5X!:`&:`<P!Z@("!`@,$A@D,$A@;!0H,E!XH,CF`0$!`@$!
M`@(#`P0$`@0&!P<("`@!`0$"`0$!`0$!`@(!`0$!`0("`@$!`0$!`0("`P,$
M!0$"`P0%!@<(`P,#`@,#`P,#`@("`@("`@("`@(9!@0"`!@`````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````PJ^`_C(2A`2%T`MUT`BJX,*,Y8HD9_6*
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
M`_'N5!\2`SR0D\IT`?"0D\K@_\.4!%`4[Q*/4H^"CH/[email protected])/*X`3P@.*0
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
%#R(`:2H`
`
end
+3 -1
View File
@@ -1520,6 +1520,8 @@ rtwn_dma_init(struct rtwn_softc *sc)
if (error != 0)
return (error);
rtwn_enable_mac_txrx(sc);
/* Set the number of pages for each queue. */
RTWN_DPRINTF(sc, RTWN_DEBUG_RESET,
"%s: pages per queue: high %d, normal %d, low %d, public %d\n",
@@ -1903,7 +1905,7 @@ rtwn_init_beacon_reg(struct rtwn_softc *sc)
rtwn_write_1(sc, R92C_BCN_CTRL(0), R92C_BCN_CTRL_DIS_TSF_UDT0);
rtwn_write_1(sc, R92C_BCN_CTRL(1), R92C_BCN_CTRL_DIS_TSF_UDT0);
rtwn_write_2(sc, R92C_TBTT_PROHIBIT, 0x6404);
rtwn_write_1(sc, R92C_DRVERLYINT, 0x05);
rtwn_init_beacon_timer(sc);
rtwn_write_1(sc, R92C_BCNDMATIM, 0x02);
rtwn_write_2(sc, R92C_BCNTCFG, 0x660f);
}
+6
View File
@@ -308,6 +308,7 @@ struct rtwn_softc {
void (*sc_fw_download_enable)(struct rtwn_softc *, int);
#endif
int (*sc_llt_init)(struct rtwn_softc *);
void (*sc_enable_mac_txrx)(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 *);
@@ -362,6 +363,7 @@ struct rtwn_softc {
uint8_t (*sc_temp_read)(struct rtwn_softc *);
void (*sc_init_tx_agg)(struct rtwn_softc *);
void (*sc_init_rx_agg)(struct rtwn_softc *);
void (*sc_init_beacon_timer)(struct rtwn_softc *);
void (*sc_init_intr)(struct rtwn_softc *);
void (*sc_init_ampdu)(struct rtwn_softc *);
void (*sc_init_edca)(struct rtwn_softc *);
@@ -515,6 +517,8 @@ void rtwn_attach_vht_cap_info_mcs(struct rtwn_softc *);
#endif
#define rtwn_llt_init(_sc) \
(((_sc)->sc_llt_init)((_sc)))
#define rtwn_enable_mac_txrx(_sc) \
(((_sc)->sc_enable_mac_txrx)((_sc)))
#define rtwn_set_page_size(_sc) \
(((_sc)->sc_set_page_size)((_sc)))
#define rtwn_lc_calib(_sc) \
@@ -587,6 +591,8 @@ void rtwn_attach_vht_cap_info_mcs(struct rtwn_softc *);
(((_sc)->sc_init_tx_agg)((_sc)))
#define rtwn_init_rx_agg(_sc) \
(((_sc)->sc_init_rx_agg)((_sc)))
#define rtwn_init_beacon_timer(_sc) \
(((_sc)->sc_init_beacon_timer)((_sc)))
#define rtwn_init_intr(_sc) \
(((_sc)->sc_init_intr)((_sc)))
#define rtwn_init_ampdu(_sc) \
+2
View File
@@ -162,6 +162,7 @@ r88ee_attach(struct rtwn_pci_softc *pc)
sc->sc_fw_download_enable = r88e_fw_download_enable;
#endif
sc->sc_llt_init = r92c_llt_init;
sc->sc_enable_mac_txrx = rtwn_nop_softc;
sc->sc_set_page_size = r92c_set_page_size;
sc->sc_lc_calib = r92c_lc_calib;
sc->sc_iq_calib = r88e_iq_calib;
@@ -185,6 +186,7 @@ r88ee_attach(struct rtwn_pci_softc *pc)
sc->sc_temp_read = r88e_temp_read;
sc->sc_init_tx_agg = rtwn_nop_softc;
sc->sc_init_rx_agg = rtwn_nop_softc;
sc->sc_init_beacon_timer = r92c_init_beacon_timer;
sc->sc_init_ampdu = r92ce_init_ampdu;
sc->sc_init_intr = r88ee_init_intr;
sc->sc_init_edca = r92ce_init_edca;
+2
View File
@@ -155,6 +155,7 @@ r88eu_attach(struct rtwn_usb_softc *uc)
sc->sc_fw_download_enable = r88e_fw_download_enable;
#endif
sc->sc_llt_init = r92c_llt_init;
sc->sc_enable_mac_txrx = rtwn_nop_softc;
sc->sc_set_page_size = r92c_set_page_size;
sc->sc_lc_calib = r92c_lc_calib;
sc->sc_iq_calib = r88e_iq_calib;
@@ -178,6 +179,7 @@ r88eu_attach(struct rtwn_usb_softc *uc)
sc->sc_temp_read = r88e_temp_read;
sc->sc_init_tx_agg = r92cu_init_tx_agg;
sc->sc_init_rx_agg = r88eu_init_rx_agg;
sc->sc_init_beacon_timer = r92c_init_beacon_timer;
sc->sc_init_ampdu = rtwn_nop_softc;
sc->sc_init_intr = r88eu_init_intr;
sc->sc_init_edca = r92c_init_edca;
+57
View File
@@ -0,0 +1,57 @@
/*
* Copyright (c) 2026 Mir Saheb Ali <mirsahebali@pm.me>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#ifndef RTL8188F_H
#define RTL8188F_H
#include <dev/rtwn/if_rtwn_ridx.h>
/*
* Global Definitions.
*/
#define R88F_HQ_NPAGES 12
#define R88F_LQ_NPAGES 2
#define R88F_NQ_NPAGES 2
#define R88F_TXPKTBUF_COUNT 177
#define R88F_TX_PAGE_COUNT 247
#define R88F_RX_DMA_BUFFER_SIZE 0x3f80
#define R88F_MAX_FW_SIZE 21020
#define R88F_RTWN_POWER_COUNT 28
/*
* Function declarations.
*/
/* r88f_rom.c */
int r88f_efuse_preread(struct rtwn_softc *);
void r88f_parse_rom(struct rtwn_softc *, uint8_t *);
/* r88f_rx.c */
int8_t r88f_get_rssi_cck(struct rtwn_softc *, void *);
int8_t r88f_get_rssi_ofdm(struct rtwn_softc *, void *);
void r88f_get_rx_stats(struct rtwn_softc *, struct ieee80211_rx_stats *,
const void *, const void *);
/* r88f_init.c */
int r88f_set_page_size(struct rtwn_softc *);
void r88f_init_ampdu(struct rtwn_softc *);
int r88f_llt_init(struct rtwn_softc *);
void r88f_init_rf(struct rtwn_softc *);
/* r88f_calib.c */
void r88f_lc_calib(struct rtwn_softc *);
void r88f_iq_calib(struct rtwn_softc *);
/* r88f_chan.c */
void r88f_set_chan(struct rtwn_softc *, struct ieee80211_channel *);
void r88f_get_txpower(struct rtwn_softc *, int, struct ieee80211_channel *,
uint8_t[RTWN_RIDX_COUNT]);
/* r88f_fw.c */
void r88f_fw_reset(struct rtwn_softc *, int);
void r88f_fw_download_enable(struct rtwn_softc *, int);
#endif /* RTL8188F_H */
+728
View File
@@ -0,0 +1,728 @@
/*
* Copyright (c) 2026 Mir Saheb Ali <mirsahebali@pm.me>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <sys/cdefs.h>
#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/rtl8192c/r92c_reg.h>
#include <dev/rtwn/rtl8723b/r23b_reg.h>
#include <dev/rtwn/rtl8188f/r88f.h>
#include <dev/rtwn/rtl8188f/r88f_reg.h>
#define OFDM_LSTF_MASK 0x70000000
void
r88f_lc_calib(struct rtwn_softc *sc)
{
uint32_t reg;
uint32_t rf_amode, lstf;
int i;
/* Check continuous TX and Packet TX */
lstf = rtwn_bb_read(sc, R92C_OFDM1_LSTF);
if (lstf & OFDM_LSTF_MASK) {
/* Disable all continuous TX */
reg = lstf & ~OFDM_LSTF_MASK;
rtwn_bb_write(sc, R92C_OFDM1_LSTF, reg);
} else {
/* Deal with Packet TX case */
/* block all queues */
rtwn_write_1(sc, R92C_TXPAUSE, 0xff);
}
/* Read original RF mode Path A */
rf_amode = rtwn_rf_read(sc, 0, R92C_RF_CHNLBW);
/* Start LC calibration */
rtwn_rf_write(sc, 0, R92C_RF_CHNLBW, rf_amode | 0x08000);
for (i = 0; i < 100; i++) {
if ((rtwn_rf_read(sc, 0, R92C_RF_CHNLBW) & 0x08000) == 0)
break;
rtwn_delay(sc, 10);
}
if (i == 100)
device_printf(sc->sc_dev, "LC calibration timed out.\n");
rtwn_rf_write(sc, 0, R92C_RF_CHNLBW, rf_amode);
/* Restore original parameters */
if (lstf & OFDM_LSTF_MASK)
rtwn_bb_write(sc, R92C_OFDM1_LSTF, lstf);
else /* Deal with Packet TX case */
rtwn_write_1(sc, R92C_TXPAUSE, 0x00);
}
#define R88F_ADDA_REGS 16
#define R88F_MAC_REGS 4
#define R88F_BB_REGS 9
struct r88f_iqk_calib_regs {
uint32_t adda_regs[R88F_ADDA_REGS];
uint32_t mac_regs[R88F_MAC_REGS];
uint32_t bb_regs[R88F_BB_REGS];
uint32_t hssi_param1;
};
struct r88f_iqk_result {
uint32_t before;
uint32_t after;
};
static const uint32_t iqk_adda_regs[R88F_ADDA_REGS] = {
R88F_FPGA0_XCD_SWITCH_CTRL, R88F_BLUETOOTH,
R88F_RX_WAIT_CCA, R88F_TX_CCK_RFON,
R88F_TX_CCK_BBON, R88F_TX_OFDM_RFON,
R88F_TX_OFDM_BBON, R88F_TX_TO_RX,
R88F_TX_TO_TX, R88F_RX_CCK,
R88F_RX_OFDM, R88F_RX_WAIT_RIFS,
R88F_RX_TO_RX, R88F_STANDBY,
R88F_SLEEP, R88F_PMPD_ANAEN
};
static const uint32_t iqk_mac_regs[R88F_MAC_REGS] = {
R92C_TXPAUSE, R92C_BCN_CTRL(0),
R92C_BCN_CTRL(1), R92C_GPIO_MUXCFG
};
static const uint32_t iqk_bb_regs[R88F_BB_REGS] = {
R92C_OFDM0_TRXPATHENA, R92C_OFDM0_TRMUXPAR,
R88F_FPGA0_XCD_RF_SW_CTRL, R92C_CONFIG_ANT(0), R92C_CONFIG_ANT(1),
R92C_FPGA0_RFIFACESW(0), R92C_FPGA0_RFIFACEOE(0),
R92C_FPGA0_RFIFACEOE(1), R92C_FPGA0_RFMOD
};
static void
r88f_iqk_save_regs(struct rtwn_softc *sc, struct r88f_iqk_calib_regs *backup)
{
int i;
for (i = 0; i < R88F_ADDA_REGS; i++)
backup->adda_regs[i] = rtwn_bb_read(sc, iqk_adda_regs[i]);
for (i = 0; i < R88F_MAC_REGS - 1; i++)
backup->mac_regs[i] = rtwn_read_1(sc, iqk_mac_regs[i]);
backup->mac_regs[i] = rtwn_bb_read(sc, iqk_mac_regs[i]);
for (i = 0; i < R88F_BB_REGS; i++)
backup->bb_regs[i] = rtwn_bb_read(sc, iqk_bb_regs[i]);
}
static void
r88f_iqk_restore_regs(struct rtwn_softc *sc,
const struct r88f_iqk_calib_regs *backup)
{
int i;
for (i = 0; i < R88F_ADDA_REGS; i++)
rtwn_bb_write(sc, iqk_adda_regs[i], backup->adda_regs[i]);
for (i = 0; i < R88F_MAC_REGS - 1; i++)
rtwn_write_1(sc, iqk_mac_regs[i], backup->mac_regs[i]);
rtwn_bb_write(sc, iqk_mac_regs[i], backup->mac_regs[i]);
for (i = 0; i < R88F_BB_REGS; i++)
rtwn_bb_write(sc, iqk_bb_regs[i], backup->bb_regs[i]);
}
static void
r88f_path_adda_on(struct rtwn_softc *sc)
{
int i;
rtwn_bb_write(sc, iqk_adda_regs[0], 0x03c00014);
for (i = 1; i < R88F_ADDA_REGS; i++)
rtwn_bb_write(sc, iqk_adda_regs[i], 0x03c00014);
}
static void
r88f_fill_iqk_matrix_a(struct rtwn_softc *sc,
const struct r88f_iqk_result *tx_result,
const struct r88f_iqk_result *rx_result,
bool tx_only)
{
uint32_t oldval, x, tx0_a, result_reg;
int y, tx0_c;
uint32_t reg;
reg = rtwn_bb_read(sc, R92C_OFDM0_TXIQIMBALANCE(0));
oldval = reg >> 22;
x = tx_result->before;
if ((x & 0x00000200) != 0)
x = x | 0xfffffc00;
tx0_a = (x * oldval) >> 8;
reg = rtwn_bb_read(sc, R92C_OFDM0_TXIQIMBALANCE(0));
reg &= ~0x3ff;
reg |= tx0_a;
rtwn_bb_write(sc, R92C_OFDM0_TXIQIMBALANCE(0), reg);
reg = rtwn_bb_read(sc, R92C_OFDM0_ECCATHRESHOLD);
reg &= ~0x80000000;
if ((x * oldval >> 7) & 0x1)
reg |= 0x80000000;
rtwn_bb_write(sc, R92C_OFDM0_ECCATHRESHOLD, reg);
y = tx_result->after;
if ((y & 0x00000200) != 0)
y |= 0xfffffc00;
tx0_c = (y * oldval) >> 8;
rtwn_bb_setbits(sc, R92C_OFDM0_TXAFE(0), 0xf0000000,
((tx0_c & 0x3c0) >> 6) << 28);
reg = rtwn_bb_read(sc, R92C_OFDM0_TXIQIMBALANCE(0));
reg &= ~0x003f0000;
reg |= ((tx0_a & 0x3f) << 16);
rtwn_bb_write(sc, R92C_OFDM0_TXIQIMBALANCE(0), reg);
reg = rtwn_bb_read(sc, R92C_OFDM0_ECCATHRESHOLD);
reg &= ~0x20000000;
if ((y * oldval >> 7) & 0x1)
reg |= 0x20000000;
rtwn_bb_write(sc, R92C_OFDM0_ECCATHRESHOLD, reg);
if (tx_only) {
RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB, "%s: only TX\n", __func__);
return;
}
result_reg = rx_result->before;
rtwn_bb_setbits(sc, R92C_OFDM0_RXIQIMBALANCE(0), 0x3ff,
result_reg & 0x3ff);
result_reg = rx_result->after & 0x3f;
rtwn_bb_setbits(sc, R92C_OFDM0_RXIQIMBALANCE(0), 0xfc00,
(result_reg << 10) & 0xfc00);
result_reg = (rx_result->after >> 6) & 0xf;
rtwn_bb_setbits(sc, R92C_OFDM0_RXIQEXTANTA, 0xf0000000,
result_reg << 28);
}
static bool
r88f_iq_calib_get_tx_result(struct rtwn_softc *sc,
struct r88f_iqk_result *tx_result)
{
uint32_t reg_eac, reg_e94, reg_e9c;
reg_eac = rtwn_bb_read(sc, R92C_RX_POWER_IQK_AFTER(0));
reg_e94 = rtwn_bb_read(sc, R92C_TX_POWER_IQK_BEFORE(0));
tx_result->before = (reg_e94 >> 16) & 0x3ff;
reg_e9c = rtwn_bb_read(sc, R92C_TX_POWER_IQK_AFTER(0));
tx_result->after = (reg_e9c >> 16) & 0x3ff;
return (!(reg_eac & 0x10000000) &&
(tx_result->before != 0x142) &&
(tx_result->after != 0x042));
}
static bool
r88f_iq_calib_get_rx_result(struct rtwn_softc *sc, uint32_t lok_result,
struct r88f_iqk_result *rx_result)
{
uint32_t reg_eac, reg_ea4;
/* Reload LOK value from TX calibration */
rtwn_rf_write(sc, 0, R92C_RF_TXM_IDAC, lok_result);
reg_eac = rtwn_bb_read(sc, R92C_RX_POWER_IQK_AFTER(0));
reg_ea4 = rtwn_bb_read(sc, R92C_RX_POWER_IQK_BEFORE(0));
rx_result->before = (reg_ea4 >> 16) & 0x3ff;
rx_result->after = (reg_eac >> 16) & 0x3ff;
return (!(reg_eac & 0x08000000) &&
(rx_result->before != 0x132) &&
(rx_result->after != 0x036));
}
static bool
r88f_iqk_path_a_tx(struct rtwn_softc *sc, uint32_t *lok_result,
struct r88f_iqk_result *tx_result)
{
uint32_t reg;
/* Leave IQK mode */
reg = rtwn_bb_read(sc, R92C_FPGA0_IQK);
reg &= 0x000000ff;
rtwn_bb_write(sc, R92C_FPGA0_IQK, reg);
/* Enable path A PA in TX IQK mode */
rtwn_rf_setbits(sc, 0, R88E_RF_WE_LUT, 0, 0x80000);
rtwn_rf_write(sc, 0, R92C_RF_RCK_OS, 0x20000);
rtwn_rf_write(sc, 0, R92C_RF_TXPA_G(0), 0x0000f);
rtwn_rf_write(sc, 0, R92C_RF_TXPA_G(1), 0x07ff7);
/* PA, PAD gain adjust */
rtwn_rf_write(sc, 0, R88F_RF_GAIN_CCA, 0x980);
rtwn_rf_write(sc, 0, R88F_RF_PAD_TXG, 0x5102a);
/* Enter IQK mode */
reg = rtwn_bb_read(sc, R92C_FPGA0_IQK);
reg &= 0x000000ff;
reg |= 0x80800000;
rtwn_bb_write(sc, R92C_FPGA0_IQK, reg);
/* path-A IQK settings */
rtwn_bb_write(sc, R92C_TX_IQK_TONE(0), 0x18008c1c);
rtwn_bb_write(sc, R92C_RX_IQK_TONE(0), 0x38008c1c);
rtwn_bb_write(sc, R92C_TX_IQK_PI(0), 0x821403ff);
rtwn_bb_write(sc, R92C_RX_IQK_PI(0), 0x28160000);
/* LO calibration setting */
rtwn_bb_write(sc, R92C_IQK_AGC_RSP, 0x00462911);
/* One shot, path A LOK & IQK */
rtwn_bb_write(sc, R92C_IQK_AGC_PTS, 0xf9000000);
rtwn_bb_write(sc, R92C_IQK_AGC_PTS, 0xf8000000);
rtwn_delay(sc, 25);
/* Leave IQK mode */
reg = rtwn_bb_read(sc, R92C_FPGA0_IQK);
reg &= 0x000000ff;
rtwn_bb_write(sc, R92C_FPGA0_IQK, reg);
rtwn_rf_write(sc, 0, R88F_RF_GAIN_CCA, 0x180);
*lok_result = rtwn_rf_read(sc, 0, R92C_RF_TXM_IDAC);
return (r88f_iq_calib_get_tx_result(sc, tx_result));
}
static bool
r88f_iqk_path_a_tx_rx(struct rtwn_softc *sc, uint32_t lok_result,
struct r88f_iqk_result *rx_result)
{
uint32_t reg;
struct r88f_iqk_result tx_verify;
/*
* Leave IQK mode
*/
reg = rtwn_bb_read(sc, R92C_FPGA0_IQK);
reg &= 0x000000ff;
rtwn_bb_write(sc, R92C_FPGA0_IQK, reg);
/*
* Enable path A PA in TX IQK mode
*/
rtwn_rf_setbits(sc, 0, R88E_RF_WE_LUT, 0, 0x80000);
rtwn_rf_write(sc, 0, R92C_RF_RCK_OS, 0x30000);
rtwn_rf_write(sc, 0, R92C_RF_TXPA_G(0), 0x0000f);
rtwn_rf_write(sc, 0, R92C_RF_TXPA_G(1), 0xf1173);
/* PA,PAD gain adjust */
rtwn_rf_write(sc, 0, R88F_RF_GAIN_CCA, 0x980);
rtwn_rf_write(sc, 0, R88F_RF_PAD_TXG, 0x5102a);
/*
* Enter IQK mode
*/
reg = rtwn_bb_read(sc, R92C_FPGA0_IQK);
reg &= 0x000000ff;
reg |= 0x80800000;
rtwn_bb_write(sc, R92C_FPGA0_IQK, reg);
/*
* TX IQK settings
*/
rtwn_bb_write(sc, R92C_TX_IQK, 0x01007c00);
rtwn_bb_write(sc, R92C_RX_IQK, 0x01004800);
/* path-A IQK setting */
rtwn_bb_write(sc, R92C_TX_IQK_TONE(0), 0x10008c1c);
rtwn_bb_write(sc, R92C_RX_IQK_TONE(0), 0x30008c1c);
rtwn_bb_write(sc, R92C_TX_IQK_PI(0), 0x82160fff);
rtwn_bb_write(sc, R92C_RX_IQK_PI(0), 0x28160000);
/* LO calibration setting */
rtwn_bb_write(sc, R92C_IQK_AGC_RSP, 0x00462911);
/* One shot, path A LOK & IQK */
rtwn_bb_write(sc, R92C_IQK_AGC_PTS, 0xf9000000);
rtwn_bb_write(sc, R92C_IQK_AGC_PTS, 0xf8000000);
rtwn_delay(sc, 25);
/*
* Leave IQK mode
*/
reg = rtwn_bb_read(sc, R92C_FPGA0_IQK);
reg &= 0x000000ff;
rtwn_bb_write(sc, R92C_FPGA0_IQK, reg);
rtwn_rf_write(sc, 0, R88F_RF_GAIN_CCA, 0x180);
if (!r88f_iq_calib_get_tx_result(sc, &tx_verify)) {
/* TX verification failed */
RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB,
"%s: TX verification failed in RX path\n", __func__);
return (false);
}
rtwn_bb_write(sc, R92C_TX_IQK, 0x80007c00 |
(tx_verify.before << 16) | tx_verify.after);
/*
* Modify RX IQK mode table
*/
reg = rtwn_bb_read(sc, R92C_FPGA0_IQK);
reg &= 0x000000ff;
rtwn_bb_write(sc, R92C_FPGA0_IQK, reg);
rtwn_rf_setbits(sc, 0, R88E_RF_WE_LUT, 0, 0x80000);
rtwn_rf_write(sc, 0, R92C_RF_RCK_OS, 0x30000);
rtwn_rf_write(sc, 0, R92C_RF_TXPA_G(0), 0x0000f);
rtwn_rf_write(sc, 0, R92C_RF_TXPA_G(1), 0xf7ff2);
/*
* PA, PAD setting
*/
rtwn_rf_write(sc, 0, R88F_RF_GAIN_CCA, 0x980);
rtwn_rf_write(sc, 0, R88F_RF_PAD_TXG, 0x51000);
/*
* Enter IQK mode
*/
reg = rtwn_bb_read(sc, R92C_FPGA0_IQK);
reg &= 0x000000ff;
reg |= 0x80800000;
rtwn_bb_write(sc, R92C_FPGA0_IQK, reg);
/*
* RX IQK setting
*/
rtwn_bb_write(sc, R92C_RX_IQK, 0x01004800);
/* path-A IQK setting */
rtwn_bb_write(sc, R92C_TX_IQK_TONE(0), 0x30008c1c);
rtwn_bb_write(sc, R92C_RX_IQK_TONE(0), 0x10008c1c);
rtwn_bb_write(sc, R92C_TX_IQK_PI(0), 0x82160000);
rtwn_bb_write(sc, R92C_RX_IQK_PI(0), 0x281613ff);
/* LO calibration setting */
rtwn_bb_write(sc, R92C_IQK_AGC_RSP, 0x0046a911);
/* One shot, path A LOK & IQK */
rtwn_bb_write(sc, R92C_IQK_AGC_PTS, 0xf9000000);
rtwn_bb_write(sc, R92C_IQK_AGC_PTS, 0xf8000000);
rtwn_delay(sc, 25);
/*
* Leave IQK Mode
*/
reg = rtwn_bb_read(sc, R92C_FPGA0_IQK);
reg &= 0x000000ff;
rtwn_bb_write(sc, R92C_FPGA0_IQK, reg);
rtwn_rf_write(sc, 0, R88F_RF_GAIN_CCA, 0x180);
return (r88f_iq_calib_get_rx_result(sc, lok_result, rx_result));
}
#define R88F_MAX_TOLERANCE 5
static bool
r88f_iq_calib_compare_results(struct r88f_iqk_result *tx_result1,
struct r88f_iqk_result *rx_result1,
struct r88f_iqk_result *tx_result2,
struct r88f_iqk_result *rx_result2,
struct r88f_iqk_result **tx_candidate,
struct r88f_iqk_result **rx_candidate)
{
uint32_t diff;
bool tx_good = false;
int32_t tmp1, tmp2;
diff = abs((int32_t)tx_result1->before - (int32_t)tx_result2->before);
if (diff <= R88F_MAX_TOLERANCE) {
tmp1 = tx_result1->after & 0x00000200 ?
(tx_result1->after | 0xfffffc00) : tx_result1->after;
tmp2 = tx_result2->after & 0x00000200 ?
(tx_result2->after | 0xfffffc00) : tx_result2->after;
diff = abs(tmp1 - tmp2);
if (diff <= R88F_MAX_TOLERANCE) {
*tx_candidate = tx_result1;
tx_good = true;
}
}
diff = abs((int32_t)rx_result1->before - (int32_t)rx_result2->before);
if (diff > R88F_MAX_TOLERANCE) {
if (tx_good && (rx_result1->before + rx_result1->after) == 0)
*tx_candidate = tx_result2;
return (false);
}
tmp1 = (rx_result1->after & 0x200) ?
(0xfffffc00 | rx_result1->after) : rx_result1->after;
tmp2 = (rx_result2->after & 0x200) ?
(0xfffffc00 | rx_result2->after) : rx_result2->after;
diff = abs(tmp1 - tmp2);
if (diff > R88F_MAX_TOLERANCE)
return (false);
*rx_candidate = rx_result1;
return (tx_good);
}
static void
r88f_iq_calib_run(struct rtwn_softc *sc, struct r88f_iqk_calib_regs *regs,
struct r88f_iqk_result *tx_result, struct r88f_iqk_result *rx_result, int t)
{
uint32_t rx_initial_gain, lok_result;
uint32_t path_sel_rf, path_sel_bb;
uint32_t reg;
int retry = 2;
int i;
bool path_a_ok;
/*
* Note: IQ calibration must be performed after loading
* PHY_REG.txt , and radio_a, radio_b.txt
*/
rx_initial_gain = rtwn_bb_read(sc, R92C_OFDM0_AGCCORE1(0));
if (t == 0) {
r88f_iqk_save_regs(sc, regs);
}
r88f_path_adda_on(sc);
if (t == 0) {
/* Save ADDA parameters, turn Path A ADDA on */
regs->hssi_param1 = rtwn_bb_read(sc, R92C_HSSI_PARAM1(0));
}
/* save RF path */
path_sel_bb = rtwn_bb_read(sc, R23B_ANT_SEL);
path_sel_rf = rtwn_rf_read(sc, 0, R23B_RF_S0S1);
/* BB setting */
rtwn_bb_write(sc, R92C_OFDM0_TRXPATHENA, 0x03a05600);
rtwn_bb_write(sc, R92C_OFDM0_TRMUXPAR, 0x000800e4);
rtwn_bb_write(sc, R88F_FPGA0_XCD_RF_SW_CTRL, 0x25204000);
rtwn_bb_setbits(sc, R92C_TX_PTCL_CTRL, 0, 0x00ff0000);
reg = rtwn_bb_read(sc, R92C_FPGA0_IQK);
reg &= 0xff;
reg |= 0x80800000;
rtwn_bb_write(sc, R92C_FPGA0_IQK, reg);
rtwn_bb_write(sc, R92C_TX_IQK, 0x01007c00);
rtwn_bb_write(sc, R92C_RX_IQK, 0x01004800);
for (i = 0; i < retry; i++) {
path_a_ok = r88f_iqk_path_a_tx(sc, &lok_result, tx_result);
if (path_a_ok) {
rtwn_bb_write(sc, R92C_FPGA0_IQK, 0x00);
break;
}
}
for (i = 0; i < retry; i++) {
path_a_ok = r88f_iqk_path_a_tx_rx(sc, lok_result, rx_result);
if (path_a_ok) {
rtwn_bb_write(sc, R92C_FPGA0_IQK, 0x00);
break;
}
}
if (!path_a_ok)
RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB,
"%s: Path A IQK failed!\n", __func__);
/* Back to BB mode, load original value */
reg = rtwn_bb_read(sc, R92C_FPGA0_IQK);
reg &= 0xff;
rtwn_bb_write(sc, R92C_FPGA0_IQK, reg);
if (t == 0)
return;
if (!(regs->hssi_param1 & R92C_HSSI_PARAM1_PI)) {
/*
* Switch back BB to SI mode after finishing
* IQ Calibration
*/
rtwn_bb_write(sc, R92C_HSSI_PARAM1(0), 0x01000000);
rtwn_bb_write(sc, R92C_HSSI_PARAM1(1), 0x01000000);
}
/* Reload ADDA power saving, MAC and BB paramters */
r88f_iqk_restore_regs(sc, regs);
/* Reload RF path */
rtwn_bb_write(sc, R23B_ANT_SEL, path_sel_bb);
rtwn_rf_write(sc, 0, R23B_RF_S0S1, path_sel_rf);
/* Restore RX initial gain */
reg = rtwn_bb_read(sc, R92C_OFDM0_AGCCORE1(0));
reg &= 0xffffff00;
reg |= 0x50;
rtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(0), reg);
reg = rtwn_bb_read(sc, R92C_OFDM0_AGCCORE1(0));
reg &= 0xffffff00;
reg |= rx_initial_gain & 0xff;
rtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(0), reg);
/* Load 0xe30 IQC default value */
rtwn_bb_write(sc, R92C_TX_IQK_TONE(0), 0x01008c00);
rtwn_bb_write(sc, R92C_RX_IQK_TONE(0), 0x01008c00);
}
void
r88f_iq_calib(struct rtwn_softc *sc)
{
struct r88f_iqk_calib_regs regs;
struct r88f_iqk_result tx_result[3] = { {0, 0} };
struct r88f_iqk_result rx_result[3] = { {0, 0} };
/* Final results */
struct r88f_iqk_result *tx_candidate = NULL;
struct r88f_iqk_result *rx_candidate = NULL;
uint32_t path_sel_bb, path_sel_rf;
int i;
/* Save RF path */
path_sel_bb = rtwn_bb_read(sc, R23B_ANT_SEL);
path_sel_rf = rtwn_rf_read(sc, 0, R23B_RF_S0S1);
for (i = 0; i < 3; i++) {
r88f_iq_calib_run(sc, &regs, &tx_result[i], &rx_result[i], i);
if (i == 1) {
/* Compare 0 vs 1 */
if (r88f_iq_calib_compare_results(&tx_result[0],
&rx_result[0],
&tx_result[1], &rx_result[1],
&tx_candidate, &rx_candidate)) {
RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB,
"%s: Run 0-1 passed\n", __func__);
goto write;
}
}
if (i == 2) {
/* Compare 0 vs 2 */
if (r88f_iq_calib_compare_results(&tx_result[0],
&rx_result[0], &tx_result[2],
&rx_result[2], &tx_candidate,
&rx_candidate)) {
RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB,
"%s: Run 0-2 passed\n", __func__);
goto write;
}
/* Compare 1 vs 2 */
if (r88f_iq_calib_compare_results(&tx_result[1],
&rx_result[1], &tx_result[2],
&rx_result[2], &tx_candidate,
&rx_candidate)) {
RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB,
"%s: Run 1-2 passed\n", __func__);
} else {
if (tx_candidate == NULL)
tx_candidate = &tx_result[0];
if (rx_candidate == NULL)
rx_candidate = &rx_result[0];
/* check complete failure */
if (tx_candidate->before == 0 &&
tx_candidate->after == 0 &&
rx_candidate->before == 0 &&
rx_candidate->after == 0) {
RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB,
"%s: IQK failed completely\n", __func__);
goto done;
}
RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB,
"%s: using fallback candidate\n", __func__);
}
}
RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB,
"IQK run %d: TX b=%#x a=%#x RX b=%#x a=%#x\n", i,
tx_result[i].before, tx_result[i].after,
rx_result[i].before, rx_result[i].after);
}
write:
r88f_fill_iqk_matrix_a(sc, tx_candidate, rx_candidate ?
rx_candidate : NULL,
(rx_candidate == NULL || rx_candidate->before == 0));
if (tx_candidate == NULL || (tx_candidate->before == 0 &&
tx_candidate->after == 0)) {
RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB,
"%s: TX IQK failed completely\n", __func__);
goto done;
}
RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB,
"%s: IQK candidate - TX: before=%#x after=%#x RX: before=%#x after=%#x\n",
__func__, tx_candidate->before, tx_candidate->after,
rx_candidate ? rx_candidate->before : 0,
rx_candidate ? rx_candidate->after : 0);
done:
r88f_iqk_save_regs(sc, &regs);
/* Restore RF path */
rtwn_bb_write(sc, R23B_ANT_SEL, path_sel_bb);
rtwn_rf_write(sc, 0, R23B_RF_S0S1, path_sel_rf);
}
+358
View File
@@ -0,0 +1,358 @@
/*
* Copyright (c) 2026 Mir Saheb Ali <mirsahebali@pm.me>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <sys/cdefs.h>
#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_ridx.h>
#include <dev/rtwn/rtl8188e/r88e.h>
#include <dev/rtwn/rtl8188e/r88e_priv.h>
#include <dev/rtwn/rtl8188e/r88e_reg.h>
#include <dev/rtwn/rtl8192c/r92c.h>
#include <dev/rtwn/rtl8192c/r92c_var.h>
#include <dev/rtwn/rtl8723b/r23b_reg.h>
#include <dev/rtwn/rtl8812a/r12a_reg.h>
#include <dev/rtwn/rtl8188f/r88f.h>
#include <dev/rtwn/rtl8188f/r88f_reg.h>
static int
rtwn_chan2group(int chan)
{
int group;
if (chan <= 2)
group = 0;
else if (chan <= 5)
group = 1;
else if (chan <= 8)
group = 2;
else if (chan <= 11)
group = 3;
else
group = 4;
return (group);
}
void
r88f_get_txpower(struct rtwn_softc *sc, int chain,
struct ieee80211_channel *c, uint8_t power[RTWN_RIDX_COUNT])
{
struct r92c_softc *rs = sc->sc_priv;
const struct rtwn_r88e_txpwr *rt = rs->rs_txpwr;
uint32_t reg;
uint8_t cckpow, htpow, ofdmpow;
int8_t diff;
int ridx, chan, group;
/* Determine channel group. */
chan = rtwn_chan2centieee(c); /* XXX center freq! */
group = rtwn_chan2group(chan);
memset(power, 0, R88F_RTWN_POWER_COUNT * sizeof(power[0]));
/* Compute per-CCK rate Tx power. */
cckpow = rt->cck_tx_pwr[group];
for (ridx = RTWN_RIDX_CCK1; ridx <= RTWN_RIDX_CCK11; ridx++) {
power[ridx] = cckpow;
if (power[ridx] > R92C_MAX_TX_PWR)
power[ridx] = R92C_MAX_TX_PWR;
}
reg = rtwn_read_4(sc, R92C_TXAGC_A_CCK1_MCS32);
reg &= 0xffff00ff;
reg |= (cckpow << 8);
rtwn_write_4(sc, R92C_TXAGC_A_CCK1_MCS32, reg);
reg = rtwn_read_4(sc, R92C_TXAGC_B_CCK11_A_CCK2_11);
reg &= 0xff;
reg |= ((cckpow << 8) | (cckpow << 16) | (cckpow << 24));
rtwn_write_4(sc, R92C_TXAGC_B_CCK11_A_CCK2_11, reg);
htpow = rt->ht40_tx_pwr[group];
/* Compute per-OFDM rate Tx power. */
diff = rt->ofdm_tx_pwr_diff;
ofdmpow = htpow + diff;
for (ridx = RTWN_RIDX_OFDM6; ridx <= RTWN_RIDX_OFDM54; ridx++) {
power[ridx] = ofdmpow;
if (power[ridx] > R92C_MAX_TX_PWR)
power[ridx] = R92C_MAX_TX_PWR;
}
/* Compute per-MCS Tx power. */
diff = rt->bw20_tx_pwr_diff;
htpow += diff;
for (ridx = RTWN_RIDX_HT_MCS(0); ridx < RTWN_RIDX_HT_MCS(8); ridx++) {
power[ridx] = htpow;
if (power[ridx] > R92C_MAX_TX_PWR)
power[ridx] = R92C_MAX_TX_PWR;
}
}
static void
r88f_set_txpower(struct rtwn_softc *sc, struct ieee80211_channel *c)
{
uint8_t power[RTWN_RIDX_COUNT];
memset(power, 0, sizeof(power));
/* Compute per-rate Tx power values. */
r88f_get_txpower(sc, 0, c, power);
/* Write per-rate Tx power values to hardware. */
r92c_write_txpower(sc, 0, power);
}
static void
r88f_spur_calibration(struct rtwn_softc *sc, struct ieee80211_channel *c,
int chan)
{
static const uint32_t frequencies[14 + 1] = {
[5] = 0xFCCD,
[6] = 0xFC4D,
[7] = 0xFFCD,
[8] = 0xFF4D,
[11] = 0xFDCD,
[13] = 0xFCCD,
[14] = 0xFF9A
};
static const uint32_t reg_d40[14 + 1] = {
[5] = 0x06000000,
[6] = 0x00000600,
[13] = 0x06000000
};
static const uint32_t reg_d44[14 + 1] = {
[11] = 0x04000000
};
static const uint32_t reg_d4c[14 + 1] = {
[7] = 0x06000000,
[8] = 0x00000380,
[14] = 0x00180000
};
const uint8_t threshold = 0x16;
bool do_notch, hw_ctrl, sw_ctrl, hw_ctrl_s1 = 0, sw_ctrl_s1 = 0;
uint32_t reg, initial_gain, reg948;
rtwn_bb_setbits(sc, R88F_OFDM0_RX_D_SYNC_PATH, 0, 0x1f000000);
/* enable notch filter */
rtwn_bb_setbits(sc, R88F_OFDM0_RX_D_SYNC_PATH, 0, 0x00000200);
if (chan <= 14 && frequencies[chan] > 0) {
reg948 = rtwn_read_4(sc, R23B_ANT_SEL);
hw_ctrl = reg948 & 0x00000040;
sw_ctrl = !hw_ctrl;
if (hw_ctrl) {
reg = rtwn_read_4(sc, R88F_FPGA0_XB_RF_INT_OE);
reg &= 0x00000038;
hw_ctrl_s1 = reg == 0x00000008;
} else if (sw_ctrl) {
sw_ctrl_s1 = !(reg948 & 0x00000200);
}
if (hw_ctrl_s1 || sw_ctrl_s1) {
initial_gain = rtwn_read_4(sc, R92C_OFDM0_AGCCORE1(0));
/* Disable CCK block */
rtwn_bb_setbits(sc, R92C_FPGA0_RFMOD,
R92C_RFMOD_CCK_EN, 0);
rtwn_bb_setbits(sc, R92C_OFDM0_AGCCORE1(0),
R92C_OFDM0_AGCCORE1_GAIN_M, 0x30);
/* disable 3-wire */
rtwn_bb_write(sc, R88F_FPGA0_ANALOG4, 0xccf000c0);
/* Setup PSD */
rtwn_bb_write(sc, R88F_FPGA0_PSD_FUNC,
frequencies[chan]);
/* Start PSD */
rtwn_bb_write(sc, R88F_FPGA0_PSD_FUNC,
0x400000 | frequencies[chan]);
rtwn_delay(sc, 30);
do_notch = rtwn_bb_read(sc, R88F_FPGA0_PSD_REPORT) >=
threshold;
/* turn off PSD */
rtwn_bb_write(sc, R88F_FPGA0_PSD_FUNC,
frequencies[chan]);
/* enable 3-wire */
rtwn_bb_write(sc, R88F_FPGA0_ANALOG4, 0xccc000c0);
/* Enable CCK block */
rtwn_bb_setbits(sc, R92C_FPGA0_RFMOD, 0,
R92C_RFMOD_CCK_EN);
rtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(0), initial_gain);
if (do_notch) {
rtwn_bb_write(sc, R88F_OFDM1_CSI_FIX_MASK1,
reg_d40[chan]);
rtwn_bb_write(sc, R88F_OFDM1_CSI_FIX_MASK2,
reg_d44[chan]);
rtwn_bb_write(sc, 0xd48, 0x0);
rtwn_bb_write(sc, 0xd4c, reg_d4c[chan]);
/* enable CSI mask */
rtwn_bb_setbits(sc, R88F_OFDM1_CFO_TRACKING, 0,
0x10000000);
return;
}
}
}
/* disable CSI mask function */
rtwn_bb_setbits(sc, R88F_OFDM1_CFO_TRACKING, 0x10000000, 0);
}
void
r88f_set_chan(struct rtwn_softc *sc, struct ieee80211_channel *c)
{
struct r92c_softc *rs = sc->sc_priv;
uint32_t reg;
uint8_t chan, subchannel;
bool sec_ch_above;
chan = rtwn_chan2centieee(c); /* XXX center freq! */
/* Set Tx power for this new channel. */
r88f_set_txpower(sc, c);
/* Spur calibration */
r88f_spur_calibration(sc, c, chan);
/* Set bandwidth mode */
rtwn_bb_setbits(sc, R92C_FPGA0_RFMOD, R92C_RFMOD_40MHZ,
IEEE80211_IS_CHAN_HT40(c));
rtwn_bb_setbits(sc, R92C_FPGA1_RFMOD, R92C_RFMOD_40MHZ,
IEEE80211_IS_CHAN_HT40(c));
/* RXADC CLK */
rtwn_bb_setbits(sc, R92C_FPGA0_RFMOD, 0, 0x00000700);
/* TXDAC CLK */
rtwn_bb_setbits(sc, R92C_FPGA0_RFMOD, 0x00002000,
0x00004000 | 0x00001000);
/* Small bandwidth */
rtwn_bb_setbits(sc, R92C_OFDM0_TXPSEUDONOISEWGT, 0xc0000000, 0);
/* ADC buffer clk */
rtwn_bb_setbits(sc, R92C_OFDM0_TXPSEUDONOISEWGT, 0x20000000,
0x10000000);
/* ADC buffer clk */
rtwn_bb_setbits(sc, R88F_OFDM0_XA_RX_AFE, 0x20000000, 0x10000000);
/* OFDM Rx DFIR */
rtwn_bb_setbits(sc, R88F_RX_DFIR, 0x00080000, 0);
reg = rtwn_bb_read(sc, R88F_RX_DFIR);
reg &= ~0x00f00000;
reg |= 0x00200000;
if (IEEE80211_IS_CHAN_HT20(c) || IEEE80211_IS_CHAN_VHT20(c) ||
(!IEEE80211_IS_CHAN_HT(c) && !IEEE80211_IS_CHAN_VHT(c)))
reg |= 0x00100000;
else if (IEEE80211_IS_CHAN_HT40(c) || IEEE80211_IS_CHAN_VHT40(c))
reg |= 0x00400000;
rtwn_bb_write(sc, R88F_RX_DFIR, reg);
if (IEEE80211_IS_CHAN_HT40(c) || IEEE80211_IS_CHAN_VHT40(c)) {
if (IEEE80211_IS_CHAN_HT40U(c) ||
IEEE80211_IS_CHAN_VHT40U(c)) {
sec_ch_above = 1;
chan += 2;
} else {
sec_ch_above = 0;
chan -= 2;
}
/* Set Control channel to upper or lower. */
reg = rtwn_bb_read(sc, R92C_CCK0_SYSTEM);
reg &= ~R92C_CCK0_SYSTEM_CCK_SIDEBAND;
if (!sec_ch_above)
reg |= R92C_CCK0_SYSTEM_CCK_SIDEBAND;
rtwn_bb_write(sc, R92C_CCK0_SYSTEM, reg);
if (sec_ch_above)
subchannel = 2;
else
subchannel = 1;
rtwn_bb_setbits(sc, R12A_DATA_SEC, 0x0000000F, subchannel);
rtwn_bb_setbits(sc, R92C_RRSR, R92C_RRSR_RSC_LOWSUBCHNL |
R92C_RRSR_RSC_UPSUBCHNL, 0);
}
/* RF TRX_BW */
reg = chan;
if (IEEE80211_IS_CHAN_HT20(c) || IEEE80211_IS_CHAN_VHT20(c) ||
(!IEEE80211_IS_CHAN_HT(c) && !IEEE80211_IS_CHAN_VHT(c)))
reg |= R88F_RF_CHNLBW_BW20;
else if (IEEE80211_IS_CHAN_HT40(c) || IEEE80211_IS_CHAN_VHT40(c))
reg |= R88F_RF_CHNLBW_BW40;
rtwn_rf_write(sc, 0, R92C_RF_CHNLBW, reg);
/* FILTER BW&RC Corner (ACPR) */
if (IEEE80211_IS_CHAN_HT20(c) || IEEE80211_IS_CHAN_VHT20(c) ||
(!IEEE80211_IS_CHAN_HT(c) && !IEEE80211_IS_CHAN_VHT(c)))
reg = 0x00065;
else if (IEEE80211_IS_CHAN_HT40(c) || IEEE80211_IS_CHAN_VHT40(c))
reg = 0x00025;
rtwn_rf_write(sc, 0, R88F_RF_RXG_GAIN, reg);
if (IEEE80211_IS_CHAN_HT20(c) || IEEE80211_IS_CHAN_VHT20(c) ||
(!IEEE80211_IS_CHAN_HT(c) && !IEEE80211_IS_CHAN_VHT(c)))
reg = 0x0;
else if (IEEE80211_IS_CHAN_HT40(c) || IEEE80211_IS_CHAN_VHT40(c))
reg = 0x01000;
rtwn_rf_write(sc, 0, R92C_RF_RX_BB2, reg);
rtwn_rf_write(sc, 0, R92C_RF_RX_G2, 0x1c6c);
rtwn_rf_write(sc, 0, R88F_RF_GAIN_CCA,
R88F_RF_PKTBUF_DBG_CTRL);
rtwn_rf_write(sc, 0, R92C_RF_CHNLBW,
(rs->rf_chnlbw[0] & ~0xfff) | chan | R88E_RF_CHNLBW_BW20);
}
+79
View File
@@ -0,0 +1,79 @@
/*
* Copyright (c) 2026 Mir Saheb Ali <mirsahebali@pm.me>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <sys/cdefs.h>
#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/rtl8192e/r92e.h>
#include <dev/rtwn/rtl8192e/r92e_reg.h>
#include <dev/rtwn/rtl8188f/r88f.h>
#define R88E_RSV_CTRL_MIO_EN 0x0100
#define R88E_RSV_CTRL_MCU_RST 0x0800
#ifndef RTWN_WITHOUT_UCODE
void
r88f_fw_reset(struct rtwn_softc *sc, int reason)
{
switch (reason) {
case RTWN_FW_RESET_CHECKSUM:
rtwn_setbits_1(sc, R92C_MCUFWDL, 0, R92C_MCUFWDL_CHKSUM_RPT);
/* FALLTHROUGH */
case RTWN_FW_RESET_DOWNLOAD:
case RTWN_FW_RESET_SHUTDOWN:
/* Reset MCU IO wrapper. */
rtwn_setbits_2(sc, R92C_RSV_CTRL, R88E_RSV_CTRL_MIO_EN, 0);
rtwn_setbits_2(sc, R92C_SYS_FUNC_EN, R92C_SYS_FUNC_EN_CPUEN, 0);
/* Enable MCU IO wrapper. */
rtwn_setbits_2(sc, R92C_RSV_CTRL, 0, R88E_RSV_CTRL_MIO_EN);
rtwn_setbits_2(sc, R92C_SYS_FUNC_EN, 0, R92C_SYS_FUNC_EN_CPUEN);
return;
}
}
void
r88f_fw_download_enable(struct rtwn_softc *sc, int enable)
{
if (enable) {
/* Enable FW download. */
rtwn_setbits_1(sc, R92C_MCUFWDL, 0, R92C_MCUFWDL_EN);
rtwn_setbits_4(sc, R92C_MCUFWDL, R92C_MCUFWDL_ROM_DLEN, 0);
/* Wait 100ms */
rtwn_delay(sc, 100);
} else {
rtwn_setbits_1(sc, R92C_MCUFWDL, R92C_MCUFWDL_EN, 0);
}
}
#endif
+212
View File
@@ -0,0 +1,212 @@
/*
* Copyright (c) 2026 Mir Saheb Ali <mirsahebali@pm.me>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <sys/cdefs.h>
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/if_rtwn_debug.h>
#include <dev/rtwn/rtl8192c/r92c.h>
#include <dev/rtwn/rtl8192c/r92c_priv.h>
#include <dev/rtwn/rtl8192c/r92c_reg.h>
#include <dev/rtwn/rtl8192c/r92c_var.h>
#include <dev/rtwn/rtl8192e/r92e_reg.h>
#include <dev/rtwn/rtl8812a/r12a_reg.h>
#include <dev/rtwn/rtl8188f/r88f.h>
#include <dev/rtwn/rtl8188f/r88f_reg.h>
int
r88f_llt_init(struct rtwn_softc *sc)
{
int ntries;
rtwn_setbits_4(sc, R92E_AUTO_LLT, 0, R92E_AUTO_LLT_EN);
for (ntries = 0; ntries < 1000; ntries++) {
if (!(rtwn_read_4(sc, R92E_AUTO_LLT) & R92E_AUTO_LLT_EN))
return (0);
rtwn_delay(sc, 2);
}
return (ETIMEDOUT);
}
int
r88f_set_page_size(struct rtwn_softc *sc)
{
return (rtwn_write_1(sc, R92C_PBP,
SM(R92C_PBP_PSRX, R92C_PBP_256) |
SM(R92C_PBP_PSTX, R92C_PBP_256)));
}
void
r88f_init_ampdu(struct rtwn_softc *sc)
{
/* Setup AMPDU aggregation. */
rtwn_setbits_1(sc, R12A_HT_SINGLE_AMPDU, 0,
R12A_HT_SINGLE_AMPDU_PKT_ENA);
rtwn_write_2(sc, R92C_MAX_AGGR_NUM, 0x0c14);
rtwn_write_1(sc, R12A_AMPDU_MAX_TIME, 0x70);
rtwn_write_4(sc, R92C_AGGLEN_LMT, 0xffffffff);
/* For VHT packet length 11K */
rtwn_write_1(sc, R92C_RX_PKT_LIMIT, 0x18);
rtwn_write_1(sc, R92C_PIFS, 0);
rtwn_write_1(sc, R92C_FWHW_TXQ_CTRL, 0x80);
rtwn_write_4(sc, R92C_FAST_EDCA_CTRL, 0x03086666);
rtwn_write_1(sc, R92C_USTIME_TSF, 0x28);
rtwn_write_1(sc, R92C_USTIME_EDCA, 0x28);
/* To prevent bus resetting the mac. */
rtwn_setbits_1(sc, R92C_RSV_CTRL, 0,
R92C_RSV_CTRL_R_DIS_PRST_0 | R92C_RSV_CTRL_R_DIS_PRST_1);
}
static int
r88f_read_efuse_1(struct rtwn_softc *sc, uint16_t offset, uint8_t *data)
{
int i;
uint8_t val8;
uint32_t reg;
/* Write Address */
rtwn_write_1(sc, R92C_EFUSE_CTRL + 1, offset & 0xff);
val8 = rtwn_read_1(sc, R92C_EFUSE_CTRL + 2);
val8 &= 0xfc;
val8 |= (offset >> 8) & 0x03;
rtwn_write_1(sc, R92C_EFUSE_CTRL + 2, val8);
val8 = rtwn_read_1(sc, R92C_EFUSE_CTRL + 3);
rtwn_write_1(sc, R92C_EFUSE_CTRL + 3, val8 & 0x7f);
/* Poll for data read */
reg = rtwn_bb_read(sc, R92C_EFUSE_CTRL);
for (i = 0; i < 500; i++) {
reg = rtwn_bb_read(sc, R92C_EFUSE_CTRL);
if (reg & 0x80000000)
break;
}
if (i == 500)
return (-EIO);
rtwn_delay(sc, 50);
reg = rtwn_bb_read(sc, R92C_EFUSE_CTRL);
*data = reg & 0xff;
return (0);
}
#define PPG_BB_GAIN_2G_TXA_OFFSET_8188F 0xee
#define PPG_BB_GAIN_2G_TX_OFFSET_MASK 0x0f
#define OFDM_RF_PATH_RX_A 0x00000001
#define OFDM_RF_PATH_TX_A 0x00000010
#define OFDM_RF_PATH_TX_MASK 0xf0
#define OFDM_RF_PATH_RX_MASK 0x0f
static void
r88f_enable_rf(struct rtwn_softc *sc)
{
uint8_t pg_pwrtrim = 0xff, val8;
int8_t bb_gain;
/* Somehow this is not found in the efuse we read earlier. */
r88f_read_efuse_1(sc, PPG_BB_GAIN_2G_TXA_OFFSET_8188F, &pg_pwrtrim);
if (pg_pwrtrim != 0xff) {
bb_gain = pg_pwrtrim & PPG_BB_GAIN_2G_TX_OFFSET_MASK;
if (bb_gain == PPG_BB_GAIN_2G_TX_OFFSET_MASK)
bb_gain = 0;
else if (bb_gain & 1)
bb_gain = bb_gain >> 1;
else
bb_gain = -(bb_gain >> 1);
val8 = abs(bb_gain);
if (bb_gain > 0)
val8 |= 0x00000020;
rtwn_rf_setbits(sc, 0, R88F_RF_UNKNOWN_55,
0xfc000, val8 << 14);
}
rtwn_write_1(sc, R92C_RF_CTRL, R92C_RF_CTRL_EN |
R92C_RF_CTRL_RSTB | R92C_RF_CTRL_SDMRSTB);
rtwn_bb_setbits(sc, R92C_OFDM0_TRXPATHENA, OFDM_RF_PATH_RX_MASK |
OFDM_RF_PATH_TX_MASK, OFDM_RF_PATH_RX_A | OFDM_RF_PATH_TX_A);
rtwn_write_1(sc, R92C_TXPAUSE, 0x00);
}
void
r88f_init_rf(struct rtwn_softc *sc)
{
struct r92c_softc *rs = sc->sc_priv;
uint32_t reg, type;
int i = 0;
r88f_enable_rf(sc);
/* Save RF_ENV control type. */
reg = rtwn_bb_read(sc, R92C_FPGA0_RFIFACESW(0));
type = reg & 0x10;
/* Set RF_ENV enable. */
rtwn_bb_setbits(sc, R92C_FPGA0_RFIFACEOE(0), 0, 0x100000);
rtwn_delay(sc, 1);
/* Set RF_ENV output high. */
rtwn_bb_setbits(sc, R92C_FPGA0_RFIFACEOE(0), 0, 0x10);
rtwn_delay(sc, 1);
/* Set address and data lengths of RF registers. */
rtwn_bb_setbits(sc, R92C_HSSI_PARAM2(0),
R92C_HSSI_PARAM2_ADDR_LENGTH, 0);
rtwn_delay(sc, 1);
rtwn_bb_setbits(sc, R92C_HSSI_PARAM2(0),
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[0], 0);
/* Restore RF_ENV control type. */
rtwn_bb_setbits(sc, R92C_FPGA0_RFIFACESW(0), 0x10, type);
/* Cache RF register CHNLBW. */
rs->rf_chnlbw[i] = rtwn_rf_read(sc, 0, 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);
}
+214
View File
@@ -0,0 +1,214 @@
/* $OpenBSD: r92creg.h,v 1.30 2023/04/28 01:24:14 kevlo Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2015 Stefan Sperling <stsp@openbsd.org>
* Copyright (c) 2023 Kevin Lo <kevlo@FreeBSD.org>
* Copyright (c) 2026 Mir Saheb Ali <mirsahebali@pm.me>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef R88F_PRIV_H
#define R88F_PRIV_H
#include <dev/rtwn/rtl8188f/r88f_rom_defs.h>
/*
* MAC initialization values.
*/
static const struct rtwn_mac_prog rtl8188ftv_mac[] = {
{ 0x024, 0xdf }, { 0x025, 0x07 }, { 0x02b, 0x1c }, { 0x283, 0x20 },
{ 0x421, 0x0f }, { 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, 0x44 },
{ 0x461, 0x44 }, { 0x4bc, 0xc0 }, { 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 }, { 0x550, 0x10 },
{ 0x551, 0x10 }, { 0x559, 0x02 }, { 0x55c, 0x28 }, { 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, 0x28 },
{ 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 rtl8188ftv_bb_regs[] = {
0x800, 0x804, 0x808, 0x80c, 0x810, 0x814, 0x818, 0x81c, 0x820,
0x824, 0x828, 0x82c, 0x830, 0x834, 0x838, 0x83c, 0x840, 0x844,
0x848, 0x84c, 0x850, 0x854, 0x858, 0x85c, 0x860, 0x864, 0x868,
0x86c, 0x870, 0x874, 0x878, 0x87c, 0x880, 0x884, 0x888, 0x88c,
0x890, 0x894, 0x898, 0x89c, 0x900, 0x904, 0x908, 0x90c, 0x910,
0x914, 0x948, 0x94c, 0x950, 0x954, 0x958, 0x95c, 0x96c, 0xa00,
0xa04, 0xa08, 0xa0c, 0xa10, 0xa14, 0xa18, 0xa1c, 0xa20, 0xa24,
0xa28, 0xa2c, 0xa70, 0xa74, 0xa78, 0xa7c, 0xa80, 0xa84, 0xa88,
0xa8c, 0xa90, 0xa94, 0xa98, 0xa9c, 0xaa0, 0xb2c, 0xc00, 0xc04,
0xc08, 0xc0c, 0xc10, 0xc14, 0xc18, 0xc1c, 0xc20, 0xc24, 0xc28,
0xc2c, 0xc30, 0xc34, 0xc38, 0xc3c, 0xc40, 0xc44, 0xc48, 0xc4c,
0xc50, 0xc54, 0xc58, 0xc5c, 0xc60, 0xc64, 0xc68, 0xc6c, 0xc70,
0xc74, 0xc78, 0xc7c, 0xc80, 0xc84, 0xc88, 0xc8c, 0xc90, 0xc94,
0xc98, 0xc9c, 0xca0, 0xca4, 0xca8, 0xcac, 0xcb0, 0xcb4, 0xcb8,
0xcbc, 0xcc0, 0xcc4, 0xcc8, 0xccc, 0xcd0, 0xcd4, 0xcd8, 0xcdc,
0xce0, 0xce4, 0xce8, 0xcec, 0xd00, 0xd04, 0xd08, 0xd0c, 0xd10,
0xd14, 0xd18, 0xd2c, 0xd30, 0xd34, 0xd38, 0xd3c, 0xd40, 0xd44,
0xd48, 0xd4c, 0xd50, 0xd54, 0xd58, 0xd5c, 0xd60, 0xd64, 0xd68,
0xd6c, 0xd70, 0xd74, 0xd78, 0xe00, 0xe04, 0xe08, 0xe10, 0xe14,
0xe18, 0xe1c, 0xe28, 0xe30, 0xe34, 0xe38, 0xe3c, 0xe40, 0xe44,
0xe48, 0xe4c, 0xe50, 0xe54, 0xe58, 0xe5c, 0xe60, 0xe60, 0xe64,
0xe6c, 0xe70, 0xe74, 0xe78, 0xe7c, 0xe80, 0xe84, 0xe88, 0xe8c,
0xed0, 0xed4, 0xed8, 0xedc, 0xee0, 0xeec, 0xf14, 0xf4c, 0xf00
};
static const uint32_t rtl8188ftv_bb_vals[] = {
0x80045700, 0x00000001, 0x0000fc00, 0x0000000a, 0x10001331,
0x020c3d10, 0x00200385, 0x00000000, 0x01000100, 0x00390204,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00010000, 0x00000000, 0x00000000, 0x00000000,
0x00030000, 0x00000000, 0x569a569a, 0x569a569a, 0x00000130,
0x00000000, 0x00000000, 0x27272700, 0x00000000, 0x25004000,
0x00000808, 0x004f0201, 0xb0000b1e, 0x00000007, 0x00000000,
0xccc000c0, 0x00000800, 0xfffffffe, 0x40302010, 0x00706050,
0x00000000, 0x00000023, 0x00000000, 0x81121111, 0x00000002,
0x00000201, 0x99000000, 0x00000010, 0x20003000, 0x4a880000,
0x4bc5d87a, 0x04eb9b79, 0x00000003, 0x00d047c8, 0x80ff800c,
0x8c898300, 0x2e7f120f, 0x9500bb78, 0x1114d028, 0x00881117,
0x89140f00, 0xd1d80000, 0x5a7da0bd, 0x0000223b, 0x00d30000,
0x101fbf00, 0x00000007, 0x00000900, 0x225b0606, 0x218075b1,
0x00120000, 0x040c0000, 0x12345678, 0xabcdef00, 0x001b1b89,
0x05100000, 0x3f000000, 0x00000000, 0x00000000, 0x48071d40,
0x03a05611, 0x000000e4, 0x6c6c6c6c, 0x18800000, 0x40000100,
0x08800000, 0x40000100, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x69e9cc4a, 0x31000040, 0x21688080, 0x00001714,
0x1f78403f, 0x00010036, 0xec020107, 0x007f037f, 0x69553420,
0x43bc0094, 0x00013169, 0x00250492, 0x00000000, 0x7112848b,
0x47c07bff, 0x00000036, 0x2c7f000d, 0x020600db, 0x0000001f,
0x00b91612, 0x390000e4, 0x11f60000, 0x40000100, 0x20200000,
0x00091521, 0x00000000, 0x00121820, 0x00007f7f, 0x00000000,
0x000300a0, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x28000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x64b22427, 0x00766932,
0x00222222, 0x10000000, 0x37644302, 0x2f97d40c, 0x04030740,
0x40020401, 0x0000907f, 0x20010201, 0xa0633333, 0x3333bc53,
0x7a8f5b6f, 0xcb979975, 0x00000000, 0x80608000, 0x98000000,
0x40127353, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x6437140a, 0x00000000, 0x00000282, 0x30032064, 0x4653de68,
0x04518a3c, 0x00002101, 0x2a201c16, 0x1812362e, 0x322c2220,
0x000e3c24, 0x2d2d2d2d, 0x2d2d2d2d, 0x0390272d, 0x2d2d2d2d,
0x2d2d2d2d, 0x2d2d2d2d, 0x2d2d2d2d, 0x00000000, 0x1000dc1f,
0x10008c1f, 0x02140102, 0x681604c2, 0x01007c00, 0x01004800,
0xfb000000, 0x000028d1, 0x1000dc1f, 0x10008c1f, 0x02140102,
0x28160d05, 0x00000008, 0x021400a0, 0x281600a0, 0x01c00010,
0x01c00010, 0x02000010, 0x02000010, 0x02000010, 0x02000010,
0x01c00010, 0x02000010, 0x01c00010, 0x01c00010, 0x01c00010,
0x01c00010, 0x00000010, 0x00000010, 0x03c00010, 0x00000003,
0x00000000, 0x00000300
};
static const struct rtwn_bb_prog rtl8188ftv_bb[] = {
{
nitems(rtl8188ftv_bb_regs),
rtl8188ftv_bb_regs,
rtl8188ftv_bb_vals,
{ 0 },
NULL
}
};
static const uint32_t rtl8188ftv_agc_vals[] = {
0xfc000001, 0xfb010001, 0xfa020001, 0xf9030001, 0xf8040001,
0xf7050001, 0xf6060001, 0xf5070001, 0xf4080001, 0xf3090001,
0xf20a0001, 0xf10b0001, 0xf00c0001, 0xef0d0001, 0xee0e0001,
0xed0f0001, 0xec100001, 0xeb110001, 0xea120001, 0xe9130001,
0xe8140001, 0xe7150001, 0xe6160001, 0xe5170001, 0xe4180001,
0xe3190001, 0xe21a0001, 0xe11b0001, 0xe01c0001, 0xc21d0001,
0xc11e0001, 0xc01f0001, 0xa5200001, 0xa4210001, 0xa3220001,
0xa2230001, 0xa1240001, 0xa0250001, 0x65260001, 0x64270001,
0x63280001, 0x62290001, 0x612a0001, 0x442b0001, 0x432c0001,
0x422d0001, 0x412e0001, 0x402f0001, 0x21300001, 0x20310001,
0x05320001, 0x04330001, 0x03340001, 0x02350001, 0x01360001,
0x00370001, 0x00380001, 0x00390001, 0x003a0001, 0x003b0001,
0x003c0001, 0x003d0001, 0x003e0001, 0x003f0001
};
static const struct rtwn_agc_prog rtl8188ftv_agc[] = {
{
nitems(rtl8188ftv_agc_vals),
rtl8188ftv_agc_vals,
{ 0 },
NULL
}
};
/*
* RF initialization values.
*/
static const uint8_t rtl8188ftv_rf_regs[] = {
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, 0xef, 0x3b, 0x3b, 0xef,
0xef, 0x30, 0x31, 0x32, 0xef, 0x00, 0x18, 0xfe, 0xfe, 0x1f,
0xfe, 0xfe, 0x1e, 0x1f, 0x00
};
static const uint32_t rtl8188ftv_rf_vals[] = {
0x30000, 0x08400, 0x00407, 0x00012, 0x01c6c, 0x80009, 0x00880,
0x1a060, 0x28000, 0x060c0, 0xd0000, 0xc0160, 0x01552, 0x00000,
0xff9f0, 0x22218, 0x34c00, 0x4484b, 0x0112a, 0x0053e, 0x10408,
0x10200, 0x80001, 0x40001, 0x00400, 0xc0000, 0x02400, 0x00009,
0x40c91, 0x99999, 0x000a3, 0x8f820, 0x76c06, 0x00000, 0x80000,
0x00180, 0x001a0, 0xe8231, 0xfac2c, 0x00141, 0x517f0, 0x00090,
0x00190, 0x00290, 0x01064, 0x09064, 0x11064, 0x19064, 0x00c07,
0x48000, 0x739d0, 0x0add2, 0x09dd0, 0x08cf3, 0x07cf0, 0x06ced,
0x05cd2, 0x04ccf, 0x03ccc, 0x02cc9, 0x01c4c, 0x00c49, 0x30159,
0x48000, 0x0002a, 0x00025, 0x65540, 0x88000, 0x020a0, 0xf0f00,
0xe0b00, 0xd0900, 0xc0700, 0xb0600, 0xa0400, 0x90200, 0x80000,
0x7bf00, 0x60b00, 0x5c900, 0x40700, 0x30600, 0x2d500, 0x10200,
0x0e000, 0x000a0, 0x00010, 0x0c0a8, 0x10400, 0x00000, 0x80000,
0x10000, 0x0000f, 0x07efe, 0x00000, 0x10159, 0x0fc07, 0x00000,
0x00000, 0x80003, 0x00000, 0x00000, 0x00001, 0x80000, 0x33d95
};
static const struct rtwn_rf_prog rtl8188ftv_rf[] = {
{
nitems(rtl8188ftv_rf_regs),
rtl8188ftv_rf_regs,
rtl8188ftv_rf_vals,
{ 0 },
NULL
},
{ 0, NULL, NULL, { 0 }, NULL }
};
#endif /* R88F_PRIV_H */
+80
View File
@@ -0,0 +1,80 @@
/*
* Copyright (c) 2026 Mir Saheb Ali <mirsahebali@pm.me>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#ifndef R88F_REG_H
#define R88F_REG_H
/*
* Baseband registers.
*/
/* FPGA0. */
#define R88F_FPGA0_PSD_FUNC 0x808
#define R88F_FPGA0_XB_RF_INT_OE 0x864
#define R88F_FPGA0_XCD_RF_SW_CTRL 0x874
#define R88F_FPGA0_ANALOG4 0x88c
#define R88F_FPGA0_PSD_REPORT 0x8b4
/* Noise Histogram. */
#define R88F_NHM_TH9_TH10_8723B 0x890
#define R88F_NHM_TIMER_8723B 0x894
#define R88F_NHM_TH3_TO_TH0_8723B 0x898
#define R88F_NHM_TH7_TO_TH4_8723B 0x89c
/* RX/CCK. */
#define R88F_RX_DFIR 0x954
#define R88F_CCK_PD_THRESH 0xa0a
/* OFDM0. */
#define R88F_OFDM0_FA_RSTC 0xc0c
#define R88F_OFDM0_XA_RX_AFE 0xc10
#define R88F_OFDM0_RX_D_SYNC_PATH 0xc40
/* OFDM1. */
#define R88F_OFDM1_CFO_TRACKING 0xd2c
#define R88F_OFDM1_CSI_FIX_MASK1 0xd40
#define R88F_OFDM1_CSI_FIX_MASK2 0xd44
/* ADDA registers. */
#define R88F_SLEEP 0xee0
#define R88F_RX_OFDM 0xed0
#define R88F_STANDBY 0xedc
#define R88F_RX_WAIT_RIFS 0xed4
#define R88F_RX_TO_RX 0xed8
#define R88F_PMPD_ANAEN 0xeec
#define R88F_RX_CCK 0xe8c
#define R88F_TX_OFDM_RFON 0xe7c
#define R88F_TX_TO_TX 0xe88
#define R88F_FPGA0_XCD_SWITCH_CTRL 0x85c
#define R88F_BLUETOOTH 0xe6c
#define R88F_TX_OFDM_BBON 0xe80
#define R88F_TX_CCK_RFON 0xe74
#define R88F_TX_TO_RX 0xe84
#define R88F_TX_CCK_BBON 0xe78
#define R88F_RX_WAIT_CCA 0xe70
/*
* RF (6052) registers.
*/
#define R88F_RF_GAIN_CCA 0xdf
#define R88F_RF_UNKNOWN_55 0x55
#define R88F_RF_PAD_TXG 0x56
#define R88F_RF_RXG_GAIN 0x87
/* Bits for R92C_RF_CHNLBW. */
#define R88F_RF_CHNLBW_BW20 0xc00
#define R88F_RF_CHNLBW_BW40 0x400
/* Bits for R88F_RF_RXG_GAIN. */
#define R88F_RF_TXA_PREPAD 0x65
/* Bits for R88F_RF_GAIN_CCA. */
#define R88F_RF_PKTBUF_DBG_CTRL 0x140
/* Bits for R88F_CCK_PD_THRESH. */
#define R88F_CCK_PD_TYPE1_LV1_TH 0x83
#endif /* R88F_REG_H */
+121
View File
@@ -0,0 +1,121 @@
/* $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>
* Copyright (c) 2026 Mir Saheb Ali <mirsahebali@pm.me>
*
* 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>
#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_priv.h>
#include <dev/rtwn/rtl8188e/r88e_rom_image.h>
#include <dev/rtwn/rtl8192c/r92c_var.h>
#include <dev/rtwn/rtl8192c/r92c_reg.h>
#include <dev/rtwn/rtl8188f/r88f.h>
#include <dev/rtwn/rtl8188f/r88f_priv.h>
#include <dev/rtwn/rtl8188f/r88f_rom_image.h>
#define R88F_XTAL1_MASK 0x007e0000 /* bits 22:17 */
#define R88F_XTAL0_MASK 0x0001f800 /* bits 16:11 */
int
r88f_efuse_preread(struct rtwn_softc *sc)
{
int error;
uint32_t reg;
/* Switch to the WIFI bank. */
reg = rtwn_read_4(sc, R92C_EFUSE_TEST);
reg = RW(reg, R92C_EFUSE_TEST_SEL, 0);
error = rtwn_write_4(sc, R92C_EFUSE_TEST, reg);
if (error != 0)
return (error);
error = rtwn_write_1(sc, R92C_EFUSE_ACCESS, R92C_EFUSE_ACCESS_OFF);
rtwn_delay(sc, 10);
return (error);
}
void
r88f_parse_rom(struct rtwn_softc *sc, uint8_t *buf)
{
struct r92c_softc *rs = sc->sc_priv;
struct rtwn_r88e_txpwr *rt = rs->rs_txpwr;
struct r88f_rom *rom = (struct r88f_rom *)buf;
int i;
rt->bw20_tx_pwr_diff = RTWN_SIGN4TO8(MS(rom->tx_pwr_diff, HIGH_PART));
rt->ofdm_tx_pwr_diff = RTWN_SIGN4TO8(MS(rom->tx_pwr_diff, LOW_PART));
for (i = 0; i < nitems(rom->ht40_tx_pwr); i++) {
rt->ht40_tx_pwr[i] = rom->ht40_tx_pwr[i];
if (rt->ht40_tx_pwr[i] > 0x3f)
rt->ht40_tx_pwr[i] = 0x27;
}
for (i = 0; i < nitems(rom->cck_tx_pwr); i++) {
rt->cck_tx_pwr[i] = rom->cck_tx_pwr[i];
if (rt->cck_tx_pwr[i] > 0x3f)
rt->cck_tx_pwr[i] = 0x22;
}
rs->crystalcap = rom->crystalcap & 0x3f;
rs->regulatory = MS(rom->rf_board_opt, R92C_ROM_RF1_REGULATORY);
rs->board_type =
MS(RTWN_GET_ROM_VAR(rom->rf_board_opt, R92C_BOARD_TYPE_DONGLE),
R92C_ROM_RF1_BOARD_TYPE);
RTWN_DPRINTF(sc, RTWN_DEBUG_ROM, "%s: regulatory type %d\n",
__func__, rs->regulatory);
sc->thermal_meter = rom->thermal_meter;
rtwn_r92c_set_rom_opts(sc, buf);
}
+12
View File
@@ -0,0 +1,12 @@
/*
* Copyright (c) 2026 Mir Saheb Ali <mirsahebali@pm.me>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#ifndef R88F_ROM_DEFS_H
#define R88F_ROM_DEFS_H
#include <dev/rtwn/rtl8188e/r88e_rom_defs.h>
#endif /* R88F_ROM_DEFS_H */
+56
View File
@@ -0,0 +1,56 @@
/*-
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
* Copyright (c) 2026 Mir Saheb Ali <mirsahebali@pm.me>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef R88F_ROM_IMAGE_H
#define R88F_ROM_IMAGE_H
#include <dev/rtwn/rtl8188f/r88f_rom_defs.h>
/*
* RTL8188FTV ROM image.
*/
struct r88f_rom {
uint8_t reserved1[16];
uint8_t cck_tx_pwr[R88E_GROUP_2G];
uint8_t ht40_tx_pwr[R88E_GROUP_2G - 1];
uint8_t tx_pwr_diff;
uint8_t reserved2[156];
uint8_t channel_plan;
uint8_t crystalcap;
uint8_t thermal_meter;
uint8_t iqk_lck;
uint8_t pa_type;
uint8_t lna_type_2g;
uint8_t reserved3[3];
uint8_t rf_board_opt;
uint8_t rf_feature_opt;
uint8_t rf_bt_opt;
uint8_t version;
uint8_t customer_id;
uint8_t reserved4[10];
uint16_t vid;
uint16_t pid;
uint8_t usb_opt;
uint8_t reserved5[2];
uint8_t macaddr[IEEE80211_ADDR_LEN];
uint8_t reserved6[291];
} __packed;
_Static_assert(sizeof(struct r88f_rom) == R88E_EFUSE_MAP_LEN,
"R88E_EFUSE_MAP_LEN must be equal to sizeof(struct r88f_rom)!");
#endif /* R88F_ROM_IMAGE_H */
+132
View File
@@ -0,0 +1,132 @@
/*
* Copyright (c) 2026 Mir Saheb Ali <mirsahebali@pm.me>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <sys/cdefs.h>
#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_ridx.h>
#include <dev/rtwn/rtl8188e/r88e_rx_desc.h>
#include <dev/rtwn/rtl8192c/r92c.h>
#include <dev/rtwn/rtl8192c/r92c_rx_desc.h>
#include <dev/rtwn/rtl8192e/r92e_reg.h>
#include <dev/rtwn/rtl8188f/r88f.h>
int8_t
r88f_get_rssi_cck(struct rtwn_softc *sc, void *physt)
{
struct r88e_rx_phystat *phy = (struct r88e_rx_phystat *)physt;
int8_t lna_idx, vga_idx, rssi;
lna_idx = (phy->agc_rpt & 0xe0) >> 5;
vga_idx = (phy->agc_rpt & 0x1f);
rssi = -(2 * vga_idx);
switch (lna_idx) {
case 7:
if (vga_idx > 27)
rssi = -100;
else
rssi += -46;
break;
case 5:
rssi += -32;
break;
case 3:
rssi += -20;
break;
case 1:
rssi += -6;
break;
default:
rssi = 0;
break;
}
return (rssi);
}
int8_t
r88f_get_rssi_ofdm(struct rtwn_softc *sc, void *physt)
{
struct r88e_rx_phystat *phy = (struct r88e_rx_phystat *)physt;
int rssi;
/* Get average RSSI. */
rssi = ((le32toh(phy->sig_qual) >> 1) & 0x7f) - 110;
return (rssi);
}
void
r88f_get_rx_stats(struct rtwn_softc *sc, struct ieee80211_rx_stats *rxs,
const void *desc, const void *physt_ptr)
{
const struct r92c_rx_stat *stat = desc;
uint32_t rxdw1, rxdw3;
uint8_t rate;
rxdw1 = le32toh(stat->rxdw1);
rxdw3 = le32toh(stat->rxdw3);
rate = MS(rxdw3, R92E_RXDW3_RATE);
if (rxdw1 & R92C_RXDW1_AMPDU)
rxs->c_pktflags |= IEEE80211_RX_F_AMPDU;
else if (rxdw1 & R92C_RXDW1_AMPDU_MORE)
rxs->c_pktflags |= IEEE80211_RX_F_AMPDU_MORE;
if ((rxdw3 & R92C_RXDW3_SPLCP) && RTWN_RATE_IS_HT(rate))
rxs->c_pktflags |= IEEE80211_RX_F_SHORTGI;
if (rxdw3 & R92C_RXDW3_HT40)
rxs->c_width = IEEE80211_RX_FW_40MHZ;
else
rxs->c_width = IEEE80211_RX_FW_20MHZ;
if (RTWN_RATE_IS_CCK(rate))
rxs->c_phytype = IEEE80211_RX_FP_11B;
else if (RTWN_RATE_IS_OFDM(rate))
rxs->c_phytype = IEEE80211_RX_FP_11G;
else
rxs->c_phytype = IEEE80211_RX_FP_11NG;
/* Map HW rate index to 802.11 rate. */
if (RTWN_RATE_IS_CCK(rate) || RTWN_RATE_IS_OFDM(rate)) {
rxs->c_rate = ridx2rate[rate];
if (RTWN_RATE_IS_CCK(rate))
rxs->c_pktflags |= IEEE80211_RX_F_CCK;
else
rxs->c_pktflags |= IEEE80211_RX_F_OFDM;
} else { /* MCS0~15. */
rxs->c_rate =
IEEE80211_RATE_MCS | (RTWN_RIDX_TO_MCS(rate));
rxs->c_pktflags |= IEEE80211_RX_F_HT;
}
}
+24
View File
@@ -0,0 +1,24 @@
/*
* Copyright (c) 2026 Mir Saheb Ali <mirsahebali@pm.me>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#ifndef RTL8188FU_H
#define RTL8188FU_H
#include <dev/rtwn/rtl8188f/r88f.h>
/*
* Function declarations
*/
/* r88fu_init.c */
int r88fu_power_on(struct rtwn_softc *);
void r88fu_power_off(struct rtwn_softc *);
void r88fu_init_rx_agg(struct rtwn_softc *);
void r88fu_init_tx_agg(struct rtwn_softc *);
void r88fu_init_bb(struct rtwn_softc *);
void r88fu_post_init(struct rtwn_softc *);
#endif /* RTL8188FU_H */
+254
View File
@@ -0,0 +1,254 @@
/* $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>
* Copyright (c) 2026 Mir Saheb Ali <mirsahebali@pm.me>
*
* 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>
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/if_rtwn_nop.h>
#include <dev/rtwn/usb/rtwn_usb_var.h>
#include <dev/rtwn/rtl8188e/r88e_priv.h>
#include <dev/rtwn/rtl8188e/r88e_rom_image.h> /* for 'macaddr' field */
#include <dev/rtwn/rtl8188e/usb/r88eu.h>
#include <dev/rtwn/rtl8192c/r92c_reg.h>
#include <dev/rtwn/rtl8192c/r92c_var.h>
#include <dev/rtwn/rtl8192c/usb/r92cu.h>
#include <dev/rtwn/rtl8192c/usb/r92cu_tx_desc.h>
#include <dev/rtwn/rtl8192e/r92e.h>
#include <dev/rtwn/rtl8723b/r23b.h>
#include <dev/rtwn/rtl8812a/r12a.h>
#include <dev/rtwn/rtl8812a/usb/r12au.h>
#include <dev/rtwn/rtl8812a/usb/r12au_tx_desc.h>
#include <dev/rtwn/rtl8188f/r88f.h>
#include <dev/rtwn/rtl8188f/r88f_priv.h>
#include <dev/rtwn/rtl8188f/r88f_reg.h>
#include <dev/rtwn/rtl8188f/r88f_rom_defs.h>
#include <dev/rtwn/rtl8188f/r88f_rom_image.h>
#include <dev/rtwn/rtl8188f/usb/r88fu.h>
static struct rtwn_r88e_txpwr r88e_txpwr;
void r88fu_attach(struct rtwn_usb_softc *);
static void
r88fu_set_macaddr(struct rtwn_softc *sc, uint8_t *buf)
{
struct r88f_rom *rom = (struct r88f_rom *)buf;
IEEE80211_ADDR_COPY(sc->sc_ic.ic_macaddr, rom->macaddr);
}
static void
r88f_postattach(struct rtwn_softc *sc)
{
struct r92c_softc *rs = sc->sc_priv;
struct ieee80211com *ic = &sc->sc_ic;
rs->rs_scan_start = ic->ic_scan_start;
ic->ic_scan_start = r92c_scan_start;
rs->rs_scan_end = ic->ic_scan_end;
ic->ic_scan_end = r92c_scan_end;
}
static void
r88fu_attach_private(struct rtwn_softc *sc)
{
struct r92c_softc *rs;
rs = malloc(sizeof(struct r92c_softc), M_RTWN_PRIV, M_WAITOK | M_ZERO);
rs->rs_txpwr = &r88e_txpwr;
rs->rs_txagc = NULL;
rs->rs_set_bw20 = r88e_set_bw20;
rs->rs_get_txpower = r88f_get_txpower;
rs->rs_set_gain = r88e_set_gain;
rs->rs_tx_enable_ampdu = r88e_tx_enable_ampdu;
rs->rs_tx_setup_hwseq = r88e_tx_setup_hwseq;
rs->rs_tx_setup_macid = r88e_tx_setup_macid;
rs->rs_set_rom_opts = r88fu_set_macaddr;
rs->rf_read_delay[0] = 10;
rs->rf_read_delay[1] = 100;
rs->rf_read_delay[2] = 10;
sc->sc_priv = rs;
}
static void
r88fu_enable_mac_txrx(struct rtwn_softc *sc)
{
rtwn_setbits_2(sc, R92C_CR, 0, R92C_CR_MACTXEN | R92C_CR_MACRXEN);
rtwn_bb_setbits(sc, R92C_TXDMA_OFFSET_CHK, 0, R92C_RQPN);
}
static void
r88fu_adj_devcaps(struct rtwn_softc *sc)
{
/* XXX TODO? */
}
void
r88fu_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 = 6;
/* Common part. */
sc->sc_flags = RTWN_FLAG_EXT_HDR;
sc->sc_set_chan = r88f_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 = r88f_get_rx_stats;
sc->sc_get_rssi_cck = r88f_get_rssi_cck;
sc->sc_get_rssi_ofdm = r88f_get_rssi_ofdm;
sc->sc_classify_intr = r12au_classify_intr;
sc->sc_handle_tx_report = r12a_ratectl_tx_complete;
sc->sc_handle_tx_report2 = rtwn_nop_softc_uint8_int;
sc->sc_handle_c2h_report = r92e_handle_c2h_report;
sc->sc_check_frame = rtwn_nop_int_softc_mbuf;
sc->sc_rf_read = r92c_rf_read;
sc->sc_rf_write = r88e_rf_write;
sc->sc_check_condition = r92c_check_condition;
sc->sc_efuse_postread = rtwn_nop_softc;
sc->sc_efuse_preread = r88f_efuse_preread;
sc->sc_parse_rom = r88f_parse_rom;
sc->sc_set_led = r88e_set_led;
sc->sc_power_on = r88fu_power_on;
sc->sc_power_off = r88fu_power_off;
#ifndef RTWN_WITHOUT_UCODE
sc->sc_fw_reset = r88f_fw_reset;
sc->sc_fw_download_enable = r88f_fw_download_enable;
#endif
sc->sc_llt_init = r88f_llt_init;
sc->sc_enable_mac_txrx = r88fu_enable_mac_txrx;
sc->sc_set_page_size = r88f_set_page_size;
sc->sc_lc_calib = r88f_lc_calib;
sc->sc_iq_calib = r88f_iq_calib;
sc->sc_read_chipid_vendor = rtwn_nop_softc_uint32;
sc->sc_adj_devcaps = r88fu_adj_devcaps;
sc->sc_vap_preattach = rtwn_nop_softc_vap;
sc->sc_postattach = r88f_postattach;
sc->sc_detach_private = r92c_detach_private;
sc->sc_set_media_status = r88e_set_media_status;
#ifndef RTWN_WITHOUT_UCODE
sc->sc_set_rsvd_page = r88e_set_rsvd_page;
sc->sc_set_pwrmode = r88e_set_pwrmode;
sc->sc_set_rssi = rtwn_nop_softc; /* XXX TODO? */
#endif
sc->sc_beacon_init = r92c_beacon_init;
sc->sc_beacon_enable = r88e_beacon_enable;
sc->sc_sta_beacon_enable = r88e_sta_beacon_enable;
sc->sc_beacon_set_rate = rtwn_nop_void_int;
sc->sc_beacon_select = rtwn_nop_softc_int;
sc->sc_temp_measure = r88e_temp_measure;
sc->sc_temp_read = r88e_temp_read;
sc->sc_init_tx_agg = r88fu_init_tx_agg;
sc->sc_init_rx_agg = r88fu_init_rx_agg;
sc->sc_init_beacon_timer = rtwn_nop_softc;
sc->sc_init_ampdu = r88f_init_ampdu;
sc->sc_init_intr = r88eu_init_intr;
sc->sc_init_edca = r92c_init_edca;
sc->sc_init_bb = r88fu_init_bb;
sc->sc_init_rf = r88f_init_rf;
sc->sc_init_antsel = r23b_init_antsel;
sc->sc_post_init = r88fu_post_init;
sc->sc_init_bcnq1_boundary = rtwn_nop_int_softc;
sc->sc_set_tx_power = r92c_set_tx_power;
sc->mac_prog = &rtl8188ftv_mac[0];
sc->mac_size = nitems(rtl8188ftv_mac);
sc->bb_prog = &rtl8188ftv_bb[0];
sc->bb_size = nitems(rtl8188ftv_bb);
sc->agc_prog = &rtl8188ftv_agc[0];
sc->agc_size = nitems(rtl8188ftv_agc);
sc->rf_prog = &rtl8188ftv_rf[0];
sc->name = "RTL8188FTV";
sc->fwname = "rtwn-rtl8188fufw";
sc->fwsig = 0x88f;
sc->ackto = 0x40;
sc->npubqpages = R88EU_PUBQ_NPAGES;
sc->nhqpages = R88F_HQ_NPAGES;
sc->nlqpages = R88F_LQ_NPAGES;
sc->nnqpages = R88F_NQ_NPAGES;
sc->page_size = R92C_TX_PAGE_SIZE;
sc->page_count = R88F_TX_PAGE_COUNT;
sc->pktbuf_count = R88F_TXPKTBUF_COUNT;
sc->txdesc_len = sizeof(struct r12au_tx_desc);
sc->efuse_maxlen = R88E_EFUSE_MAX_LEN;
sc->efuse_maplen = R88E_EFUSE_MAP_LEN;
sc->rx_dma_size = R88F_RX_DMA_BUFFER_SIZE;
sc->macid_limit = R88E_MACID_MAX + 1;
sc->cam_entry_limit = R92C_CAM_ENTRY_COUNT;
sc->fwsize_limit = R88F_MAX_FW_SIZE;
sc->temp_delta = R88E_CALIB_THRESHOLD;
sc->bcn_status_reg[0] = R92C_TDECTRL;
sc->bcn_status_reg[1] = R92C_TDECTRL;
sc->rcr = 0;
sc->ntxchains = 1;
sc->nrxchains = 1;
r88fu_attach_private(sc);
}
+444
View File
@@ -0,0 +1,444 @@
/* $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>
* Copyright (c) 2026 Mir Saheb Ali <mirsahebali@pm.me>
*
* 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>
#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/usb/rtwn_usb_var.h>
#include <dev/rtwn/if_rtwn_debug.h>
#include <dev/rtwn/rtl8188e/r88e.h>
#include <dev/rtwn/rtl8188e/usb/r88eu.h>
#include <dev/rtwn/rtl8188e/usb/r88eu_reg.h>
#include <dev/rtwn/rtl8192c/r92c.h>
#include <dev/rtwn/rtl8192c/r92c_var.h>
#include <dev/rtwn/rtl8192c/usb/r92cu.h>
#include <dev/rtwn/rtl8192e/r92e_reg.h>
#include <dev/rtwn/rtl8188f/r88f_reg.h>
#include <dev/rtwn/rtl8188f/usb/r88fu.h>
void
r88fu_init_tx_agg(struct rtwn_softc *sc)
{
uint8_t agg_ctrl, rxdma_mode, usb_tx_agg_desc_num = 6;
uint32_t agg_rx;
/* TX aggregation */
rtwn_setbits_4(sc, R92C_TDECTRL, 0xf << 4, usb_tx_agg_desc_num << 4);
rtwn_write_1(sc, R92E_DWBCN1_CTRL, usb_tx_agg_desc_num << 1);
/* RX aggegation */
agg_ctrl = rtwn_read_1(sc, R92C_TRXDMA_CTRL);
agg_ctrl &= ~0x00000004;
agg_rx = rtwn_read_1(sc, R92C_RXDMA_AGG_PG_TH);
agg_rx &= ~0x80000000;
agg_rx &= ~0xff0f; /* reset agg size and timeout */
rxdma_mode = rtwn_read_1(sc, R92E_RXDMA_PRO);
rxdma_mode &= ~0x00000002;
rtwn_write_1(sc, R92C_TRXDMA_CTRL, agg_ctrl);
rtwn_write_4(sc, R92C_RXDMA_AGG_PG_TH, agg_rx);
rtwn_write_1(sc, R92E_RXDMA_PRO, rxdma_mode);
}
int
r88fu_power_on(struct rtwn_softc *sc)
{
#define RTWN_CHK(res) do { \
if (res != 0) \
return (EIO); \
} while (0)
int ntries;
/* Enable WL suspend. */
RTWN_CHK(rtwn_setbits_2(sc, R92C_APS_FSMCO,
R92C_APS_FSMCO_AFSM_HSUS | R92C_APS_FSMCO_AFSM_PCIE, 0));
/* Turn off USB APHY LDO under suspend mode. */
RTWN_CHK(rtwn_setbits_1(sc, 0xc4, 0x10, 0));
RTWN_CHK(rtwn_setbits_2(sc, R92C_APS_FSMCO, R92C_APS_FSMCO_APFM_RSM, 0));
/* 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);
}
/* Disable HWPDN. */
RTWN_CHK(rtwn_setbits_2(sc, R92C_APS_FSMCO, R92C_APS_FSMCO_APDM_HPDN, 0));
/* Disable WL suspend. */
RTWN_CHK(rtwn_setbits_2(sc, R92C_APS_FSMCO, R92C_APS_FSMCO_AFSM_HSUS, 0));
/* Auto enable WLAN. */
RTWN_CHK(rtwn_setbits_2(sc, R92C_APS_FSMCO, 0, R92C_APS_FSMCO_APFM_ONMAC));
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);
/* Reduce RF noise. */
rtwn_write_1(sc, R92C_AFE_LDO_CTRL, 0x35);
/* 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 |
R92C_CR_ENSEC | R92C_CR_CALTMR_EN));
return (0);
#undef RTWN_CHK
}
#define R88F_RXPKT_NUM_RW_RELEASE_ENABLE 0x00040000
#define R88F_RXPKT_NUM_RXDMA_IDLE 0x00020000
static int
r88fu_flush_fifo(struct rtwn_softc *sc)
{
uint32_t reg;
int retry, retval;
rtwn_write_1(sc, R92C_TXPAUSE, 0xff);
rtwn_bb_setbits(sc, R92C_RXPKT_NUM, 0, R88F_RXPKT_NUM_RW_RELEASE_ENABLE);
retry = 100;
/* setting retval to (EBUSY = 16) */
retval = -16;
do {
reg = rtwn_bb_read(sc, R92C_RXPKT_NUM);
if (reg & R88F_RXPKT_NUM_RXDMA_IDLE) {
retval = 0;
break;
}
} while (retry--);
rtwn_write_2(sc, R92C_RQPN_NPQ, 0);
rtwn_bb_write(sc, R92C_RQPN, 0x80000000);
rtwn_delay(sc, 2);
if (!retry)
device_printf(sc->sc_dev, "%s: Failed to flush FIFO\n", __func__);
return (retval);
}
void
r88fu_power_off(struct rtwn_softc *sc)
{
uint8_t reg;
int error, ntries;
r88fu_flush_fifo(sc);
/* Disable any kind of TX reports. */
error = rtwn_setbits_1(sc, R88E_TX_RPT_CTRL,
R88E_TX_RPT1_ENA | R88E_TX_RPT2_ENA, 0);
if (error == ENXIO) /* hardware gone */
return;
/* Stop Rx. */
rtwn_write_1(sc, R92C_CR, 0);
/* Move card to Low Power State. */
/* Block all Tx queues. */
rtwn_write_1(sc, R92C_TXPAUSE, R92C_TX_QUEUE_ALL);
for (ntries = 0; ntries < 10; ntries++) {
/* Should be zero if no packet is transmitting. */
if (rtwn_read_4(sc, R88E_SCH_TXCMD) == 0)
break;
rtwn_delay(sc, 5000);
}
if (ntries == 10) {
device_printf(sc->sc_dev, "%s: failed to block Tx queues\n",
__func__);
return;
}
/* CCK and OFDM are disabled, and clock are gated. */
rtwn_setbits_1(sc, R92C_SYS_FUNC_EN, R92C_SYS_FUNC_EN_BBRSTB, 0);
rtwn_delay(sc, 1);
/* Reset MAC TRX */
rtwn_write_1(sc, R92C_CR,
R92C_CR_HCI_TXDMA_EN | R92C_CR_HCI_RXDMA_EN |
R92C_CR_TXDMA_EN | R92C_CR_RXDMA_EN |
R92C_CR_PROTOCOL_EN | R92C_CR_SCHEDULE_EN);
/* check if removed later */
rtwn_setbits_1_shift(sc, R92C_CR, R92C_CR_ENSEC, 0, 1);
/* Respond TxOK to scheduler */
rtwn_setbits_1(sc, R92C_DUAL_TSF_RST, 0, 0x20);
/* If firmware in ram code, do reset. */
#ifndef RTWN_WITHOUT_UCODE
if (rtwn_read_1(sc, R92C_MCUFWDL) & R92C_MCUFWDL_RDY)
r88f_fw_reset(sc, RTWN_FW_RESET_SHUTDOWN);
#endif
/* Reset MCU ready status. */
rtwn_write_1(sc, R92C_MCUFWDL, 0);
/* Disable 32k. */
rtwn_setbits_1(sc, R88E_32K_CTRL, 0x01, 0);
/* Move card to Disabled state. */
/* Turn off RF. */
rtwn_write_1(sc, R92C_RF_CTRL, 0);
/* LDO Sleep mode. */
rtwn_setbits_1(sc, R92C_LPLDO_CTRL, 0, R92C_LPLDO_CTRL_SLEEP);
/* Turn off MAC by HW state machine */
rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, 0,
R92C_APS_FSMCO_APFM_OFF, 1);
for (ntries = 0; ntries < 10; ntries++) {
/* Wait until it will be disabled. */
if ((rtwn_read_2(sc, R92C_APS_FSMCO) &
R92C_APS_FSMCO_APFM_OFF) == 0)
break;
rtwn_delay(sc, 5000);
}
if (ntries == 10) {
device_printf(sc->sc_dev, "%s: could not turn off MAC\n",
__func__);
return;
}
/* schmit trigger */
rtwn_setbits_1(sc, R92C_AFE_XTAL_CTRL + 2, 0, 0x80);
/* Enable WL suspend. */
rtwn_setbits_1_shift(sc, R92C_APS_FSMCO,
R92C_APS_FSMCO_AFSM_PCIE, R92C_APS_FSMCO_AFSM_HSUS, 1);
/* Enable bandgap mbias in suspend. */
rtwn_write_1(sc, R92C_APS_FSMCO + 3, 0);
/* Clear SIC_EN register. */
rtwn_setbits_1(sc, R92C_GPIO_MUXCFG + 1, 0x10, 0);
/* Set USB suspend enable local register */
rtwn_setbits_1(sc, R92C_USB_SUSPEND, 0, 0x10);
/* Reset MCU IO Wrapper. */
reg = rtwn_read_1(sc, R92C_RSV_CTRL + 1);
rtwn_write_1(sc, R92C_RSV_CTRL + 1, reg & ~0x08);
rtwn_write_1(sc, R92C_RSV_CTRL + 1, reg | 0x08);
/* marked as 'For Power Consumption' code. */
rtwn_write_1(sc, R92C_GPIO_OUT, rtwn_read_1(sc, R92C_GPIO_IN));
rtwn_write_1(sc, R92C_GPIO_IOSEL, 0xff);
rtwn_write_1(sc, R92C_GPIO_IO_SEL,
rtwn_read_1(sc, R92C_GPIO_IO_SEL) << 4);
rtwn_setbits_1(sc, R92C_GPIO_MOD, 0, 0x0f);
/* Set LNA, TRSW, EX_PA Pin to output mode. */
rtwn_write_4(sc, R88E_BB_PAD_CTRL, 0x00080808);
}
void
r88fu_init_rx_agg(struct rtwn_softc *sc)
{
rtwn_setbits_1(sc, R92E_RXDMA_PRO, 0x3c, 0x1c);
rtwn_setbits_1(sc, R92C_TRXDMA_CTRL, 0, R92C_TRXDMA_CTRL_RXDMA_AGG_EN);
/* set 5 is the dmasize */
rtwn_write_1(sc, R92C_RXDMA_AGG_PG_TH, 5);
/* set 32 is the dmatiming */
rtwn_write_1(sc, R92C_RXDMA_AGG_PG_TH + 1, 32);
rtwn_setbits_1(sc, R92E_RXDMA_PRO, 0, R92E_RXDMA_PRO_DMA_MODE);
}
#define R88F_XTAL1_M 0x007E0000U
#define R88F_XTAL1_S 17
#define R88F_XTAL0_M 0x0001F800U
#define R88F_XTAL0_S 11
static void
r88fu_set_crystal_cap(struct rtwn_softc *sc)
{
struct r92c_softc *rs = sc->sc_priv;
uint32_t reg;
uint8_t cap;
cap = rs->crystalcap & 0x3f;
reg = rtwn_bb_read(sc, R92C_AFE_XTAL_CTRL);
RTWN_DPRINTF(sc, RTWN_DEBUG_USB,
"%s: Adjusting crystal cap from 0x%x (actually 0x%x 0x%x) to 0x%x\n",
__func__,
rs->crystalcap,
MS(reg, R88F_XTAL1),
MS(reg, R88F_XTAL0),
cap);
reg &= ~(R88F_XTAL1_M | R88F_XTAL0_M);
reg |= SM(R88F_XTAL1, cap) | SM(R88F_XTAL0, cap);
rtwn_bb_write(sc, R92C_AFE_XTAL_CTRL, reg);
}
static void
r88f_init_bb_common(struct rtwn_softc *sc)
{
r92c_init_bb_common(sc);
rtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(0), 0x69553422);
rtwn_delay(sc, 1);
rtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(0), 0x69553420);
rtwn_delay(sc, 1);
r88fu_set_crystal_cap(sc);
}
void
r88fu_init_bb(struct rtwn_softc *sc)
{
/* Enable BB and RF */
rtwn_setbits_2(sc, R92C_SYS_FUNC_EN, 0,
R92C_SYS_FUNC_EN_BBRSTB | R92C_SYS_FUNC_EN_BB_GLB_RST |
R92C_SYS_FUNC_EN_DIO_RF);
/*
* Per vendor driver, run power sequence before init of RF
*/
rtwn_write_1(sc, R92C_RF_CTRL, R92C_RF_CTRL_EN | R92C_RF_CTRL_RSTB | R92C_RF_CTRL_SDMRSTB);
rtwn_write_1(sc, R92C_SYS_FUNC_EN,
R92C_SYS_FUNC_EN_USBA | R92C_SYS_FUNC_EN_USBD |
R92C_SYS_FUNC_EN_BB_GLB_RST | R92C_SYS_FUNC_EN_BBRSTB);
rtwn_delay(sc, 10);
rtwn_rf_write(sc, 0, R92C_RF_IQADJ_G(0), 0x780);
r88f_init_bb_common(sc);
/* CCK PD */
rtwn_write_1(sc, R88F_CCK_PD_THRESH, R88F_CCK_PD_TYPE1_LV1_TH);
}
static void
r88fu_init_stats(struct rtwn_softc *sc)
{
uint32_t clr;
rtwn_write_2(sc, R88F_NHM_TIMER_8723B + 2, 0xc350);
rtwn_write_2(sc, R88F_NHM_TH9_TH10_8723B + 2, 0xffff);
rtwn_write_4(sc, R88F_NHM_TH3_TO_TH0_8723B, 0xffffff50);
rtwn_write_4(sc, R88F_NHM_TH7_TO_TH4_8723B, 0xffffffff);
rtwn_setbits_4(sc, R92C_FPGA0_IQK, 0, 0xff);
clr = 0x00000100 | 0x00000200 | 0x00000400;
rtwn_setbits_4(sc, R88F_NHM_TH9_TH10_8723B, clr, 0x00000100);
rtwn_setbits_4(sc, R88F_OFDM0_FA_RSTC, 0, 0x00000080);
}
void
r88fu_post_init(struct rtwn_softc *sc)
{
uint8_t reg8;
/*
* This should enable thermal meter
*/
rtwn_rf_setbits(sc, 0, R88E_RF_T_METER, 0, 0x30000);
rtwn_setbits_1(sc, R88E_TX_RPT_CTRL, 0, R88E_TX_RPT2_ENA);
/* Set MAX RPT MACID */
rtwn_write_1(sc, R88E_TX_RPT_CTRL + 1, R88E_TX_RPT2_ENA);
/* TX report Timer. Unit: 32us */
rtwn_write_2(sc, R88E_TX_RPT_TIME, 0xcdf0);
/* tmp ps ? */
reg8 = rtwn_read_1(sc, 0xa3);
reg8 &= 0xf8;
rtwn_write_1(sc, 0xa3, reg8);
/* Perform LO and IQ calibrations. */
r88f_iq_calib(sc);
/* Perform LC calibration. */
r88f_lc_calib(sc);
rtwn_write_1(sc, R92C_USB_HRPWM, 0);
if (sc->sc_ratectl_sysctl == RTWN_RATECTL_FW) {
/* No support (yet?) for f/w rate adaptation. */
sc->sc_ratectl = RTWN_RATECTL_NET80211;
} else
sc->sc_ratectl = sc->sc_ratectl_sysctl;
r88fu_init_stats(sc);
}
+2
View File
@@ -192,6 +192,7 @@ r92ce_attach(struct rtwn_pci_softc *pc)
sc->sc_fw_download_enable = r92c_fw_download_enable;
#endif
sc->sc_llt_init = r92c_llt_init;
sc->sc_enable_mac_txrx = rtwn_nop_softc;
sc->sc_set_page_size = r92c_set_page_size;
sc->sc_lc_calib = r92c_lc_calib;
sc->sc_iq_calib = r92ce_iq_calib;
@@ -215,6 +216,7 @@ r92ce_attach(struct rtwn_pci_softc *pc)
sc->sc_temp_read = r92c_temp_read;
sc->sc_init_tx_agg = rtwn_nop_softc;
sc->sc_init_rx_agg = rtwn_nop_softc;
sc->sc_init_beacon_timer = r92c_init_beacon_timer;
sc->sc_init_ampdu = r92ce_init_ampdu;
sc->sc_init_intr = r92ce_init_intr;
sc->sc_init_edca = r92ce_init_edca;
+1
View File
@@ -45,6 +45,7 @@ void r92c_read_chipid_vendor(struct rtwn_softc *, uint32_t);
/* r92c_beacon.c */
void r92c_beacon_init(struct rtwn_softc *, void *, int);
void r92c_init_beacon_timer(struct rtwn_softc *);
void r92c_beacon_enable(struct rtwn_softc *, int, int);
void r92c_sta_beacon_enable(struct rtwn_softc *, int, bool);
+6
View File
@@ -48,6 +48,12 @@
#include <dev/rtwn/rtl8192c/r92c_reg.h>
#include <dev/rtwn/rtl8192c/r92c_tx_desc.h>
void
r92c_init_beacon_timer(struct rtwn_softc *sc)
{
rtwn_write_1(sc, R92C_DRVERLYINT, 0x05);
}
void
r92c_beacon_init(struct rtwn_softc *sc, void *buf, int id)
{
+5
View File
@@ -39,6 +39,7 @@
#define R92C_LDOHCI12_CTRL 0x022
#define R92C_LPLDO_CTRL 0x023
#define R92C_AFE_XTAL_CTRL 0x024
#define R92C_AFE_LDO_CTRL 0x027
#define R92C_AFE_PLL_CTRL 0x028
#define R92C_APE_PLL_CTRL_EXT 0x02c
#define R92C_MAC_PHY_CTRL R92C_APE_PLL_CTRL_EXT
@@ -338,6 +339,10 @@
#define R92C_AFE_PLL_CTRL_WDOGB 0x0010
#define R92C_AFE_PLL_CTRL_LPFEN 0x0020
/* Bits for R92C_EFUSE_TEST. */
#define R92C_EFUSE_TEST_SEL_M 0x00000300
#define R92C_EFUSE_TEST_SEL_S 8
/* Bits for R92C_EFUSE_CTRL. */
#define R92C_EFUSE_CTRL_DATA_M 0x000000ff
#define R92C_EFUSE_CTRL_DATA_S 0
+2
View File
@@ -184,6 +184,7 @@ r92cu_attach(struct rtwn_usb_softc *uc)
sc->sc_fw_download_enable = r92c_fw_download_enable;
#endif
sc->sc_llt_init = r92c_llt_init;
sc->sc_enable_mac_txrx = rtwn_nop_softc;
sc->sc_set_page_size = r92c_set_page_size;
sc->sc_lc_calib = r92c_lc_calib;
sc->sc_iq_calib = r92c_iq_calib;
@@ -207,6 +208,7 @@ r92cu_attach(struct rtwn_usb_softc *uc)
sc->sc_temp_read = r92c_temp_read;
sc->sc_init_tx_agg = r92cu_init_tx_agg;
sc->sc_init_rx_agg = r92cu_init_rx_agg;
sc->sc_init_beacon_timer = r92c_init_beacon_timer;
sc->sc_init_ampdu = r92c_init_ampdu;
sc->sc_init_intr = r92cu_init_intr;
sc->sc_init_edca = r92c_init_edca;
+11
View File
@@ -37,9 +37,20 @@
#define R92E_LDOV12_CTRL 0x014
#define R92E_AFE_XTAL_CTRL 0x02c
#define R92E_APE_PLL_CTRL_EXT 0x078
#define R92E_AUTO_LLT 0x224
#define R92E_DWBCN1_CTRL 0x228
#define R92E_RXDMA_PRO 0x290
#define R92E_RXDW3_RATE_M 0x0000007f
#define R92E_RXDW3_RATE_S 0
/* Bits for R92E_AFE_XTAL_CTRL. */
#define R92E_AFE_XTAL_CTRL_ADDR_M 0x00fff000
#define R92E_AFE_XTAL_CTRL_ADDR_S 12
/* Bits for R92E_AUTO_LLT. */
#define R92E_AUTO_LLT_EN 0x00010000
/* Bits for R92E_RXDMA_PRO. */
#define R92E_RXDMA_PRO_DMA_MODE 0x02
#endif /* R92E_REG_H */
+2
View File
@@ -133,6 +133,7 @@ r92eu_attach(struct rtwn_usb_softc *uc)
sc->sc_fw_download_enable = r12a_fw_download_enable;
#endif
sc->sc_llt_init = r92e_llt_init;
sc->sc_enable_mac_txrx = rtwn_nop_softc;
sc->sc_set_page_size = rtwn_nop_int_softc;
sc->sc_lc_calib = r92c_lc_calib;
sc->sc_iq_calib = rtwn_nop_softc; /* XXX TODO */
@@ -158,6 +159,7 @@ r92eu_attach(struct rtwn_usb_softc *uc)
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_beacon_timer = r92c_init_beacon_timer;
sc->sc_init_ampdu = rtwn_nop_softc;
sc->sc_init_intr = r12a_init_intr;
sc->sc_init_edca = r92c_init_edca;
+2
View File
@@ -118,6 +118,7 @@ r23bu_attach(struct rtwn_usb_softc *uc)
sc->sc_fw_download_enable = r23b_fw_download_enable;
#endif
sc->sc_llt_init = r92e_llt_init;
sc->sc_enable_mac_txrx = rtwn_nop_softc;
sc->sc_set_page_size = r23b_set_page_size;
sc->sc_lc_calib = r23b_lc_calib;
sc->sc_iq_calib = r23b_iq_calib;
@@ -143,6 +144,7 @@ r23bu_attach(struct rtwn_usb_softc *uc)
sc->sc_temp_read = r88e_temp_read;
sc->sc_init_tx_agg = r21au_init_tx_agg;
sc->sc_init_rx_agg = r23bu_init_rx_agg;
sc->sc_init_beacon_timer = r92c_init_beacon_timer;
sc->sc_init_ampdu = r23bu_init_ampdu;
sc->sc_init_intr = r92cu_init_intr;
sc->sc_init_edca = r92c_init_edca;
+2
View File
@@ -234,6 +234,7 @@ r12au_attach(struct rtwn_usb_softc *uc)
sc->sc_fw_download_enable = r12a_fw_download_enable;
#endif
sc->sc_llt_init = r92c_llt_init;
sc->sc_enable_mac_txrx = rtwn_nop_softc;
sc->sc_set_page_size = r12a_set_page_size;
sc->sc_lc_calib = r12a_lc_calib;
sc->sc_iq_calib = r12a_iq_calib;
@@ -259,6 +260,7 @@ r12au_attach(struct rtwn_usb_softc *uc)
sc->sc_temp_read = r88e_temp_read;
sc->sc_init_tx_agg = r92cu_init_tx_agg;
sc->sc_init_rx_agg = r12au_init_rx_agg;
sc->sc_init_beacon_timer = r92c_init_beacon_timer;
sc->sc_init_ampdu = r12au_init_ampdu;
sc->sc_init_intr = r12a_init_intr;
sc->sc_init_edca = r12a_init_edca;
+2
View File
@@ -218,6 +218,7 @@ r21au_attach(struct rtwn_usb_softc *uc)
sc->sc_fw_download_enable = r12a_fw_download_enable;
#endif
sc->sc_llt_init = r92c_llt_init;
sc->sc_enable_mac_txrx = rtwn_nop_softc;
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;
@@ -243,6 +244,7 @@ r21au_attach(struct rtwn_usb_softc *uc)
sc->sc_temp_read = r88e_temp_read;
sc->sc_init_tx_agg = r21au_init_tx_agg;
sc->sc_init_rx_agg = r12au_init_rx_agg;
sc->sc_init_beacon_timer = r92c_init_beacon_timer;
sc->sc_init_ampdu = r12au_init_ampdu;
sc->sc_init_intr = r12a_init_intr;
sc->sc_init_edca = r12a_init_edca;
+10
View File
@@ -21,6 +21,7 @@
void r92cu_attach(struct rtwn_usb_softc *);
void r92eu_attach(struct rtwn_usb_softc *);
void r88eu_attach(struct rtwn_usb_softc *);
void r88fu_attach(struct rtwn_usb_softc *);
void r23bu_attach(struct rtwn_usb_softc *);
void r12au_attach(struct rtwn_usb_softc *);
void r21au_attach(struct rtwn_usb_softc *);
@@ -29,6 +30,7 @@ enum {
RTWN_CHIP_RTL8192CU,
RTWN_CHIP_RTL8192EU,
RTWN_CHIP_RTL8188EU,
RTWN_CHIP_RTL8188FU,
RTWN_CHIP_RTL8723BU,
RTWN_CHIP_RTL8812AU,
RTWN_CHIP_RTL8821AU,
@@ -134,6 +136,13 @@ static const STRUCT_USB_HOST_ID rtwn_devs[] = {
RTWN_RTL8188EU_DEV(MERCUSYS, MW150US),
#undef RTWN_RTL8188EU_DEV
/* RTL8188FU */
#define RTWN_RTL8188FU_DEV(v,p) \
{ USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, \
RTWN_USB_DEVINFO(RTWN_CHIP_RTL8188FU, 0)) }
RTWN_RTL8188FU_DEV(REALTEK, RTL8188FTV),
#undef RTWN_RTL8188FU_DEV
/* RTL8723BU */
#define RTWN_RTL8723BU_DEV(v, p, i) \
{ USB_VP(USB_VENDOR_##v, USB_PRODUCT_##v##_##p), \
@@ -196,6 +205,7 @@ 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_RTL8188FU] = r88fu_attach,
[RTWN_CHIP_RTL8723BU] = r23bu_attach,
[RTWN_CHIP_RTL8812AU] = r12au_attach,
[RTWN_CHIP_RTL8821AU] = r21au_attach
+1
View File
@@ -4134,6 +4134,7 @@ product RATOC REXUSB60F 0xb020 USB serial adapter REX-USB60F
/* Green House and CompUSA OEM this part */
product REALTEK USB20CRW 0x0158 USB20CRW Card Reader
product REALTEK RTL8188ETV 0x0179 RTL8188ETV
product REALTEK RTL8188FTV 0xf179 RTL8188FTV
product REALTEK RTL8188CTV 0x018a RTL8188CTV
product REALTEK RTL8821AU_2 0x0811 RTL8821AU
product REALTEK RTW8821CU_CD 0x1a2b RTW8821CU_CD
+5
View File
@@ -22,6 +22,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: ${SRCTOP}/sys/dev/rtwn/rtl8188f
SRCS += r88f.h r88f_calib.c r88f_chan.c r88f_fw.c r88f_init.c \
r88f_priv.h r88f_reg.h r88f_rx.c r88f_rom.c r88f_rom_defs.h \
r88f_rom_image.h
.PATH: ${SRCTOP}/sys/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 \
+4
View File
@@ -12,6 +12,10 @@ SRCS = rtwn_usb_attach.c rtwn_usb_ep.c rtwn_usb_reg.c rtwn_usb_rx.c \
SRCS += r88eu_attach.c r88eu_init.c \
r88eu.h r88eu_reg.h
.PATH: ${SRCTOP}/sys/dev/rtwn/rtl8188f/usb
SRCS += r88fu_attach.c r88fu_init.c \
r88fu.h
.PATH: ${SRCTOP}/sys/dev/rtwn/rtl8192c/usb
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
+2 -1
View File
@@ -1,4 +1,5 @@
SUBDIR= rtwnrtl8188eu rtwnrtl8192cT rtwnrtl8192cU rtwnrtl8192eu rtwnrtl8812au \
rtwnrtl8821au rtwnrtl8192cE rtwnrtl8192cEB rtwnrtl8188ee rtwnrtl8723bu
rtwnrtl8821au rtwnrtl8192cE rtwnrtl8192cEB rtwnrtl8188ee rtwnrtl8723bu \
rtwnrtl8188fu
.include <bsd.subdir.mk>
@@ -0,0 +1,4 @@
KMOD= rtwn-rtl8188fufw
IMG= rtwn-rtl8188fufw
.include <bsd.kmod.mk>