[rtems-libbsd commit] dev/rtwn: Import new files from FreeBSD.

Sebastian Huber sebh at rtems.org
Mon Jul 17 14:04:46 UTC 2017


Module:    rtems-libbsd
Branch:    master
Commit:    658f9b89679bcbb933b5d97da1a3391cb2f882b4
Changeset: http://git.rtems.org/rtems-libbsd/commit/?id=658f9b89679bcbb933b5d97da1a3391cb2f882b4

Author:    Christian Mauderer <Christian.Mauderer at embedded-brains.de>
Date:      Mon Jul 17 15:32:52 2017 +0200

dev/rtwn: Import new files from FreeBSD.

---

 freebsd/sys/dev/rtwn/rtl8192c/r92c_llt.c         |  75 +++++
 freebsd/sys/dev/rtwn/rtl8192e/r92e.h             |  82 +++++
 freebsd/sys/dev/rtwn/rtl8192e/r92e_chan.c        | 296 +++++++++++++++++
 freebsd/sys/dev/rtwn/rtl8192e/r92e_fw.c          | 139 ++++++++
 freebsd/sys/dev/rtwn/rtl8192e/r92e_init.c        | 387 +++++++++++++++++++++++
 freebsd/sys/dev/rtwn/rtl8192e/r92e_led.c         |  71 +++++
 freebsd/sys/dev/rtwn/rtl8192e/r92e_priv.h        | 262 +++++++++++++++
 freebsd/sys/dev/rtwn/rtl8192e/r92e_reg.h         |  47 +++
 freebsd/sys/dev/rtwn/rtl8192e/r92e_rf.c          |  90 ++++++
 freebsd/sys/dev/rtwn/rtl8192e/r92e_rom.c         | 146 +++++++++
 freebsd/sys/dev/rtwn/rtl8192e/r92e_rom_defs.h    |  42 +++
 freebsd/sys/dev/rtwn/rtl8192e/r92e_rom_image.h   |  87 +++++
 freebsd/sys/dev/rtwn/rtl8192e/r92e_rx.c          |  99 ++++++
 freebsd/sys/dev/rtwn/rtl8192e/r92e_var.h         |  54 ++++
 freebsd/sys/dev/rtwn/rtl8192e/usb/r92eu.h        |  43 +++
 freebsd/sys/dev/rtwn/rtl8192e/usb/r92eu_attach.c | 204 ++++++++++++
 freebsd/sys/dev/rtwn/rtl8192e/usb/r92eu_init.c   |  98 ++++++
 freebsd/sys/dev/rtwn/rtl8192e/usb/r92eu_reg.h    |  36 +++
 libbsd.py                                        |  28 +-
 libbsd_waf.py                                    |  10 +
 20 files changed, 2291 insertions(+), 5 deletions(-)

diff --git a/freebsd/sys/dev/rtwn/rtl8192c/r92c_llt.c b/freebsd/sys/dev/rtwn/rtl8192c/r92c_llt.c
new file mode 100644
index 0000000..595d79e
--- /dev/null
+++ b/freebsd/sys/dev/rtwn/rtl8192c/r92c_llt.c
@@ -0,0 +1,75 @@
+#include <machine/rtems-bsd-kernel-space.h>
+
+/*	$OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $	*/
+
+/*-
+ * Copyright (c) 2010 Damien Bergamini <damien.bergamini at free.fr>
+ * Copyright (c) 2014 Kevin Lo <kevlo at FreeBSD.org>
+ * Copyright (c) 2015-2016 Andriy Voskoboinyk <avos at 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 <rtems/bsd/local/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);
+}
diff --git a/freebsd/sys/dev/rtwn/rtl8192e/r92e.h b/freebsd/sys/dev/rtwn/rtl8192e/r92e.h
new file mode 100644
index 0000000..a961236
--- /dev/null
+++ b/freebsd/sys/dev/rtwn/rtl8192e/r92e.h
@@ -0,0 +1,82 @@
+/*-
+ * Copyright (c) 2017 Kevin Lo <kevlo at 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 */
diff --git a/freebsd/sys/dev/rtwn/rtl8192e/r92e_chan.c b/freebsd/sys/dev/rtwn/rtl8192e/r92e_chan.c
new file mode 100644
index 0000000..130ac5c
--- /dev/null
+++ b/freebsd/sys/dev/rtwn/rtl8192e/r92e_chan.c
@@ -0,0 +1,296 @@
+#include <machine/rtems-bsd-kernel-space.h>
+
+/*-
+ * Copyright (c) 2017 Kevin Lo <kevlo at 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 <rtems/bsd/local/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);
+}
diff --git a/freebsd/sys/dev/rtwn/rtl8192e/r92e_fw.c b/freebsd/sys/dev/rtwn/rtl8192e/r92e_fw.c
new file mode 100644
index 0000000..1eca975
--- /dev/null
+++ b/freebsd/sys/dev/rtwn/rtl8192e/r92e_fw.c
@@ -0,0 +1,139 @@
+#include <machine/rtems-bsd-kernel-space.h>
+
+/*-
+ * Copyright (c) 2017 Kevin Lo <kevlo at 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 <rtems/bsd/local/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
diff --git a/freebsd/sys/dev/rtwn/rtl8192e/r92e_init.c b/freebsd/sys/dev/rtwn/rtl8192e/r92e_init.c
new file mode 100644
index 0000000..649e657
--- /dev/null
+++ b/freebsd/sys/dev/rtwn/rtl8192e/r92e_init.c
@@ -0,0 +1,387 @@
+#include <machine/rtems-bsd-kernel-space.h>
+
+/*-
+ * Copyright (c) 2017 Kevin Lo <kevlo at 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 <rtems/bsd/local/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);
+}
diff --git a/freebsd/sys/dev/rtwn/rtl8192e/r92e_led.c b/freebsd/sys/dev/rtwn/rtl8192e/r92e_led.c
new file mode 100644
index 0000000..a304083
--- /dev/null
+++ b/freebsd/sys/dev/rtwn/rtl8192e/r92e_led.c
@@ -0,0 +1,71 @@
+#include <machine/rtems-bsd-kernel-space.h>
+
+/*-
+ * Copyright (c) 2017 Kevin Lo <kevlo at 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 <rtems/bsd/local/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. */
+	}
+}
diff --git a/freebsd/sys/dev/rtwn/rtl8192e/r92e_priv.h b/freebsd/sys/dev/rtwn/rtl8192e/r92e_priv.h
new file mode 100644
index 0000000..1bcae4f
--- /dev/null
+++ b/freebsd/sys/dev/rtwn/rtl8192e/r92e_priv.h
@@ -0,0 +1,262 @@
+/*-
+ * Copyright (c) 2017 Kevin Lo <kevlo at 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 */
diff --git a/freebsd/sys/dev/rtwn/rtl8192e/r92e_reg.h b/freebsd/sys/dev/rtwn/rtl8192e/r92e_reg.h
new file mode 100644
index 0000000..eb2b1f2
--- /dev/null
+++ b/freebsd/sys/dev/rtwn/rtl8192e/r92e_reg.h
@@ -0,0 +1,47 @@
+/*-
+ * Copyright (c) 2017 Kevin Lo <kevlo at 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 */
diff --git a/freebsd/sys/dev/rtwn/rtl8192e/r92e_rf.c b/freebsd/sys/dev/rtwn/rtl8192e/r92e_rf.c
new file mode 100644
index 0000000..b114054
--- /dev/null
+++ b/freebsd/sys/dev/rtwn/rtl8192e/r92e_rf.c
@@ -0,0 +1,90 @@
+#include <machine/rtems-bsd-kernel-space.h>
+
+/*-
+ * Copyright (c) 2017 Kevin Lo <kevlo at 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 <rtems/bsd/local/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);
+}
diff --git a/freebsd/sys/dev/rtwn/rtl8192e/r92e_rom.c b/freebsd/sys/dev/rtwn/rtl8192e/r92e_rom.c
new file mode 100644
index 0000000..7c2dd4a
--- /dev/null
+++ b/freebsd/sys/dev/rtwn/rtl8192e/r92e_rom.c
@@ -0,0 +1,146 @@
+#include <machine/rtems-bsd-kernel-space.h>
+
+/*-
+ * Copyright (c) 2017 Kevin Lo <kevlo at 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 <rtems/bsd/local/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);
+}
diff --git a/freebsd/sys/dev/rtwn/rtl8192e/r92e_rom_defs.h b/freebsd/sys/dev/rtwn/rtl8192e/r92e_rom_defs.h
new file mode 100644
index 0000000..1dc4c65
--- /dev/null
+++ b/freebsd/sys/dev/rtwn/rtl8192e/r92e_rom_defs.h
@@ -0,0 +1,42 @@
+/*-
+ * Copyright (c) 2017 Kevin Lo <kevlo at 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 */
diff --git a/freebsd/sys/dev/rtwn/rtl8192e/r92e_rom_image.h b/freebsd/sys/dev/rtwn/rtl8192e/r92e_rom_image.h
new file mode 100644
index 0000000..8a5bd52
--- /dev/null
+++ b/freebsd/sys/dev/rtwn/rtl8192e/r92e_rom_image.h
@@ -0,0 +1,87 @@
+/*-
+ * Copyright (c) 2017 Kevin Lo <kevlo at 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 */
diff --git a/freebsd/sys/dev/rtwn/rtl8192e/r92e_rx.c b/freebsd/sys/dev/rtwn/rtl8192e/r92e_rx.c
new file mode 100644
index 0000000..4e2591d
--- /dev/null
+++ b/freebsd/sys/dev/rtwn/rtl8192e/r92e_rx.c
@@ -0,0 +1,99 @@
+#include <machine/rtems-bsd-kernel-space.h>
+
+/*-
+ * Copyright (c) 2010 Damien Bergamini <damien.bergamini at free.fr>
+ * Copyright (c) 2014, 2017 Kevin Lo <kevlo at FreeBSD.org>
+ * Copyright (c) 2015-2016 Andriy Voskoboinyk <avos at 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 <rtems/bsd/local/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));
+}
diff --git a/freebsd/sys/dev/rtwn/rtl8192e/r92e_var.h b/freebsd/sys/dev/rtwn/rtl8192e/r92e_var.h
new file mode 100644
index 0000000..5da3418
--- /dev/null
+++ b/freebsd/sys/dev/rtwn/rtl8192e/r92e_var.h
@@ -0,0 +1,54 @@
+/*-
+ * Copyright (c) 2017 Kevin Lo <kevlo at 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 */
diff --git a/freebsd/sys/dev/rtwn/rtl8192e/usb/r92eu.h b/freebsd/sys/dev/rtwn/rtl8192e/usb/r92eu.h
new file mode 100644
index 0000000..a59ceb6
--- /dev/null
+++ b/freebsd/sys/dev/rtwn/rtl8192e/usb/r92eu.h
@@ -0,0 +1,43 @@
+/*-
+ * Copyright (c) 2017 Kevin Lo <kevlo at 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 */
diff --git a/freebsd/sys/dev/rtwn/rtl8192e/usb/r92eu_attach.c b/freebsd/sys/dev/rtwn/rtl8192e/usb/r92eu_attach.c
new file mode 100644
index 0000000..d237731
--- /dev/null
+++ b/freebsd/sys/dev/rtwn/rtl8192e/usb/r92eu_attach.c
@@ -0,0 +1,204 @@
+#include <machine/rtems-bsd-kernel-space.h>
+
+/*-
+ * Copyright (c) 2017 Kevin Lo <kevlo at 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 <rtems/bsd/local/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);
+}
diff --git a/freebsd/sys/dev/rtwn/rtl8192e/usb/r92eu_init.c b/freebsd/sys/dev/rtwn/rtl8192e/usb/r92eu_init.c
new file mode 100644
index 0000000..8755c3f
--- /dev/null
+++ b/freebsd/sys/dev/rtwn/rtl8192e/usb/r92eu_init.c
@@ -0,0 +1,98 @@
+#include <machine/rtems-bsd-kernel-space.h>
+
+/*-
+ * Copyright (c) 2017 Kevin Lo <kevlo at 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 <rtems/bsd/local/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;
+}
diff --git a/freebsd/sys/dev/rtwn/rtl8192e/usb/r92eu_reg.h b/freebsd/sys/dev/rtwn/rtl8192e/usb/r92eu_reg.h
new file mode 100644
index 0000000..e6c8af4
--- /dev/null
+++ b/freebsd/sys/dev/rtwn/rtl8192e/usb/r92eu_reg.h
@@ -0,0 +1,36 @@
+/*-
+ * Copyright (c) 2017 Kevin Lo <kevlo at 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 */
diff --git a/libbsd.py b/libbsd.py
index 18dfe8a..3f4ed74 100644
--- a/libbsd.py
+++ b/libbsd.py
@@ -1005,19 +1005,19 @@ def dev_wlan_rtwn(mm):
             'sys/dev/rtwn/if_rtwn_efuse.h',
             'sys/dev/rtwn/if_rtwn_fw.h',
             'sys/dev/rtwn/if_rtwn_nop.h',
-            'sys/dev/rtwn/if_rtwnreg.h',
             'sys/dev/rtwn/if_rtwn_ridx.h',
             'sys/dev/rtwn/if_rtwn_rx.h',
             'sys/dev/rtwn/if_rtwn_task.h',
             'sys/dev/rtwn/if_rtwn_tx.h',
+            'sys/dev/rtwn/if_rtwnreg.h',
             'sys/dev/rtwn/if_rtwnvar.h',
             'sys/dev/rtwn/pci/rtwn_pci_attach.h',
             'sys/dev/rtwn/pci/rtwn_pci_reg.h',
             'sys/dev/rtwn/pci/rtwn_pci_rx.h',
             'sys/dev/rtwn/pci/rtwn_pci_tx.h',
             'sys/dev/rtwn/pci/rtwn_pci_var.h',
-            'sys/dev/rtwn/rtl8188e/r88e_fw_cmd.h',
             'sys/dev/rtwn/rtl8188e/r88e.h',
+            'sys/dev/rtwn/rtl8188e/r88e_fw_cmd.h',
             'sys/dev/rtwn/rtl8188e/r88e_priv.h',
             'sys/dev/rtwn/rtl8188e/r88e_reg.h',
             'sys/dev/rtwn/rtl8188e/r88e_rom_defs.h',
@@ -1031,8 +1031,8 @@ def dev_wlan_rtwn(mm):
             'sys/dev/rtwn/rtl8192c/pci/r92ce_reg.h',
             'sys/dev/rtwn/rtl8192c/pci/r92ce_rx_desc.h',
             'sys/dev/rtwn/rtl8192c/pci/r92ce_tx_desc.h',
-            'sys/dev/rtwn/rtl8192c/r92c_fw_cmd.h',
             'sys/dev/rtwn/rtl8192c/r92c.h',
+            'sys/dev/rtwn/rtl8192c/r92c_fw_cmd.h',
             'sys/dev/rtwn/rtl8192c/r92c_priv.h',
             'sys/dev/rtwn/rtl8192c/r92c_reg.h',
             'sys/dev/rtwn/rtl8192c/r92c_rom_defs.h',
@@ -1044,8 +1044,16 @@ def dev_wlan_rtwn(mm):
             'sys/dev/rtwn/rtl8192c/usb/r92cu_priv.h',
             'sys/dev/rtwn/rtl8192c/usb/r92cu_reg.h',
             'sys/dev/rtwn/rtl8192c/usb/r92cu_tx_desc.h',
-            'sys/dev/rtwn/rtl8812a/r12a_fw_cmd.h',
+            'sys/dev/rtwn/rtl8192e/r92e.h',
+            'sys/dev/rtwn/rtl8192e/r92e_priv.h',
+            'sys/dev/rtwn/rtl8192e/r92e_reg.h',
+            'sys/dev/rtwn/rtl8192e/r92e_rom_defs.h',
+            'sys/dev/rtwn/rtl8192e/r92e_rom_image.h',
+            'sys/dev/rtwn/rtl8192e/r92e_var.h',
+            'sys/dev/rtwn/rtl8192e/usb/r92eu.h',
+            'sys/dev/rtwn/rtl8192e/usb/r92eu_reg.h',
             'sys/dev/rtwn/rtl8812a/r12a.h',
+            'sys/dev/rtwn/rtl8812a/r12a_fw_cmd.h',
             'sys/dev/rtwn/rtl8812a/r12a_priv.h',
             'sys/dev/rtwn/rtl8812a/r12a_reg.h',
             'sys/dev/rtwn/rtl8812a/r12a_rom_defs.h',
@@ -1077,8 +1085,8 @@ def dev_wlan_rtwn(mm):
     )
     mod.addKernelSpaceSourceFiles(
         [
-            'sys/dev/rtwn/if_rtwn_beacon.c',
             'sys/dev/rtwn/if_rtwn.c',
+            'sys/dev/rtwn/if_rtwn_beacon.c',
             'sys/dev/rtwn/if_rtwn_calib.c',
             'sys/dev/rtwn/if_rtwn_cam.c',
             'sys/dev/rtwn/if_rtwn_efuse.c',
@@ -1116,6 +1124,7 @@ def dev_wlan_rtwn(mm):
             'sys/dev/rtwn/rtl8192c/r92c_chan.c',
             'sys/dev/rtwn/rtl8192c/r92c_fw.c',
             'sys/dev/rtwn/rtl8192c/r92c_init.c',
+            'sys/dev/rtwn/rtl8192c/r92c_llt.c',
             'sys/dev/rtwn/rtl8192c/r92c_rf.c',
             'sys/dev/rtwn/rtl8192c/r92c_rom.c',
             'sys/dev/rtwn/rtl8192c/r92c_rx.c',
@@ -1125,6 +1134,15 @@ def dev_wlan_rtwn(mm):
             'sys/dev/rtwn/rtl8192c/usb/r92cu_led.c',
             'sys/dev/rtwn/rtl8192c/usb/r92cu_rx.c',
             'sys/dev/rtwn/rtl8192c/usb/r92cu_tx.c',
+            'sys/dev/rtwn/rtl8192e/r92e_chan.c',
+            'sys/dev/rtwn/rtl8192e/r92e_fw.c',
+            'sys/dev/rtwn/rtl8192e/r92e_init.c',
+            'sys/dev/rtwn/rtl8192e/r92e_led.c',
+            'sys/dev/rtwn/rtl8192e/r92e_rf.c',
+            'sys/dev/rtwn/rtl8192e/r92e_rom.c',
+            'sys/dev/rtwn/rtl8192e/r92e_rx.c',
+            'sys/dev/rtwn/rtl8192e/usb/r92eu_attach.c',
+            'sys/dev/rtwn/rtl8192e/usb/r92eu_init.c',
             'sys/dev/rtwn/rtl8812a/r12a_beacon.c',
             'sys/dev/rtwn/rtl8812a/r12a_calib.c',
             'sys/dev/rtwn/rtl8812a/r12a_caps.c',
diff --git a/libbsd_waf.py b/libbsd_waf.py
index 5d0d5d0..6d024f9 100644
--- a/libbsd_waf.py
+++ b/libbsd_waf.py
@@ -856,6 +856,7 @@ def build(bld):
               'freebsd/sys/dev/rtwn/rtl8192c/r92c_chan.c',
               'freebsd/sys/dev/rtwn/rtl8192c/r92c_fw.c',
               'freebsd/sys/dev/rtwn/rtl8192c/r92c_init.c',
+              'freebsd/sys/dev/rtwn/rtl8192c/r92c_llt.c',
               'freebsd/sys/dev/rtwn/rtl8192c/r92c_rf.c',
               'freebsd/sys/dev/rtwn/rtl8192c/r92c_rom.c',
               'freebsd/sys/dev/rtwn/rtl8192c/r92c_rx.c',
@@ -865,6 +866,15 @@ def build(bld):
               'freebsd/sys/dev/rtwn/rtl8192c/usb/r92cu_led.c',
               'freebsd/sys/dev/rtwn/rtl8192c/usb/r92cu_rx.c',
               'freebsd/sys/dev/rtwn/rtl8192c/usb/r92cu_tx.c',
+              'freebsd/sys/dev/rtwn/rtl8192e/r92e_chan.c',
+              'freebsd/sys/dev/rtwn/rtl8192e/r92e_fw.c',
+              'freebsd/sys/dev/rtwn/rtl8192e/r92e_init.c',
+              'freebsd/sys/dev/rtwn/rtl8192e/r92e_led.c',
+              'freebsd/sys/dev/rtwn/rtl8192e/r92e_rf.c',
+              'freebsd/sys/dev/rtwn/rtl8192e/r92e_rom.c',
+              'freebsd/sys/dev/rtwn/rtl8192e/r92e_rx.c',
+              'freebsd/sys/dev/rtwn/rtl8192e/usb/r92eu_attach.c',
+              'freebsd/sys/dev/rtwn/rtl8192e/usb/r92eu_init.c',
               'freebsd/sys/dev/rtwn/rtl8812a/r12a_beacon.c',
               'freebsd/sys/dev/rtwn/rtl8812a/r12a_calib.c',
               'freebsd/sys/dev/rtwn/rtl8812a/r12a_caps.c',




More information about the vc mailing list