@@ -1,9 +1,10 @@
-/* $NetBSD: if_urtwn.c,v 1.48 2016/10/12 02:56:45 nat Exp $ */
+/* $NetBSD: if_urtwn.c,v 1.49 2016/10/12 03:23:29 nat Exp $ */
/* $OpenBSD: if_urtwn.c,v 1.42 2015/02/10 23:25:46 mpi Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
+ * Copyright (c) 2016 Nathanial Sloss <nathanialsloss@yahoo.com.au>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -19,11 +20,12 @@
*/
/*-
- * Driver for Realtek RTL8188CE-VAU/RTL8188CUS/RTL8188EU/RTL8188RU/RTL8192CU.
+ * Driver for Realtek RTL8188CE-VAU/RTL8188CUS/RTL8188EU/RTL8188RU/RTL8192CU
+ * RTL8192EU.
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_urtwn.c,v 1.48 2016/10/12 02:56:45 nat Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_urtwn.c,v 1.49 2016/10/12 03:23:29 nat Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -99,10 +101,13 @@
#define URTWN_DEV(v,p) { { USB_VENDOR_##v, USB_PRODUCT_##v##_##p }, 0 }
#define URTWN_RTL8188E_DEV(v,p) \
{ { USB_VENDOR_##v, USB_PRODUCT_##v##_##p }, FLAG_RTL8188E }
+#define URTWN_RTL8192EU_DEV(v,p) \
+ { { USB_VENDOR_##v, USB_PRODUCT_##v##_##p }, FLAG_RTL8192E }
static const struct urtwn_dev {
struct usb_devno dev;
uint32_t flags;
#define FLAG_RTL8188E __BIT(0)
+#define FLAG_RTL8192E __BIT(1)
} urtwn_devs[] = {
URTWN_DEV(ABOCOM, RTL8188CU_1),
URTWN_DEV(ABOCOM, RTL8188CU_2),
@@ -184,9 +189,13 @@
URTWN_RTL8188E_DEV(ELECOM, WDC150SU2M),
URTWN_RTL8188E_DEV(REALTEK, RTL8188ETV),
URTWN_RTL8188E_DEV(REALTEK, RTL8188EU),
+
+ /* URTWN_RTL8192EU */
+ URTWN_RTL8192EU_DEV(REALTEK, RTL8192EU),
};
#undef URTWN_DEV
#undef URTWN_RTL8188E_DEV
+#undef URTWN_RTL8192EU_DEV
static int urtwn_match(device_t, cfdata_t, void *);
static void urtwn_attach(device_t, device_t, void *);
@@ -223,6 +232,8 @@
uint32_t);
static void urtwn_r88e_rf_write(struct urtwn_softc *, int, uint8_t,
uint32_t);
+static void urtwn_r92e_rf_write(struct urtwn_softc *, int, uint8_t,
+ uint32_t);
static uint32_t urtwn_rf_read(struct urtwn_softc *, int, uint8_t);
static int urtwn_llt_write(struct urtwn_softc *, uint32_t, uint32_t);
static uint8_t urtwn_efuse_read_1(struct urtwn_softc *, uint16_t);
@@ -262,6 +273,7 @@
static void urtwn_watchdog(struct ifnet *);
static int urtwn_ioctl(struct ifnet *, u_long, void *);
static int urtwn_r92c_power_on(struct urtwn_softc *);
+static int urtwn_r92e_power_on(struct urtwn_softc *);
static int urtwn_r88e_power_on(struct urtwn_softc *);
static int urtwn_llt_init(struct urtwn_softc *);
static void urtwn_fw_reset(struct urtwn_softc *);
@@ -293,6 +305,7 @@
static int urtwn_reset(struct ifnet *);
static void urtwn_chip_stop(struct urtwn_softc *);
static void urtwn_newassoc(struct ieee80211_node *, int);
+static void urtwn_delay_ms(struct urtwn_softc *, int ms);
/* Aliases. */
#define urtwn_bb_write urtwn_write_4
@@ -313,8 +326,8 @@
{
struct usb_attach_arg *uaa = aux;
- return urtwn_lookup(urtwn_devs, uaa->uaa_vendor, uaa->uaa_product) != NULL ?
- UMATCH_VENDOR_PRODUCT : UMATCH_NONE;
+ return urtwn_lookup(urtwn_devs, uaa->uaa_vendor, uaa->uaa_product) !=
+ NULL ? UMATCH_VENDOR_PRODUCT : UMATCH_NONE;
}
static void
@@ -337,6 +350,8 @@
dev = urtwn_lookup(urtwn_devs, uaa->uaa_vendor, uaa->uaa_product);
if (dev != NULL && ISSET(dev->flags, FLAG_RTL8188E))
SET(sc->chip, URTWN_CHIP_88E);
+ if (dev != NULL && ISSET(dev->flags, FLAG_RTL8192E))
+ SET(sc->chip, URTWN_CHIP_92EU);
aprint_naive("\n");
aprint_normal("\n");
@@ -357,6 +372,7 @@
mutex_init(&sc->sc_task_mtx, MUTEX_DEFAULT, IPL_NET);
mutex_init(&sc->sc_tx_mtx, MUTEX_DEFAULT, IPL_NONE);
+ mutex_init(&sc->sc_rx_mtx, MUTEX_DEFAULT, IPL_NONE);
mutex_init(&sc->sc_fwcmd_mtx, MUTEX_DEFAULT, IPL_NONE);
mutex_init(&sc->sc_write_mtx, MUTEX_DEFAULT, IPL_NONE);
@@ -391,17 +407,22 @@
if (sc->chip & URTWN_CHIP_92C) {
sc->ntxchains = (sc->chip & URTWN_CHIP_92C_1T2R) ? 1 : 2;
sc->nrxchains = 2;
+ } else if (sc->chip & URTWN_CHIP_92EU) {
+ sc->ntxchains = 2;
+ sc->nrxchains = 2;
} else {
sc->ntxchains = 1;
sc->nrxchains = 1;
}
- if (ISSET(sc->chip, URTWN_CHIP_88E))
+ if (ISSET(sc->chip, URTWN_CHIP_88E) ||
+ ISSET(sc->chip, URTWN_CHIP_92EU))
urtwn_r88e_read_rom(sc);
else
urtwn_read_rom(sc);
aprint_normal_dev(self, "MAC/BB RTL%s, RF 6052 %zdT%zdR, address %s\n",
+ (sc->chip & URTWN_CHIP_92EU) ? "8192EU" :
(sc->chip & URTWN_CHIP_92C) ? "8192CU" :
(sc->chip & URTWN_CHIP_88E) ? "8188EU" :
(sc->board_type == R92C_BOARD_TYPE_HIGHPA) ? "8188RU" :
@@ -539,6 +560,7 @@
mutex_destroy(&sc->sc_write_mtx);
mutex_destroy(&sc->sc_fwcmd_mtx);
mutex_destroy(&sc->sc_tx_mtx);
+ mutex_destroy(&sc->sc_rx_mtx);
mutex_destroy(&sc->sc_task_mtx);
return 0;
@@ -564,10 +586,11 @@
urtwn_open_pipes(struct urtwn_softc *sc)
{
/* Bulk-out endpoints addresses (from highest to lowest prio). */
- static const uint8_t epaddr[] = { 0x02, 0x03, 0x05 };
+ static uint8_t epaddr[3];
+ static uint8_t rxepaddr[3];
usb_interface_descriptor_t *id;
usb_endpoint_descriptor_t *ed;
- size_t i, ntx = 0;
+ size_t i, ntx = 0, nrx = 0;
int error;
DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
@@ -578,8 +601,16 @@
ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i);
if (ed != NULL &&
UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK &&
- UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT)
+ UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT) {
+ epaddr[ntx] = ed->bEndpointAddress;
ntx++;
+ }
+ if (ed != NULL &&
+ UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK &&
+ UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN) {
+ rxepaddr[nrx] = ed->bEndpointAddress;
+ nrx++;
+ }
}
DPRINTFN(DBG_INIT, ("%s: %s: found %zd bulk-out pipes\n",
device_xname(sc->sc_dev), __func__, ntx));
@@ -588,16 +619,19 @@
"%zd: invalid number of Tx bulk pipes\n", ntx);
return EIO;
}
- sc->rx_npipe = 1;
+ sc->rx_npipe = nrx;
sc->tx_npipe = ntx;
/* Open bulk-in pipe at address 0x81. */
- error = usbd_open_pipe(sc->sc_iface, 0x81, USBD_EXCLUSIVE_USE,
- &sc->rx_pipe);
- if (error != 0) {
- aprint_error_dev(sc->sc_dev, "could not open Rx bulk pipe"
- ": %d\n", error);
- goto fail;
+ for (i = 0; i < nrx; i++) {
+ error = usbd_open_pipe(sc->sc_iface, rxepaddr[i],
+ USBD_EXCLUSIVE_USE, &sc->rx_pipe[i]);
+ if (error != 0) {
+ aprint_error_dev(sc->sc_dev,
+ "could not open Rx bulk pipe 0x%02x: %d\n",
+ rxepaddr[i], error);
+ goto fail;
+ }
}
/* Open bulk-out pipes (up to 3). */
@@ -632,14 +666,17 @@
DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
- /* Close Rx pipe. */
+ /* Close Rx pipes. */
CTASSERT(sizeof(pipe) == sizeof(void *));
- pipe = atomic_swap_ptr(&sc->rx_pipe, NULL);
- if (pipe != NULL) {
- usbd_close_pipe(pipe);
+ for (i = 0; i < sc->rx_npipe; i++) {
+ pipe = atomic_swap_ptr(&sc->rx_pipe[i], NULL);
+ if (pipe != NULL) {
+ usbd_close_pipe(pipe);
+ }
}
+
/* Close Tx pipes. */
- for (i = 0; i < R92C_MAX_EPOUT; i++) {
+ for (i = 0; i < sc->tx_npipe; i++) {
pipe = atomic_swap_ptr(&sc->tx_pipe[i], NULL);
if (pipe != NULL) {
usbd_close_pipe(pipe);
@@ -656,20 +693,24 @@
DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
- for (i = 0; i < URTWN_RX_LIST_COUNT; i++) {
- data = &sc->rx_data[i];
+ for (size_t j = 0; j < sc->rx_npipe; j++) {
+ TAILQ_INIT(&sc->rx_free_list[j]);
+ for (i = 0; i < URTWN_RX_LIST_COUNT; i++) {
+ data = &sc->rx_data[j][i];
- data->sc = sc; /* Backpointer for callbacks. */
+ data->sc = sc; /* Backpointer for callbacks. */
- error = usbd_create_xfer(sc->rx_pipe, URTWN_RXBUFSZ,
- USBD_SHORT_XFER_OK, 0, &data->xfer);
- if (error) {
- aprint_error_dev(sc->sc_dev,
- "could not allocate xfer\n");
- break;
- }
+ error = usbd_create_xfer(sc->rx_pipe[j], URTWN_RXBUFSZ,
+ USBD_SHORT_XFER_OK, 0, &data->xfer);
+ if (error) {
+ aprint_error_dev(sc->sc_dev,
+ "could not allocate xfer\n");
+ break;
+ }
- data->buf = usbd_get_buffer(data->xfer);
+ data->buf = usbd_get_buffer(data->xfer);
+ TAILQ_INSERT_TAIL(&sc->rx_free_list[j], data, next);
+ }
}
if (error != 0)
urtwn_free_rx_list(sc);
@@ -685,11 +726,13 @@
DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
/* NB: Caller must abort pipe first. */
- for (i = 0; i < URTWN_RX_LIST_COUNT; i++) {
- CTASSERT(sizeof(xfer) == sizeof(void *));
- xfer = atomic_swap_ptr(&sc->rx_data[i].xfer, NULL);
- if (xfer != NULL)
- usbd_destroy_xfer(xfer);
+ for (size_t j = 0; j < sc->rx_npipe; j++) {
+ for (i = 0; i < URTWN_RX_LIST_COUNT; i++) {
+ CTASSERT(sizeof(xfer) == sizeof(void *));
+ xfer = atomic_swap_ptr(&sc->rx_data[j][i].xfer, NULL);
+ if (xfer != NULL)
+ usbd_destroy_xfer(xfer);
+ }
}
}
@@ -977,7 +1020,7 @@
for (ntries = 0; ntries < 100; ntries++) {
if (!(urtwn_read_1(sc, R92C_HMETFR) & (1 << fwcur)))
break;
- DELAY(1);
+ DELAY(10);
}
if (ntries == 100) {
aprint_error_dev(sc->sc_dev,
@@ -991,13 +1034,23 @@
/* Write the first word last since that will trigger the FW. */
cp = (uint8_t *)&cmd;
+ cmd.id = id;
if (len >= 4) {
- cmd.id = id | R92C_CMD_FLAG_EXT;
- urtwn_write_region(sc, R92C_HMEBOX_EXT(fwcur), &cp[1], 2);
- urtwn_write_4(sc, R92C_HMEBOX(fwcur),
- cp[0] + (cp[3] << 8) + (cp[4] << 16) + (cp[5] << 24));
+ if (!ISSET(sc->chip, URTWN_CHIP_92EU)) {
+ cmd.id |= R92C_CMD_FLAG_EXT;
+ urtwn_write_region(sc, R92C_HMEBOX_EXT(fwcur),
+ &cp[1], 2);
+ urtwn_write_4(sc, R92C_HMEBOX(fwcur),
+ cp[0] + (cp[3] << 8) + (cp[4] << 16) +
+ (cp[5] << 24));
+ } else {
+ urtwn_write_region(sc, R92E_HMEBOX_EXT(fwcur),
+ &cp[4], 2);
+ urtwn_write_4(sc, R92C_HMEBOX(fwcur),
+ cp[0] + (cp[1] << 8) + (cp[2] << 16) +
+ (cp[3] << 24));
+ }
} else {
- cmd.id = id;
urtwn_write_region(sc, R92C_HMEBOX(fwcur), cp, len);
}
@@ -1029,6 +1082,15 @@
SM(R88E_LSSI_PARAM_ADDR, addr) | SM(R92C_LSSI_PARAM_DATA, val));
}
+static void
+urtwn_r92e_rf_write(struct urtwn_softc *sc, int chain, uint8_t addr,
+ uint32_t val)
+{
+
+ urtwn_bb_write(sc, R92C_LSSI_PARAM(chain),
+ SM(R88E_LSSI_PARAM_ADDR, addr) | SM(R92C_LSSI_PARAM_DATA, val));
+}
+
static uint32_t
urtwn_rf_read(struct urtwn_softc *sc, int chain, uint8_t addr)
{
@@ -1184,7 +1246,8 @@
DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
- if (ISSET(sc->chip, URTWN_CHIP_88E))
+ if (ISSET(sc->chip, URTWN_CHIP_88E) ||
+ ISSET(sc->chip, URTWN_CHIP_92EU))
return 0;
reg = urtwn_read_4(sc, R92C_SYS_CFG);
@@ -1349,7 +1412,7 @@
/* Read full ROM image. */
memset(&sc->r88e_rom, 0xff, sizeof(sc->r88e_rom));
- while (addr < 1024) {
+ while (addr < 4096) {
reg = urtwn_efuse_read_1(sc, addr);
if (reg == 0xff)
break;
@@ -1392,8 +1455,13 @@
IEEE80211_ADDR_COPY(ic->ic_myaddr, &sc->r88e_rom[0xd7]);
- sc->sc_rf_write = urtwn_r88e_rf_write;
- sc->sc_power_on = urtwn_r88e_power_on;
+ if (ISSET(sc->chip, URTWN_CHIP_92EU)) {
+ sc->sc_power_on = urtwn_r92e_power_on;
+ sc->sc_rf_write = urtwn_r92e_rf_write;
+ } else {
+ sc->sc_power_on = urtwn_r88e_power_on;
+ sc->sc_rf_write = urtwn_r88e_rf_write;
+ }
sc->sc_dma_init = urtwn_r88e_dma_init;
mutex_exit(&sc->sc_write_mtx);
@@ -1433,7 +1501,7 @@
struct ieee80211_rateset *rs = &ni->ni_rates;
struct r92c_fw_cmd_macid_cfg cmd;
uint32_t rates, basicrates;
- uint32_t mask;
+ uint32_t mask, rrsr_mask, rrsr_rate;
uint8_t mode;
size_t maxrate, maxbasicrate, i, j;
int error;
@@ -1443,7 +1511,7 @@
KASSERT(mutex_owned(&sc->sc_write_mtx));
/* Get normal and basic rates mask. */
- rates = basicrates = 0;
+ rates = basicrates = 1;
maxrate = maxbasicrate = 0;
for (i = 0; i < rs->rs_nrates; i++) {
/* Convert 802.11 rate to HW rate index. */
@@ -1478,12 +1546,17 @@
"maxrate=%zx, maxbasicrate=%zx\n",
device_xname(sc->sc_dev), __func__, mode, rates, basicrates,
maxrate, maxbasicrate));
- if (basicrates == 0) {
- basicrates |= 1; /* add 1Mbps */
+
+ if (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE) {
+ maxbasicrate |= R92C_RATE_SHORTGI;
+ maxrate |= R92C_RATE_SHORTGI;
}
/* Set rates mask for group addressed frames. */
cmd.macid = URTWN_MACID_BC | URTWN_MACID_VALID;
+ if (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE)
+ cmd.macid |= URTWN_MACID_SHORTGI;
+
mask = (mode << 28) | basicrates;
cmd.mask[0] = (uint8_t)mask;
cmd.mask[1] = (uint8_t)(mask >> 8);
@@ -1502,6 +1575,9 @@
/* Set rates mask for unicast frames. */
cmd.macid = URTWN_MACID_BSS | URTWN_MACID_VALID;
+ if (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE)
+ cmd.macid |= URTWN_MACID_SHORTGI;
+
mask = (mode << 28) | rates;
cmd.mask[0] = (uint8_t)mask;
cmd.mask[1] = (uint8_t)(mask >> 8);
@@ -1517,6 +1593,13 @@
__func__, maxrate));
urtwn_write_1(sc, R92C_INIDATA_RATE_SEL(URTWN_MACID_BSS), maxrate);
+ rrsr_rate = ic->ic_fixed_rate;
+ if (rrsr_rate == -1)
+ rrsr_rate = 11;
+
+ rrsr_mask = 0xffff >> (15 - rrsr_rate);
+ urtwn_write_2(sc, R92C_RRSR, rrsr_mask);
+
/* Indicate highest supported rate. */
ni->ni_txrate = rs->rs_nrates - 1;
@@ -1603,7 +1686,17 @@
KASSERT(mutex_owned(&sc->sc_write_mtx));
if (led == URTWN_LED_LINK) {
- if (ISSET(sc->chip, URTWN_CHIP_88E)) {
+ if (ISSET(sc->chip, URTWN_CHIP_92EU)) {
+ urtwn_write_1(sc, 0x64, urtwn_read_1(sc, 0x64) & 0xfe);
+ reg = urtwn_read_1(sc, R92C_LEDCFG1) & R92E_LEDSON;
+ urtwn_write_1(sc, R92C_LEDCFG1, reg |
+ (R92C_LEDCFG0_DIS << 1));
+ if (on) {
+ reg = urtwn_read_1(sc, R92C_LEDCFG1) &
+ R92E_LEDSON;
+ urtwn_write_1(sc, R92C_LEDCFG1, reg);
+ }
+ } else if (ISSET(sc->chip, URTWN_CHIP_88E)) {
reg = urtwn_read_1(sc, R92C_LEDCFG2) & 0xf0;
urtwn_write_1(sc, R92C_LEDCFG2, reg | 0x60);
if (!on) {
@@ -1644,6 +1737,7 @@
urtwn_calib_to_cb(struct urtwn_softc *sc, void *arg)
{
struct r92c_fw_cmd_rssi cmd;
+ struct r92e_fw_cmd_rssi cmde;
DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
@@ -1654,11 +1748,20 @@
if (sc->avg_pwdb != -1) {
/* Indicate Rx signal strength to FW for rate adaptation. */
memset(&cmd, 0, sizeof(cmd));
+ memset(&cmde, 0, sizeof(cmde));
cmd.macid = 0; /* BSS. */
+ cmde.macid = 0; /* BSS. */
cmd.pwdb = sc->avg_pwdb;
+ cmde.pwdb = sc->avg_pwdb;
DPRINTFN(DBG_RF, ("%s: %s: sending RSSI command avg=%d\n",
device_xname(sc->sc_dev), __func__, sc->avg_pwdb));
- urtwn_fw_cmd(sc, R92C_CMD_RSSI_SETTING, &cmd, sizeof(cmd));
+ if (!ISSET(sc->chip, URTWN_CHIP_92EU)) {
+ urtwn_fw_cmd(sc, R92C_CMD_RSSI_SETTING, &cmd,
+ sizeof(cmd));
+ } else {
+ urtwn_fw_cmd(sc, R92E_CMD_RSSI_REPORT, &cmde,
+ sizeof(cmde));
+ }
}
/* Do temperature compensation. */
@@ -1863,20 +1966,12 @@
case IEEE80211_S_AUTH:
/* Set initial gain under link. */
reg = urtwn_bb_read(sc, R92C_OFDM0_AGCCORE1(0));
-#ifdef doaslinux
reg = RW(reg, R92C_OFDM0_AGCCORE1_GAIN, 0x32);
-#else
- reg = RW(reg, R92C_OFDM0_AGCCORE1_GAIN, 0x20);
-#endif
urtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(0), reg);
if (!ISSET(sc->chip, URTWN_CHIP_88E)) {
reg = urtwn_bb_read(sc, R92C_OFDM0_AGCCORE1(1));
-#ifdef doaslinux
reg = RW(reg, R92C_OFDM0_AGCCORE1_GAIN, 0x32);
-#else
- reg = RW(reg, R92C_OFDM0_AGCCORE1_GAIN, 0x20);
-#endif
urtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(1), reg);
}
@@ -1994,7 +2089,8 @@
urtwn_write_1(sc, R92C_T2T_SIFS + 1, sifs_time);
/* Intialize rate adaptation. */
- if (ISSET(sc->chip, URTWN_CHIP_88E))
+ if (ISSET(sc->chip, URTWN_CHIP_88E) ||
+ ISSET(sc->chip, URTWN_CHIP_92EU))
ni->ni_txrate = ni->ni_rates.rs_nrates - 1;
else
urtwn_ra_init(sc);
@@ -2252,7 +2348,7 @@
/* Get RSSI from PHY status descriptor if present. */
if (infosz != 0 && (rxdw0 & R92C_RXDW0_PHYST)) {
- if (ISSET(sc->chip, URTWN_CHIP_88E))
+ if (!ISSET(sc->chip, URTWN_CHIP_92C))
rssi = urtwn_r88e_get_rssi(sc, rate, &stat[1]);
else
rssi = urtwn_get_rssi(sc, rate, &stat[1]);
@@ -2338,6 +2434,7 @@
struct urtwn_rx_data *data = priv;
struct urtwn_softc *sc = data->sc;
struct r92c_rx_stat *stat;
+ size_t pidx = data->pidx;
uint32_t rxdw0;
uint8_t *buf;
int len, totlen, pktlen, infosz, npkts;
@@ -2345,9 +2442,15 @@
DPRINTFN(DBG_FN|DBG_RX, ("%s: %s: status=%d\n",
device_xname(sc->sc_dev), __func__, status));
+ mutex_enter(&sc->sc_rx_mtx);
+ TAILQ_REMOVE(&sc->rx_free_list[pidx], data, next);
+ TAILQ_INSERT_TAIL(&sc->rx_free_list[pidx], data, next);
+ /* Put this Rx buffer back to our free list. */
+ mutex_exit(&sc->sc_rx_mtx);
+
if (__predict_false(status != USBD_NORMAL_COMPLETION)) {
if (status == USBD_STALLED)
- usbd_clear_endpoint_stall_async(sc->rx_pipe);
+ usbd_clear_endpoint_stall_async(sc->rx_pipe[pidx]);
else if (status != USBD_CANCELLED)
goto resubmit;
return;
@@ -2439,6 +2542,7 @@
struct usbd_pipe *pipe = sc->tx_pipe[pidx];
usbd_clear_endpoint_stall_async(pipe);
}
+ printf("ERROR1\n");
ifp->if_oerrors++;
}
splx(s);
@@ -2447,8 +2551,8 @@
ifp->if_opackets++;
urtwn_start(ifp);
-
splx(s);
+
}
static int
@@ -2459,7 +2563,7 @@
struct ieee80211_frame *wh;
struct ieee80211_key *k = NULL;
struct r92c_tx_desc *txd;
- size_t i, padsize, xferlen;
+ size_t i, padsize, xferlen, txd_len;
uint16_t seq, sum;
uint8_t raid, type, tid;
int s, hasqos, error;
@@ -2468,7 +2572,11 @@
wh = mtod(m, struct ieee80211_frame *);
type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
+ txd_len = sizeof(*txd);
+ if (!ISSET(sc->chip, URTWN_CHIP_92EU))
+ txd_len = 32;
+
if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
k = ieee80211_crypto_encap(ic, ni, m);
if (k == NULL)
@@ -2502,19 +2610,25 @@
tid = R92C_TXDW1_QSEL_MGNT;
}
- if (((sizeof(*txd) + m->m_pkthdr.len) % 64) == 0) /* XXX: 64 */
+ if (((txd_len + m->m_pkthdr.len) % 64) == 0) /* XXX: 64 */
padsize = 8;
else
padsize = 0;
+ if (ISSET(sc->chip, URTWN_CHIP_92EU))
+ padsize = 0;
+
/* Fill Tx descriptor. */
txd = (struct r92c_tx_desc *)data->buf;
- memset(txd, 0, sizeof(*txd) + padsize);
+ memset(txd, 0, txd_len + padsize);
txd->txdw0 |= htole32(
SM(R92C_TXDW0_PKTLEN, m->m_pkthdr.len) |
- SM(R92C_TXDW0_OFFSET, sizeof(*txd)) |
- R92C_TXDW0_OWN | R92C_TXDW0_FSG | R92C_TXDW0_LSG);
+ SM(R92C_TXDW0_OFFSET, txd_len));
+ if (!ISSET(sc->chip, URTWN_CHIP_92EU)) {
+ txd->txdw0 |= htole32(
+ R92C_TXDW0_OWN | R92C_TXDW0_FSG | R92C_TXDW0_LSG);
+ }
if (IEEE80211_IS_MULTICAST(wh->i_addr1))
txd->txdw0 |= htole32(R92C_TXDW0_BMCAST);
@@ -2536,13 +2650,12 @@
("%s: %s: data packet: tid=%d, raid=%d\n",
device_xname(sc->sc_dev), __func__, tid, raid));
- if (ISSET(sc->chip, URTWN_CHIP_88E)) {
+ if (!ISSET(sc->chip, URTWN_CHIP_92C)) {
txd->txdw1 |= htole32(
SM(R88E_TXDW1_MACID, URTWN_MACID_BSS) |
SM(R92C_TXDW1_QSEL, tid) |
SM(R92C_TXDW1_RAID, raid) |
R92C_TXDW1_AGGBK);
- txd->txdw2 |= htole32(R88E_TXDW2_AGGBK);
} else
txd->txdw1 |= htole32(
SM(R92C_TXDW1_MACID, URTWN_MACID_BSS) |
@@ -2550,6 +2663,11 @@
SM(R92C_TXDW1_RAID, raid) |
R92C_TXDW1_AGGBK);
+ if (ISSET(sc->chip, URTWN_CHIP_88E))
+ txd->txdw2 |= htole32(R88E_TXDW2_AGGBK);
+ if (ISSET(sc->chip, URTWN_CHIP_92EU))
+ txd->txdw3 |= htole32(R92E_TXDW3_AGGBK);
+
if (hasqos) {
txd->txdw4 |= htole32(R92C_TXDW4_QOS);
}
@@ -2597,25 +2715,34 @@
/* Use 1Mbps */
txd->txdw5 |= htole32(SM(R92C_TXDW5_DATARATE, 0));
}
-
/* Set sequence number */
seq = LE_READ_2(&wh->i_seq[0]) >> IEEE80211_SEQ_SEQ_SHIFT;
- txd->txdseq |= htole16(seq);
+ if (!ISSET(sc->chip, URTWN_CHIP_92EU)) {
+ txd->txdseq |= htole16(seq);
- if (!hasqos) {
- /* Use HW sequence numbering for non-QoS frames. */
- txd->txdw4 |= htole32(R92C_TXDW4_HWSEQ);
- txd->txdseq |= htole16(0x8000); /* WTF? */
+ if (!hasqos) {
+ /* Use HW sequence numbering for non-QoS frames. */
+ txd->txdw4 |= htole32(R92C_TXDW4_HWSEQ);
+ txd->txdseq |= htole16(R92C_HWSEQ_EN);
+ }
+ } else {
+ txd->txdseq2 |= htole16((seq & R92E_HWSEQ_MASK) <<
+ R92E_HWSEQ_SHIFT);
+ if (!hasqos) {
+ /* Use HW sequence numbering for non-QoS frames. */
+ txd->txdw4 |= htole32(R92C_TXDW4_HWSEQ);
+ txd->txdw7 |= htole16(R92C_HWSEQ_EN);
+ }
}
/* Compute Tx descriptor checksum. */
sum = 0;
- for (i = 0; i < sizeof(*txd) / 2; i++)
+ for (i = 0; i < R92C_TXDESC_SUMSIZE / 2; i++)
sum ^= ((uint16_t *)txd)[i];
txd->txdsum = sum; /* NB: already little endian. */
- xferlen = sizeof(*txd) + m->m_pkthdr.len + padsize;
- m_copydata(m, 0, m->m_pkthdr.len, (char *)&txd[1] + padsize);
+ xferlen = txd_len + m->m_pkthdr.len + padsize;
+ m_copydata(m, 0, m->m_pkthdr.len, (char *)&txd[0] + txd_len + padsize);
s = splnet();
usbd_setup_xfer(data->xfer, data, data->buf, xferlen,
@@ -2714,6 +2841,7 @@
if (m->m_len < (int)sizeof(*eh) &&
(m = m_pullup(m, sizeof(*eh))) == NULL) {
+ printf("ERROR6\n");
ifp->if_oerrors++;
continue;
}
@@ -2721,6 +2849,7 @@
ni = ieee80211_find_txnode(ic, eh->ether_dhost);
if (ni == NULL) {
m_freem(m);
+ printf("ERROR5\n");
ifp->if_oerrors++;
continue;
}
@@ -2729,6 +2858,7 @@
if ((m = ieee80211_encap(ic, m, ni)) == NULL) {
ieee80211_free_node(ni);
+ printf("ERROR4\n");
ifp->if_oerrors++;
continue;
}
@@ -2738,6 +2868,7 @@
if (urtwn_tx(sc, m, ni, data) != 0) {
m_freem(m);
ieee80211_free_node(ni);
+ printf("ERROR3\n");
ifp->if_oerrors++;
continue;
}
@@ -2761,6 +2892,7 @@
if (--sc->tx_timer == 0) {
aprint_error_dev(sc->sc_dev, "device timeout\n");
/* urtwn_init(ifp); XXX needs a process context! */
+ printf("ERROR2\n");
ifp->if_oerrors++;
return;
}
@@ -2858,7 +2990,7 @@
urtwn_write_1(sc, R92C_RSV_CTRL, 0);
/* Move SPS into PWM mode. */
urtwn_write_1(sc, R92C_SPS0_CTRL, 0x2b);
- DELAY(100);
+ DELAY(5);
reg = urtwn_read_1(sc, R92C_LDOV12D_CTRL);
if (!(reg & R92C_LDOV12D_CTRL_LDV12_EN)) {
@@ -2877,7 +3009,7 @@
if (!(urtwn_read_2(sc, R92C_APS_FSMCO) &
R92C_APS_FSMCO_APFM_ONMAC))
break;
- DELAY(5);
+ DELAY(100);
}
if (ntries == 1000) {
aprint_error_dev(sc->sc_dev,
@@ -2925,6 +3057,86 @@
}
static int
+urtwn_r92e_power_on(struct urtwn_softc *sc)
+{
+ uint32_t reg;
+ uint32_t val;
+ int ntries;
+
+ DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
+
+ KASSERT(mutex_owned(&sc->sc_write_mtx));
+
+ /* Enable radio, GPIO and LED functions. */
+ KASSERT((R92C_APS_FSMCO_AFSM_HSUS | R92C_APS_FSMCO_PDN_EN |
+ R92C_APS_FSMCO_PFM_ALDN) == 0x0812);
+ urtwn_write_2(sc, R92C_APS_FSMCO,
+ R92C_APS_FSMCO_AFSM_HSUS |
+ R92C_APS_FSMCO_PDN_EN |
+ R92C_APS_FSMCO_PFM_ALDN);
+
+ if (urtwn_read_4(sc, R92E_SYS_CFG1_8192E) & R92E_SPSLDO_SEL){
+ /* LDO. */
+ urtwn_write_1(sc, R92E_LDO_SWR_CTRL, 0xc3);
+ }
+ else {
+ urtwn_write_2(sc, R92C_SYS_SWR_CTRL2, urtwn_read_2(sc,
+ R92C_SYS_SWR_CTRL2) & 0xffff);
+ urtwn_write_1(sc, R92E_LDO_SWR_CTRL, 0x83);
+ }
+
+ for (ntries = 0; ntries < 2; ntries++) {
+ urtwn_write_1(sc, R92C_AFE_PLL_CTRL,
+ urtwn_read_1(sc, R92C_AFE_PLL_CTRL));
+ urtwn_write_2(sc, R92C_AFE_CTRL4, urtwn_read_2(sc,
+ R92C_AFE_CTRL4));
+ }
+
+ /* Reset BB. */
+ urtwn_write_1(sc, R92C_SYS_FUNC_EN,
+ urtwn_read_1(sc, R92C_SYS_FUNC_EN) & ~(R92C_SYS_FUNC_EN_BBRSTB |
+ R92C_SYS_FUNC_EN_BB_GLB_RST));
+
+ urtwn_write_1(sc, R92C_AFE_XTAL_CTRL + 2, urtwn_read_1(sc,
+ R92C_AFE_XTAL_CTRL + 2) | 0x80);
+
+ /* Disable HWPDN. */
+ urtwn_write_2(sc, R92C_APS_FSMCO, urtwn_read_2(sc,
+ R92C_APS_FSMCO) & ~R92C_APS_FSMCO_APDM_HPDN);
+
+ /* Disable WL suspend. */
+ urtwn_write_2(sc, R92C_APS_FSMCO, urtwn_read_2(sc,
+ R92C_APS_FSMCO) & ~(R92C_APS_FSMCO_AFSM_PCIE |
+ R92C_APS_FSMCO_AFSM_HSUS));
+
+ urtwn_write_4(sc, R92C_APS_FSMCO, urtwn_read_4(sc,
+ R92C_APS_FSMCO) | R92C_APS_FSMCO_RDY_MACON);
+ urtwn_write_2(sc, R92C_APS_FSMCO, urtwn_read_2(sc,
+ R92C_APS_FSMCO) | R92C_APS_FSMCO_APFM_ONMAC);
+ for (ntries = 0; ntries < 10000; ntries++) {
+ val = urtwn_read_2(sc, R92C_APS_FSMCO) &
+ R92C_APS_FSMCO_APFM_ONMAC;
+ if (val == 0x0)
+ break;
+ DELAY(10);
+ }
+ if (ntries == 10000) {
+ aprint_error_dev(sc->sc_dev,
+ "timeout waiting for chip power up\n");
+ return ETIMEDOUT;
+ }
+
+ urtwn_write_2(sc, R92C_CR, 0x00);
+ reg = urtwn_read_2(sc, R92C_CR);
+ reg |= R92C_CR_HCI_TXDMA_EN | R92C_CR_HCI_RXDMA_EN |
+ R92C_CR_TXDMA_EN | R92C_CR_RXDMA_EN | R92C_CR_PROTOCOL_EN |
+ R92C_CR_SCHEDULE_EN | R92C_CR_ENSEC;
+ urtwn_write_2(sc, R92C_CR, reg);
+
+ return 0;
+}
+
+static int
urtwn_r88e_power_on(struct urtwn_softc *sc)
{
uint32_t reg;
@@ -2988,17 +3200,36 @@
urtwn_llt_init(struct urtwn_softc *sc)
{
size_t i, page_count, pktbuf_count;
+ uint32_t val;
int error;
DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
KASSERT(mutex_owned(&sc->sc_write_mtx));
- page_count = (sc->chip & URTWN_CHIP_88E) ?
- R88E_TX_PAGE_COUNT : R92C_TX_PAGE_COUNT;
- pktbuf_count = (sc->chip & URTWN_CHIP_88E) ?
- R88E_TXPKTBUF_COUNT : R92C_TXPKTBUF_COUNT;
+ if (sc->chip & URTWN_CHIP_88E)
+ page_count = R88E_TX_PAGE_COUNT;
+ else if (sc->chip & URTWN_CHIP_92EU)
+ page_count = R92E_TX_PAGE_COUNT;
+ else
+ page_count = R92C_TX_PAGE_COUNT;
+ if (sc->chip & URTWN_CHIP_88E)
+ pktbuf_count = R88E_TXPKTBUF_COUNT;
+ else if (sc->chip & URTWN_CHIP_92EU)
+ pktbuf_count = R88E_TXPKTBUF_COUNT;
+ else
+ pktbuf_count = R92C_TXPKTBUF_COUNT;
+ if (sc->chip & URTWN_CHIP_92EU) {
+ val = urtwn_read_4(sc, R92E_AUTO_LLT) | R92E_AUTO_LLT_EN;
+ urtwn_write_4(sc, R92E_AUTO_LLT, val);
+ DELAY(100);
+ val = urtwn_read_4(sc, R92E_AUTO_LLT);
+ if (val & R92E_AUTO_LLT_EN)
+ return EIO;
+ return 0;
+ }
+
/* Reserve pages [0; page_count]. */
for (i = 0; i < page_count; i++) {
if ((error = urtwn_llt_write(sc, i, i + 1)) != 0)
@@ -3054,9 +3285,25 @@
KASSERT(mutex_owned(&sc->sc_write_mtx));
+ if (ISSET(sc->chip, URTWN_CHIP_92EU)) {
+ reg = urtwn_read_2(sc, R92C_RSV_CTRL) & ~R92E_RSV_MIO_EN;
+ urtwn_write_2(sc,R92C_RSV_CTRL, reg);
+ }
+ DELAY(50);
+
reg = urtwn_read_2(sc, R92C_SYS_FUNC_EN);
urtwn_write_2(sc, R92C_SYS_FUNC_EN, reg & ~R92C_SYS_FUNC_EN_CPUEN);
+ DELAY(50);
+
urtwn_write_2(sc, R92C_SYS_FUNC_EN, reg | R92C_SYS_FUNC_EN_CPUEN);
+ DELAY(50);
+
+ if (ISSET(sc->chip, URTWN_CHIP_92EU)) {
+ reg = urtwn_read_2(sc, R92C_RSV_CTRL) | R92E_RSV_MIO_EN;
+ urtwn_write_2(sc,R92C_RSV_CTRL, reg);
+ }
+ DELAY(50);
+
}
static int
@@ -3108,6 +3355,8 @@
/* Read firmware image from the filesystem. */
if (ISSET(sc->chip, URTWN_CHIP_88E))
name = "rtl8188eufw.bin";
+ else if (ISSET(sc->chip, URTWN_CHIP_92EU))
+ name = "rtl8192eefw.bin";
else if ((sc->chip & (URTWN_CHIP_UMC_A_CUT | URTWN_CHIP_92C)) ==
URTWN_CHIP_UMC_A_CUT)
name = "rtl8192cfwU.bin";
@@ -3136,11 +3385,13 @@
return error;
}
+ len = fwlen;
ptr = fw;
hdr = (const struct r92c_fw_hdr *)ptr;
/* Check if there is a valid FW header and skip it. */
if ((le16toh(hdr->signature) >> 4) == 0x88c ||
(le16toh(hdr->signature) >> 4) == 0x88e ||
+ (le16toh(hdr->signature) >> 4) == 0x92e ||
(le16toh(hdr->signature) >> 4) == 0x92c) {
DPRINTFN(DBG_INIT, ("%s: %s: FW V%d.%d %02d-%02d %02d:%02d\n",
device_xname(sc->sc_dev), __func__,
@@ -3151,13 +3402,14 @@
}
if (urtwn_read_1(sc, R92C_MCUFWDL) & R92C_MCUFWDL_RAM_DL_SEL) {
- if (ISSET(sc->chip, URTWN_CHIP_88E))
+ if (ISSET(sc->chip, URTWN_CHIP_88E) ||
+ ISSET(sc->chip, URTWN_CHIP_92EU))
urtwn_r88e_fw_reset(sc);
else
urtwn_fw_reset(sc);
- urtwn_write_1(sc, R92C_MCUFWDL, 0);
}
- if (!ISSET(sc->chip, URTWN_CHIP_88E)) {
+ if (!ISSET(sc->chip, URTWN_CHIP_88E) &&
+ !ISSET(sc->chip, URTWN_CHIP_92EU)) {
urtwn_write_2(sc, R92C_SYS_FUNC_EN,
urtwn_read_2(sc, R92C_SYS_FUNC_EN) |
R92C_SYS_FUNC_EN_CPUEN);
@@ -3171,8 +3423,9 @@
/* Reset the FWDL checksum. */
urtwn_write_1(sc, R92C_MCUFWDL,
- urtwn_read_1(sc, R92C_MCUFWDL) | R92C_MCUFWDL_CHKSUM_RPT);
+ urtwn_read_1(sc, R92C_MCUFWDL) | R92C_MCUFWDL_CHKSUM_RPT);
+ DELAY(50);
/* download firmware */
for (page = 0; len > 0; page++) {
mlen = MIN(len, R92C_FW_PAGE_SIZE);
@@ -3208,7 +3461,8 @@
reg = urtwn_read_4(sc, R92C_MCUFWDL);
reg = (reg & ~R92C_MCUFWDL_WINTINI_RDY) | R92C_MCUFWDL_RDY;
urtwn_write_4(sc, R92C_MCUFWDL, reg);
- if (ISSET(sc->chip, URTWN_CHIP_88E))
+ if (ISSET(sc->chip, URTWN_CHIP_88E) ||
+ ISSET(sc->chip, URTWN_CHIP_92EU))
urtwn_r88e_fw_reset(sc);
for (ntries = 0; ntries < 1000; ntries++) {
if (urtwn_read_4(sc, R92C_MCUFWDL) & R92C_MCUFWDL_WINTINI_RDY)
@@ -3390,6 +3644,10 @@
for (i = 0; i < __arraycount(rtl8188eu_mac); i++)
urtwn_write_1(sc, rtl8188eu_mac[i].reg,
rtl8188eu_mac[i].val);
+ } else if (ISSET(sc->chip, URTWN_CHIP_92EU)) {
+ for (i = 0; i < __arraycount(rtl8192eu_mac); i++)
+ urtwn_write_1(sc, rtl8192eu_mac[i].reg,
+ rtl8192eu_mac[i].val);
} else {
for (i = 0; i < __arraycount(rtl8192cu_mac); i++)
urtwn_write_1(sc, rtl8192cu_mac[i].reg,
@@ -3415,7 +3673,8 @@
R92C_SYS_FUNC_EN_BBRSTB | R92C_SYS_FUNC_EN_BB_GLB_RST |
R92C_SYS_FUNC_EN_DIO_RF);
- if (!ISSET(sc->chip, URTWN_CHIP_88E)) {
+ if (!ISSET(sc->chip, URTWN_CHIP_88E) &&
+ !ISSET(sc->chip, URTWN_CHIP_92EU)) {
urtwn_write_1(sc, R92C_AFE_PLL_CTRL, 0x83);
urtwn_write_1(sc, R92C_AFE_PLL_CTRL + 1, 0xdb);
}
@@ -3426,7 +3685,8 @@
R92C_SYS_FUNC_EN_USBA | R92C_SYS_FUNC_EN_USBD |
R92C_SYS_FUNC_EN_BB_GLB_RST | R92C_SYS_FUNC_EN_BBRSTB);
- if (!ISSET(sc->chip, URTWN_CHIP_88E)) {
+ if (!ISSET(sc->chip, URTWN_CHIP_88E) &&
+ !ISSET(sc->chip, URTWN_CHIP_92EU)) {
urtwn_write_1(sc, R92C_LDOHCI12_CTRL, 0x0f);
urtwn_write_1(sc, 0x15, 0xe9);
urtwn_write_1(sc, R92C_AFE_XTAL_CTRL + 1, 0x80);
@@ -3435,6 +3695,8 @@
/* Select BB programming based on board type. */
if (ISSET(sc->chip, URTWN_CHIP_88E))
prog = &rtl8188eu_bb_prog;
+ else if (ISSET(sc->chip, URTWN_CHIP_92EU))
+ prog = &rtl8192eu_bb_prog;
else if (!(sc->chip & URTWN_CHIP_92C)) {
if (sc->board_type == R92C_BOARD_TYPE_MINICARD) {
prog = &rtl8188ce_bb_prog;
@@ -3455,13 +3717,13 @@
/* additional delay depend on registers */
switch (prog->regs[i]) {
case 0xfe:
- usbd_delay_ms(sc->sc_udev, 50);
+ urtwn_delay_ms(sc, 50);
break;
case 0xfd:
- usbd_delay_ms(sc->sc_udev, 5);
+ urtwn_delay_ms(sc, 5);
break;
case 0xfc:
- usbd_delay_ms(sc->sc_udev, 1);
+ urtwn_delay_ms(sc, 1);
break;
case 0xfb:
DELAY(50);
@@ -3522,12 +3784,18 @@
DELAY(1);
}
- if (ISSET(sc->chip, URTWN_CHIP_88E)) {
+ if (ISSET(sc->chip, URTWN_CHIP_88E) ||
+ ISSET(sc->chip, URTWN_CHIP_92EU)) {
urtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(0), 0x69553422);
DELAY(1);
urtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(0), 0x69553420);
DELAY(1);
+ if (ISSET(sc->chip, URTWN_CHIP_92EU)) {
+ urtwn_write_2(sc, R92C_AFE_CTRL3, urtwn_read_2(sc,
+ R92C_AFE_CTRL3));
+ }
+
crystalcap = sc->r88e_rom[0xb9];
if (crystalcap == 0xff)
crystalcap = 0x20;
@@ -3556,6 +3824,8 @@
/* Select RF programming based on board type. */
if (ISSET(sc->chip, URTWN_CHIP_88E))
prog = rtl8188eu_rf_prog;
+ else if (ISSET(sc->chip, URTWN_CHIP_92EU))
+ prog = rtl8192eu_rf_prog;
else if (!(sc->chip & URTWN_CHIP_92C)) {
if (sc->board_type == R92C_BOARD_TYPE_MINICARD) {
prog = rtl8188ce_rf_prog;
@@ -3578,23 +3848,23 @@
reg = urtwn_bb_read(sc, R92C_FPGA0_RFIFACEOE(i));
reg |= 0x100000;
urtwn_bb_write(sc, R92C_FPGA0_RFIFACEOE(i), reg);
- DELAY(1);
+ DELAY(50);
/* Set RF_ENV output high. */
reg = urtwn_bb_read(sc, R92C_FPGA0_RFIFACEOE(i));
reg |= 0x10;
urtwn_bb_write(sc, R92C_FPGA0_RFIFACEOE(i), reg);
- DELAY(1);
+ DELAY(50);
/* Set address and data lengths of RF registers. */
reg = urtwn_bb_read(sc, R92C_HSSI_PARAM2(i));
reg &= ~R92C_HSSI_PARAM2_ADDR_LENGTH;
urtwn_bb_write(sc, R92C_HSSI_PARAM2(i), reg);
- DELAY(1);
+ DELAY(50);
reg = urtwn_bb_read(sc, R92C_HSSI_PARAM2(i));
reg &= ~R92C_HSSI_PARAM2_DATA_LENGTH;
urtwn_bb_write(sc, R92C_HSSI_PARAM2(i), reg);
- DELAY(1);
+ DELAY(50);
/* Write RF initialization values for this chain. */
for (j = 0; j < prog[i].count; j++) {
@@ -3604,11 +3874,11 @@
* These are fake RF registers offsets that
* indicate a delay is required.
*/
- usbd_delay_ms(sc->sc_udev, 50);
+ urtwn_delay_ms(sc, 50);
continue;
}
urtwn_rf_write(sc, i, prog[i].regs[j], prog[i].vals[j]);
- DELAY(1);
+ DELAY(5);
}
/* Restore RF_ENV control type. */
@@ -3638,6 +3908,8 @@
DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
KASSERT(mutex_owned(&sc->sc_write_mtx));
+ if (ISSET(sc->chip, URTWN_CHIP_92EU))
+ return;
for (idx = 0; idx < R92C_CAM_ENTRY_COUNT; idx++) {
content = (idx & 3)
@@ -4008,7 +4280,8 @@
for (i = 0; i < sc->ntxchains; i++) {
/* Compute per-rate Tx power values. */
- if (ISSET(sc->chip, URTWN_CHIP_88E))
+ if (ISSET(sc->chip, URTWN_CHIP_88E) ||
+ ISSET(sc->chip, URTWN_CHIP_92EU))
urtwn_r88e_get_txpower(sc, i, chan, ht40m, power);
else
urtwn_get_txpower(sc, i, chan, ht40m, power);
@@ -4091,7 +4364,8 @@
urtwn_bb_write(sc, R92C_FPGA1_RFMOD,
urtwn_bb_read(sc, R92C_FPGA1_RFMOD) & ~R92C_RFMOD_40MHZ);
- if (!ISSET(sc->chip, URTWN_CHIP_88E)) {
+ if (!ISSET(sc->chip, URTWN_CHIP_88E) &&
+ !ISSET(sc->chip, URTWN_CHIP_92EU)) {
urtwn_bb_write(sc, R92C_FPGA0_ANAPARAM2,
urtwn_bb_read(sc, R92C_FPGA0_ANAPARAM2) |
R92C_FPGA0_ANAPARAM2_CBW20);
@@ -4100,7 +4374,8 @@
/* Select 20MHz bandwidth. */
urtwn_rf_write(sc, 0, R92C_RF_CHNLBW,
(sc->rf_chnlbw[0] & ~0xfff) | chan |
- (ISSET(sc->chip, URTWN_CHIP_88E) ?
+ (ISSET(sc->chip, URTWN_CHIP_88E) ||
+ ISSET(sc->chip, URTWN_CHIP_92EU) ?
R88E_RF_CHNLBW_BW20 : R92C_RF_CHNLBW_BW20));
}
}
@@ -4284,7 +4559,7 @@
urtwn_rf_read(sc, 0, R92C_RF_CHNLBW) | R92C_RF_CHNLBW_LCSTART);
/* Give calibration the time to complete. */
- usbd_delay_ms(sc->sc_udev, 100);
+ urtwn_delay_ms(sc, 100);
/* Restore configuration. */
if ((txmode & 0x70) != 0) {
@@ -4303,17 +4578,22 @@
static void
urtwn_temp_calib(struct urtwn_softc *sc)
{
- int temp;
+ int temp, t_meter_reg;
DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
KASSERT(mutex_owned(&sc->sc_write_mtx));
+ if (!ISSET(sc->chip, URTWN_CHIP_92EU))
+ t_meter_reg = R92C_RF_T_METER;
+ else
+ t_meter_reg = R92E_RF_T_METER;
+
if (sc->thcal_state == 0) {
/* Start measuring temperature. */
DPRINTFN(DBG_RF, ("%s: %s: start measuring temperature\n",
device_xname(sc->sc_dev), __func__));
- urtwn_rf_write(sc, 0, R92C_RF_T_METER, 0x60);
+ urtwn_rf_write(sc, 0, t_meter_reg, 0x60);
sc->thcal_state = 1;
return;
}
@@ -4323,7 +4603,7 @@
temp = urtwn_rf_read(sc, 0, R92C_RF_T_METER) & 0x1f;
DPRINTFN(DBG_RF, ("%s: %s: temperature=%d\n", device_xname(sc->sc_dev),
__func__, temp));
- if (temp == 0) /* Read failed, skip. */
+ if (temp == 0) /* Read failed, skip. */
return;
/*
@@ -4398,15 +4678,20 @@
urtwn_write_1(sc, R92C_RX_DRVINFO_SZ, 4);
/* Init interrupts. */
- if (ISSET(sc->chip, URTWN_CHIP_88E)) {
+ if (ISSET(sc->chip, URTWN_CHIP_88E) ||
+ ISSET(sc->chip, URTWN_CHIP_92EU)) {
urtwn_write_4(sc, R88E_HISR, 0xffffffff);
urtwn_write_4(sc, R88E_HIMR, R88E_HIMR_CPWM | R88E_HIMR_CPWM2 |
R88E_HIMR_TBDER | R88E_HIMR_PSTIMEOUT);
urtwn_write_4(sc, R88E_HIMRE, R88E_HIMRE_RXFOVW |
R88E_HIMRE_TXFOVW | R88E_HIMRE_RXERR | R88E_HIMRE_TXERR);
- urtwn_write_1(sc, R92C_USB_SPECIAL_OPTION,
- urtwn_read_1(sc, R92C_USB_SPECIAL_OPTION) |
- R92C_USB_SPECIAL_OPTION_INT_BULK_SEL);
+ if (ISSET(sc->chip, URTWN_CHIP_88E)) {
+ urtwn_write_1(sc, R92C_USB_SPECIAL_OPTION,
+ urtwn_read_1(sc, R92C_USB_SPECIAL_OPTION) |
+ R92C_USB_SPECIAL_OPTION_INT_BULK_SEL);
+ }
+ if (ISSET(sc->chip, URTWN_CHIP_92EU))
+ urtwn_write_1(sc, R92C_USB_HRPWM, 0);
} else {
urtwn_write_4(sc, R92C_HISR, 0xffffffff);
urtwn_write_4(sc, R92C_HIMR, 0xffffffff);
@@ -4447,7 +4732,8 @@
urtwn_edca_init(sc);
/* Setup rate fallback. */
- if (!ISSET(sc->chip, URTWN_CHIP_88E)) {
+ if (!ISSET(sc->chip, URTWN_CHIP_88E) &&
+ !ISSET(sc->chip, URTWN_CHIP_92EU)) {
urtwn_write_4(sc, R92C_DARFRC + 0, 0x00000000);
urtwn_write_4(sc, R92C_DARFRC + 4, 0x10080404);
urtwn_write_4(sc, R92C_RARFRC + 0, 0x04030201);
@@ -4473,7 +4759,8 @@
urtwn_read_1(sc, R92C_USB_SPECIAL_OPTION) &
~R92C_USB_SPECIAL_OPTION_AGG_EN);
urtwn_write_1(sc, R92C_RXDMA_AGG_PG_TH, 48);
- if (ISSET(sc->chip, URTWN_CHIP_88E))
+ if (ISSET(sc->chip, URTWN_CHIP_88E) ||
+ ISSET(sc->chip, URTWN_CHIP_92EU))
urtwn_write_1(sc, R92C_RXDMA_AGG_PG_TH + 1, 4);
else
urtwn_write_1(sc, R92C_USB_DMA_AGG_TO, 4);
@@ -4485,7 +4772,8 @@
urtwn_write_1(sc, R92C_BCNDMATIM, R92C_DMA_ATIME_INT_TIME);
urtwn_write_2(sc, R92C_BCNTCFG, 0x660f);
- if (!ISSET(sc->chip, URTWN_CHIP_88E)) {
+ if (!ISSET(sc->chip, URTWN_CHIP_88E) &&
+ !ISSET(sc->chip, URTWN_CHIP_92EU)) {
/* Setup AMPDU aggregation. */
urtwn_write_4(sc, R92C_AGGLEN_LMT, 0x99997631); /* MCS7~0 */
urtwn_write_1(sc, R92C_AGGR_BREAK_TIME, 0x16);
@@ -4512,7 +4800,8 @@
urtwn_bb_init(sc);
urtwn_rf_init(sc);
- if (ISSET(sc->chip, URTWN_CHIP_88E)) {
+ if (ISSET(sc->chip, URTWN_CHIP_88E) ||
+ ISSET(sc->chip, URTWN_CHIP_92EU)) {
urtwn_write_2(sc, R92C_CR,
urtwn_read_2(sc, R92C_CR) | R92C_CR_MACTXEN |
R92C_CR_MACRXEN);
@@ -4539,7 +4828,8 @@
/* Perform LC calibration. */
urtwn_lc_calib(sc);
- if (!ISSET(sc->chip, URTWN_CHIP_88E)) {
+ if (!ISSET(sc->chip, URTWN_CHIP_88E) &&
+ !ISSET(sc->chip, URTWN_CHIP_92EU)) {
/* Fix USB interference issue. */
urtwn_write_1(sc, 0xfe40, 0xe0);
urtwn_write_1(sc, 0xfe41, 0x8d);
@@ -4549,7 +4839,8 @@
urtwn_pa_bias_init(sc);
}
- if (!(sc->chip & (URTWN_CHIP_92C | URTWN_CHIP_92C_1T2R))) {
+ if (!(sc->chip & (URTWN_CHIP_92C | URTWN_CHIP_92C_1T2R)) ||
+ !(sc->chip & URTWN_CHIP_92EU)) {
/* 1T1R */
urtwn_bb_write(sc, R92C_FPGA0_RFPARAM(0),
urtwn_bb_read(sc, R92C_FPGA0_RFPARAM(0)) | __BIT(13));
@@ -4560,26 +4851,31 @@
urtwn_read_1(sc, R92C_GPIO_MUXCFG) & ~R92C_GPIO_MUXCFG_ENBT);
/* Fix for lower temperature. */
- if (!ISSET(sc->chip, URTWN_CHIP_88E))
+ if (!ISSET(sc->chip, URTWN_CHIP_88E) &&
+ !ISSET(sc->chip, URTWN_CHIP_92EU))
urtwn_write_1(sc, 0x15, 0xe9);
/* Set default channel. */
urtwn_set_chan(sc, ic->ic_curchan, IEEE80211_HTINFO_2NDCHAN_NONE);
/* Queue Rx xfers. */
- for (i = 0; i < URTWN_RX_LIST_COUNT; i++) {
- data = &sc->rx_data[i];
- usbd_setup_xfer(data->xfer, data, data->buf, URTWN_RXBUFSZ,
- USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, urtwn_rxeof);
- error = usbd_transfer(data->xfer);
- if (__predict_false(error != USBD_NORMAL_COMPLETION &&
- error != USBD_IN_PROGRESS))
- goto fail;
+ for (size_t j = 0; j < sc->rx_npipe; j++) {
+ for (i = 0; i < URTWN_RX_LIST_COUNT; i++) {
+ data = &sc->rx_data[j][i];
+ usbd_setup_xfer(data->xfer, data, data->buf,
+ URTWN_RXBUFSZ, USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT,
+ urtwn_rxeof);
+ error = usbd_transfer(data->xfer);
+ if (__predict_false(error != USBD_NORMAL_COMPLETION &&
+ error != USBD_IN_PROGRESS))
+ goto fail;
+ }
}
/* We're ready to go. */
ifp->if_flags &= ~IFF_OACTIVE;
ifp->if_flags |= IFF_RUNNING;
+ sc->sc_running = true;
mutex_exit(&sc->sc_write_mtx);
@@ -4621,18 +4917,22 @@
callout_stop(&sc->sc_calib_to);
/* Abort Tx. */
- for (i = 0; i < R92C_MAX_EPOUT; i++) {
+ for (i = 0; i < sc->tx_npipe; i++) {
if (sc->tx_pipe[i] != NULL)
usbd_abort_pipe(sc->tx_pipe[i]);
}
/* Stop Rx pipe. */
- usbd_abort_pipe(sc->rx_pipe);
+ for (i = 0; i < sc->rx_npipe; i++) {
+ if (sc->rx_pipe[i] != NULL)
+ usbd_abort_pipe(sc->rx_pipe[i]);
+ }
/* Free Tx/Rx buffers. */
urtwn_free_tx_list(sc);
urtwn_free_rx_list(sc);
+ sc->sc_running = false;
if (disable)
urtwn_chip_stop(sc);
}
@@ -4659,6 +4959,9 @@
DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
+ if (ISSET(sc->chip, URTWN_CHIP_92EU))
+ return;
+
mutex_enter(&sc->sc_write_mtx);
/*
@@ -4688,7 +4991,8 @@
urtwn_write_1(sc, R92C_MCUFWDL, 0);
/* If firmware in ram code, do reset */
if (ISSET(sc->sc_flags, URTWN_FLAG_FWREADY)) {
- if (ISSET(sc->chip, URTWN_CHIP_88E))
+ if (ISSET(sc->chip, URTWN_CHIP_88E) ||
+ ISSET(sc->chip, URTWN_CHIP_92EU))
urtwn_r88e_fw_reset(sc);
else
urtwn_fw_reset(sc);
@@ -4767,6 +5071,15 @@
urtwn_write_1(sc, R92C_RSV_CTRL, 0x0E);
mutex_exit(&sc->sc_write_mtx);
+}
+
+static void
+urtwn_delay_ms(struct urtwn_softc *sc, int ms)
+{
+ if (sc->sc_running == false)
+ DELAY(ms * 1000);
+ else
+ usbd_delay_ms(sc->sc_udev, ms);
}
MODULE(MODULE_CLASS_DRIVER, if_urtwn, "bpf");
@@ -1,8 +1,9 @@
-/* $NetBSD: if_urtwn_data.h,v 1.3 2014/07/20 13:25:23 nonaka Exp $ */
+/* $NetBSD: if_urtwn_data.h,v 1.4 2016/10/12 03:23:29 nat Exp $ */
/* $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
+ * Copyright (c) 2016 Nathanial Sloss <nathanialsloss@yahoo.com.au>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -23,7 +24,34 @@
static const struct {
uint16_t reg;
uint8_t val;
-} rtl8188eu_mac[] = {
+} rtl8192eu_mac[]={
+ { 0x011, 0xeb }, { 0x012, 0x07 }, { 0x014, 0x75 }, { 0x303, 0xa7 },
+ { 0x428, 0x0a }, { 0x429, 0x10 }, { 0x430, 0x00 }, { 0x431, 0x00 },
+ { 0x432, 0x00 }, { 0x433, 0x01 }, { 0x434, 0x04 }, { 0x435, 0x05 },
+ { 0x436, 0x07 }, { 0x437, 0x08 }, { 0x43c, 0x04 }, { 0x43d, 0x05 },
+ { 0x43e, 0x07 }, { 0x43f, 0x08 }, { 0x440, 0x5d }, { 0x441, 0x01 },
+ { 0x442, 0x00 }, { 0x444, 0x10 }, { 0x445, 0x00 }, { 0x446, 0x00 },
+ { 0x447, 0x00 }, { 0x448, 0x00 }, { 0x449, 0xf0 }, { 0x44a, 0x0f },
+ { 0x44b, 0x3e }, { 0x44c, 0x10 }, { 0x44d, 0x00 }, { 0x44e, 0x00 },
+ { 0x44f, 0x00 }, { 0x450, 0x00 }, { 0x451, 0xf0 }, { 0x452, 0x0f },
+ { 0x453, 0x00 }, { 0x456, 0x5e }, { 0x460, 0x66 }, { 0x461, 0x66 },
+ { 0x4c8, 0xff }, { 0x4c9, 0x08 }, { 0x4cc, 0xff }, { 0x4cd, 0xff },
+ { 0x4ce, 0x01 }, { 0x500, 0x26 }, { 0x501, 0xa2 }, { 0x502, 0x2f },
+ { 0x503, 0x00 }, { 0x504, 0x28 }, { 0x505, 0xa3 }, { 0x506, 0x5e },
+ { 0x507, 0x00 }, { 0x508, 0x2b }, { 0x509, 0xa4 }, { 0x50a, 0x5e },
+ { 0x50b, 0x00 }, { 0x50c, 0x4f }, { 0x50d, 0xa4 }, { 0x50e, 0x00 },
+ { 0x50f, 0x00 }, { 0x512, 0x1c }, { 0x514, 0x0a }, { 0x516, 0x0a },
+ { 0x525, 0x4f }, { 0x540, 0x12 }, { 0x541, 0x64 }, { 0x550, 0x10 },
+ { 0x551, 0x10 }, { 0x559, 0x02 }, { 0x55c, 0x50 }, { 0x55d, 0xff },
+ { 0x605, 0x30 }, { 0x608, 0x0e }, { 0x609, 0x2a }, { 0x620, 0xff },
+ { 0x621, 0xff }, { 0x622, 0xff }, { 0x623, 0xff }, { 0x624, 0xff },
+ { 0x625, 0xff }, { 0x626, 0xff }, { 0x627, 0xff }, { 0x638, 0x50 },
+ { 0x63c, 0x0a }, { 0x63d, 0x0a }, { 0x63e, 0x0e }, { 0x63f, 0x0e },
+ { 0x640, 0x40 }, { 0x642, 0x40 }, { 0x643, 0x00 }, { 0x652, 0xc8 },
+ { 0x66e, 0x05 }, { 0x700, 0x21 }, { 0x701, 0x43 }, { 0x702, 0x65 },
+ { 0x703, 0x87 }, { 0x708, 0x21 }, { 0x709, 0x43 }, { 0x70a, 0x65 },
+ { 0x70b, 0x87 },
+}, rtl8188eu_mac[] = {
{ 0x026, 0x41 }, { 0x027, 0x35 }, { 0x040, 0x00 }, { 0x428, 0x0a },
{ 0x429, 0x10 }, { 0x430, 0x00 }, { 0x431, 0x01 }, { 0x432, 0x02 },
{ 0x433, 0x04 }, { 0x434, 0x05 }, { 0x435, 0x06 }, { 0x436, 0x07 },
@@ -492,6 +520,120 @@
};
/*
+ * RTL819E.
+ */
+static const uint16_t rtl8192eu_bb_regs[] = {
+ 0x800, 0x804, 0x808, 0x80c, 0x810, 0x814, 0x818, 0x81c,
+ 0x820, 0x824, 0x828, 0x82c, 0x830, 0x834, 0x838, 0x83c,
+ 0x840, 0x844, 0x848, 0x84c, 0x850, 0x854, 0x858, 0x85c,
+ 0x860, 0x864, 0x868, 0x86c, 0x870, 0x874, 0x878, 0x87c,
+ 0x880, 0x884, 0x888, 0x88c, 0x890, 0x894, 0x898, 0x900,
+ 0x904, 0x908, 0x90c, 0x910, 0x914, 0x918, 0x91c, 0x924,
+ 0x928, 0x92c, 0x930, 0x934, 0x938, 0x93c, 0x940, 0x944,
+ 0x94c, 0xa00, 0xa04, 0xa08, 0xa0c, 0xa10, 0xa14, 0xa18,
+ 0xa1c, 0xa20, 0xa24, 0xa28, 0xa2c, 0xa70, 0xa74, 0xa78,
+ 0xa7c, 0xa80, 0xb38, 0xc00, 0xc04, 0xc08, 0xc0c, 0xc10,
+ 0xc14, 0xc18, 0xc1c, 0xc20, 0xc24, 0xc28, 0xc2c, 0xc30,
+ 0xc34, 0xc38, 0xc3c, 0xc40, 0xc44, 0xc48, 0xc4c, 0xc50,
+ 0xc54, 0xc58, 0xc5c, 0xc60, 0xc64, 0xc68, 0xc6c, 0xc70,
+ 0xc74, 0xc78, 0xc7c, 0xc80, 0xc84, 0xc88, 0xc8c, 0xc90,
+ 0xc94, 0xc98, 0xc9c, 0xca0, 0xca4, 0xca8, 0xcac, 0xcb0,
+ 0xcb4, 0xcb8, 0xcbc, 0xcc0, 0xcc4, 0xcc8, 0xccc, 0xcd0,
+ 0xcd4, 0xcd8, 0xcdc, 0xce0, 0xce4, 0xce8, 0xcec, 0xd00,
+ 0xd04, 0xd08, 0xd0c, 0xd10, 0xd14, 0xd18, 0xd1c, 0xd2c,
+ 0xd30, 0xd34, 0xd38, 0xd3c, 0xd40, 0xd44, 0xd48, 0xd4c,
+ 0xd50, 0xd54, 0xd58, 0xd5c, 0xd60, 0xd64, 0xd68, 0xd6c,
+ 0xd70, 0xd74, 0xd78, 0xd80, 0xd84, 0xd88, 0xe00, 0xe04,
+ 0xe08, 0xe10, 0xe14, 0xe18, 0xe1c, 0xe28, 0xe30, 0xe34,
+ 0xe38, 0xe3c, 0xe40, 0xe44, 0xe48, 0xe4c, 0xe50, 0xe54,
+ 0xe58, 0xe5c, 0xe60, 0xe68, 0xe6c, 0xe70, 0xe74, 0xe78,
+ 0xe7c, 0xe80, 0xe84, 0xe88, 0xe8c, 0xed0, 0xed4, 0xed8,
+ 0xedc, 0xee0, 0xeec, 0xee4, 0xee8, 0xf14, 0xf4c, 0xf00,
+};
+
+static const uint32_t rtl8192eu_bb_vals[] = {
+ 0x80040000, 0x00000003, 0x0000fc00, 0x0000000a, 0x10001331,
+ 0x020c3d10, 0x02220385, 0x00000000, 0x01000100, 0x00390204,
+ 0x01000100, 0x00390204, 0x32323232, 0x30303030, 0x30303030,
+ 0x30303030, 0x00010000, 0x00010000, 0x28282828, 0x28282828,
+ 0x00000000, 0x00000000, 0x009a009a, 0x01000014, 0x66f60000,
+ 0x061f0000, 0x30303030, 0x30303030, 0x00000000, 0x55004200,
+ 0x08080808, 0x00000000, 0xb0000c1c, 0x00000001, 0x00000000,
+ 0xcc0000c0, 0x00000800, 0xfffffffe, 0x40302010, 0x00000000,
+ 0x00000023, 0x00000000, 0x81121313, 0x806c0001, 0x00000001,
+ 0x00000000, 0x00010000, 0x00000001, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000008, 0x00d0c7c8, 0x81ff000c, 0x8c838300,
+ 0x2e68120f, 0x95009b78, 0x1114d028, 0x00881117, 0x89140f00,
+ 0x1a1b0000, 0x090e1317, 0x00000204, 0x00d30000, 0x101fff00,
+ 0x00000007, 0x00000900, 0x225b0606, 0x218075b1, 0x00000000,
+ 0x48071d40, 0x03a05633, 0x000000e4, 0x6c6c6c6c, 0x08800000,
+ 0x40000100, 0x08800000, 0x40000100, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x69e9ac47, 0x469652af, 0x49795994,
+ 0x0a97971c, 0x1f7c403f, 0x000100b7, 0xec020107, 0x007f037f,
+ 0x00340020, 0x0080801f, 0x00000020, 0x00248492, 0x00000000,
+ 0x7112848b, 0x47c00bff, 0x00000036, 0x00000600, 0x02013169,
+ 0x0000001f, 0x00b91612, 0x40000100, 0x21f60000, 0x40000100,
+ 0xa0e40000, 0x00121820, 0x00000000, 0x00121820, 0x00007f7f,
+ 0x00000000, 0x000300a0, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x28000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x64b22427,
+ 0x00766932, 0x00222222, 0x00040000, 0x77644302, 0x2f97d40c,
+ 0x00080740, 0x00020403, 0x0000907f, 0x20010201, 0xa0633333,
+ 0x3333bc43, 0x7a8f5b6b, 0x0000007f, 0xcc979975, 0x00000000,
+ 0x80608000, 0x00000000, 0x00127353, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x6437140a, 0x00000000, 0x00000282,
+ 0x30032064, 0x4653de68, 0x04518a3c, 0x00002101, 0x2a201c16,
+ 0x1812362e, 0x322c2220, 0x000e3c24, 0x01081008, 0x00000800,
+ 0xf0b50000, 0x30303030, 0x30303030, 0x03903030, 0x30303030,
+ 0x30303030, 0x30303030, 0x30303030, 0x00000000, 0x1000dc1f,
+ 0x10008c1f, 0x02140102, 0x681604c2, 0x01007c00, 0x01004800,
+ 0xfb000000, 0x000028d1, 0x1000dc1f, 0x10008c1f, 0x02140102,
+ 0x28160d05, 0x00000008, 0x0fc05656, 0x03c09696, 0x03c09696,
+ 0x0c005656, 0x0c005656, 0x0c005656, 0x0c005656, 0x03c09696,
+ 0x0c005656, 0x03c09696, 0x03c09696, 0x03c09696, 0x03c09696,
+ 0x0000d6d6, 0x0000d6d6, 0x0fc01616, 0xb0000c1c, 0x00000001,
+ 0x00000003, 0x00000000, 0x00000300,
+};
+
+static const uint32_t rtl8192eu_agc_vals[] = {
+ 0xfb000001, 0xfb010001, 0xfb020001, 0xfb030001, 0xfb040001,
+ 0xfb050001, 0xfa060001, 0xf9070001, 0xf8080001, 0xf7090001,
+ 0xf60a0001, 0xf50b0001, 0xf40c0001, 0xf30d0001, 0xf20e0001,
+ 0xf10f0001, 0xf0100001, 0xef110001, 0xee120001, 0xed130001,
+ 0xec140001, 0xeb150001, 0xea160001, 0xe9170001, 0xe8180001,
+ 0xe7190001, 0xc81a0001, 0xc71b0001, 0xc61c0001, 0x071d0001,
+ 0x061e0001, 0x051f0001, 0x04200001, 0x03210001, 0xaa220001,
+ 0xa9230001, 0xa8240001, 0xa7250001, 0xa6260001, 0x85270001,
+ 0x84280001, 0x83290001, 0x252a0001, 0x242b0001, 0x232c0001,
+ 0x222d0001, 0x672e0001, 0x662f0001, 0x65300001, 0x64310001,
+ 0x63320001, 0x62330001, 0x61340001, 0x45350001, 0x44360001,
+ 0x43370001, 0x42380001, 0x41390001, 0x403a0001, 0x403b0001,
+ 0x403c0001, 0x403d0001, 0x403e0001, 0x403f0001, 0xfb400001,
+ 0xfb410001, 0xfb420001, 0xfb430001, 0xfb440001, 0xfb450001,
+ 0xfa460001, 0xf9470001, 0xf8480001, 0xf7490001, 0xf64a0001,
+ 0xf54b0001, 0xf44c0001, 0xf34d0001, 0xf24e0001, 0xf14f0001,
+ 0xf0500001, 0xef510001, 0xee520001, 0xed530001, 0xec540001,
+ 0xeb550001, 0xea560001, 0xe9570001, 0xe8580001, 0xe7590001,
+ 0xe65a0001, 0xe55b0001, 0xe45c0001, 0xe35d0001, 0xe25e0001,
+ 0xe15f0001, 0x8a600001, 0x89610001, 0x88620001, 0x87630001,
+ 0x86640001, 0x85650001, 0x84660001, 0x83670001, 0x82680001,
+ 0x6b690001, 0x6a6a0001, 0x696b0001, 0x686c0001, 0x676d0001,
+ 0x666e0001, 0x656f0001, 0x64700001, 0x63710001, 0x62720001,
+ 0x61730001, 0x49740001, 0x48750001, 0x47760001, 0x46770001,
+ 0x45780001, 0x44790001, 0x437a0001, 0x427b0001, 0x417c0001,
+ 0x407d0001, 0x407e0001, 0x407f0001,
+};
+
+static const struct urtwn_bb_prog rtl8192eu_bb_prog = {
+ __arraycount(rtl8192eu_bb_regs),
+ rtl8192eu_bb_regs,
+ rtl8192eu_bb_vals,
+ __arraycount(rtl8192eu_agc_vals),
+ rtl8192eu_agc_vals
+};
+
+/*
* RTL8188RU.
*/
static const uint16_t rtl8188ru_bb_regs[] = {
@@ -751,6 +893,83 @@
__arraycount(rtl8192ce_rf1_regs),
rtl8192ce_rf1_regs,
rtl8188cu_rf_vals
+ }
+};
+
+/*
+ * RTL8192EU.
+ */
+static const uint8_t rtl8192eu_rf_regs[] = {
+ 0x7f, 0x81, 0x00, 0x08, 0x18, 0x19, 0x1b, 0x1e, 0x1f, 0x2f,
+ 0x3f, 0x42, 0x57, 0x58, 0x67, 0x83, 0xb0, 0xb1, 0xb2, 0xb4,
+ 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbf, 0xc2, 0xc3,
+ 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xdf, 0xef, 0x51,
+ 0x52, 0x53, 0x56, 0x35, 0x35, 0x35, 0x36, 0x36, 0x36, 0x36,
+ 0x18, 0x5a, 0x19, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34,
+ 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34,
+ 0x34, 0x34, 0x34, 0x34, 0x34, 0x00, 0x84, 0x86, 0x87, 0x8e,
+ 0x8f, 0xef, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
+ 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
+ 0xef, 0xfe, 0x18, 0xfe, 0xfe, 0xfe, 0xfe, 0x1e, 0x1f, 0x00,
+};
+
+static const uint32_t rtl8192eu_rf_vals[] = {
+ 0x00082, 0x3fc00, 0x30000, 0x08400, 0x00407, 0x00012, 0x00064,
+ 0x80009, 0x00880, 0x1a060, 0x00000, 0x060c0, 0xd0000, 0xbe180,
+ 0x01552, 0x00000, 0xff9f1, 0x55418, 0x8cc00, 0x43083, 0x08166,
+ 0x0803e, 0x1c69f, 0x0407f, 0x80001, 0x40001, 0x00400, 0xc0000,
+ 0x02400, 0x00009, 0x40c91, 0x99999, 0x000a3, 0x88820, 0x76c06,
+ 0x00000, 0x80000, 0x00180, 0x001a0, 0x69545, 0x7e45e, 0x00071,
+ 0x51ff3, 0x000a8, 0x001e2, 0x002a8, 0x01c24, 0x09c24, 0x11c24,
+ 0x19c24, 0x00c07, 0x48000, 0x739d0, 0x0a093, 0x0908f, 0x0808c,
+ 0x0704d, 0x0604a, 0x05047, 0x0400a, 0x03007, 0x02004, 0x01001,
+ 0x00000, 0x0add7, 0x09dd4, 0x08dd1, 0x07dce, 0x06dcb, 0x05dc8,
+ 0x04dc5, 0x034cc, 0x0244f, 0x0144c, 0x00014, 0x30159, 0x68180,
+ 0x0014e, 0x48e00, 0x65540, 0x88000, 0x020a0, 0xf07b0, 0xf02b0,
+ 0xef7b0, 0xd4fb0, 0xcf060, 0xb0090, 0xa0080, 0x90080, 0x8f780,
+ 0x787b0, 0x78730, 0x60fb0, 0x5ffa0, 0x40620, 0x37090, 0x20080,
+ 0x1f060, 0x0ffb0, 0x000a0, 0x00000, 0x0fc07, 0x00000, 0x00000,
+ 0x00000, 0x00000, 0x00001, 0x80000, 0x33e70,
+};
+
+static const uint8_t rtl8192eu_rf2_regs[] = {
+ 0x7f, 0x81, 0x00, 0x08, 0x18, 0x19, 0x1b, 0x1e, 0x1f, 0x2f,
+ 0x3f, 0x42, 0x57, 0x58, 0x67, 0x7f, 0x81, 0x83, 0xdf, 0xef,
+ 0x51, 0x52, 0x53, 0x56, 0x35, 0x35, 0x35, 0x36, 0x36, 0x36,
+ 0x36, 0x18, 0x5a, 0x19, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34,
+ 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34,
+ 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x00, 0x84, 0x86, 0x87,
+ 0x8e, 0x8f, 0xef, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
+ 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
+ 0x3b, 0xef, 0x00, 0xfe, 0xfe, 0xfe, 0xfe, 0x1e, 0x1f, 0x00,
+};
+
+static const uint32_t rtl8192eu_rf2_vals[] = {
+ 0x00082, 0x3fc00, 0x30000, 0x08400, 0x00407, 0x00012, 0x00064,
+ 0x80009, 0x00880, 0x1a060, 0x00000, 0x060c0, 0xd0000, 0xbe180,
+ 0x01552, 0x00082, 0x3f000, 0x00000, 0x00180, 0x001a0, 0x69545,
+ 0x7e42e, 0x00071, 0x51ff3, 0x000a8, 0x001e0, 0x002a8, 0x01ca8,
+ 0x09c24, 0x11c24, 0x19c24, 0x00c07, 0x48000, 0x739d0, 0x0a093,
+ 0x0908f, 0x0808c, 0x0704d, 0x0604a, 0x05047, 0x0400a, 0x03007,
+ 0x02004, 0x01001, 0x00000, 0x0add7, 0x09dd4, 0x08dd1, 0x07dce,
+ 0x06dcb, 0x05dc8, 0x04dc5, 0x034cc, 0x0244f, 0x0144c, 0x00014,
+ 0x30159, 0x68180, 0x000ce, 0x48a00, 0x65540, 0x88000, 0x020a0,
+ 0xf07b0, 0xf02b0, 0xef7b0, 0xd4fb0, 0xcf060, 0xb0090, 0xa0080,
+ 0x90080, 0x8f780, 0x787b0, 0x78730, 0x60fb0, 0x5ffa0, 0x40620,
+ 0x37090, 0x20080, 0x1f060, 0x0ffb0, 0x000a0, 0x10159, 0x00000,
+ 0x00000, 0x00000, 0x00000, 0x00001, 0x80000, 0x33e70,
+};
+
+static const struct urtwn_rf_prog rtl8192eu_rf_prog[] = {
+ {
+ __arraycount(rtl8192eu_rf_regs),
+ rtl8192eu_rf_regs,
+ rtl8192eu_rf_vals
+ },
+ {
+ __arraycount(rtl8192eu_rf2_regs),
+ rtl8192eu_rf2_regs,
+ rtl8192eu_rf2_vals
}
};