Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 6 Jun 2018 20:11:53 -0400
From:      Farhan Khan <khanzf@gmail.com>
To:        freebsd-wireless@freebsd.org
Subject:   RTL8188EE monitor mode patch
Message-ID:  <CAFd4kYBbewOa1ZOYer=R%2BJ%2BXHSzNbETJo_AQocyGcpi4JxzqRA@mail.gmail.com>

next in thread | raw e-mail | index | archive | help

[-- Attachment #1 --]
Hi all,

First ever patch submission, quite nervous. I have attached the diff
to this email. This is for the Realtek rtl8188ee PCI driver. Currently
only works in monitor mode and will receive wireless frames. I am very
interested in moving forward with getting read/write working.

Known bugs:
* Unloading the driver without bringing it down will result in a
kernel panic. This appears to be an issue with the firmware running
C2H code, and then attempting to write back to memory that was freed
by the kernel.
* Bringing the interface down, then back up will cause frames to
arrive in spurts or not at all. This behavior only seemed to start
after git commit 960c0f3d880f9767027c05614f2184ce4b93fa99. One
solution is to revert sys/dev/rtwn/pci/* to the previous state and the
issue appears to stop.

You will notice what appear to be a lot of hard-coded register values.
This is because I am basing this off of the Linux driver, and Realtek
does not provide any documentation on how their driver works.

My git repository is here: https://github.com/khanzf/freebsd

Please let me know if there are any bugs or problems that need to be remediated.
Thank you,
--
Farhan Khan
PGP Fingerprint: B28D 2726 E2BC A97E 3854 5ABE 9A9F 00BC D525 16EE

[-- Attachment #2 --]
diff --git a/sys/contrib/dev/rtwn/rtwn-rtl8188eefw.fw.uu b/sys/contrib/dev/rtwn/rtwn-rtl8188eefw.fw.uu
new file mode 100644
index 00000000000..68df43ca99d
--- /dev/null
+++ b/sys/contrib/dev/rtwn/rtwn-rtl8188eefw.fw.uu
@@ -0,0 +1,253 @@
+begin 644 rtwn-rtl8188eefw.fw
+MX8@0``@````0)2%6L"L``*($```````````````````"134`````````````
+M````````P58`````````````````````````````````````````````````
+M````````````H<T```````#A_```````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+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
++Y#3[]8/@_R(`,@@`
+`
+end
diff --git a/sys/dev/rtwn/pci/rtwn_pci_attach.h b/sys/dev/rtwn/pci/rtwn_pci_attach.h
index 6df5812e4cd..389d52fff95 100644
--- a/sys/dev/rtwn/pci/rtwn_pci_attach.h
+++ b/sys/dev/rtwn/pci/rtwn_pci_attach.h
@@ -17,9 +17,11 @@
  */
 
 void	r92ce_attach(struct rtwn_pci_softc *);
+void	r88ee_attach(struct rtwn_pci_softc *);
 
 enum {
 	RTWN_CHIP_RTL8192CE,
+	RTWN_CHIP_RTL8188EE,
 	RTWN_CHIP_MAX_PCI
 };
 
@@ -32,13 +34,15 @@ struct rtwn_pci_ident {
 
 static const struct rtwn_pci_ident rtwn_pci_ident_table[] = {
 	{ 0x10ec, 0x8176, "Realtek RTL8188CE", RTWN_CHIP_RTL8192CE },
+	{ 0x10ec, 0x8179, "Realtek RTL8188EE", RTWN_CHIP_RTL8188EE },
 	{ 0, 0, NULL, RTWN_CHIP_MAX_PCI }
 };
 
 typedef void	(*chip_pci_attach)(struct rtwn_pci_softc *);
 
 static const chip_pci_attach rtwn_chip_pci_attach[RTWN_CHIP_MAX_PCI] = {
-	[RTWN_CHIP_RTL8192CE] = r92ce_attach
+	[RTWN_CHIP_RTL8192CE] = r92ce_attach,
+	[RTWN_CHIP_RTL8188EE] = r88ee_attach
 };
 
 static __inline void
diff --git a/sys/dev/rtwn/rtl8188e/pci/r88ee.h b/sys/dev/rtwn/rtl8188e/pci/r88ee.h
new file mode 100644
index 00000000000..3534cb3a86d
--- /dev/null
+++ b/sys/dev/rtwn/rtl8188e/pci/r88ee.h
@@ -0,0 +1,75 @@
+/*-
+ * Copyright (c) 2018 Farhan Khan <khanzf@gmail.com>
+ *
+ * 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 RTL8188EE_H
+#define RTL8188EE_H
+
+#include <dev/rtwn/rtl8188e/r88e.h>
+
+
+/*
+ * Global definitions.
+ */
+#define R88EE_PUBQ_NPAGES	176
+#define R88EE_HPQ_NPAGES	41
+#define R88EE_LPQ_NPAGES	28
+#define R88EE_TX_PAGE_COUNT	\
+	(R88EE_PUBQ_NPAGES + R88EE_HPQ_NPAGES + R88EE_LPQ_NPAGES)
+
+
+/*
+ * Function declarations.
+ */
+/* r88ee_calib.c */
+void	r88ee_iq_calib(struct rtwn_softc *);
+
+/* r88ee_fw.c */
+#ifndef RTWN_WITHOUT_UCODE
+void	r88ee_fw_reset(struct rtwn_softc *, int);
+#endif
+
+/* r88ee_init.c */
+void	r88ee_init_intr(struct rtwn_softc *);
+void	r88ee_init_edca(struct rtwn_softc *);
+int	r88ee_power_on(struct rtwn_softc *);
+void	r88ee_power_off(struct rtwn_softc *);
+void	r88ee_init_ampdu(struct rtwn_softc *);
+void	r88ee_post_init(struct rtwn_softc *);
+void	r88ee_init_rx_agg(struct rtwn_softc *);
+void	r88ee_init_rf(struct rtwn_softc *);
+
+/* r88ee_led.c */
+void	r88ee_set_led(struct rtwn_softc *, int, int);
+
+/* r88ee_rx.c */
+int	r88ee_classify_intr(struct rtwn_softc *, void *, int);
+void	r88ee_enable_intr(struct rtwn_pci_softc *);
+void	r88ee_start_xfers(struct rtwn_softc *);
+
+/* r88ee_tx.c */
+void	r88ee_setup_tx_desc(struct rtwn_pci_softc *, void *, uint32_t);
+void	r88ee_tx_postsetup(struct rtwn_pci_softc *, void *,
+	    bus_dma_segment_t[]);
+void	r88ee_copy_tx_desc(void *, const void *);
+void	r88ee_dump_tx_desc(struct rtwn_softc *, const void *);
+
+/* r88ee_rf.c */
+uint32_t	r88ee_rf_read(struct rtwn_softc *, int, uint8_t);
+void	r88ee_rf_write(struct rtwn_softc *, int, uint8_t, uint32_t);
+
+#endif	/* RTL8188EE_H */
diff --git a/sys/dev/rtwn/rtl8188e/pci/r88ee_attach.c b/sys/dev/rtwn/rtl8188e/pci/r88ee_attach.c
new file mode 100644
index 00000000000..a3e310e8fdb
--- /dev/null
+++ b/sys/dev/rtwn/rtl8188e/pci/r88ee_attach.c
@@ -0,0 +1,264 @@
+/*	$OpenBSD: if_rtwn.c,v 1.6 2015/08/28 00:03:53 deraadt Exp $	*/
+
+/*-
+ * Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
+ * Copyright (c) 2015 Stefan Sperling <stsp@openbsd.org>
+ * Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
+ * Copyright (c) 2018 Farhan Khan <khanzf@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_wlan.h"
+
+#include <sys/param.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/mbuf.h>
+#include <sys/kernel.h>
+#include <sys/socket.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/queue.h>
+#include <sys/taskqueue.h>
+#include <sys/bus.h>
+#include <sys/endian.h>
+#include <sys/linker.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/rman.h>
+
+#include <net/if.h>
+#include <net/ethernet.h>
+#include <net/if_media.h>
+
+#include <net80211/ieee80211_var.h>
+#include <net80211/ieee80211_radiotap.h>
+
+#include <dev/rtwn/if_rtwnreg.h>
+#include <dev/rtwn/if_rtwnvar.h>
+#include <dev/rtwn/if_rtwn_nop.h>
+
+#include <dev/rtwn/rtl8188e/r88e_priv.h>
+#include <dev/rtwn/pci/rtwn_pci_var.h>
+#include <dev/rtwn/rtl8192c/r92c.h>
+#include <dev/rtwn/rtl8192c/r92c_var.h>
+#include <dev/rtwn/rtl8192c/pci/r92ce.h>
+
+#include <dev/rtwn/rtl8192c/r92c_var.h>
+#include <dev/rtwn/rtl8192c/pci/r92ce.h>
+#include <dev/rtwn/rtl8192c/pci/r92ce_priv.h>
+#include <dev/rtwn/rtl8192c/pci/r92ce_reg.h>
+#include <dev/rtwn/rtl8192c/pci/r92ce_tx_desc.h>
+#include <dev/rtwn/rtl8192c/r92c.h>
+
+#include <dev/rtwn/rtl8188e/pci/r88ee.h>
+#include <dev/rtwn/rtl8188e/pci/r88ee_priv.h>
+#include <dev/rtwn/rtl8188e/pci/r88ee_reg.h>
+#include <dev/rtwn/rtl8188e/pci/r88ee_tx_desc.h>
+#include <dev/rtwn/rtl8188e/usb/r88eu.h>
+#include <dev/rtwn/rtl8192e/r92e.h>
+
+static struct rtwn_r92c_txpwr r88ee_txpwr;
+
+void	r88ee_attach(struct rtwn_pci_softc *);
+
+static void
+r88ee_postattach(struct rtwn_softc *sc)
+{
+	struct r92c_softc *rs = sc->sc_priv;
+	struct ieee80211com *ic = &sc->sc_ic;
+	sc->fwname = "rtwn-rtl8188eefw";
+	sc->fwsig = 0x88E;
+
+	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
+r88ee_set_name(struct rtwn_softc *sc)
+{
+	sc->name = "RTL8188EE";
+}
+
+static void
+r88ee_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			= &r88ee_txpwr;
+
+	rs->rs_set_bw20			= r88e_set_bw20;
+	rs->rs_get_txpower		= r88e_get_txpower;
+	rs->rs_set_gain			= r88e_set_gain;
+	rs->rs_tx_enable_ampdu		= r88e_tx_enable_ampdu;
+	rs->rs_tx_setup_hwseq		= r88e_tx_setup_hwseq;
+	rs->rs_tx_setup_macid		= r88e_tx_setup_macid;
+	rs->rs_set_name			= r88ee_set_name;
+
+	/* XXX TODO: test with net80211 ratectl! */
+#ifndef RTWN_WITHOUT_UCODE
+	rs->rs_c2h_timeout		= hz;
+
+	callout_init_mtx(&rs->rs_c2h_report, &sc->sc_mtx, 0);
+#endif
+
+	rs->rf_read_delay[0]		= 1000;
+	rs->rf_read_delay[1]		= 1000;
+	rs->rf_read_delay[2]		= 1000;
+
+	sc->sc_priv = rs;
+
+}
+
+static void
+r88ee_adj_devcaps(struct rtwn_softc *sc)
+{
+	struct ieee80211com *ic = &sc->sc_ic;
+
+	/*
+	 * XXX do NOT enable PMGT until RSVD_PAGE command
+	 * will not be tested / fixed + HRPWM register must be set too.
+	 */
+	ic->ic_caps &= ~IEEE80211_C_PMGT;
+}
+
+void
+r88ee_attach(struct rtwn_pci_softc *pc)
+{
+	struct rtwn_softc *sc		= &pc->pc_sc;
+
+	/* PCIe part. */
+	pc->pc_setup_tx_desc		= r88ee_setup_tx_desc;
+	pc->pc_tx_postsetup		= r92ce_tx_postsetup;
+	pc->pc_copy_tx_desc		= r88ee_copy_tx_desc;
+	pc->pc_enable_intr		= r88ee_enable_intr;
+
+	pc->pc_qmap			= 0xe771;
+	pc->tcr				= 0x8200;
+
+	/* Common part. */
+	/* RTL8192C* cannot use pairwise keys from first 4 slots */
+	sc->sc_flags			= RTWN_FLAG_EXT_HDR; //RTWN_FLAG_CAM_FIXED;
+
+	sc->sc_start_xfers		= r88ee_start_xfers;
+	sc->sc_set_chan			= r92c_set_chan;
+	sc->sc_fill_tx_desc		= r92c_fill_tx_desc;
+	sc->sc_fill_tx_desc_raw		= r92c_fill_tx_desc_raw;
+	sc->sc_fill_tx_desc_null	= r92c_fill_tx_desc_null; /* XXX recheck */
+	sc->sc_dump_tx_desc		= r88ee_dump_tx_desc;
+	sc->sc_tx_radiotap_flags	= r92c_tx_radiotap_flags;
+	sc->sc_rx_radiotap_flags	= r92c_rx_radiotap_flags;
+	sc->sc_get_rssi_cck		= r88e_get_rssi_cck;
+	sc->sc_get_rssi_ofdm		= r88e_get_rssi_ofdm;
+	sc->sc_classify_intr		= r88ee_classify_intr;
+	sc->sc_handle_tx_report		= rtwn_nop_softc_uint8_int;
+	sc->sc_handle_c2h_report	= rtwn_nop_softc_uint8_int;
+	sc->sc_check_frame		= rtwn_nop_int_softc_mbuf;
+	sc->sc_rf_read			= r92c_rf_read;
+	sc->sc_rf_write			= r88e_rf_write;
+	sc->sc_check_condition		= r92c_check_condition;
+	sc->sc_efuse_postread		= r92c_efuse_postread;
+	sc->sc_parse_rom		= r88ee_parse_rom;
+	sc->sc_set_led			= r88e_set_led;
+	sc->sc_power_on			= r88ee_power_on;
+	sc->sc_power_off		= r88ee_power_off;
+#ifndef RTWN_WITHOUT_UCODE
+	sc->sc_fw_reset			= r88e_fw_reset;
+	sc->sc_fw_download_enable	= r88ee_fw_download_enable;
+#endif
+	sc->sc_set_page_size		= r92c_set_page_size;
+	sc->sc_lc_calib			= r92c_lc_calib;
+	sc->sc_iq_calib			= r88e_iq_calib;
+	sc->sc_read_chipid_vendor	= rtwn_nop_softc_uint32;
+	sc->sc_adj_devcaps		= r88ee_adj_devcaps;
+	sc->sc_vap_preattach		= rtwn_nop_softc_vap;
+	sc->sc_postattach		= r88ee_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			= r92c_set_rssi;
+#endif
+	sc->sc_beacon_init		= r92c_beacon_init;
+	sc->sc_beacon_enable		= r88e_beacon_enable;
+	sc->sc_beacon_set_rate		= rtwn_nop_void_int;
+	sc->sc_beacon_select		= rtwn_nop_softc_int;
+	sc->sc_temp_measure		= r88e_temp_measure;
+	sc->sc_temp_read		= r88e_temp_read;
+	sc->sc_init_tx_agg		= rtwn_nop_softc;
+	sc->sc_init_rx_agg		= rtwn_nop_softc;
+	sc->sc_init_ampdu		= r92ce_init_ampdu;
+	sc->sc_init_intr		= r88ee_init_intr;
+	sc->sc_init_edca		= r92ce_init_edca;
+	sc->sc_init_bb			= r88ee_init_bb;
+	sc->sc_init_rf			= r92c_init_rf;
+	sc->sc_init_antsel		= rtwn_nop_softc;
+	sc->sc_post_init		= r88ee_post_init;
+	sc->sc_init_bcnq1_boundary	= rtwn_nop_int_softc;
+
+	sc->mac_prog			= &rtl8188ee_mac[0];
+	sc->mac_size			= nitems(rtl8188ee_mac);
+	sc->bb_prog			= &rtl8188ee_bb[0];
+	sc->bb_size			= nitems(rtl8188ee_bb);
+	sc->agc_prog			= &rtl8188ee_agc[0];
+	sc->agc_size			= nitems(rtl8188ee_agc);
+	sc->rf_prog			= &rtl8188ee_rf[0];
+
+	sc->page_count			= 0xAF;
+	sc->pktbuf_count		= 0xAB;
+
+	sc->ackto			= 0x40;
+	sc->npubqpages			= 115;
+	sc->nhqpages			= R92CE_HPQ_NPAGES;
+	sc->nnqpages			= 1;
+	sc->nlqpages			= 13;
+	sc->page_size			= R92C_TX_PAGE_SIZE;
+
+	sc->txdesc_len			= sizeof(struct r88ee_tx_desc);
+	sc->efuse_maxlen		= R88E_EFUSE_MAX_LEN;
+	sc->efuse_maplen		= R88E_EFUSE_MAP_LEN;
+	sc->rx_dma_size			= R88E_RX_DMA_BUFFER_SIZE;
+
+	sc->macid_limit			= R88E_MACID_MAX + 1;
+	sc->cam_entry_limit		= R92C_CAM_ENTRY_COUNT;
+	sc->fwsize_limit		= 77895;
+	sc->temp_delta			= R88E_CALIB_THRESHOLD;
+
+	sc->bcn_status_reg[0]		= R92C_TDECTRL;
+	/*
+	 * TODO: some additional setup is required
+	 * to maintain few beacons at the same time.
+	 *
+	 * XXX BCNQ1 mechanism is not needed here; move it to the USB module.
+	 */
+	sc->bcn_status_reg[1]		= R92C_TDECTRL;
+	sc->rcr				= 0xf000780e;
+
+	sc->sc_llt_init			= r88ee_llt_init;
+	sc->sc_get_rx_stats		= r88e_get_rx_stats;
+
+	sc->ntxchains			= 1;
+	sc->nrxchains			= 1;
+
+	r88ee_attach_private(sc);
+}
diff --git a/sys/dev/rtwn/rtl8188e/pci/r88ee_calib.c b/sys/dev/rtwn/rtl8188e/pci/r88ee_calib.c
new file mode 100644
index 00000000000..3cd75d1c216
--- /dev/null
+++ b/sys/dev/rtwn/rtl8188e/pci/r88ee_calib.c
@@ -0,0 +1,65 @@
+/*	$OpenBSD: if_rtwn.c,v 1.6 2015/08/28 00:03:53 deraadt Exp $	*/
+
+/*-
+ * Copyright (c) 2018 Farhan Khan <khanzf@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_wlan.h"
+
+#include <sys/param.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/mbuf.h>
+#include <sys/kernel.h>
+#include <sys/socket.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/queue.h>
+#include <sys/taskqueue.h>
+#include <sys/bus.h>
+#include <sys/endian.h>
+#include <sys/linker.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/rman.h>
+
+#include <net/if.h>
+#include <net/ethernet.h>
+#include <net/if_media.h>
+
+#include <net80211/ieee80211_var.h>
+#include <net80211/ieee80211_radiotap.h>
+
+#include <dev/rtwn/if_rtwnreg.h>
+#include <dev/rtwn/if_rtwnvar.h>
+#include <dev/rtwn/if_rtwn_debug.h>
+
+#include <dev/rtwn/pci/rtwn_pci_var.h>
+
+#include <dev/rtwn/rtl8188e/pci/r88ee.h>
+#include <dev/rtwn/rtl8188e/pci/r88ee_reg.h>
+
+
+#define RTWN_IQ_CAL_NRUN	3
+void
+r88ee_iq_calib(struct rtwn_softc *sc)
+{
+	/* Currently unimplemented */
+}
+#undef RTWN_IQ_CAL_NRUN
diff --git a/sys/dev/rtwn/rtl8188e/pci/r88ee_init.c b/sys/dev/rtwn/rtl8188e/pci/r88ee_init.c
new file mode 100644
index 00000000000..412a7149556
--- /dev/null
+++ b/sys/dev/rtwn/rtl8188e/pci/r88ee_init.c
@@ -0,0 +1,256 @@
+/*-
+ * Copyright (c) 2017 Farhan Khan <khanzf@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_wlan.h"
+
+#include <sys/param.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/mbuf.h>
+#include <sys/kernel.h>
+#include <sys/socket.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/queue.h>
+#include <sys/taskqueue.h>
+#include <sys/bus.h>
+#include <sys/endian.h>
+#include <sys/linker.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/rman.h>
+
+#include <net/if.h>
+#include <net/ethernet.h>
+#include <net/if_media.h>
+
+#include <net80211/ieee80211_var.h>
+#include <net80211/ieee80211_radiotap.h>
+
+#include <dev/rtwn/if_rtwnvar.h>
+
+#include <dev/rtwn/pci/rtwn_pci_var.h>
+#include <dev/rtwn/rtl8188e/r88e_reg.h>
+#include <dev/rtwn/rtl8192c/r92c.h>
+#include <dev/rtwn/rtl8192c/pci/r92ce_reg.h>
+#include <dev/rtwn/rtl8192c/pci/r92ce.h>
+
+#include <dev/rtwn/rtl8188e/pci/r88ee.h>
+#include <dev/rtwn/rtl8188e/pci/r88ee_reg.h>
+#include <dev/rtwn/rtl8188e/pci/r88ee_pwrseq.h>
+#include <dev/rtwn/rtl8192c/r92c_var.h>
+
+void
+r88ee_init_intr(struct rtwn_softc *sc)
+{
+	/* Disable interrupts. */
+	rtwn_write_4(sc, 0xb0, 0x200084ff);
+	rtwn_write_4(sc, 0xb8, 0x100);
+	rtwn_write_1(sc, 0x01AF, 0x0);
+	rtwn_write_4(sc, 0x0058, 0xc0); 
+}
+
+void
+r88ee_init_edca(struct rtwn_softc *sc)
+{
+	rtwn_write_1(sc, R88EE_SIFS_TRX + 1, 0x0a);
+	rtwn_write_1(sc, R88EE_SIFS_SPEC + 1, 0x0a);
+	rtwn_write_1(sc, R88EE_SIFS_SPEC_MAC + 1, 0x0a);
+	rtwn_write_2(sc, R88EE_SIFS_RESP_OFDM, 0x0e0e);
+}
+
+int
+r88ee_power_on(struct rtwn_softc *sc)
+{
+	uint8_t bytetmp;
+
+	bytetmp = rtwn_read_1(sc, R92C_APS_FSMCO + 1) & (~0x80);
+	rtwn_write_1(sc, R92C_APS_FSMCO + 1, bytetmp);
+
+	rtwn_write_1(sc, R92C_RSV_CTRL, 0x00);
+
+	/* Power sequence: NIC enable flow */
+	rtwn_setbits_1(sc, 0x5, 0x18, 0x0);
+	if (!r88ee_pwrseq_polling(sc, 0x6, 0x2, 0x2))
+		return false;
+	rtwn_setbits_1(sc, 0x2, 0x3, 0x0);
+	rtwn_setbits_1(sc, 0x26, 0x80, 0x80);
+	rtwn_setbits_1(sc, 0x5, 0x80, 0x0);
+	rtwn_setbits_1(sc, 0x5, 0x18, 0x0);
+	rtwn_setbits_1(sc, 0x5, 0x1, 0x1);
+	if (!r88ee_pwrseq_polling(sc, 0x5, 0x1, 0x0))
+		return false;
+	/* End of power sequence */
+
+	bytetmp = rtwn_read_1(sc, R92C_SYS_CLKR);
+
+	rtwn_write_1(sc, R92C_SYS_CLKR, bytetmp | 0x08);
+	bytetmp = rtwn_read_1(sc, R92C_GPIO_MUXCFG+1);
+	rtwn_write_1(sc, R92C_GPIO_MUXCFG+1, (bytetmp & (~0x10)));
+	rtwn_write_1(sc, 0x367, 0x80);
+
+	rtwn_write_2(sc, R92C_CR, 0x2ff);
+	rtwn_write_1(sc, R92C_CR+1, 0x06);
+	rtwn_write_1(sc, R92C_MSR, 0x00);
+
+	rtwn_write_4(sc, R92C_INT_MIG, 0);
+
+	rtwn_write_1(sc, R92C_PCIE_CTRL_REG+1, 0); /* Enable RX DMA */
+
+	rtwn_write_1(sc, 0x04CA, 0x0B);
+	rtwn_write_4(sc, R92C_RCR, sc->rcr);
+
+	rtwn_write_4(sc, R92C_MCUTST_1, 0x0);
+
+	return(0);
+
+}
+
+void
+r88ee_power_off(struct rtwn_softc *sc)
+{
+	uint32_t count = 0;
+	uint8_t tmp;
+
+	tmp = rtwn_read_1(sc, R88E_TX_RPT_CTRL);
+	rtwn_write_1(sc, R88E_TX_RPT_CTRL, tmp & (~0x02));
+
+	tmp = rtwn_read_1(sc, R88EE_RXDMA_CONTROL);
+
+	while (!(tmp & 0x02) && (count++ < 100)) {
+		rtwn_delay(sc, 10);
+		tmp = rtwn_read_1(sc, R88EE_RXDMA_CONTROL);
+		count++;
+	}
+
+	rtwn_write_1(sc, R92C_PCIE_CTRL_REG+1, 0xFF);
+
+	/* Power sequence: Disable NIC LPS enable Flow */
+	rtwn_setbits_1(sc, 0x522, 0xff, 0x7f);
+	r88ee_pwrseq_polling(sc, 0x5f8, 0xff, 0x0);
+	r88ee_pwrseq_polling(sc, 0x5f9, 0xff, 0x0);
+	r88ee_pwrseq_polling(sc, 0x5fa, 0xff, 0x0);
+	r88ee_pwrseq_polling(sc, 0x5fb, 0xff, 0x0);
+	rtwn_setbits_1(sc, 0x2, 0x1, 0x0);
+	rtwn_setbits_1(sc, 0x100, 0xff, 0x3f);
+	rtwn_setbits_1(sc, 0x101, 0x2, 0x0);
+	rtwn_setbits_1(sc, 0x553, 0x20, 0x20);
+	/* End of power sequence */
+
+	rtwn_write_1(sc, R92C_RF_CTRL, 0x00);
+
+	tmp = rtwn_read_1(sc, R92C_SYS_FUNC_EN+1);
+	rtwn_write_1(sc, R92C_SYS_FUNC_EN+1, (tmp & (~0x04)));
+	rtwn_write_1(sc, R92C_SYS_FUNC_EN+1, (tmp | 0x04));
+
+	tmp = rtwn_read_1(sc, R92C_SYS_FUNC_EN+1);
+	rtwn_write_1(sc, R92C_SYS_FUNC_EN + 1, (tmp & (~0x04)));
+	rtwn_write_1(sc, R92C_MCUFWDL, 0x00);
+
+	tmp = rtwn_read_1(sc, R88E_32K_CTRL);
+	rtwn_write_1(sc, R88E_32K_CTRL, (tmp & (~0x01)));
+
+	/* Power sequence: NIC Disable flow */
+	rtwn_setbits_1(sc, 0x1f, 0xff, 0x0);
+	rtwn_setbits_1(sc, 0x23, 0x10, 0x10);
+	rtwn_setbits_1(sc, 0x5, 0x2, 0x2);
+	r88ee_pwrseq_polling(sc, 0x5, 0x2, 0x0);
+	rtwn_setbits_1(sc, 0x26, 0x80, 0x80);
+	/* End of power sequence */
+
+	tmp = rtwn_read_1(sc, R92C_RSV_CTRL+1);
+	rtwn_write_1(sc, R92C_RSV_CTRL+1, (tmp & (~0x08)));
+	tmp = rtwn_read_1(sc, R92C_RSV_CTRL+1);
+	rtwn_write_1(sc, R92C_RSV_CTRL+1, (tmp | 0x08));
+
+	rtwn_write_1(sc, R92C_RSV_CTRL, 0x0E);
+
+	tmp = rtwn_read_1(sc, R92C_GPIO_IN);
+	rtwn_write_1(sc, R92C_GPIO_OUT, tmp);
+	rtwn_write_1(sc, R92C_GPIO_IO_SEL, 0x7F);
+
+	tmp = rtwn_read_1(sc, R92C_GPIO_IO_SEL);
+	rtwn_write_1(sc, R92C_GPIO_IO_SEL, (tmp << 4) | tmp);
+	tmp = rtwn_read_1(sc, R92C_GPIO_IO_SEL+1);
+	rtwn_write_1(sc, R92C_GPIO_IO_SEL+1, tmp | 0x0F);
+
+	rtwn_write_4(sc, R88EE_GPIO_IO_SEL_2+2, 0x00080808);
+}
+
+void
+r88ee_init_ampdu(struct rtwn_softc *sc)
+{
+	/* Not implemented */
+}
+
+void
+r88ee_post_init(struct rtwn_softc *sc)
+{
+     rtwn_write_2(sc, R92C_FWHW_TXQ_CTRL,
+         0x1f00 | R92C_FWHW_TXQ_CTRL_AMPDU_RTY_NEW);
+
+     rtwn_write_1(sc, R92C_BCN_MAX_ERR, 0xff);
+
+     /* Perform LO and IQ calibrations. */
+     rtwn_iq_calib(sc);
+     /* Perform LC calibration. */
+     rtwn_lc_calib(sc);
+
+     r92c_pa_bias_init(sc);
+
+     /* Fix for lower temperature. */
+     rtwn_write_1(sc, 0x15, 0xe9);
+
+#ifndef RTWN_WITHOUT_UCODE
+     if (sc->sc_flags & RTWN_FW_LOADED) {
+          struct r92c_softc *rs = sc->sc_priv;
+
+          if (sc->sc_ratectl_sysctl == RTWN_RATECTL_FW) {
+               /* XXX TODO: fix (see comment in r92cu_init.c) */
+               sc->sc_ratectl = RTWN_RATECTL_NET80211;
+          } else
+               sc->sc_ratectl = sc->sc_ratectl_sysctl;
+
+          /* Start C2H event handling. */
+          callout_reset(&rs->rs_c2h_report, rs->rs_c2h_timeout,
+              r92c_handle_c2h_report, sc);
+     } else
+#endif
+          sc->sc_ratectl = RTWN_RATECTL_NONE;
+}
+
+void
+r88ee_init_rx_agg(struct rtwn_softc *sc) {
+	struct rtwn_pci_softc *pc = sc->sc_priv;
+
+	uint16_t tmp;
+
+	tmp = rtwn_read_2(sc, R88EE_TRXDMA_CTRL);
+	tmp &= 0xf;
+	tmp |= 0xE771;
+	rtwn_write_2(sc, R88EE_TRXDMA_CTRL, tmp);
+
+	rtwn_write_4(sc, R92C_RCR, sc->rcr);
+	rtwn_write_2(sc, R92C_RXFLTMAP2, 0xffff);
+	rtwn_write_4(sc, R92C_TCR, pc->tcr);
+
+	rtwn_write_1(sc, R92C_PCIE_CTRL_REG+1, 0);
+
+}
diff --git a/sys/dev/rtwn/rtl8188e/pci/r88ee_priv.h b/sys/dev/rtwn/rtl8188e/pci/r88ee_priv.h
new file mode 100644
index 00000000000..b94150658a4
--- /dev/null
+++ b/sys/dev/rtwn/rtl8188e/pci/r88ee_priv.h
@@ -0,0 +1,236 @@
+/*	$OpenBSD: if_rtwnreg.h,v 1.3 2015/06/14 08:02:47 stsp Exp $	*/
+
+/*-
+ * Copyright (c) 2018 Farhan Khan <khanzf@gmail.com>
+ *
+ * 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 R88EE_PRIV_H
+#define R88EE_PRIV_H
+
+#include <dev/rtwn/rtl8188e/r88e_priv.h>
+
+/*
+ * RF initialization values.
+ */
+static const uint8_t rtl8188ee_rf_regs0[] = {
+	0x000, 0x008, 0x018, 0x019, 0x01E,
+	0x01F, 0x02F, 0x03F, 0x042, 0x057,
+	0x058, 0x067, 0x083, 0x0B0, 0x0B1,
+	0x0B2, 0x0B4, 0x0B6, 0x0B7, 0x0B8,
+	0x0B9, 0x0BA, 0x0BB, 0x0BF, 0x0C2,
+	0x0C3, 0x0C4, 0x0C5, 0x0C6, 0x0C7,
+	0x0C8, 0x0C9, 0x0CA, 0x0DF, 0x0EF,
+	0x051, 0x052, 0x053, 0x056, 0x035,
+	0x035, 0x035, 0x036, 0x036, 0x036,
+	0x036, 0x0B6, 0x018, 0x05A, 0x019,
+	0x034, 0x034, 0x034, 0x034, 0x034,
+	0x034, 0x034, 0x034, 0x034, 0x034,
+	0x034, 0x000, 0x084, 0x086, 0x087,
+	0x08E, 0x08F, 0x0EF, 0x03B, 0x03B,
+	0x03B, 0x03B, 0x03B, 0x03B, 0x03B,
+	0x03B, 0x03B, 0x03B, 0x03B, 0x03B,
+
+	0x03B, 0x03B, 0x03B, 0x03B, 0x0EF,
+	0x000, 0x018, 0x0F9, 0x0F9, 0x01E,
+	0x0F9, 0x0F9, 0x01E, 0x01F, 0x000
+
+};
+
+static const uint32_t rtl8188ee_rf_vals0[] = {
+	0x00030000, 0x00084000, 0x00000407, 0x00000012, 0x00080009,
+	0x00000880, 0x0001A060, 0x00000000, 0x000060C0, 0x000D0000,
+	0x000BE180, 0x00001552, 0x00000000, 0x000FF8FC, 0x00054400,
+	0x000CCC19, 0x00043003, 0x0004953E, 0x0001C718, 0x000060FF,
+	0x00080001, 0x00040000, 0x00000400, 0x000C0000, 0x00002400,
+	0x00000009, 0x00040C91, 0x00099999, 0x000000A3, 0x00088820,
+	0x00076C06, 0x00000000, 0x00080000, 0x00000180, 0x000001A0,
+	0x0006B27D, 0x0007E49D, 0x00000073, 0x00051FF3, 0x00000086,
+	0x00000186, 0x00000286, 0x00001C25, 0x00009C25, 0x00011C25,
+	0x00019C25, 0x00048538, 0x00000C07, 0x0004BD00, 0x000739D0,
+	0x0000ADF3, 0x00009DF0, 0x00008DED, 0x00007DEA, 0x00006DE7,
+	0x000054EE, 0x000044EB, 0x000034E8, 0x0000246B, 0x00001468,
+	0x0000006D, 0x00030159, 0x00068200, 0x000000CE, 0x00048A00,
+	0x00065540, 0x00088000, 0x000020A0, 0x000F02B0, 0x000EF7B0,
+	0x000D4FB0, 0x000CF060, 0x000B0090, 0x000A0080, 0x00090080,
+	0x0008F780, 0x000722B0, 0x0006F7B0, 0x00054FB0, 0x0004F060,
+	0x00030090, 0x00020080, 0x00010080, 0x0000F780, 0x000000A0,
+
+	0x00010159, 0x0000F407, 0x0000C350, 0x0000C350, 0x00080003,
+	0x0000C350, 0x0000C350, 0x00000001, 0x00080000, 0x00033e60
+};
+
+_Static_assert(nitems(rtl8188ee_rf_regs0) == nitems(rtl8188ee_rf_vals0),
+    "rtl8188ee_rf_regs0 and rtl8188ee_rf_vals0 must be the same size!");
+
+
+static const struct rtwn_rf_prog rtl8188ee_rf[] = {
+	{
+		nitems(rtl8188ee_rf_regs0),
+		rtl8188ee_rf_regs0,
+		rtl8188ee_rf_vals0,
+		{ 0x0 },
+		NULL,
+	},
+	{ 0, NULL, NULL, { 0 }, NULL }
+};
+
+/*
+ * MAC initialization values.
+ */
+static const struct rtwn_mac_prog rtl8188ee_mac[] = {
+	{ 0x026, 0x41 }, { 0x027, 0x35 }, { 0x428, 0x0A }, { 0x429, 0x10 },
+	{ 0x430, 0x00 }, { 0x431, 0x01 }, { 0x432, 0x02 }, { 0x433, 0x04 },
+	{ 0x434, 0x05 }, { 0x435, 0x06 }, { 0x436, 0x07 }, { 0x437, 0x08 },
+	{ 0x438, 0x00 }, { 0x439, 0x00 }, { 0x43A, 0x01 }, { 0x43B, 0x02 },
+	{ 0x43C, 0x04 }, { 0x43D, 0x05 }, { 0x43E, 0x06 }, { 0x43F, 0x07 },
+	{ 0x440, 0x5D }, { 0x441, 0x01 }, { 0x442, 0x00 }, { 0x444, 0x15 },
+	{ 0x445, 0xF0 }, { 0x446, 0x0F }, { 0x447, 0x00 }, { 0x458, 0x41 },
+	{ 0x459, 0xA8 }, { 0x45A, 0x72 }, { 0x45B, 0xB9 }, { 0x460, 0x66 },
+	{ 0x461, 0x66 }, { 0x480, 0x08 }, { 0x4C8, 0xFF }, { 0x4C9, 0x08 },
+	{ 0x4CC, 0xFF }, { 0x4CD, 0xFF }, { 0x4CE, 0x01 }, { 0x4D3, 0x01 },
+	{ 0x500, 0x26 }, { 0x501, 0xA2 }, { 0x502, 0x2F }, { 0x503, 0x00 },
+	{ 0x504, 0x28 }, { 0x505, 0xA3 }, { 0x506, 0x5E }, { 0x507, 0x00 },
+	{ 0x508, 0x2B }, { 0x509, 0xA4 }, { 0x50A, 0x5E }, { 0x50B, 0x00 },
+	{ 0x50C, 0x4F }, { 0x50D, 0xA4 }, { 0x50E, 0x00 }, { 0x50F, 0x00 },
+	{ 0x512, 0x1C }, { 0x514, 0x0A }, { 0x516, 0x0A }, { 0x525, 0x4F },
+	{ 0x550, 0x10 }, { 0x551, 0x10 }, { 0x559, 0x02 }, { 0x55D, 0xFF },
+	{ 0x605, 0x30 }, { 0x608, 0x0E }, { 0x609, 0x2A }, { 0x620, 0xFF },
+	{ 0x621, 0xFF }, { 0x622, 0xFF }, { 0x623, 0xFF }, { 0x624, 0xFF },
+	{ 0x625, 0xFF }, { 0x626, 0xFF }, { 0x627, 0xFF }, { 0x652, 0x20 },
+	{ 0x63C, 0x0A }, { 0x63D, 0x0A }, { 0x63E, 0x0E }, { 0x63F, 0x0E },
+	{ 0x640, 0x40 }, { 0x66E, 0x05 }, { 0x700, 0x21 }, { 0x701, 0x43 },
+	{ 0x702, 0x65 }, { 0x703, 0x87 }, { 0x708, 0x21 }, { 0x709, 0x43 },
+	{ 0x70A, 0x65 }, { 0x70B, 0x87 }
+};
+
+/*
+ * Baseband initialization values.
+ */
+static const uint16_t rtl8188ee_bb_phy_regs0[] = {
+	0x800, 0x804, 0x808, 0x80C, 0x810, 0x814, 0x818, 0x81C, 0x820,
+	0x824, 0x828, 0x82C, 0x830, 0x834, 0x838, 0x83C, 0x840, 0x844,
+	0x848, 0x84C, 0x850, 0x854, 0x858, 0x85C, 0x860, 0x864, 0x868,
+	0x86C, 0x870, 0x874, 0x878, 0x87C, 0x880, 0x884, 0x888, 0x88C,
+	0x890, 0x894, 0x898, 0x89C, 0x900, 0x904, 0x908, 0x90C, 0x910,
+	0x914, 0xA00, 0xA04, 0xA08, 0xA0C, 0xA10, 0xA14, 0xA18, 0xA1C,
+	0xA20, 0xA24, 0xA28, 0xA2C, 0xA70, 0xA74, 0xA78, 0xA7C, 0xA80,
+	0xB2C, 0xC00, 0xC04, 0xC08, 0xC0C, 0xC10, 0xC14, 0xC18, 0xC1C,
+	0xC20, 0xC24, 0xC28, 0xC2C, 0xC30, 0xC34, 0xC38, 0xC3C, 0xC40,
+	0xC44, 0xC48, 0xC4C, 0xC50, 0xC54, 0xC58, 0xC5C, 0xC60, 0xC64,
+	0xC68, 0xC6C, 0xC70, 0xC74, 0xC78, 0xC7C, 0xC80, 0xC84, 0xC88,
+	0xC8C, 0xC90, 0xC94, 0xC98, 0xC9C, 0xCA0, 0xCA4, 0xCA8, 0xCAC,
+	0xCB0, 0xCB4, 0xCB8, 0xCBC, 0xCC0, 0xCC4, 0xCC8, 0xCCC, 0xCD0,
+	0xCD4, 0xCD8, 0xCDC, 0xCE0, 0xCE4, 0xCE8, 0xCEC, 0xD00, 0xD04,
+	0xD08, 0xD0C, 0xD10, 0xD14, 0xD18, 0xD2C, 0xD30, 0xD34, 0xD38,
+	0xD3C, 0xD40, 0xD44, 0xD48, 0xD4C, 0xD50, 0xD54, 0xD58, 0xD5C,
+	0xD60, 0xD64, 0xD68, 0xD6C, 0xD70, 0xD74, 0xD78, 0xE00, 0xE04,
+	0xE08, 0xE10, 0xE14, 0xE18, 0xE1C, 0xE28, 0xE30, 0xE34, 0xE38,
+	0xE3C, 0xE40, 0xE44, 0xE48, 0xE4C, 0xE50, 0xE54, 0xE58, 0xE5C,
+	0xE60, 0xE68, 0xE6C, 0xE70, 0xE74, 0xE78, 0xE7C, 0xE80, 0xE84,
+	0xE88, 0xE8C, 0xED0, 0xED4, 0xED8, 0xEDC, 0xEE0, 0xEEC, 0xF14,
+	0xF4C, 0xF00
+};
+
+static const uint32_t rtl8188ee_bb_phy_vals0[] = {
+	0x80040000, 0x00000003, 0x0000FC00, 0x0000000A, 0x10001331,
+	0x020C3D10, 0x02200385, 0x00000000, 0x01000100, 0x00390204,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00010000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x569A11A9, 0x01000014, 0x66F60110,
+	0x061F0649, 0x00000000, 0x27272700, 0x07000760, 0x25004000,
+	0x00000808, 0x00000000, 0xB0000C1C, 0x00000001, 0x00000000,
+	0xCCC000C0, 0x00000800, 0xFFFFFFFE, 0x40302010, 0x00706050,
+	0x00000000, 0x00000023, 0x00000000, 0x81121111, 0x00000002,
+	0x00000201, 0x00D047C8, 0x80FF000C, 0x8C838300, 0x2E7F120F,
+	0x9500BB78, 0x1114D028, 0x00881117, 0x89140F00, 0x1A1B0000,
+	0x090E1317, 0x00000204, 0x00D30000, 0x101FBF00, 0x00000007,
+	0x00000900, 0x225B0606, 0x218075B1, 0x80000000, 0x48071D40,
+	0x03A05611, 0x000000E4, 0x6C6C6C6C, 0x08800000, 0x40000100,
+	0x08800000, 0x40000100, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x69E9AC47, 0x469652AF, 0x49795994, 0x0A97971C,
+	0x1F7C403F, 0x000100B7, 0xEC020107, 0x007F037F, 0x69553420,
+	0x43BC0094, 0x00013169, 0x00250492, 0x00000000, 0x7112848B,
+	0x47C00BFF, 0x00000036, 0x2C7F000D, 0x020610DB, 0x0000001F,
+	0x00B91612, 0x390000E4, 0x20F60000, 0x40000100, 0x20200000,
+	0x00091521, 0x00000000, 0x00121820, 0x00007F7F, 0x00000000,
+	0x000300A0, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x28000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x64B22427, 0x00766932,
+	0x00222222, 0x00000000, 0x37644302, 0x2F97D40C, 0x00000740,
+	0x00020401, 0x0000907F, 0x20010201, 0xA0633333, 0x3333BC43,
+	0x7A8F5B6F, 0xCC979975, 0x00000000, 0x80608000, 0x00000000,
+	0x00127353, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x6437140A, 0x00000000, 0x00000282, 0x30032064, 0x4653DE68,
+	0x04518A3C, 0x00002101, 0x2A201C16, 0x1812362E, 0x322C2220,
+	0x000E3C24, 0x2D2D2D2D, 0x2D2D2D2D, 0x0390272D, 0x2D2D2D2D,
+	0x2D2D2D2D, 0x2D2D2D2D, 0x2D2D2D2D, 0x00000000, 0x1000DC1F,
+	0x10008C1F, 0x02140102, 0x681604C2, 0x01007C00, 0x01004800,
+	0xFB000000, 0x000028D1, 0x1000DC1F, 0x10008C1F, 0x02140102,
+	0x28160D05, 0x00000008, 0x001B25A4, 0x00C00014, 0x00C00014,
+	0x01000014, 0x01000014, 0x01000014, 0x01000014, 0x00C00014,
+	0x01000014, 0x00C00014, 0x00C00014, 0x00C00014, 0x00C00014,
+	0x00000014, 0x00000014, 0x01C00014, 0x00000003, 0x00000000,
+	0x00000300
+}, rtl8188ee_bb_agc_vals0[] = {
+	0xFB000001, 0xFB010001, 0xFB020001, 0xFB030001, 0xFB040001,
+	0xFB050001, 0xFA060001, 0xF9070001, 0xF8080001, 0xF7090001,
+	0xF60A0001, 0xF50B0001, 0xF40C0001, 0xF30D0001, 0xF20E0001,
+	0xF10F0001, 0xF0100001, 0xEF110001, 0xEE120001, 0xED130001,
+	0xEC140001, 0xEB150001, 0xEA160001, 0xE9170001, 0xE8180001,
+	0xE7190001, 0xE61A0001, 0xE51B0001, 0xE41C0001, 0xE31D0001,
+	0xE21E0001, 0xE11F0001, 0x8A200001, 0x89210001, 0x88220001,
+	0x87230001, 0x86240001, 0x85250001, 0x84260001, 0x83270001,
+	0x82280001, 0x6B290001, 0x6A2A0001, 0x692B0001, 0x682C0001,
+	0x672D0001, 0x662E0001, 0x652F0001, 0x64300001, 0x63310001,
+	0x62320001, 0x61330001, 0x46340001, 0x45350001, 0x44360001,
+	0x43370001, 0x42380001, 0x41390001, 0x403A0001, 0x403B0001,
+	0x403C0001, 0x403D0001, 0x403E0001, 0x403F0001, 0xFB400001,
+	0xFB410001, 0xFB420001, 0xFB430001, 0xFB440001, 0xFB450001,
+	0xFB460001, 0xFB470001, 0xFB480001, 0xFA490001, 0xF94A0001,
+	0xF84B0001, 0xF74C0001, 0xF64D0001, 0xF54E0001, 0xF44F0001,
+	0xF3500001, 0xF2510001, 0xF1520001, 0xF0530001, 0xEF540001,
+	0xEE550001, 0xED560001, 0xEC570001, 0xEB580001, 0xEA590001,
+	0xE95A0001, 0xE85B0001, 0xE75C0001, 0xE65D0001, 0xE55E0001,
+	0xE45F0001, 0xE3600001, 0xE2610001, 0xC3620001, 0xC2630001,
+	0xC1640001, 0x8B650001, 0x8A660001, 0x89670001, 0x88680001,
+	0x87690001, 0x866A0001, 0x856B0001, 0x846C0001, 0x676D0001,
+	0x666E0001, 0x656F0001, 0x64700001, 0x63710001, 0x62720001,
+	0x61730001, 0x60740001, 0x46750001, 0x45760001, 0x44770001,
+	0x43780001, 0x42790001, 0x417A0001, 0x407B0001, 0x407C0001,
+	0x407D0001, 0x407E0001, 0x407F0001
+};
+
+static const struct rtwn_bb_prog rtl8188ee_bb[] = {
+	{
+		nitems(rtl8188ee_bb_phy_regs0),
+		rtl8188ee_bb_phy_regs0,
+		rtl8188ee_bb_phy_vals0,
+		{ (0x01 | 0x02) },
+		NULL
+	}
+};
+
+static const struct rtwn_agc_prog rtl8188ee_agc[] = {
+	{
+		nitems(rtl8188ee_bb_agc_vals0),
+		rtl8188ee_bb_agc_vals0,
+		{ 0 },
+		NULL
+	}
+};
+
+#endif	/* R88EE_PRIV_H */
diff --git a/sys/dev/rtwn/rtl8188e/pci/r88ee_pwrseq.c b/sys/dev/rtwn/rtl8188e/pci/r88ee_pwrseq.c
new file mode 100644
index 00000000000..01d16f6fc24
--- /dev/null
+++ b/sys/dev/rtwn/rtl8188e/pci/r88ee_pwrseq.c
@@ -0,0 +1,44 @@
+/*-
+ * Copyright (c) 2018 Farhan Khan <khanzf@gmail.com>
+ *
+ * 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$
+ */
+
+#include <dev/rtwn/rtl8188e/pci/r88ee_pwrseq.h>
+
+int r88ee_pwrseq_polling(struct rtwn_softc *sc, uint32_t offset, uint32_t msk, uint8_t value)
+{
+	uint8_t reg;
+	uint32_t polling;
+	for(polling=0;polling<5000;polling++) {
+		reg = rtwn_read_1(sc, offset);
+		reg &= msk;
+		if (reg == (value & msk))
+			break;
+		else
+			rtwn_delay(sc, 10);
+	}
+
+	if (polling > 5000)
+		return false;
+
+	return true;
+}
+
+inline void r88ee_pwrseq_delay(struct rtwn_softc *sc, uint32_t offset)
+{
+	rtwn_delay(sc, offset * 1000);
+}
+
diff --git a/sys/dev/rtwn/rtl8188e/pci/r88ee_pwrseq.h b/sys/dev/rtwn/rtl8188e/pci/r88ee_pwrseq.h
new file mode 100644
index 00000000000..4a920337633
--- /dev/null
+++ b/sys/dev/rtwn/rtl8188e/pci/r88ee_pwrseq.h
@@ -0,0 +1,53 @@
+/*-
+ * Copyright (c) 2018 Farhan Khan <khanzf@gmail.com>
+ *
+ * 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 RTL88EE_PWRSEQ_H
+#define RTL88EE_PWRSEQ_H
+
+#include <sys/param.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/mbuf.h>
+#include <sys/kernel.h>
+#include <sys/socket.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/queue.h>
+#include <sys/taskqueue.h>
+#include <sys/bus.h>
+#include <sys/endian.h>
+
+#include <net/if.h>
+#include <net/if_var.h>
+#include <net/ethernet.h>
+#include <net/if_media.h>
+
+#include <net80211/ieee80211_var.h>
+#include <net80211/ieee80211_radiotap.h>
+#include <net80211/ieee80211_ratectl.h>
+#ifdef  IEEE80211_SUPPORT_SUPERG
+#include <net80211/ieee80211_superg.h>
+#endif
+
+#include <dev/rtwn/if_rtwnreg.h>
+#include <dev/rtwn/if_rtwnvar.h>
+
+int r88ee_pwrseq_polling(struct rtwn_softc *sc, uint32_t offset, uint32_t msk, uint8_t value);
+inline void r88ee_pwrseq_delay(struct rtwn_softc *sc, uint32_t offset);
+
+#endif
diff --git a/sys/dev/rtwn/rtl8188e/pci/r88ee_reg.h b/sys/dev/rtwn/rtl8188e/pci/r88ee_reg.h
new file mode 100644
index 00000000000..d585f6284ad
--- /dev/null
+++ b/sys/dev/rtwn/rtl8188e/pci/r88ee_reg.h
@@ -0,0 +1,121 @@
+/*	$OpenBSD: if_rtwnreg.h,v 1.3 2015/06/14 08:02:47 stsp Exp $	*/
+
+/*-
+ * Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
+ * Copyright (c) 2015 Stefan Sperling <stsp@openbsd.org>
+ * Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
+ * Copyright (c) 2018 Farhan Khan <khanzf@gmail.com>
+ *
+ * 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 R88EEE_REG_H
+#define R88EEE_REG_H
+
+#include <dev/rtwn/rtl8192c/r92c_reg.h>
+
+#define R88EE_MAX_CHAINS		4
+
+/*
+ * MAC registers.
+ */
+/* System Configuration. */
+#define R88EE_PCIE_MIO_INTF		0x0e4
+#define R88EE_PCIE_MIO_INTD		0x0e8
+/* PCIe Configuration. */
+#define R88EE_PCIE_CTRL_REG		0x300
+#define R88EE_INT_MIG			0x304
+#define R88EE_BCNQ_DESA			0x308
+#define R88EE_HQ_DESA			0x310
+#define R88EE_MGQ_DESA			0x318
+#define R88EE_VOQ_DESA			0x320
+#define R88EE_VIQ_DESA			0x328
+#define R88EE_BEQ_DESA			0x330
+#define R88EE_BKQ_DESA			0x338
+#define R88EE_RX_DESA			0x340
+#define R88EE_DBI			0x348
+#define R88EE_MDIO			0x354
+#define R88EE_DBG_SEL			0x360
+#define R88EE_PCIE_HRPWM			0x361
+#define R88EE_PCIE_HCPWM			0x363
+#define R88EE_UART_CTRL			0x364
+#define R88EE_UART_TX_DES		0x370
+#define R88EE_UART_RX_DES		0x378
+
+/* EDCA Registers */
+#define R88EE_SIFS_CTX			0x0514
+#define R88EE_SIFS_TRX			0x0516
+#define R88EE_SIFS_SPEC			0x0428
+#define R88EE_SIFS_SPEC_MAC		0x063A
+#define R88EE_SIFS_RESP_OFDM		0x063E
+
+/* Bits for R88EE_GPIO_MUXCFG. */
+#define R88EE_GPIO_MUXCFG_RFKILL		0x0008
+
+/* Bits for R88EE_GPIO_IO_SEL. */
+#define R88EE_GPIO_IO_SEL_2                     0x0062
+#define R88EE_GPIO_IO_SEL_RFKILL		0x0008
+
+/* Bits for R88EE_LEDCFG2. */
+#define R88EE_LEDCFG2_EN			0x60
+#define R88EE_LEDCFG2_DIS			0x68
+
+/* Bits for R88EE_HIMR. */
+#define R88EE_IMR_ROK		0x00000001	/* receive DMA OK */
+#define R88EE_IMR_VODOK		0x00000002	/* AC_VO DMA OK */
+#define R88EE_IMR_VIDOK		0x00000004	/* AC_VI DMA OK */
+#define R88EE_IMR_BEDOK		0x00000008	/* AC_BE DMA OK */
+#define R88EE_IMR_BKDOK		0x00000010	/* AC_BK DMA OK */
+#define R88EE_IMR_TXBDER	0x00000020	/* beacon transmit error */
+#define R88EE_IMR_MGNTDOK	0x00000040	/* management queue DMA OK */
+#define R88EE_IMR_TBDOK		0x00000080	/* beacon transmit OK */
+#define R88EE_IMR_HIGHDOK	0x00000100	/* high queue DMA OK */
+#define R88EE_IMR_BDOK		0x00000200	/* beacon queue DMA OK */
+#define R88EE_IMR_ATIMEND	0x00000400	/* ATIM window end interrupt */
+#define R88EE_IMR_RDU		0x00000800	/* Rx descriptor unavailable */
+#define R88EE_IMR_RXFOVW	0x00001000	/* receive FIFO overflow */
+#define R88EE_IMR_BCNINT	0x00002000	/* beacon DMA interrupt 0 */
+#define R88EE_IMR_PSTIMEOUT	0x00004000	/* powersave timeout */
+#define R88EE_IMR_TXFOVW	0x00008000	/* transmit FIFO overflow */
+#define R88EE_IMR_TIMEOUT1	0x00010000	/* timeout interrupt 1 */
+#define R88EE_IMR_TIMEOUT2	0x00020000	/* timeout interrupt 2 */
+#define R88EE_IMR_BCNDOK1	0x00040000	/* beacon queue DMA OK (1) */
+#define R88EE_IMR_BCNDOK2	0x00080000	/* beacon queue DMA OK (2) */
+#define R88EE_IMR_BCNDOK3	0x00100000	/* beacon queue DMA OK (3) */
+#define R88EE_IMR_BCNDOK4	0x00200000	/* beacon queue DMA OK (4) */
+#define R88EE_IMR_BCNDOK5	0x00400000	/* beacon queue DMA OK (5) */
+#define R88EE_IMR_BCNDOK6	0x00800000	/* beacon queue DMA OK (6) */
+#define R88EE_IMR_BCNDOK7	0x01000000	/* beacon queue DMA OK (7) */
+#define R88EE_IMR_BCNDOK8	0x02000000	/* beacon queue DMA OK (8) */
+#define R88EE_IMR_BCNDMAINT1	0x04000000	/* beacon DMA interrupt 1 */
+#define R88EE_IMR_BCNDMAINT2	0x08000000	/* beacon DMA interrupt 2 */
+#define R88EE_IMR_BCNDMAINT3	0x10000000	/* beacon DMA interrupt 3 */
+#define R88EE_IMR_BCNDMAINT4	0x20000000	/* beacon DMA interrupt 4 */
+#define R88EE_IMR_BCNDMAINT5	0x40000000	/* beacon DMA interrupt 5 */
+#define R88EE_IMR_BCNDMAINT6	0x80000000	/* beacon DMA interrupt 6 */
+#define R88EE_HIMR		0xb0
+#define R88EE_ISR		0xb4
+#define R88EE_HIMRE		0xb8
+#define R88EE_HISRE		0xbc
+
+/* Shortcut. */
+#define R88EE_IBSS_INT_MASK	\
+	(R88EE_IMR_BCNINT | R88EE_IMR_TBDOK | R88EE_IMR_TBDER)
+
+/* Power On/Off DMA */
+#define R88EE_RXDMA_CONTROL     0x0286
+#define	R88EE_TRXDMA_CTRL       0x010C
+
+#endif	/* R99EE_REG_H */
diff --git a/sys/dev/rtwn/rtl8188e/pci/r88ee_rf.c b/sys/dev/rtwn/rtl8188e/pci/r88ee_rf.c
new file mode 100644
index 00000000000..3f4e2e3d607
--- /dev/null
+++ b/sys/dev/rtwn/rtl8188e/pci/r88ee_rf.c
@@ -0,0 +1,106 @@
+/*-
+ * Copyright (c) 2017 Farhan Khan <khanzf@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_wlan.h"
+
+#include <sys/param.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/mbuf.h>
+#include <sys/kernel.h>
+#include <sys/socket.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/queue.h>
+#include <sys/taskqueue.h>
+#include <sys/bus.h>
+#include <sys/endian.h>
+#include <sys/linker.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/rman.h>
+
+#include <net/if.h>
+#include <net/ethernet.h>
+#include <net/if_media.h>
+
+#include <net80211/ieee80211_var.h>
+#include <net80211/ieee80211_radiotap.h>
+
+#include <dev/rtwn/if_rtwnvar.h>
+#include <dev/rtwn/if_rtwn_debug.h>
+
+#include <dev/rtwn/rtl8188e/r88e.h>
+#include <dev/rtwn/rtl8188e/r88e_reg.h>
+#include <dev/rtwn/pci/rtwn_pci_var.h>
+
+#include <dev/rtwn/rtl8192c/r92c_var.h>
+#include <dev/rtwn/rtl8188e/pci/r88ee.h>
+#include <dev/rtwn/rtl8192c/pci/r92ce_reg.h>
+#include <dev/rtwn/rtl8188e/pci/r88ee_reg.h>
+
+#include <net80211/ieee80211_var.h>
+#include <net80211/ieee80211_radiotap.h>
+
+#include <dev/rtwn/if_rtwnreg.h>
+#include <dev/rtwn/if_rtwnvar.h>
+#include <dev/rtwn/if_rtwn_debug.h>
+
+#include <dev/rtwn/pci/rtwn_pci_var.h>
+
+uint32_t
+r88ee_rf_read(struct rtwn_softc *sc, int chain, uint8_t addr)
+{
+	struct r92c_softc *rs = sc->sc_priv;
+	uint32_t reg[R88EE_MAX_CHAINS], val;
+
+	reg[0] = rtwn_bb_read(sc, R92C_HSSI_PARAM2(0));
+
+	if (chain != 0)
+		reg[chain] = rtwn_bb_read(sc, R92C_HSSI_PARAM2(chain));
+	else
+		reg[chain] = reg[0];
+
+
+	rtwn_bb_write(sc, R92C_HSSI_PARAM2(0),
+		reg[0] & ~R92C_HSSI_PARAM2_READ_EDGE);
+	rtwn_delay(sc, rs->rf_read_delay[1]);
+
+	rtwn_bb_write(sc, R92C_HSSI_PARAM2(chain),
+		(reg[chain] & (~R92C_HSSI_PARAM2_READ_ADDR_M)) |
+		(addr << 23) | R92C_HSSI_PARAM2_READ_EDGE);
+	rtwn_delay(sc, rs->rf_read_delay[2]);
+
+	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 val;
+}
+
+void
+r88ee_rf_write(struct rtwn_softc *sc, int chain, uint8_t addr,
+	uint32_t val)
+{
+	rtwn_bb_write(sc, R92C_LSSI_PARAM(chain),
+		((addr << R92C_LSSI_PARAM_ADDR_S) |
+		(val & R92C_LSSI_PARAM_DATA_M)) & 0x0fffffff);
+}
diff --git a/sys/dev/rtwn/rtl8188e/pci/r88ee_rx.c b/sys/dev/rtwn/rtl8188e/pci/r88ee_rx.c
new file mode 100644
index 00000000000..09c566d37a2
--- /dev/null
+++ b/sys/dev/rtwn/rtl8188e/pci/r88ee_rx.c
@@ -0,0 +1,139 @@
+/*-
+ * Copyright (c) 2017 Farhan Khan <khanzf@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_wlan.h"
+
+#include <sys/param.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/mbuf.h>
+#include <sys/kernel.h>
+#include <sys/socket.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/queue.h>
+#include <sys/taskqueue.h>
+#include <sys/bus.h>
+#include <sys/endian.h>
+#include <sys/linker.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/rman.h>
+
+#include <net/if.h>
+#include <net/ethernet.h>
+#include <net/if_media.h>
+
+#include <net80211/ieee80211_var.h>
+#include <net80211/ieee80211_radiotap.h>
+
+#include <dev/rtwn/if_rtwnvar.h>
+#include <dev/rtwn/if_rtwn_debug.h>
+
+#include <dev/rtwn/rtl8188e/r88e.h>
+#include <dev/rtwn/rtl8188e/r88e_reg.h>
+#include <dev/rtwn/pci/rtwn_pci_var.h>
+
+#include <dev/rtwn/rtl8188e/pci/r88ee.h>
+#include <dev/rtwn/rtl8192c/pci/r92ce_reg.h>
+#include <dev/rtwn/rtl8188e/pci/r88ee_reg.h>
+
+int
+r88ee_classify_intr(struct rtwn_softc *sc, void *arg, int len __unused)
+{
+	uint32_t status;
+	uint32_t statusb;
+	int *rings = arg;
+	int ret;
+
+	*rings = 0;
+
+	rtwn_write_4(sc, R88EE_HIMR, 0x0);
+	rtwn_write_4(sc, R88EE_HIMRE, 0x0);
+
+	status = rtwn_read_4(sc, R88EE_ISR) & 0x200084ff;
+	rtwn_write_4(sc, R88EE_ISR, status);
+	statusb = rtwn_read_4(sc, R88EE_HISRE) & 0x100;
+	rtwn_write_4(sc, R88EE_HISRE, statusb);
+
+	if (!status || statusb == 0xffff) {
+		return 0;
+	}
+
+	/* Ack interrupts. */
+	if (statusb & R92C_IMR_BDOK)
+		*rings |= (1 << RTWN_PCI_BEACON_QUEUE);
+	if (statusb & R92C_IMR_HIGHDOK)
+		*rings |= (1 << RTWN_PCI_HIGH_QUEUE);
+	if (statusb & R92C_IMR_MGNTDOK)
+		*rings |= (1 << RTWN_PCI_MGNT_QUEUE);
+	if (statusb & R92C_IMR_BKDOK)
+		*rings |= (1 << RTWN_PCI_BK_QUEUE);
+	if (statusb & R92C_IMR_BEDOK)
+		*rings |= (1 << RTWN_PCI_BE_QUEUE);
+	if (statusb & R92C_IMR_VIDOK)
+		*rings |= (1 << RTWN_PCI_VI_QUEUE);
+	if (statusb & R92C_IMR_VODOK)
+		*rings |= (1 << RTWN_PCI_VO_QUEUE);
+
+	ret = 0;
+	if (status & R92C_IMR_RXFOVW)
+		ret |= RTWN_PCI_INTR_RX_OVERFLOW;
+	if (status & R92C_IMR_RDU)
+		ret |= RTWN_PCI_INTR_RX_DESC_UNAVAIL;
+	if (status & R92C_IMR_ROK)
+		ret |= RTWN_PCI_INTR_RX_DONE;
+	if (status & R92C_IMR_TXFOVW)
+		ret |= RTWN_PCI_INTR_TX_OVERFLOW;
+	if (status & R92C_IMR_PSTIMEOUT)
+		ret |= RTWN_PCI_INTR_PS_TIMEOUT;
+
+	return (ret);
+}
+
+void
+r88ee_enable_intr(struct rtwn_pci_softc *pc)
+{
+	struct rtwn_softc *sc = &pc->pc_sc;
+
+	/* Enable interrupts */
+	rtwn_write_4(sc, R88EE_HIMR, 0x200084ff);
+	rtwn_write_4(sc, R88EE_HIMRE, 0x100);
+
+        /* there are some C2H CMDs have been sent
+         * before system interrupt is enabled, e.g., C2H, CPWM.
+         * So we need to clear all C2H events that FW has notified,
+         * otherwise FW won't schedule any commands anymore.
+         */
+	rtwn_write_1(sc, 0x01AF, 0);
+        /*enable system interrupt*/
+	rtwn_write_4(sc, 0x0058, 0xC0);
+}
+
+void
+r88ee_start_xfers(struct rtwn_softc *sc)
+{
+	rtwn_write_4(sc, 0x00B0, 0x200084ff);
+	rtwn_write_4(sc, 0x00B8, 0x100);
+	rtwn_write_1(sc, 0x01AF, 0x0);
+	rtwn_write_4(sc, 0x0058, 0xc0);
+}
+
+#undef R88EE_INT_ENABLE
diff --git a/sys/dev/rtwn/rtl8188e/pci/r88ee_tx.c b/sys/dev/rtwn/rtl8188e/pci/r88ee_tx.c
new file mode 100644
index 00000000000..62f055ae279
--- /dev/null
+++ b/sys/dev/rtwn/rtl8188e/pci/r88ee_tx.c
@@ -0,0 +1,111 @@
+/*	$OpenBSD: if_rtwn.c,v 1.6 2015/08/28 00:03:53 deraadt Exp $	*/
+
+/*-
+ * Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
+ * Copyright (c) 2015 Stefan Sperling <stsp@openbsd.org>
+ * Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
+ * Copyright (c) 2018 Farhan Khan <khanzf@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_wlan.h"
+
+#include <sys/param.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/mbuf.h>
+#include <sys/kernel.h>
+#include <sys/socket.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/queue.h>
+#include <sys/taskqueue.h>
+#include <sys/bus.h>
+#include <sys/endian.h>
+#include <sys/linker.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/rman.h>
+
+#include <net/if.h>
+#include <net/ethernet.h>
+#include <net/if_media.h>
+
+#include <net80211/ieee80211_var.h>
+#include <net80211/ieee80211_radiotap.h>
+
+#include <dev/rtwn/if_rtwnvar.h>
+#include <dev/rtwn/if_rtwn_debug.h>
+
+#include <dev/rtwn/pci/rtwn_pci_var.h>
+
+#include <dev/rtwn/rtl8188e/pci/r88ee.h>
+#include <dev/rtwn/rtl8188e/pci/r88ee_tx_desc.h>
+
+
+void
+r88ee_setup_tx_desc(struct rtwn_pci_softc *pc, void *desc,
+    uint32_t next_desc_addr)
+{
+	struct r88ee_tx_desc *txd = desc;
+
+	/* setup tx desc */
+	txd->nextdescaddr = htole32(next_desc_addr);
+}
+
+void
+r88ee_tx_postsetup(struct rtwn_pci_softc *pc, void *desc,
+    bus_dma_segment_t segs[])
+{
+	/* Not implemented */
+}
+
+void
+r88ee_copy_tx_desc(void *dest, const void *src)
+{
+	struct r88ee_tx_desc *txd = dest;
+	size_t len = sizeof(struct r92c_tx_desc) +
+	    sizeof(txd->txbufsize) + sizeof(txd->pad);
+
+	if (src != NULL)
+		memcpy(dest, src, len);
+	else
+		memset(dest, 0, len);
+}
+
+void
+r88ee_dump_tx_desc(struct rtwn_softc *sc, const void *desc)
+{
+#ifdef RTWN_DEBUG
+	const struct r88ee_tx_desc *txd = desc;
+
+	RTWN_DPRINTF(sc, RTWN_DEBUG_XMIT_DESC,
+	    "%s: len %d, off %d, flags0 %02X, dw: 1 %08X, 2 %08X, 3 %04X "
+	    "(seq %04X), 4 %08X, 5 %08X, 6 %08X, size %04X, pad %04X, "
+	    "addr: %08X (64: %08X), next: %08X (64: %08X), "
+	    "rsvd: %08X %08X %08X %08X\n",
+	    __func__, le16toh(txd->pktlen), txd->offset, txd->flags0,
+	    le32toh(txd->txdw1), le32toh(txd->txdw2), le16toh(txd->txdw3),
+	    le16toh(txd->txdseq), le32toh(txd->txdw4), le32toh(txd->txdw5),
+	    le32toh(txd->txdw6), le16toh(txd->txbufsize), le16toh(txd->pad),
+	    le32toh(txd->txbufaddr), le32toh(txd->txbufaddr64),
+	    le32toh(txd->nextdescaddr), le32toh(txd->nextdescaddr64),
+	    le32toh(txd->reserved[0]), le32toh(txd->reserved[1]),
+	    le32toh(txd->reserved[2]), le32toh(txd->reserved[3]));
+#endif
+}
diff --git a/sys/dev/rtwn/rtl8188e/pci/r88ee_tx_desc.h b/sys/dev/rtwn/rtl8188e/pci/r88ee_tx_desc.h
new file mode 100644
index 00000000000..980895b7ca2
--- /dev/null
+++ b/sys/dev/rtwn/rtl8188e/pci/r88ee_tx_desc.h
@@ -0,0 +1,56 @@
+/*	$OpenBSD: if_rtwnreg.h,v 1.3 2015/06/14 08:02:47 stsp Exp $	*/
+
+/*-
+ * Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
+ * Copyright (c) 2015 Stefan Sperling <stsp@openbsd.org>
+ * Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
+ * Copyright (c) 2018 Farhan Khan <khanzf@gmail.com>
+ *
+ * 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 R88EE_TX_DESC_H
+#define R88EE_TX_DESC_H
+
+#include <dev/rtwn/rtl8188e/r88e_tx_desc.h>
+
+/* Tx MAC descriptor (PCIe). */
+struct r88ee_tx_desc {
+	uint16_t 	pktlen;
+	uint8_t		offset;
+	uint8_t		flags0;
+
+	uint32_t	txdw1;
+	uint32_t	txdw2;
+	uint16_t	txdw3;
+	uint16_t	txdseq;
+
+	uint32_t	txdw4;
+	uint32_t	txdw5;
+	uint32_t	txdw6;
+
+	uint16_t	txbufsize;
+	uint16_t	pad;
+
+	uint32_t	txbufaddr;
+	uint32_t	txbufaddr64;
+
+	uint32_t	nextdescaddr;
+	uint32_t	nextdescaddr64;
+
+	uint32_t	reserved[4];
+} __packed __attribute__((aligned(4)));
+
+#endif	/* R88EE_TX_DESC_H */
diff --git a/sys/dev/rtwn/rtl8188e/r88e.h b/sys/dev/rtwn/rtl8188e/r88e.h
index 3a3c0865a43..31639563dd5 100644
--- a/sys/dev/rtwn/rtl8188e/r88e.h
+++ b/sys/dev/rtwn/rtl8188e/r88e.h
@@ -50,6 +50,8 @@ uint8_t	r88e_temp_read(struct rtwn_softc *);
 /* r88e_chan.c */
 void	r88e_get_txpower(struct rtwn_softc *, int,
 	    struct ieee80211_channel *, uint8_t[]);
+void	r88ee_get_txpower(struct rtwn_softc *, int,
+	    struct ieee80211_channel *, uint8_t[]);
 void	r88e_set_bw20(struct rtwn_softc *, uint8_t);
 void	r88e_set_gain(struct rtwn_softc *, uint8_t);
 
@@ -58,6 +60,7 @@ void	r88e_set_gain(struct rtwn_softc *, uint8_t);
 int	r88e_fw_cmd(struct rtwn_softc *, uint8_t, const void *, int);
 void	r88e_fw_reset(struct rtwn_softc *, int);
 void	r88e_fw_download_enable(struct rtwn_softc *, int);
+void	r88ee_fw_download_enable(struct rtwn_softc *, int);
 #endif
 void	r88e_macid_enable_link(struct rtwn_softc *, int, int);
 void	r88e_set_media_status(struct rtwn_softc *, int);
@@ -68,8 +71,11 @@ int	r88e_set_pwrmode(struct rtwn_softc *, struct ieee80211vap *, int);
 
 /* r88e_init.c */
 void	r88e_init_bb(struct rtwn_softc *);
+void	r88ee_init_bb(struct rtwn_softc *);
 void	r88e_init_rf(struct rtwn_softc *);
 int	r88e_power_on(struct rtwn_softc *);
+int	r88ee_power_on(struct rtwn_softc *);
+int	r88ee_llt_init(struct rtwn_softc *sc);
 
 /* r88e_led.c */
 void	r88e_set_led(struct rtwn_softc *, int, int);
@@ -79,6 +85,7 @@ void	r88e_rf_write(struct rtwn_softc *, int, uint8_t, uint32_t);
 
 /* r88e_rom.c */
 void	r88e_parse_rom(struct rtwn_softc *, uint8_t *);
+void	r88ee_parse_rom(struct rtwn_softc *, uint8_t *);
 
 /* r88e_rx.c */
 void	r88e_ratectl_tx_complete(struct rtwn_softc *, uint8_t *, int);
diff --git a/sys/dev/rtwn/rtl8188e/r88e_fw.c b/sys/dev/rtwn/rtl8188e/r88e_fw.c
index 4ae4abbda1d..d220baa422a 100644
--- a/sys/dev/rtwn/rtl8188e/r88e_fw.c
+++ b/sys/dev/rtwn/rtl8188e/r88e_fw.c
@@ -130,6 +130,27 @@ r88e_fw_download_enable(struct rtwn_softc *sc, int enable)
 }
 #endif
 
+void
+r88ee_fw_download_enable(struct rtwn_softc *sc, int enable)
+{
+	uint8_t tmp;
+	if (enable) {
+		tmp = rtwn_read_1(sc, R92C_SYS_FUNC_EN+1);
+		rtwn_write_1(sc, R92C_SYS_FUNC_EN+1, tmp | 0x04);
+
+		tmp = rtwn_read_1(sc, R92C_MCUFWDL);
+		rtwn_write_1(sc, R92C_MCUFWDL, tmp | 0x01);
+
+		tmp = rtwn_read_1(sc, R92C_MCUFWDL + 2);
+		rtwn_write_1(sc, R92C_MCUFWDL + 2, tmp & 0xf7);
+	} else {
+		tmp = rtwn_read_1(sc, R92C_MCUFWDL);
+		rtwn_write_1(sc, R92C_MCUFWDL, tmp & 0xfe);
+
+		rtwn_write_1(sc, R92C_MCUFWDL + 1, 0x00);
+	}
+}
+
 void
 r88e_macid_enable_link(struct rtwn_softc *sc, int id, int enable)
 {
@@ -151,7 +172,6 @@ void
 r88e_set_media_status(struct rtwn_softc *sc, int macid)
 {
 	struct r88e_fw_cmd_msrrpt status;
-
 	if (macid & RTWN_MACID_VALID)
 		status.msrb0 = R88E_MSRRPT_B0_ASSOC;
 	else
diff --git a/sys/dev/rtwn/rtl8188e/r88e_init.c b/sys/dev/rtwn/rtl8188e/r88e_init.c
index 202cec154aa..b36c7dfaa7b 100644
--- a/sys/dev/rtwn/rtl8188e/r88e_init.c
+++ b/sys/dev/rtwn/rtl8188e/r88e_init.c
@@ -54,7 +54,7 @@ __FBSDID("$FreeBSD$");
 
 #include <dev/rtwn/rtl8188e/r88e.h>
 #include <dev/rtwn/rtl8188e/r88e_reg.h>
-
+#include <dev/rtwn/rtl8192c/pci/r92ce_reg.h>
 
 static void
 r88e_crystalcap_write(struct rtwn_softc *sc)
@@ -94,6 +94,93 @@ r88e_init_bb(struct rtwn_softc *sc)
 	r88e_crystalcap_write(sc);
 }
 
+int
+r88ee_llt_init(struct rtwn_softc *sc) {
+
+	rtwn_write_1(sc, R92C_RQPN_NPQ, 0x01);
+	rtwn_write_4(sc, R92C_TRXFF_BNDY, 0x80730d29);
+
+	rtwn_write_4(sc, R92C_TRXFF_BNDY, (0x25FF0000 | sc->pktbuf_count));
+	rtwn_write_1(sc, R92C_TDECTRL + 1, sc->pktbuf_count);
+
+	rtwn_write_1(sc, R88E_TXPKTBUF_BCNQ1_BDNY, sc->pktbuf_count);
+	rtwn_write_1(sc, R92C_TXPKTBUF_MGQ_BDNY, sc->pktbuf_count);
+
+	rtwn_write_1(sc, 0x45D, sc->pktbuf_count);
+	rtwn_write_1(sc, R92C_PBP, 0x11);
+	rtwn_write_1(sc, R92C_RX_DRVINFO_SZ, 0x4);
+
+	return r92c_llt_init(sc);
+}
+
+void
+r88ee_init_bb(struct rtwn_softc *sc)
+{
+	uint32_t tmp;
+	int i, j;
+
+	rtwn_setbits_2(sc, R92C_SYS_FUNC_EN, 0,
+		R92C_SYS_FUNC_EN_BBRSTB | R92C_SYS_FUNC_EN_BB_GLB_RST |
+		R92C_SYS_FUNC_EN_DIO_RF);
+
+	rtwn_write_1(sc, R92C_RF_CTRL,
+		R92C_RF_CTRL_EN | R92C_RF_CTRL_RSTB | R92C_RF_CTRL_SDMRSTB);
+
+	rtwn_write_1(sc, R92C_SYS_FUNC_EN, R92C_SYS_FUNC_EN_PPLL | R92C_SYS_FUNC_EN_PCIEA |
+		R92C_SYS_FUNC_EN_DIO_PCIE |
+		R92C_SYS_FUNC_EN_BB_GLB_RST | R92C_SYS_FUNC_EN_BBRSTB);
+
+	tmp = rtwn_read_4(sc, 0x4c);
+	rtwn_write_4(sc, 0x4c, tmp | 0xff7fffff);
+
+	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);
+		}
+	}
+
+	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_setbits(sc, R92C_FPGA0_RFMOD, 0x1000000, 0);
+	rtwn_bb_setbits(sc, R92C_FPGA0_RFMOD, 0x2000000, 0);
+
+}
+
 int
 r88e_power_on(struct rtwn_softc *sc)
 {
diff --git a/sys/dev/rtwn/rtl8188e/r88e_rom.c b/sys/dev/rtwn/rtl8188e/r88e_rom.c
index b12d7db83d4..2831bac7ed0 100644
--- a/sys/dev/rtwn/rtl8188e/r88e_rom.c
+++ b/sys/dev/rtwn/rtl8188e/r88e_rom.c
@@ -82,4 +82,34 @@ r88e_parse_rom(struct rtwn_softc *sc, uint8_t *buf)
 
 	sc->thermal_meter = rom->thermal_meter;
 	IEEE80211_ADDR_COPY(sc->sc_ic.ic_macaddr, rom->macaddr);
+
+}
+
+void
+r88ee_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 r88ee_rom *rom = (struct r88ee_rom *)buf;
+	int i;
+
+	rt->bw20_tx_pwr_diff = RTWN_SIGN4TO8(MS(rom->rfpath[0].rfpath_24g.bw20_ofdm, HIGH_PART));
+	rt->ofdm_tx_pwr_diff = RTWN_SIGN4TO8(MS(rom->rfpath[0].rfpath_24g.bw20_ofdm, LOW_PART));
+
+	for(i = 0; i < R88E_GROUP_2G; i++)
+		rt->cck_tx_pwr[i] = rom->rfpath[0].rfpath_24g.index_cck_base[i];
+	for(i = 0; i < R88E_GROUP_2G - 1; i++)
+		rt->ht40_tx_pwr[i] = rom->rfpath[0].rfpath_24g.index_bw40_base[i];
+
+	rs->board_type =
+		MS(RTWN_GET_ROM_VAR(rom->rf_board_opt, R92C_BOARD_TYPE_DONGLE),
+		R92C_ROM_RF1_BOARD_TYPE);
+	rs->regulatory = MS(rom->rf_board_opt, R92C_ROM_RF1_REGULATORY);
+
+	rt->bw20_tx_pwr_diff = 0;
+	rt->ofdm_tx_pwr_diff = 0;
+
+	rtwn_r92c_set_name(sc);
+
+	IEEE80211_ADDR_COPY(sc->sc_ic.ic_macaddr, rom->macaddr);
 }
diff --git a/sys/dev/rtwn/rtl8188e/r88e_rom_image.h b/sys/dev/rtwn/rtl8188e/r88e_rom_image.h
index c80028e00d6..c491f677ab9 100644
--- a/sys/dev/rtwn/rtl8188e/r88e_rom_image.h
+++ b/sys/dev/rtwn/rtl8188e/r88e_rom_image.h
@@ -57,4 +57,71 @@ struct r88e_rom {
 _Static_assert(sizeof(struct r88e_rom) == R88E_EFUSE_MAP_LEN,
     "R88E_EFUSE_MAP_LEN must be equal to sizeof(struct r88e_rom)!");
 
+/*
+ * RTL8188EE ROM image.
+ * Largely derived from this:
+ * http://src.illumos.org/source/xref/linux-master/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.c#1576
+ */
+
+struct _bw40_bw20_ofdm_cck {
+	uint8_t				bw40:4;
+	uint8_t				bw20:4;
+	uint8_t				ofdm:4;
+	uint8_t				cck:4;
+} __packed;
+
+struct _r88ee_rom_24g {
+	uint8_t				index_cck_base[6];
+	uint8_t				index_bw40_base[6-1];
+	uint8_t				bw20_ofdm;
+	struct _bw40_bw20_ofdm_cck	bw40_bw20_ofdm_cck[4-1];
+} __packed;
+
+struct _r88ee_rom_5g {
+	uint8_t				index_bw40_base[14];
+	uint8_t				bw20_ofdm;
+	uint8_t				bw40_bw20[4-1];
+	uint8_t				ofdm_1[2];
+} __packed;
+
+struct _r88ee_rf_path {
+	struct _r88ee_rom_24g		rfpath_24g;
+	struct _r88ee_rom_5g		rfpath_5g;
+} __packed;
+
+struct r88ee_rom {
+	uint16_t			id; /* Always 0x8129 */
+
+	uint8_t				hpon[4];
+	uint16_t			clk;
+	uint8_t				testr[8];
+
+	struct _r88ee_rf_path		rfpath[4];
+
+	uint8_t				unknown3[16];
+	uint16_t			channel_plan;
+	uint8_t				xtal;
+	uint8_t				thermal_meter;
+	uint8_t				unknown4[5];
+	uint8_t				rf_board_opt;
+	uint8_t				rf_feature_opt;
+	uint8_t				rf_bt_setting;
+	uint8_t				version;
+	uint8_t				customer_id;
+	uint8_t				reserved1[3];
+	uint8_t				rf_antenna_opt;
+
+	uint8_t				reserved2[6];
+	uint8_t				macaddr[IEEE80211_ADDR_LEN];
+	uint16_t			vid;
+	uint16_t			did;
+	uint16_t			svid;
+	uint16_t			smid;
+
+	uint8_t				unknown5[290];
+} __packed; // Should be 512 byte
+
+_Static_assert(sizeof(struct r88ee_rom) == R88E_EFUSE_MAP_LEN,
+    "R88EE_EFUSE_MAP_LEN must be equal to sizeof(struct r88ee_rom)!");
+
 #endif	/* R88E_ROM_IMAGE_H */
diff --git a/sys/modules/rtwn_pci/Makefile b/sys/modules/rtwn_pci/Makefile
index 730991eedcd..e8110173670 100644
--- a/sys/modules/rtwn_pci/Makefile
+++ b/sys/modules/rtwn_pci/Makefile
@@ -17,6 +17,12 @@ SRCS	+= r92ce_attach.c r92ce_calib.c r92ce_fw.c r92ce_init.c r92ce_led.c \
 	   r92ce_rx.c r92ce_tx.c \
 	   r92ce.h r92ce_priv.h r92ce_reg.h r92ce_rx_desc.h r92ce_tx_desc.h
 
+.PATH: ${.SRCTOP}/sys/dev/rtwn/rtl8188e/pci
+SRCS    += r88ee_attach.c r88ee_calib.c r88ee_init.c \
+	   r88ee_tx.c r88ee_pwrseq.c r88ee_rx.c r88ee_rf.c \
+	   r88ee.h r88ee_priv.h r88ee_reg.h r88ee_tx_desc.h \
+	   r88ee_pwrseq.h
+
 opt_rtwn.h:
 	@echo "#define RTWN_DEBUG 1" > ${.TARGET}
 .if ${MK_SOURCELESS_UCODE} == "no"
diff --git a/sys/modules/rtwnfw/Makefile b/sys/modules/rtwnfw/Makefile
index fe606bb25e5..be6eb0df6e0 100644
--- a/sys/modules/rtwnfw/Makefile
+++ b/sys/modules/rtwnfw/Makefile
@@ -1,6 +1,6 @@
 # $FreeBSD$
 
 SUBDIR=	rtwnrtl8188eu rtwnrtl8192cT rtwnrtl8192cU rtwnrtl8192eu rtwnrtl8812au \
-	rtwnrtl8821au rtwnrtl8192cE rtwnrtl8192cEB
+	rtwnrtl8821au rtwnrtl8192cE rtwnrtl8192cEB rtwnrtl8188ee
 
 .include <bsd.subdir.mk>
diff --git a/sys/modules/rtwnfw/rtwnrtl8188ee/Makefile b/sys/modules/rtwnfw/rtwnrtl8188ee/Makefile
new file mode 100644
index 00000000000..8464ab39fdf
--- /dev/null
+++ b/sys/modules/rtwnfw/rtwnrtl8188ee/Makefile
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+KMOD=	rtwn-rtl8188eefw
+IMG=	rtwn-rtl8188eefw
+
+.include <bsd.kmod.mk>

Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAFd4kYBbewOa1ZOYer=R%2BJ%2BXHSzNbETJo_AQocyGcpi4JxzqRA>