Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 6 Jun 2018 20:29:31 -0400
From:      Farhan Khan <khanzf@gmail.com>
To:        freebsd-wireless@freebsd.org
Subject:   Re: RTL8188EE monitor mode patch
Message-ID:  <CAFd4kYAd9DM6OrCaU_%2Bnb=X341M%2BeHEsQGpnteo8OWPfsT06RA@mail.gmail.com>
In-Reply-To: <CAFd4kYBbewOa1ZOYer=R%2BJ%2BXHSzNbETJo_AQocyGcpi4JxzqRA@mail.gmail.com>
References:  <CAFd4kYBbewOa1ZOYer=R%2BJ%2BXHSzNbETJo_AQocyGcpi4JxzqRA@mail.gmail.com>

next in thread | previous in thread | raw e-mail | index | archive | help
On Wed, Jun 6, 2018 at 8:11 PM, Farhan Khan <khanzf@gmail.com> wrote:
> 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

Sincere apologies, I sent it as an attachment, not just the text. Please
see below.
----

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?CAFd4kYAd9DM6OrCaU_%2Bnb=X341M%2BeHEsQGpnteo8OWPfsT06RA>