realtekwifi: Upgrade to FreeBSD 12.

This driver was completely rewritten and merged with its USB counterpart
in FreeBSD 12. I've imported the USB code, even though it's not compiled
in at all, because it's more than likely I'll get around to USB WiFi support
before FreeBSD 13 comes...

Untested, because I don't have one of these PCI devices.
This commit is contained in:
Augustin Cavalier
2019-01-10 20:43:15 -05:00
parent 860d86851e
commit 478b2a6ab0
169 changed files with 28981 additions and 5140 deletions
@@ -14,10 +14,50 @@ SubDirCcFlags [ FDefines _KERNEL=1 FBSD_DRIVER=1 _XOPEN_SOURCE ]
UseHeaders [ FDirName $(SUBDIR) ] : true ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) dev rtwn ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) dev rtwn pci ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) dev rtwn rtl8192c ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) dev rtwn rtl8192c pci ] ;
KernelAddon realtekwifi :
if_rtwn.c
glue.c
if_rtwn.c
if_rtwn_beacon.c
if_rtwn_calib.c
if_rtwn_cam.c
if_rtwn_efuse.c
if_rtwn_fw.c
if_rtwn_rx.c
if_rtwn_task.c
if_rtwn_tx.c
# pci/
rtwn_pci_attach.c
rtwn_pci_reg.c
rtwn_pci_rx.c
rtwn_pci_tx.c
# rtl8192c/
r92c_attach.c
r92c_beacon.c
r92c_calib.c
r92c_chan.c
r92c_fw.c
r92c_init.c
r92c_llt.c
r92c_rf.c
r92c_rom.c
r92c_rx.c
r92c_tx.c
# rtl8192c/pci/
r92ce_attach.c
r92ce_calib.c
r92ce_fw.c
r92ce_init.c
r92ce_led.c
r92ce_rx.c
r92ce_tx.c
:
freebsd_wlan.a
libfreebsd_network.a
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,269 @@
/*-
* Copyright (c) 2010 Damien Bergamini <[email protected]>
* Copyright (c) 2014 Kevin Lo <[email protected]>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <[email protected]>
*
* 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: releng/12.0/sys/dev/rtwn/if_rtwn_beacon.c 310867 2016-12-30 22:24:01Z avos $");
#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/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_beacon.h>
#include <dev/rtwn/if_rtwn_debug.h>
#include <dev/rtwn/if_rtwn_tx.h>
#include <dev/rtwn/rtl8192c/r92c_reg.h>
static void
rtwn_reset_beacon_valid(struct rtwn_softc *sc, int id)
{
KASSERT (id == 0 || id == 1, ("wrong port id %d\n", id));
/* XXX cannot be cleared on RTL8188CE */
rtwn_setbits_1_shift(sc, sc->bcn_status_reg[id],
R92C_TDECTRL_BCN_VALID, 0, 2);
RTWN_DPRINTF(sc, RTWN_DEBUG_BEACON,
"%s: 'beacon valid' bit for vap %d was unset\n",
__func__, id);
}
static int
rtwn_check_beacon_valid(struct rtwn_softc *sc, int id)
{
uint16_t reg;
int ntries;
if (id == RTWN_VAP_ID_INVALID)
return (0);
reg = sc->bcn_status_reg[id];
for (ntries = 0; ntries < 10; ntries++) {
if (rtwn_read_4(sc, reg) & R92C_TDECTRL_BCN_VALID) {
RTWN_DPRINTF(sc, RTWN_DEBUG_BEACON,
"%s: beacon for vap %d was recognized\n",
__func__, id);
break;
}
rtwn_delay(sc, sc->bcn_check_interval);
}
if (ntries == 10)
return (ETIMEDOUT);
return (0);
}
void
rtwn_switch_bcnq(struct rtwn_softc *sc, int id)
{
if (sc->cur_bcnq_id != id) {
/* Wait until any previous transmit completes. */
(void) rtwn_check_beacon_valid(sc, sc->cur_bcnq_id);
/* Change current port. */
rtwn_beacon_select(sc, id);
sc->cur_bcnq_id = id;
}
/* Reset 'beacon valid' bit. */
rtwn_reset_beacon_valid(sc, id);
}
int
rtwn_setup_beacon(struct rtwn_softc *sc, struct ieee80211_node *ni)
{
struct ieee80211vap *vap = ni->ni_vap;
struct rtwn_vap *uvp = RTWN_VAP(vap);
struct mbuf *m;
RTWN_ASSERT_LOCKED(sc);
if (ni->ni_chan == IEEE80211_CHAN_ANYC)
return (EINVAL);
m = ieee80211_beacon_alloc(ni);
if (m == NULL) {
device_printf(sc->sc_dev,
"%s: could not allocate beacon frame\n", __func__);
return (ENOMEM);
}
if (uvp->bcn_mbuf != NULL) {
rtwn_beacon_unload(sc, uvp->id);
m_freem(uvp->bcn_mbuf);
}
uvp->bcn_mbuf = m;
rtwn_beacon_set_rate(sc, &uvp->bcn_desc.txd[0],
IEEE80211_IS_CHAN_5GHZ(ni->ni_chan));
return (rtwn_tx_beacon_check(sc, uvp));
}
/*
* Push a beacon frame into the chip. Beacon will
* be repeated by the chip every R92C_BCN_INTERVAL.
*/
static int
rtwn_tx_beacon(struct rtwn_softc *sc, struct rtwn_vap *uvp)
{
int error;
RTWN_ASSERT_LOCKED(sc);
RTWN_DPRINTF(sc, RTWN_DEBUG_BEACON,
"%s: sending beacon for vap %d\n", __func__, uvp->id);
error = rtwn_tx_start(sc, NULL, uvp->bcn_mbuf, &uvp->bcn_desc.txd[0],
IEEE80211_FC0_TYPE_MGT, uvp->id);
return (error);
}
void
rtwn_update_beacon(struct ieee80211vap *vap, int item)
{
struct ieee80211com *ic = vap->iv_ic;
struct rtwn_softc *sc = ic->ic_softc;
struct rtwn_vap *uvp = RTWN_VAP(vap);
struct ieee80211_beacon_offsets *bo = &vap->iv_bcn_off;
struct ieee80211_node *ni = vap->iv_bss;
int mcast = 0;
RTWN_LOCK(sc);
if (uvp->bcn_mbuf == NULL) {
uvp->bcn_mbuf = ieee80211_beacon_alloc(ni);
if (uvp->bcn_mbuf == NULL) {
device_printf(sc->sc_dev,
"%s: could not allocate beacon frame\n", __func__);
RTWN_UNLOCK(sc);
return;
}
}
RTWN_DPRINTF(sc, RTWN_DEBUG_BEACON,
"%s: vap id %d, iv_csa_count %d, ic_csa_count %d, item %d\n",
__func__, uvp->id, vap->iv_csa_count, ic->ic_csa_count, item);
switch (item) {
case IEEE80211_BEACON_CSA:
if (vap->iv_csa_count != ic->ic_csa_count) {
/*
* XXX two APs with different beacon intervals
* are not handled properly.
*/
/* XXX check TBTT? */
taskqueue_enqueue_timeout(taskqueue_thread,
&uvp->tx_beacon_csa,
msecs_to_ticks(ni->ni_intval));
}
break;
case IEEE80211_BEACON_TIM:
mcast = 1; /* XXX */
break;
default:
break;
}
setbit(bo->bo_flags, item);
rtwn_beacon_update_begin(sc, vap);
RTWN_UNLOCK(sc);
ieee80211_beacon_update(ni, uvp->bcn_mbuf, mcast);
/* XXX clear manually */
clrbit(bo->bo_flags, IEEE80211_BEACON_CSA);
RTWN_LOCK(sc);
rtwn_tx_beacon(sc, uvp);
rtwn_beacon_update_end(sc, vap);
RTWN_UNLOCK(sc);
}
void
rtwn_tx_beacon_csa(void *arg, int npending __unused)
{
struct ieee80211vap *vap = arg;
struct ieee80211com *ic = vap->iv_ic;
struct rtwn_softc *sc = ic->ic_softc;
struct rtwn_vap *rvp = RTWN_VAP(vap);
KASSERT (rvp->id == 0 || rvp->id == 1,
("wrong port id %d\n", rvp->id));
IEEE80211_LOCK(ic);
if (ic->ic_flags & IEEE80211_F_CSAPENDING) {
RTWN_DPRINTF(sc, RTWN_DEBUG_BEACON,
"%s: vap id %d, iv_csa_count %d, ic_csa_count %d\n",
__func__, rvp->id, vap->iv_csa_count, ic->ic_csa_count);
rtwn_update_beacon(vap, IEEE80211_BEACON_CSA);
}
IEEE80211_UNLOCK(ic);
(void) rvp;
}
int
rtwn_tx_beacon_check(struct rtwn_softc *sc, struct rtwn_vap *uvp)
{
int ntries, error;
for (ntries = 0; ntries < 5; ntries++) {
rtwn_reset_beacon_valid(sc, uvp->id);
error = rtwn_tx_beacon(sc, uvp);
if (error != 0)
continue;
error = rtwn_check_beacon_valid(sc, uvp->id);
if (error == 0)
break;
}
if (ntries == 5) {
device_printf(sc->sc_dev,
"%s: cannot push beacon into chip, error %d!\n",
__func__, error);
return (error);
}
return (0);
}
@@ -0,0 +1,28 @@
/*-
* Copyright (c) 2015-2016 Andriy Voskoboinyk <[email protected]>
*
* 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: releng/12.0/sys/dev/rtwn/if_rtwn_beacon.h 310867 2016-12-30 22:24:01Z avos $
*/
#ifndef IF_RTWN_BEACON_H
#define IF_RTWN_BEACON_H
void rtwn_switch_bcnq(struct rtwn_softc *, int);
int rtwn_setup_beacon(struct rtwn_softc *, struct ieee80211_node *);
void rtwn_update_beacon(struct ieee80211vap *, int);
void rtwn_tx_beacon_csa(void *arg, int);
int rtwn_tx_beacon_check(struct rtwn_softc *, struct rtwn_vap *);
#endif /* IF_RTWN_BEACON_H */
@@ -0,0 +1,128 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <[email protected]>
* Copyright (c) 2014 Kevin Lo <[email protected]>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <[email protected]>
*
* 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: releng/12.0/sys/dev/rtwn/if_rtwn_calib.c 307529 2016-10-17 20:38:24Z avos $");
#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 <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_calib.h>
#include <dev/rtwn/if_rtwn_debug.h>
#include <dev/rtwn/if_rtwn_task.h>
static void
rtwn_temp_calib(struct rtwn_softc *sc)
{
uint8_t temp;
RTWN_ASSERT_LOCKED(sc);
if (!(sc->sc_flags & RTWN_TEMP_MEASURED)) {
/* Start measuring temperature. */
RTWN_DPRINTF(sc, RTWN_DEBUG_TEMP,
"%s: start measuring temperature\n", __func__);
rtwn_temp_measure(sc);
sc->sc_flags |= RTWN_TEMP_MEASURED;
return;
}
sc->sc_flags &= ~RTWN_TEMP_MEASURED;
/* Read measured temperature. */
temp = rtwn_temp_read(sc);
if (temp == 0) { /* Read failed, skip. */
RTWN_DPRINTF(sc, RTWN_DEBUG_TEMP,
"%s: temperature read failed, skipping\n", __func__);
return;
}
RTWN_DPRINTF(sc, RTWN_DEBUG_TEMP,
"temperature: previous %u, current %u\n",
sc->thcal_temp, temp);
/*
* Redo LC/IQ calibration if temperature changed significantly since
* last calibration.
*/
if (sc->thcal_temp == 0xff) {
/* efuse value is absent; do LCK at initial status. */
rtwn_lc_calib(sc);
sc->thcal_temp = temp;
} else if (abs(temp - sc->thcal_temp) > sc->temp_delta) {
RTWN_DPRINTF(sc, RTWN_DEBUG_TEMP,
"%s: LC/IQ calib triggered by temp: %u -> %u\n",
__func__, sc->thcal_temp, temp);
rtwn_lc_calib(sc);
rtwn_iq_calib(sc);
/* Record temperature of last calibration. */
sc->thcal_temp = temp;
}
}
static void
rtwn_calib_cb(struct rtwn_softc *sc, union sec_param *data)
{
/* Do temperature compensation. */
rtwn_temp_calib(sc);
#ifndef RTWN_WITHOUT_UCODE
if (sc->sc_ratectl == RTWN_RATECTL_FW) {
/* Refresh per-node RSSI. */
rtwn_set_rssi(sc);
}
#endif
if (sc->vaps_running > sc->monvaps_running)
callout_reset(&sc->sc_calib_to, 2*hz, rtwn_calib_to, sc);
}
void
rtwn_calib_to(void *arg)
{
struct rtwn_softc *sc = arg;
/* Do it in a process context. */
rtwn_cmd_sleepable(sc, NULL, 0, rtwn_calib_cb);
}
@@ -0,0 +1,24 @@
/*-
* Copyright (c) 2016 Andriy Voskoboinyk <[email protected]>
*
* 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: releng/12.0/sys/dev/rtwn/if_rtwn_calib.h 307529 2016-10-17 20:38:24Z avos $
*/
#ifndef IF_RTWN_CALIB_H
#define IF_RTWN_CALIB_H
void rtwn_calib_to(void *);
#endif /* IF_RTWN_CALIB_H */
@@ -0,0 +1,364 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <[email protected]>
* Copyright (c) 2014 Kevin Lo <[email protected]>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <[email protected]>
*
* 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: releng/12.0/sys/dev/rtwn/if_rtwn_cam.c 309686 2016-12-07 22:16:07Z avos $");
#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 <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_cam.h>
#include <dev/rtwn/if_rtwn_debug.h>
#include <dev/rtwn/if_rtwn_task.h>
#include <dev/rtwn/rtl8192c/r92c_reg.h>
void
rtwn_init_cam(struct rtwn_softc *sc)
{
/* Invalidate all CAM entries. */
rtwn_write_4(sc, R92C_CAMCMD,
R92C_CAMCMD_POLLING | R92C_CAMCMD_CLR);
}
static int
rtwn_cam_write(struct rtwn_softc *sc, uint32_t addr, uint32_t data)
{
int error;
error = rtwn_write_4(sc, R92C_CAMWRITE, data);
if (error != 0)
return (error);
error = rtwn_write_4(sc, R92C_CAMCMD,
R92C_CAMCMD_POLLING | R92C_CAMCMD_WRITE |
SM(R92C_CAMCMD_ADDR, addr));
return (error);
}
void
rtwn_init_seccfg(struct rtwn_softc *sc)
{
uint16_t seccfg;
/* Select decryption / encryption flags. */
seccfg = 0;
switch (sc->sc_hwcrypto) {
case RTWN_CRYPTO_SW:
break; /* nothing to do */
case RTWN_CRYPTO_PAIR:
/* NB: TXUCKEY_DEF / RXUCKEY_DEF are required for RTL8192C */
seccfg = R92C_SECCFG_TXUCKEY_DEF | R92C_SECCFG_RXUCKEY_DEF |
R92C_SECCFG_TXENC_ENA | R92C_SECCFG_RXDEC_ENA |
R92C_SECCFG_MC_SRCH_DIS;
break;
case RTWN_CRYPTO_FULL:
seccfg = R92C_SECCFG_TXUCKEY_DEF | R92C_SECCFG_RXUCKEY_DEF |
R92C_SECCFG_TXENC_ENA | R92C_SECCFG_RXDEC_ENA |
R92C_SECCFG_TXBCKEY_DEF | R92C_SECCFG_RXBCKEY_DEF;
break;
default:
KASSERT(0, ("%s: case %d was not handled\n", __func__,
sc->sc_hwcrypto));
break;
}
RTWN_DPRINTF(sc, RTWN_DEBUG_KEY, "%s: seccfg %04X, hwcrypto %d\n",
__func__, seccfg, sc->sc_hwcrypto);
rtwn_write_2(sc, R92C_SECCFG, seccfg);
}
int
rtwn_key_alloc(struct ieee80211vap *vap, struct ieee80211_key *k,
ieee80211_keyix *keyix, ieee80211_keyix *rxkeyix)
{
struct rtwn_softc *sc = vap->iv_ic->ic_softc;
int i, start;
if (&vap->iv_nw_keys[0] <= k &&
k < &vap->iv_nw_keys[IEEE80211_WEP_NKID]) {
#if __FreeBSD_version > 1200018
*keyix = ieee80211_crypto_get_key_wepidx(vap, k);
#else
*keyix = k - vap->iv_nw_keys;
#endif
if (sc->sc_hwcrypto != RTWN_CRYPTO_FULL)
k->wk_flags |= IEEE80211_KEY_SWCRYPT;
else {
RTWN_LOCK(sc);
if (isset(sc->keys_bmap, *keyix)) {
device_printf(sc->sc_dev,
"%s: group key slot %d is already used!\n",
__func__, *keyix);
/* XXX recover? */
RTWN_UNLOCK(sc);
return (0);
}
setbit(sc->keys_bmap, *keyix);
RTWN_UNLOCK(sc);
}
goto end;
}
start = sc->cam_entry_limit;
switch (sc->sc_hwcrypto) {
case RTWN_CRYPTO_SW:
k->wk_flags |= IEEE80211_KEY_SWCRYPT;
*keyix = 0;
goto end;
case RTWN_CRYPTO_PAIR:
/* all slots for pairwise keys. */
start = 0;
RTWN_LOCK(sc);
if (sc->sc_flags & RTWN_FLAG_CAM_FIXED)
start = 4;
RTWN_UNLOCK(sc);
break;
case RTWN_CRYPTO_FULL:
/* first 4 - for group keys, others for pairwise. */
start = 4;
break;
default:
KASSERT(0, ("%s: case %d was not handled!\n",
__func__, sc->sc_hwcrypto));
break;
}
RTWN_LOCK(sc);
for (i = start; i < sc->cam_entry_limit; i++) {
if (isclr(sc->keys_bmap, i)) {
setbit(sc->keys_bmap, i);
*keyix = i;
break;
}
}
RTWN_UNLOCK(sc);
if (i == sc->cam_entry_limit) {
#if __FreeBSD_version > 1200008
/* XXX check and remove keys with the same MAC address */
k->wk_flags |= IEEE80211_KEY_SWCRYPT;
*keyix = 0;
#else
device_printf(sc->sc_dev,
"%s: no free space in the key table\n", __func__);
return (0);
#endif
}
end:
*rxkeyix = *keyix;
return (1);
}
static int
rtwn_key_set_cb0(struct rtwn_softc *sc, const struct ieee80211_key *k)
{
uint8_t algo, keyid;
int i, error;
if (sc->sc_hwcrypto == RTWN_CRYPTO_FULL &&
k->wk_keyix < IEEE80211_WEP_NKID)
keyid = k->wk_keyix;
else
keyid = 0;
/* Map net80211 cipher to HW crypto algorithm. */
switch (k->wk_cipher->ic_cipher) {
case IEEE80211_CIPHER_WEP:
if (k->wk_keylen < 8)
algo = R92C_CAM_ALGO_WEP40;
else
algo = R92C_CAM_ALGO_WEP104;
break;
case IEEE80211_CIPHER_TKIP:
algo = R92C_CAM_ALGO_TKIP;
break;
case IEEE80211_CIPHER_AES_CCM:
algo = R92C_CAM_ALGO_AES;
break;
default:
device_printf(sc->sc_dev, "%s: unknown cipher %u\n",
__func__, k->wk_cipher->ic_cipher);
return (EINVAL);
}
RTWN_DPRINTF(sc, RTWN_DEBUG_KEY,
"%s: keyix %u, keyid %u, algo %u/%u, flags %04X, len %u, "
"macaddr %s\n", __func__, k->wk_keyix, keyid,
k->wk_cipher->ic_cipher, algo, k->wk_flags, k->wk_keylen,
ether_sprintf(k->wk_macaddr));
/* Clear high bits. */
rtwn_cam_write(sc, R92C_CAM_CTL6(k->wk_keyix), 0);
rtwn_cam_write(sc, R92C_CAM_CTL7(k->wk_keyix), 0);
/* Write key. */
for (i = 0; i < 4; i++) {
error = rtwn_cam_write(sc, R92C_CAM_KEY(k->wk_keyix, i),
le32dec(&k->wk_key[i * 4]));
if (error != 0)
goto fail;
}
/* Write CTL0 last since that will validate the CAM entry. */
error = rtwn_cam_write(sc, R92C_CAM_CTL1(k->wk_keyix),
le32dec(&k->wk_macaddr[2]));
if (error != 0)
goto fail;
error = rtwn_cam_write(sc, R92C_CAM_CTL0(k->wk_keyix),
SM(R92C_CAM_ALGO, algo) |
SM(R92C_CAM_KEYID, keyid) |
SM(R92C_CAM_MACLO, le16dec(&k->wk_macaddr[0])) |
R92C_CAM_VALID);
if (error != 0)
goto fail;
return (0);
fail:
device_printf(sc->sc_dev, "%s fails, error %d\n", __func__, error);
return (error);
}
static void
rtwn_key_set_cb(struct rtwn_softc *sc, union sec_param *data)
{
const struct ieee80211_key *k = &data->key;
(void) rtwn_key_set_cb0(sc, k);
}
int
rtwn_init_static_keys(struct rtwn_softc *sc, struct rtwn_vap *rvp)
{
int i, error;
if (sc->sc_hwcrypto != RTWN_CRYPTO_FULL)
return (0); /* nothing to do */
for (i = 0; i < IEEE80211_WEP_NKID; i++) {
const struct ieee80211_key *k = rvp->keys[i];
if (k != NULL) {
error = rtwn_key_set_cb0(sc, k);
if (error != 0)
return (error);
}
}
return (0);
}
static void
rtwn_key_del_cb(struct rtwn_softc *sc, union sec_param *data)
{
struct ieee80211_key *k = &data->key;
int i;
RTWN_DPRINTF(sc, RTWN_DEBUG_KEY,
"%s: keyix %u, flags %04X, macaddr %s\n", __func__,
k->wk_keyix, k->wk_flags, ether_sprintf(k->wk_macaddr));
rtwn_cam_write(sc, R92C_CAM_CTL0(k->wk_keyix), 0);
rtwn_cam_write(sc, R92C_CAM_CTL1(k->wk_keyix), 0);
/* Clear key. */
for (i = 0; i < 4; i++)
rtwn_cam_write(sc, R92C_CAM_KEY(k->wk_keyix, i), 0);
clrbit(sc->keys_bmap, k->wk_keyix);
}
static int
rtwn_process_key(struct ieee80211vap *vap, const struct ieee80211_key *k,
int set)
{
struct rtwn_softc *sc = vap->iv_ic->ic_softc;
if (k->wk_flags & IEEE80211_KEY_SWCRYPT) {
/* Not for us. */
return (1);
}
if (&vap->iv_nw_keys[0] <= k &&
k < &vap->iv_nw_keys[IEEE80211_WEP_NKID]) {
#if __FreeBSD_version <= 1200008
struct ieee80211_key *k1 = &vap->iv_nw_keys[k->wk_keyix];
if (sc->sc_hwcrypto != RTWN_CRYPTO_FULL) {
k1->wk_flags |= IEEE80211_KEY_SWCRYPT;
return (k->wk_cipher->ic_setkey(k1));
} else {
#else
if (sc->sc_hwcrypto == RTWN_CRYPTO_FULL) {
#endif
struct rtwn_vap *rvp = RTWN_VAP(vap);
RTWN_LOCK(sc);
rvp->keys[k->wk_keyix] = (set ? k : NULL);
if ((sc->sc_flags & RTWN_RUNNING) == 0) {
if (!set)
clrbit(sc->keys_bmap, k->wk_keyix);
RTWN_UNLOCK(sc);
return (1);
}
RTWN_UNLOCK(sc);
}
}
return (!rtwn_cmd_sleepable(sc, k, sizeof(*k),
set ? rtwn_key_set_cb : rtwn_key_del_cb));
}
int
rtwn_key_set(struct ieee80211vap *vap, const struct ieee80211_key *k)
{
return (rtwn_process_key(vap, k, 1));
}
int
rtwn_key_delete(struct ieee80211vap *vap, const struct ieee80211_key *k)
{
return (rtwn_process_key(vap, k, 0));
}
@@ -0,0 +1,30 @@
/*-
* Copyright (c) 2015-2016 Andriy Voskoboinyk <[email protected]>
*
* 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: releng/12.0/sys/dev/rtwn/if_rtwn_cam.h 307529 2016-10-17 20:38:24Z avos $
*/
#ifndef IF_RTWN_CAM_H
#define IF_RTWN_CAM_H
void rtwn_init_cam(struct rtwn_softc *);
void rtwn_init_seccfg(struct rtwn_softc *);
int rtwn_key_alloc(struct ieee80211vap *, struct ieee80211_key *,
ieee80211_keyix *, ieee80211_keyix *);
int rtwn_key_set(struct ieee80211vap *, const struct ieee80211_key *);
int rtwn_init_static_keys(struct rtwn_softc *, struct rtwn_vap *);
int rtwn_key_delete(struct ieee80211vap *, const struct ieee80211_key *);
#endif /* IF_RTWN_CAM_H */
@@ -0,0 +1,58 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <[email protected]>
* Copyright (c) 2014 Kevin Lo <[email protected]>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <[email protected]>
*
* 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: releng/12.0/sys/dev/rtwn/if_rtwn_debug.h 310867 2016-12-30 22:24:01Z avos $
*/
#ifndef IF_RTWN_DEBUG_H
#define IF_RTWN_DEBUG_H
#ifdef RTWN_DEBUG
enum {
RTWN_DEBUG_XMIT = 0x00000001, /* basic xmit operation */
RTWN_DEBUG_XMIT_DESC = 0x00000002, /* xmit descriptors */
RTWN_DEBUG_RECV = 0x00000004, /* basic recv operation */
RTWN_DEBUG_RECV_DESC = 0x00000008, /* recv descriptors */
RTWN_DEBUG_STATE = 0x00000010, /* 802.11 state transitions */
RTWN_DEBUG_RA = 0x00000020, /* f/w rate adaptation setup */
RTWN_DEBUG_USB = 0x00000040, /* usb requests */
RTWN_DEBUG_FIRMWARE = 0x00000080, /* firmware(9) loading debug */
RTWN_DEBUG_BEACON = 0x00000100, /* beacon handling */
RTWN_DEBUG_INTR = 0x00000200, /* ISR */
RTWN_DEBUG_TEMP = 0x00000400, /* temperature calibration */
RTWN_DEBUG_ROM = 0x00000800, /* various ROM info */
RTWN_DEBUG_KEY = 0x00001000, /* crypto keys management */
RTWN_DEBUG_TXPWR = 0x00002000, /* dump Tx power values */
RTWN_DEBUG_RSSI = 0x00004000, /* dump RSSI lookups */
RTWN_DEBUG_RESET = 0x00008000, /* initialization progress */
RTWN_DEBUG_CALIB = 0x00010000, /* calibration progress */
RTWN_DEBUG_RADAR = 0x00020000, /* radar detection status */
RTWN_DEBUG_ANY = 0xffffffff
};
#define RTWN_DPRINTF(_sc, _m, ...) do { \
if ((_sc)->sc_debug & (_m)) \
device_printf((_sc)->sc_dev, __VA_ARGS__); \
} while(0)
#else
#define RTWN_DPRINTF(_sc, _m, ...) do { (void) _sc; } while (0)
#endif
#endif /* IF_RTWN_DEBUG_H */
@@ -0,0 +1,265 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <[email protected]>
* Copyright (c) 2014 Kevin Lo <[email protected]>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <[email protected]>
*
* 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: releng/12.0/sys/dev/rtwn/if_rtwn_efuse.c 307529 2016-10-17 20:38:24Z avos $");
#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 <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/if_rtwn_debug.h>
#include <dev/rtwn/if_rtwn_efuse.h>
#include <dev/rtwn/rtl8192c/r92c_reg.h>
static int
rtwn_efuse_switch_power(struct rtwn_softc *sc)
{
uint32_t reg;
int error;
error = rtwn_write_1(sc, R92C_EFUSE_ACCESS, R92C_EFUSE_ACCESS_ON);
if (error != 0)
return (error);
reg = rtwn_read_2(sc, R92C_SYS_FUNC_EN);
if (!(reg & R92C_SYS_FUNC_EN_ELDR)) {
error = rtwn_write_2(sc, R92C_SYS_FUNC_EN,
reg | R92C_SYS_FUNC_EN_ELDR);
if (error != 0)
return (error);
}
reg = rtwn_read_2(sc, R92C_SYS_CLKR);
if ((reg & (R92C_SYS_CLKR_LOADER_EN | R92C_SYS_CLKR_ANA8M)) !=
(R92C_SYS_CLKR_LOADER_EN | R92C_SYS_CLKR_ANA8M)) {
error = rtwn_write_2(sc, R92C_SYS_CLKR,
reg | R92C_SYS_CLKR_LOADER_EN | R92C_SYS_CLKR_ANA8M);
if (error != 0)
return (error);
}
return (0);
}
int
rtwn_efuse_read_next(struct rtwn_softc *sc, uint8_t *val)
{
uint32_t reg;
int ntries, error;
if (sc->next_rom_addr >= sc->efuse_maxlen)
return (EFAULT);
reg = rtwn_read_4(sc, R92C_EFUSE_CTRL);
reg = RW(reg, R92C_EFUSE_CTRL_ADDR, sc->next_rom_addr);
reg &= ~R92C_EFUSE_CTRL_VALID;
error = rtwn_write_4(sc, R92C_EFUSE_CTRL, reg);
if (error != 0)
return (error);
/* Wait for read operation to complete. */
for (ntries = 0; ntries < 100; ntries++) {
reg = rtwn_read_4(sc, R92C_EFUSE_CTRL);
if (reg & R92C_EFUSE_CTRL_VALID)
break;
rtwn_delay(sc, 10);
}
if (ntries == 100) {
device_printf(sc->sc_dev,
"could not read efuse byte at address 0x%x\n",
sc->next_rom_addr);
return (ETIMEDOUT);
}
*val = MS(reg, R92C_EFUSE_CTRL_DATA);
sc->next_rom_addr++;
return (0);
}
static int
rtwn_efuse_read_data(struct rtwn_softc *sc, uint8_t *rom, uint8_t off,
uint8_t msk)
{
uint8_t reg;
int addr, i, error;
for (i = 0; i < 4; i++) {
if (msk & (1 << i))
continue;
addr = off * 8 + i * 2;
if (addr + 1 >= sc->efuse_maplen)
return (EFAULT);
error = rtwn_efuse_read_next(sc, &reg);
if (error != 0)
return (error);
RTWN_DPRINTF(sc, RTWN_DEBUG_ROM, "rom[0x%03X] == 0x%02X\n",
addr, reg);
rom[addr] = reg;
error = rtwn_efuse_read_next(sc, &reg);
if (error != 0)
return (error);
RTWN_DPRINTF(sc, RTWN_DEBUG_ROM, "rom[0x%03X] == 0x%02X\n",
addr + 1, reg);
rom[addr + 1] = reg;
}
return (0);
}
#ifdef RTWN_DEBUG
static void
rtwn_dump_rom_contents(struct rtwn_softc *sc, uint8_t *rom, uint16_t size)
{
int i;
/* Dump ROM contents. */
device_printf(sc->sc_dev, "%s:", __func__);
for (i = 0; i < size; i++) {
if (i % 32 == 0)
printf("\n%03X: ", i);
else if (i % 4 == 0)
printf(" ");
printf("%02X", rom[i]);
}
printf("\n");
}
#endif
static int
rtwn_efuse_read(struct rtwn_softc *sc, uint8_t *rom, uint16_t size)
{
#define RTWN_CHK(res) do { \
if ((error = res) != 0) \
goto end; \
} while(0)
uint8_t msk, off, reg;
int error;
/* Read full ROM image. */
sc->next_rom_addr = 0;
memset(rom, 0xff, size);
RTWN_CHK(rtwn_efuse_read_next(sc, &reg));
while (reg != 0xff) {
/* check for extended header */
if ((sc->sc_flags & RTWN_FLAG_EXT_HDR) &&
(reg & 0x1f) == 0x0f) {
off = reg >> 5;
RTWN_CHK(rtwn_efuse_read_next(sc, &reg));
if ((reg & 0x0f) != 0x0f)
off = ((reg & 0xf0) >> 1) | off;
else
continue;
} else
off = reg >> 4;
msk = reg & 0xf;
RTWN_CHK(rtwn_efuse_read_data(sc, rom, off, msk));
RTWN_CHK(rtwn_efuse_read_next(sc, &reg));
}
end:
#ifdef RTWN_DEBUG
if (sc->sc_debug & RTWN_DEBUG_ROM)
rtwn_dump_rom_contents(sc, rom, size);
#endif
/* Device-specific. */
rtwn_efuse_postread(sc);
if (error != 0) {
device_printf(sc->sc_dev, "%s: error while reading ROM\n",
__func__);
}
return (error);
#undef RTWN_CHK
}
static int
rtwn_efuse_read_prepare(struct rtwn_softc *sc, uint8_t *rom, uint16_t size)
{
int error;
error = rtwn_efuse_switch_power(sc);
if (error != 0)
goto fail;
error = rtwn_efuse_read(sc, rom, size);
fail:
rtwn_write_1(sc, R92C_EFUSE_ACCESS, R92C_EFUSE_ACCESS_OFF);
return (error);
}
int
rtwn_read_rom(struct rtwn_softc *sc)
{
uint8_t *rom;
int error;
rom = malloc(sc->efuse_maplen, M_TEMP, M_WAITOK);
/* Read full ROM image. */
RTWN_LOCK(sc);
error = rtwn_efuse_read_prepare(sc, rom, sc->efuse_maplen);
RTWN_UNLOCK(sc);
if (error != 0)
goto fail;
/* Parse & save data in softc. */
rtwn_parse_rom(sc, rom);
fail:
free(rom, M_TEMP);
return (error);
}
@@ -0,0 +1,25 @@
/*-
* Copyright (c) 2015-2016 Andriy Voskoboinyk <[email protected]>
*
* 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: releng/12.0/sys/dev/rtwn/if_rtwn_efuse.h 307529 2016-10-17 20:38:24Z avos $
*/
#ifndef IF_RTWN_EFUSE_H
#define IF_RTWN_EFUSE_H
int rtwn_efuse_read_next(struct rtwn_softc *, uint8_t *);
int rtwn_read_rom(struct rtwn_softc *);
#endif /* IF_RTWN_EFUSE_H */
@@ -0,0 +1,224 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <[email protected]>
* Copyright (c) 2014 Kevin Lo <[email protected]>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <[email protected]>
*
* 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: releng/12.0/sys/dev/rtwn/if_rtwn_fw.c 307529 2016-10-17 20:38:24Z avos $");
#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 <sys/firmware.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/if_rtwn_debug.h>
#include <dev/rtwn/if_rtwn_fw.h>
#include <dev/rtwn/rtl8192c/r92c_reg.h>
#ifndef RTWN_WITHOUT_UCODE
static int
rtwn_fw_loadpage(struct rtwn_softc *sc, int page, const uint8_t *buf,
int len)
{
uint32_t reg;
uint16_t off;
int mlen, error;
reg = rtwn_read_4(sc, R92C_MCUFWDL);
reg = RW(reg, R92C_MCUFWDL_PAGE, page);
rtwn_write_4(sc, R92C_MCUFWDL, reg);
error = 0;
off = R92C_FW_START_ADDR;
while (len > 0) {
if (len > R92C_FW_MAX_BLOCK_SIZE)
mlen = R92C_FW_MAX_BLOCK_SIZE;
else if (len > 4)
mlen = 4;
else
mlen = 1;
error = rtwn_fw_write_block(sc, buf, off, mlen);
if (error != 0)
break;
off += mlen;
buf += mlen;
len -= mlen;
}
if (error != 0) {
RTWN_DPRINTF(sc, RTWN_DEBUG_FIRMWARE,
"%s: could not load firmware page %d (offset %u)\n",
__func__, page, off);
}
return (error);
}
static int
rtwn_fw_checksum_report(struct rtwn_softc *sc)
{
int ntries;
for (ntries = 0; ntries < 25; ntries++) {
if (rtwn_read_4(sc, R92C_MCUFWDL) & R92C_MCUFWDL_CHKSUM_RPT)
break;
rtwn_delay(sc, 10000);
}
if (ntries == 25) {
RTWN_DPRINTF(sc, RTWN_DEBUG_FIRMWARE,
"timeout waiting for checksum report\n");
return (ETIMEDOUT);
}
return (0);
}
int
rtwn_load_firmware(struct rtwn_softc *sc)
{
const struct firmware *fw;
const struct r92c_fw_hdr *hdr;
const u_char *ptr;
size_t len;
int ntries, error;
/* Read firmware image from the filesystem. */
RTWN_UNLOCK(sc);
fw = firmware_get(sc->fwname);
RTWN_LOCK(sc);
if (fw == NULL) {
device_printf(sc->sc_dev,
"failed loadfirmware of file %s\n", sc->fwname);
return (ENOENT);
}
len = fw->datasize;
if (len < sizeof(*hdr) || len > sc->fwsize_limit) {
device_printf(sc->sc_dev, "wrong firmware size (%zu)\n", len);
error = EINVAL;
goto fail;
}
ptr = fw->data;
hdr = (const struct r92c_fw_hdr *)ptr;
/* Check if there is a valid FW header and skip it. */
if ((le16toh(hdr->signature) >> 4) == sc->fwsig) {
sc->fwver = le16toh(hdr->version);
RTWN_DPRINTF(sc, RTWN_DEBUG_FIRMWARE,
"FW V%u.%u %02u-%02u %02u:%02u\n",
le16toh(hdr->version), le16toh(hdr->subversion),
hdr->month, hdr->date, hdr->hour, hdr->minute);
ptr += sizeof(*hdr);
len -= sizeof(*hdr);
}
if (rtwn_read_1(sc, R92C_MCUFWDL) & R92C_MCUFWDL_RAM_DL_SEL) {
rtwn_write_1(sc, R92C_MCUFWDL, 0);
rtwn_fw_reset(sc, RTWN_FW_RESET_DOWNLOAD);
}
/* Enable firmware download. */
rtwn_fw_download_enable(sc, 1);
error = 0; /* compiler warning */
for (ntries = 0; ntries < 3; ntries++) {
const u_char *curr_ptr = ptr;
const int maxpages = len / R92C_FW_PAGE_SIZE;
int page;
/* Reset the FWDL checksum. */
rtwn_setbits_1(sc, R92C_MCUFWDL, 0, R92C_MCUFWDL_CHKSUM_RPT);
for (page = 0; page < maxpages; page++) {
error = rtwn_fw_loadpage(sc, page, curr_ptr,
R92C_FW_PAGE_SIZE);
if (error != 0)
break;
curr_ptr += R92C_FW_PAGE_SIZE;
}
if (page != maxpages)
continue;
if (len % R92C_FW_PAGE_SIZE != 0) {
error = rtwn_fw_loadpage(sc, page, curr_ptr,
len % R92C_FW_PAGE_SIZE);
if (error != 0)
continue;
}
/* Wait for checksum report. */
error = rtwn_fw_checksum_report(sc);
if (error == 0)
break;
}
if (ntries == 3) {
device_printf(sc->sc_dev,
"%s: failed to upload firmware %s (error %d)\n",
__func__, sc->fwname, error);
goto fail;
}
/* Disable firmware download. */
rtwn_fw_download_enable(sc, 0);
rtwn_setbits_4(sc, R92C_MCUFWDL, R92C_MCUFWDL_WINTINI_RDY,
R92C_MCUFWDL_RDY);
rtwn_fw_reset(sc, RTWN_FW_RESET_CHECKSUM);
/* Wait for firmware readiness. */
for (ntries = 0; ntries < 20; ntries++) {
if (rtwn_read_4(sc, R92C_MCUFWDL) & R92C_MCUFWDL_WINTINI_RDY)
break;
rtwn_delay(sc, 10000);
}
if (ntries == 20) {
device_printf(sc->sc_dev,
"timeout waiting for firmware readiness\n");
error = ETIMEDOUT;
goto fail;
}
fail:
firmware_put(fw, FIRMWARE_UNLOAD);
return (error);
}
#endif
@@ -0,0 +1,59 @@
/*-
* Copyright (c) 2010 Damien Bergamini <[email protected]>
* Copyright (c) 2016 Andriy Voskoboinyk <[email protected]>
*
* 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.
*
* $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $
* $FreeBSD: releng/12.0/sys/dev/rtwn/if_rtwn_fw.h 307529 2016-10-17 20:38:24Z avos $
*/
#ifndef IF_RTWN_FW_H
#define IF_RTWN_FW_H
/*
* Firmware base address.
*/
#define R92C_FW_START_ADDR 0x1000
#define R92C_FW_PAGE_SIZE 4096
#define R92C_FW_MAX_BLOCK_SIZE 196
/*
* Firmware image header.
*/
struct r92c_fw_hdr {
/* QWORD0 */
uint16_t signature;
uint8_t category;
uint8_t function;
uint16_t version;
uint16_t subversion;
/* QWORD1 */
uint8_t month;
uint8_t date;
uint8_t hour;
uint8_t minute;
uint16_t ramcodesize;
uint16_t reserved2;
/* QWORD2 */
uint32_t svnidx;
uint32_t reserved3;
/* QWORD3 */
uint32_t reserved4;
uint32_t reserved5;
} __packed;
int rtwn_load_firmware(struct rtwn_softc *);
#endif /* IF_RTWN_FW_H */
@@ -0,0 +1,69 @@
/*-
* Copyright (c) 2016 Andriy Voskoboinyk <[email protected]>
*
* 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: releng/12.0/sys/dev/rtwn/if_rtwn_nop.h 307529 2016-10-17 20:38:24Z avos $
*/
#ifndef IF_RTWN_NOP_H
#define IF_RTWN_NOP_H
static __inline void
rtwn_nop_softc(struct rtwn_softc *sc)
{
}
static __inline int
rtwn_nop_int_softc(struct rtwn_softc *sc)
{
return (0);
}
static __inline int
rtwn_nop_int_softc_mbuf(struct rtwn_softc *sc, struct mbuf *m)
{
return (0);
}
static __inline void
rtwn_nop_softc_int(struct rtwn_softc *sc, int id)
{
}
static __inline void
rtwn_nop_softc_uint32(struct rtwn_softc *sc, uint32_t reg)
{
}
static __inline void
rtwn_nop_softc_chan(struct rtwn_softc *sc, struct ieee80211_channel *c)
{
}
static __inline void
rtwn_nop_softc_vap(struct rtwn_softc *sc, struct ieee80211vap *vap)
{
}
static __inline void
rtwn_nop_softc_uint8_int(struct rtwn_softc *sc, uint8_t *buf, int len)
{
}
static __inline void
rtwn_nop_void_int(void *buf, int is5ghz)
{
}
#endif /* IF_RTWN_NOP_H */
@@ -0,0 +1,95 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <[email protected]>
* Copyright (c) 2014 Kevin Lo <[email protected]>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <[email protected]>
*
* 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: releng/12.0/sys/dev/rtwn/if_rtwn_ridx.h 331043 2018-03-16 01:03:10Z avos $
*/
#ifndef IF_RTWN_RIDX_H
#define IF_RTWN_RIDX_H
/* HW rate indices. */
#define RTWN_RIDX_CCK1 0
#define RTWN_RIDX_CCK2 1
#define RTWN_RIDX_CCK55 2
#define RTWN_RIDX_CCK11 3
#define RTWN_RIDX_OFDM6 4
#define RTWN_RIDX_OFDM9 5
#define RTWN_RIDX_OFDM12 6
#define RTWN_RIDX_OFDM18 7
#define RTWN_RIDX_OFDM24 8
#define RTWN_RIDX_OFDM36 9
#define RTWN_RIDX_OFDM48 10
#define RTWN_RIDX_OFDM54 11
#define RTWN_RIDX_HT_MCS_SHIFT 12
#define RTWN_RIDX_HT_MCS(i) (RTWN_RIDX_HT_MCS_SHIFT + (i))
#define RTWN_RIDX_COUNT 28
#define RTWN_RIDX_UNKNOWN (uint8_t)-1
#define RTWN_RATE_IS_CCK(rate) ((rate) <= RTWN_RIDX_CCK11)
#define RTWN_RATE_IS_OFDM(rate) \
((rate) >= RTWN_RIDX_OFDM6 && (rate) != RTWN_RIDX_UNKNOWN)
static const uint8_t ridx2rate[] =
{ 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
static __inline uint8_t
rate2ridx(uint8_t rate)
{
if (rate & IEEE80211_RATE_MCS) {
return ((rate & 0xf) + RTWN_RIDX_HT_MCS_SHIFT);
}
switch (rate) {
/* 11g */
case 12: return 4;
case 18: return 5;
case 24: return 6;
case 36: return 7;
case 48: return 8;
case 72: return 9;
case 96: return 10;
case 108: return 11;
/* 11b */
case 2: return 0;
case 4: return 1;
case 11: return 2;
case 22: return 3;
default: return RTWN_RIDX_UNKNOWN;
}
}
/* XXX move to net80211 */
static __inline__ uint8_t
rtwn_ctl_mcsrate(const struct ieee80211_rate_table *rt, uint8_t ridx)
{
uint8_t cix, rate;
/* Check if we are using MCS rate. */
KASSERT(ridx >= RTWN_RIDX_HT_MCS(0) && ridx != RTWN_RIDX_UNKNOWN,
("bad mcs rate index %d", ridx));
rate = (ridx - RTWN_RIDX_HT_MCS(0)) | IEEE80211_RATE_MCS;
cix = rt->info[rt->rateCodeToIndex[rate]].ctlRateIndex;
KASSERT(cix != (uint8_t)-1, ("rate %d (%d) has no info", rate, ridx));
return rt->info[cix].dot11Rate;
}
#endif /* IF_RTWN_RIDX_H */
@@ -0,0 +1,517 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <[email protected]>
* Copyright (c) 2014 Kevin Lo <[email protected]>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <[email protected]>
*
* 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: releng/12.0/sys/dev/rtwn/if_rtwn_rx.c 333813 2018-05-18 20:13:34Z mmacy $");
#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 <net/if.h>
#include <net/if_var.h>
#include <net/ethernet.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/if_rtwn_debug.h>
#include <dev/rtwn/if_rtwn_ridx.h>
#include <dev/rtwn/if_rtwn_rx.h>
#include <dev/rtwn/rtl8192c/r92c_reg.h>
void
rtwn_get_rates(struct rtwn_softc *sc, const struct ieee80211_rateset *rs,
const struct ieee80211_htrateset *rs_ht, uint32_t *rates_p,
int *maxrate_p, int basic_rates)
{
uint32_t rates;
uint8_t ridx;
int i, maxrate;
/* Get rates mask. */
rates = 0;
maxrate = 0;
/* This is for 11bg */
for (i = 0; i < rs->rs_nrates; i++) {
/* Convert 802.11 rate to HW rate index. */
ridx = rate2ridx(IEEE80211_RV(rs->rs_rates[i]));
if (ridx == RTWN_RIDX_UNKNOWN) /* Unknown rate, skip. */
continue;
if (((rs->rs_rates[i] & IEEE80211_RATE_BASIC) != 0) ||
!basic_rates) {
rates |= 1 << ridx;
if (ridx > maxrate)
maxrate = ridx;
}
}
/* If we're doing 11n, enable 11n rates */
if (rs_ht != NULL && !basic_rates) {
for (i = 0; i < rs_ht->rs_nrates; i++) {
if ((rs_ht->rs_rates[i] & 0x7f) > 0xf)
continue;
/* 11n rates start at index 12 */
ridx = RTWN_RIDX_HT_MCS((rs_ht->rs_rates[i]) & 0xf);
rates |= (1 << ridx);
/* Guard against the rate table being oddly ordered */
if (ridx > maxrate)
maxrate = ridx;
}
}
RTWN_DPRINTF(sc, RTWN_DEBUG_RA,
"%s: rates 0x%08X, maxrate %d\n", __func__, rates, maxrate);
if (rates_p != NULL)
*rates_p = rates;
if (maxrate_p != NULL)
*maxrate_p = maxrate;
}
void
rtwn_set_basicrates(struct rtwn_softc *sc, uint32_t rates)
{
RTWN_DPRINTF(sc, RTWN_DEBUG_RA, "%s: rates 0x%08X\n", __func__, rates);
rtwn_setbits_4(sc, R92C_RRSR, R92C_RRSR_RATE_BITMAP_M, rates);
}
static void
rtwn_update_avgrssi(struct rtwn_softc *sc, struct rtwn_node *un, int8_t rssi,
int is_cck)
{
int pwdb;
/* Convert antenna signal to percentage. */
if (rssi <= -100 || rssi >= 20)
pwdb = 0;
else if (rssi >= 0)
pwdb = 100;
else
pwdb = 100 + rssi;
if (is_cck) {
/* CCK gain is smaller than OFDM/MCS gain. */
pwdb += 6;
if (pwdb > 100)
pwdb = 100;
if (pwdb <= 14)
pwdb -= 4;
else if (pwdb <= 26)
pwdb -= 8;
else if (pwdb <= 34)
pwdb -= 6;
else if (pwdb <= 42)
pwdb -= 2;
}
if (un->avg_pwdb == -1) /* Init. */
un->avg_pwdb = pwdb;
else if (un->avg_pwdb < pwdb)
un->avg_pwdb = ((un->avg_pwdb * 19 + pwdb) / 20) + 1;
else
un->avg_pwdb = ((un->avg_pwdb * 19 + pwdb) / 20);
RTWN_DPRINTF(sc, RTWN_DEBUG_RSSI,
"MACID %d, PWDB %d, EMA %d\n", un->id, pwdb, un->avg_pwdb);
}
static int8_t
rtwn_get_rssi(struct rtwn_softc *sc, void *physt, int is_cck)
{
int8_t rssi;
if (is_cck)
rssi = rtwn_get_rssi_cck(sc, physt);
else /* OFDM/HT. */
rssi = rtwn_get_rssi_ofdm(sc, physt);
return (rssi);
}
static uint32_t
rtwn_get_tsf_low(struct rtwn_softc *sc, int id)
{
return (rtwn_read_4(sc, R92C_TSFTR(id)));
}
static uint32_t
rtwn_get_tsf_high(struct rtwn_softc *sc, int id)
{
return (rtwn_read_4(sc, R92C_TSFTR(id) + 4));
}
static void
rtwn_get_tsf(struct rtwn_softc *sc, uint64_t *buf, int id)
{
/* NB: we cannot read it at once. */
*buf = rtwn_get_tsf_high(sc, id);
*buf <<= 32;
*buf += rtwn_get_tsf_low(sc, id);
}
static uint64_t
rtwn_extend_rx_tsf(struct rtwn_softc *sc,
const struct rtwn_rx_stat_common *stat)
{
uint64_t tsft;
uint32_t rxdw3, tsfl, tsfl_curr;
int id;
rxdw3 = le32toh(stat->rxdw3);
tsfl = le32toh(stat->tsf_low);
id = MS(rxdw3, RTWN_RXDW3_BSSID01_FIT);
switch (id) {
case 1:
case 2:
id >>= 1;
tsfl_curr = rtwn_get_tsf_low(sc, id);
break;
default:
{
uint32_t tsfl0, tsfl1;
tsfl0 = rtwn_get_tsf_low(sc, 0);
tsfl1 = rtwn_get_tsf_low(sc, 1);
if (abs(tsfl0 - tsfl) < abs(tsfl1 - tsfl)) {
id = 0;
tsfl_curr = tsfl0;
} else {
id = 1;
tsfl_curr = tsfl1;
}
break;
}
}
tsft = rtwn_get_tsf_high(sc, id);
if (tsfl > tsfl_curr && tsfl > 0xffff0000)
tsft--;
tsft <<= 32;
tsft += tsfl;
return (tsft);
}
struct ieee80211_node *
rtwn_rx_common(struct rtwn_softc *sc, struct mbuf *m, void *desc)
{
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_node *ni;
struct ieee80211_frame_min *wh;
struct ieee80211_rx_stats rxs;
struct rtwn_node *un;
struct rtwn_rx_stat_common *stat;
void *physt;
uint32_t rxdw0;
int8_t rssi;
int cipher, infosz, is_cck, pktlen, shift;
stat = desc;
rxdw0 = le32toh(stat->rxdw0);
cipher = MS(rxdw0, RTWN_RXDW0_CIPHER);
infosz = MS(rxdw0, RTWN_RXDW0_INFOSZ) * 8;
pktlen = MS(rxdw0, RTWN_RXDW0_PKTLEN);
shift = MS(rxdw0, RTWN_RXDW0_SHIFT);
wh = (struct ieee80211_frame_min *)(mtodo(m, shift + infosz));
if ((wh->i_fc[1] & IEEE80211_FC1_PROTECTED) &&
cipher != R92C_CAM_ALGO_NONE)
m->m_flags |= M_WEP;
if (pktlen >= sizeof(*wh)) {
ni = ieee80211_find_rxnode(ic, wh);
if (ni != NULL && (ni->ni_flags & IEEE80211_NODE_HT))
m->m_flags |= M_AMPDU;
} else
ni = NULL;
un = RTWN_NODE(ni);
if (infosz != 0 && (rxdw0 & RTWN_RXDW0_PHYST))
physt = (void *)mtodo(m, shift);
else
physt = (un != NULL) ? &un->last_physt : &sc->last_physt;
bzero(&rxs, sizeof(rxs));
rtwn_get_rx_stats(sc, &rxs, desc, physt);
if (rxs.c_pktflags & IEEE80211_RX_F_AMPDU) {
/* Next MPDU will come without PHY info. */
memcpy(&sc->last_physt, physt, sizeof(sc->last_physt));
if (un != NULL)
memcpy(&un->last_physt, physt, sizeof(sc->last_physt));
}
/* Add some common bits. */
/* NB: should not happen. */
if (rxdw0 & RTWN_RXDW0_CRCERR)
rxs.c_pktflags |= IEEE80211_RX_F_FAIL_FCSCRC;
rxs.r_flags |= IEEE80211_R_TSF_START; /* XXX undocumented */
rxs.r_flags |= IEEE80211_R_TSF64;
rxs.c_rx_tsf = rtwn_extend_rx_tsf(sc, stat);
/* Get RSSI from PHY status descriptor. */
is_cck = (rxs.c_pktflags & IEEE80211_RX_F_CCK) != 0;
rssi = rtwn_get_rssi(sc, physt, is_cck);
/* XXX TODO: we really need a rate-to-string method */
RTWN_DPRINTF(sc, RTWN_DEBUG_RSSI, "%s: rssi %d, rate %d\n",
__func__, rssi, rxs.c_rate);
if (un != NULL && infosz != 0 && (rxdw0 & RTWN_RXDW0_PHYST)) {
/* Update our average RSSI. */
rtwn_update_avgrssi(sc, un, rssi, is_cck);
}
rxs.r_flags |= IEEE80211_R_NF | IEEE80211_R_RSSI;
rxs.c_nf = RTWN_NOISE_FLOOR;
rxs.c_rssi = rssi - rxs.c_nf;
(void) ieee80211_add_rx_params(m, &rxs);
if (ieee80211_radiotap_active(ic)) {
struct rtwn_rx_radiotap_header *tap = &sc->sc_rxtap;
tap->wr_flags = rtwn_rx_radiotap_flags(sc, desc);
tap->wr_tsft = htole64(rxs.c_rx_tsf);
tap->wr_rate = rxs.c_rate;
tap->wr_dbm_antsignal = rssi;
tap->wr_dbm_antnoise = rxs.c_nf;
}
/* Drop PHY descriptor. */
m_adj(m, infosz + shift);
return (ni);
}
void
rtwn_adhoc_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m, int subtype,
const struct ieee80211_rx_stats *rxs,
int rssi, int nf)
{
struct ieee80211vap *vap = ni->ni_vap;
struct rtwn_softc *sc = vap->iv_ic->ic_softc;
struct rtwn_vap *uvp = RTWN_VAP(vap);
uint64_t ni_tstamp, curr_tstamp;
uvp->recv_mgmt(ni, m, subtype, rxs, rssi, nf);
if (vap->iv_state == IEEE80211_S_RUN &&
(subtype == IEEE80211_FC0_SUBTYPE_BEACON ||
subtype == IEEE80211_FC0_SUBTYPE_PROBE_RESP)) {
ni_tstamp = le64toh(ni->ni_tstamp.tsf);
RTWN_LOCK(sc);
rtwn_get_tsf(sc, &curr_tstamp, uvp->id);
RTWN_UNLOCK(sc);
if (ni_tstamp >= curr_tstamp)
(void) ieee80211_ibss_merge(ni);
}
}
static uint8_t
rtwn_get_multi_pos(const uint8_t maddr[])
{
uint64_t mask = 0x00004d101df481b4;
uint8_t pos = 0x27; /* initial value */
int i, j;
for (i = 0; i < IEEE80211_ADDR_LEN; i++)
for (j = (i == 0) ? 1 : 0; j < 8; j++)
if ((maddr[i] >> j) & 1)
pos ^= (mask >> (i * 8 + j - 1));
pos &= 0x3f;
return (pos);
}
void
rtwn_set_multi(struct rtwn_softc *sc)
{
struct ieee80211com *ic = &sc->sc_ic;
uint32_t mfilt[2];
RTWN_ASSERT_LOCKED(sc);
/* general structure was copied from ath(4). */
if (ic->ic_allmulti == 0) {
struct ieee80211vap *vap;
struct ifnet *ifp;
struct ifmultiaddr *ifma;
/*
* Merge multicast addresses to form the hardware filter.
*/
mfilt[0] = mfilt[1] = 0;
TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
ifp = vap->iv_ifp;
if_maddr_rlock(ifp);
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
caddr_t dl;
uint8_t pos;
dl = LLADDR((struct sockaddr_dl *)
ifma->ifma_addr);
pos = rtwn_get_multi_pos(dl);
mfilt[pos / 32] |= (1 << (pos % 32));
}
if_maddr_runlock(ifp);
}
} else
mfilt[0] = mfilt[1] = ~0;
rtwn_write_4(sc, R92C_MAR + 0, mfilt[0]);
rtwn_write_4(sc, R92C_MAR + 4, mfilt[1]);
RTWN_DPRINTF(sc, RTWN_DEBUG_STATE, "%s: MC filter %08x:%08x\n",
__func__, mfilt[0], mfilt[1]);
}
static void
rtwn_rxfilter_update_mgt(struct rtwn_softc *sc)
{
uint16_t filter;
filter = 0x7f7f;
if (sc->bcn_vaps == 0) { /* STA and/or MONITOR mode vaps */
filter &= ~(
R92C_RXFLTMAP_SUBTYPE(IEEE80211_FC0_SUBTYPE_ASSOC_REQ) |
R92C_RXFLTMAP_SUBTYPE(IEEE80211_FC0_SUBTYPE_REASSOC_REQ) |
R92C_RXFLTMAP_SUBTYPE(IEEE80211_FC0_SUBTYPE_PROBE_REQ));
}
if (sc->ap_vaps == sc->nvaps - sc->mon_vaps) { /* AP vaps only */
filter &= ~(
R92C_RXFLTMAP_SUBTYPE(IEEE80211_FC0_SUBTYPE_ASSOC_RESP) |
R92C_RXFLTMAP_SUBTYPE(IEEE80211_FC0_SUBTYPE_REASSOC_RESP));
}
rtwn_write_2(sc, R92C_RXFLTMAP0, filter);
}
void
rtwn_rxfilter_update(struct rtwn_softc *sc)
{
RTWN_ASSERT_LOCKED(sc);
/* Filter for management frames. */
rtwn_rxfilter_update_mgt(sc);
/* Update Rx filter. */
rtwn_set_promisc(sc);
}
void
rtwn_rxfilter_init(struct rtwn_softc *sc)
{
RTWN_ASSERT_LOCKED(sc);
/* Setup multicast filter. */
rtwn_set_multi(sc);
/* Reject all control frames. */
rtwn_write_2(sc, R92C_RXFLTMAP1, 0x0000);
/* Reject all data frames. */
rtwn_write_2(sc, R92C_RXFLTMAP2, 0x0000);
/* Append generic Rx filter bits. */
sc->rcr |= R92C_RCR_AM | R92C_RCR_AB | R92C_RCR_APM |
R92C_RCR_HTC_LOC_CTRL | R92C_RCR_APP_PHYSTS |
R92C_RCR_APP_ICV | R92C_RCR_APP_MIC;
/* Update dynamic Rx filter parts. */
rtwn_rxfilter_update(sc);
}
void
rtwn_rxfilter_set(struct rtwn_softc *sc)
{
if (!(sc->sc_flags & RTWN_RCR_LOCKED))
rtwn_write_4(sc, R92C_RCR, sc->rcr);
}
void
rtwn_set_rx_bssid_all(struct rtwn_softc *sc, int enable)
{
if (enable)
sc->rcr &= ~R92C_RCR_CBSSID_BCN;
else
sc->rcr |= R92C_RCR_CBSSID_BCN;
rtwn_rxfilter_set(sc);
}
void
rtwn_set_promisc(struct rtwn_softc *sc)
{
struct ieee80211com *ic = &sc->sc_ic;
uint32_t mask_all, mask_min;
RTWN_ASSERT_LOCKED(sc);
mask_all = R92C_RCR_ACF | R92C_RCR_ADF | R92C_RCR_AMF | R92C_RCR_AAP;
mask_min = R92C_RCR_APM;
if (sc->bcn_vaps == 0)
mask_min |= R92C_RCR_CBSSID_BCN;
if (sc->ap_vaps == 0)
mask_min |= R92C_RCR_CBSSID_DATA;
if (ic->ic_promisc == 0 && sc->mon_vaps == 0) {
if (sc->bcn_vaps != 0)
mask_all |= R92C_RCR_CBSSID_BCN;
if (sc->ap_vaps != 0) /* for Null data frames */
mask_all |= R92C_RCR_CBSSID_DATA;
sc->rcr &= ~mask_all;
sc->rcr |= mask_min;
} else {
sc->rcr &= ~mask_min;
sc->rcr |= mask_all;
}
rtwn_rxfilter_set(sc);
}
@@ -0,0 +1,39 @@
/*-
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $FreeBSD: releng/12.0/sys/dev/rtwn/if_rtwn_rx.h 312315 2017-01-17 00:35:23Z avos $
*/
#ifndef IF_RTWN_RX_H
#define IF_RTWN_RX_H
#define RTWN_NOISE_FLOOR -95
void rtwn_get_rates(struct rtwn_softc *, const struct ieee80211_rateset *,
const struct ieee80211_htrateset *, uint32_t *, int *, int);
void rtwn_set_basicrates(struct rtwn_softc *, uint32_t);
struct ieee80211_node * rtwn_rx_common(struct rtwn_softc *, struct mbuf *,
void *);
void rtwn_adhoc_recv_mgmt(struct ieee80211_node *, struct mbuf *, int,
const struct ieee80211_rx_stats *, int, int);
void rtwn_set_multi(struct rtwn_softc *);
void rtwn_rxfilter_update(struct rtwn_softc *);
void rtwn_rxfilter_init(struct rtwn_softc *);
void rtwn_rxfilter_set(struct rtwn_softc *);
void rtwn_set_rx_bssid_all(struct rtwn_softc *, int);
void rtwn_set_promisc(struct rtwn_softc *);
#endif /* IF_RTWN_RX_H */
@@ -0,0 +1,122 @@
/*-
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/if_rtwn_task.c 307529 2016-10-17 20:38:24Z avos $");
#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 <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_task.h>
static void
rtwn_cmdq_cb(void *arg, int pending)
{
struct rtwn_softc *sc = arg;
struct rtwn_cmdq *item;
/*
* Device must be powered on (via rtwn_power_on())
* before any command may be sent.
*/
RTWN_LOCK(sc);
if (!(sc->sc_flags & RTWN_RUNNING)) {
RTWN_UNLOCK(sc);
return;
}
RTWN_CMDQ_LOCK(sc);
while (sc->cmdq[sc->cmdq_first].func != NULL) {
item = &sc->cmdq[sc->cmdq_first];
sc->cmdq_first = (sc->cmdq_first + 1) % RTWN_CMDQ_SIZE;
RTWN_CMDQ_UNLOCK(sc);
item->func(sc, &item->data);
RTWN_CMDQ_LOCK(sc);
memset(item, 0, sizeof (*item));
}
RTWN_CMDQ_UNLOCK(sc);
RTWN_UNLOCK(sc);
}
void
rtwn_cmdq_init(struct rtwn_softc *sc)
{
RTWN_CMDQ_LOCK_INIT(sc);
TASK_INIT(&sc->cmdq_task, 0, rtwn_cmdq_cb, sc);
}
void
rtwn_cmdq_destroy(struct rtwn_softc *sc)
{
if (RTWN_CMDQ_LOCK_INITIALIZED(sc))
RTWN_CMDQ_LOCK_DESTROY(sc);
}
int
rtwn_cmd_sleepable(struct rtwn_softc *sc, const void *ptr, size_t len,
CMD_FUNC_PROTO)
{
struct ieee80211com *ic = &sc->sc_ic;
KASSERT(len <= sizeof(union sec_param), ("buffer overflow"));
RTWN_CMDQ_LOCK(sc);
if (sc->sc_detached) {
RTWN_CMDQ_UNLOCK(sc);
return (ESHUTDOWN);
}
if (sc->cmdq[sc->cmdq_last].func != NULL) {
device_printf(sc->sc_dev, "%s: cmdq overflow\n", __func__);
RTWN_CMDQ_UNLOCK(sc);
return (EAGAIN);
}
if (ptr != NULL)
memcpy(&sc->cmdq[sc->cmdq_last].data, ptr, len);
sc->cmdq[sc->cmdq_last].func = func;
sc->cmdq_last = (sc->cmdq_last + 1) % RTWN_CMDQ_SIZE;
RTWN_CMDQ_UNLOCK(sc);
ieee80211_runtask(ic, &sc->cmdq_task);
return (0);
}
@@ -0,0 +1,27 @@
/*-
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $FreeBSD: releng/12.0/sys/dev/rtwn/if_rtwn_task.h 307529 2016-10-17 20:38:24Z avos $
*/
#ifndef IF_RTWN_TASK_H
#define IF_RTWN_TASK_H
void rtwn_cmdq_init(struct rtwn_softc *);
void rtwn_cmdq_destroy(struct rtwn_softc *);
int rtwn_cmd_sleepable(struct rtwn_softc *, const void *, size_t,
CMD_FUNC_PROTO);
#endif /* IF_RTWN_TASK_H */
@@ -0,0 +1,340 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* 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: releng/12.0/sys/dev/rtwn/if_rtwn_tx.c 314315 2017-02-26 20:49:35Z avos $");
#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 <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>
#include <dev/rtwn/if_rtwn_beacon.h>
#include <dev/rtwn/if_rtwn_debug.h>
#include <dev/rtwn/if_rtwn_ridx.h>
#include <dev/rtwn/if_rtwn_tx.h>
void
rtwn_drain_mbufq(struct rtwn_softc *sc)
{
struct mbuf *m;
struct ieee80211_node *ni;
RTWN_ASSERT_LOCKED(sc);
while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
m->m_pkthdr.rcvif = NULL;
ieee80211_free_node(ni);
m_freem(m);
}
}
#ifdef IEEE80211_SUPPORT_SUPERG
void
rtwn_ff_flush_all(struct rtwn_softc *sc, union sec_param *data)
{
struct ieee80211com *ic = &sc->sc_ic;
RTWN_UNLOCK(sc);
ieee80211_ff_flush_all(ic);
RTWN_LOCK(sc);
}
#endif
static uint8_t
rtwn_get_cipher(u_int ic_cipher)
{
uint8_t cipher;
switch (ic_cipher) {
case IEEE80211_CIPHER_NONE:
cipher = RTWN_TXDW1_CIPHER_NONE;
break;
case IEEE80211_CIPHER_WEP:
case IEEE80211_CIPHER_TKIP:
cipher = RTWN_TXDW1_CIPHER_RC4;
break;
case IEEE80211_CIPHER_AES_CCM:
cipher = RTWN_TXDW1_CIPHER_AES;
break;
default:
KASSERT(0, ("%s: unknown cipher %d\n", __func__,
ic_cipher));
return (RTWN_TXDW1_CIPHER_SM4);
}
return (cipher);
}
static int
rtwn_tx_data(struct rtwn_softc *sc, struct ieee80211_node *ni,
struct mbuf *m)
{
const struct ieee80211_txparam *tp = ni->ni_txparms;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = ni->ni_vap;
struct ieee80211_key *k = NULL;
struct ieee80211_frame *wh;
struct rtwn_tx_desc_common *txd;
struct rtwn_tx_buf buf;
uint8_t rate, ridx, type;
u_int cipher;
int ismcast;
RTWN_ASSERT_LOCKED(sc);
wh = mtod(m, struct ieee80211_frame *);
type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
/* Choose a TX rate index. */
if (type == IEEE80211_FC0_TYPE_MGT ||
type == IEEE80211_FC0_TYPE_CTL ||
(m->m_flags & M_EAPOL) != 0)
rate = tp->mgmtrate;
else if (ismcast)
rate = tp->mcastrate;
else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
rate = tp->ucastrate;
else {
if (sc->sc_ratectl == RTWN_RATECTL_NET80211) {
/* XXX pass pktlen */
(void) ieee80211_ratectl_rate(ni, NULL, 0);
rate = ni->ni_txrate;
} else {
if (ni->ni_flags & IEEE80211_NODE_HT)
rate = IEEE80211_RATE_MCS | 0x4; /* MCS4 */
else if (ic->ic_curmode != IEEE80211_MODE_11B)
rate = ridx2rate[RTWN_RIDX_OFDM36];
else
rate = ridx2rate[RTWN_RIDX_CCK55];
}
}
ridx = rate2ridx(rate);
cipher = IEEE80211_CIPHER_NONE;
if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
k = ieee80211_crypto_encap(ni, m);
if (k == NULL) {
device_printf(sc->sc_dev,
"ieee80211_crypto_encap returns NULL.\n");
return (ENOBUFS);
}
if (!(k->wk_flags & IEEE80211_KEY_SWCRYPT))
cipher = k->wk_cipher->ic_cipher;
/* in case packet header moved, reset pointer */
wh = mtod(m, struct ieee80211_frame *);
}
/* Fill Tx descriptor. */
txd = (struct rtwn_tx_desc_common *)&buf;
memset(txd, 0, sc->txdesc_len);
txd->txdw1 = htole32(SM(RTWN_TXDW1_CIPHER, rtwn_get_cipher(cipher)));
rtwn_fill_tx_desc(sc, ni, m, txd, ridx, tp->maxretry);
if (ieee80211_radiotap_active_vap(vap)) {
struct rtwn_tx_radiotap_header *tap = &sc->sc_txtap;
tap->wt_flags = rtwn_tx_radiotap_flags(sc, txd);
if (k != NULL)
tap->wt_flags |= IEEE80211_RADIOTAP_F_WEP;
ieee80211_radiotap_tx(vap, m);
}
return (rtwn_tx_start(sc, ni, m, (uint8_t *)txd, type, 0));
}
static int
rtwn_tx_raw(struct rtwn_softc *sc, struct ieee80211_node *ni,
struct mbuf *m, const struct ieee80211_bpf_params *params)
{
struct ieee80211vap *vap = ni->ni_vap;
struct ieee80211_key *k = NULL;
struct ieee80211_frame *wh;
struct rtwn_tx_desc_common *txd;
struct rtwn_tx_buf buf;
uint8_t type;
u_int cipher;
/* Encrypt the frame if need be. */
cipher = IEEE80211_CIPHER_NONE;
if (params->ibp_flags & IEEE80211_BPF_CRYPTO) {
/* Retrieve key for TX. */
k = ieee80211_crypto_encap(ni, m);
if (k == NULL) {
device_printf(sc->sc_dev,
"ieee80211_crypto_encap returns NULL.\n");
return (ENOBUFS);
}
if (!(k->wk_flags & IEEE80211_KEY_SWCRYPT))
cipher = k->wk_cipher->ic_cipher;
}
wh = mtod(m, struct ieee80211_frame *);
type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
/* Fill Tx descriptor. */
txd = (struct rtwn_tx_desc_common *)&buf;
memset(txd, 0, sc->txdesc_len);
txd->txdw1 = htole32(SM(RTWN_TXDW1_CIPHER, rtwn_get_cipher(cipher)));
rtwn_fill_tx_desc_raw(sc, ni, m, txd, params);
if (ieee80211_radiotap_active_vap(vap)) {
struct rtwn_tx_radiotap_header *tap = &sc->sc_txtap;
tap->wt_flags = rtwn_tx_radiotap_flags(sc, txd);
if (k != NULL)
tap->wt_flags |= IEEE80211_RADIOTAP_F_WEP;
ieee80211_radiotap_tx(vap, m);
}
return (rtwn_tx_start(sc, ni, m, (uint8_t *)txd, type, 0));
}
int
rtwn_transmit(struct ieee80211com *ic, struct mbuf *m)
{
struct rtwn_softc *sc = ic->ic_softc;
int error;
RTWN_LOCK(sc);
if ((sc->sc_flags & RTWN_RUNNING) == 0) {
RTWN_UNLOCK(sc);
return (ENXIO);
}
error = mbufq_enqueue(&sc->sc_snd, m);
if (error) {
RTWN_UNLOCK(sc);
return (error);
}
rtwn_start(sc);
RTWN_UNLOCK(sc);
return (0);
}
void
rtwn_start(struct rtwn_softc *sc)
{
struct ieee80211_node *ni;
struct mbuf *m;
RTWN_ASSERT_LOCKED(sc);
while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
if (sc->qfullmsk != 0) {
mbufq_prepend(&sc->sc_snd, m);
break;
}
ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
m->m_pkthdr.rcvif = NULL;
RTWN_DPRINTF(sc, RTWN_DEBUG_XMIT,
"%s: called; m %p, ni %p\n", __func__, m, ni);
if (rtwn_tx_data(sc, ni, m) != 0) {
if_inc_counter(ni->ni_vap->iv_ifp,
IFCOUNTER_OERRORS, 1);
m_freem(m);
#ifdef D4054
ieee80211_tx_watchdog_refresh(ni->ni_ic, -1, 0);
#endif
ieee80211_free_node(ni);
break;
}
}
}
int
rtwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
const struct ieee80211_bpf_params *params)
{
struct ieee80211com *ic = ni->ni_ic;
struct rtwn_softc *sc = ic->ic_softc;
int error;
RTWN_DPRINTF(sc, RTWN_DEBUG_XMIT, "%s: called; m %p, ni %p\n",
__func__, m, ni);
/* prevent management frames from being sent if we're not ready */
RTWN_LOCK(sc);
if (!(sc->sc_flags & RTWN_RUNNING)) {
error = ENETDOWN;
goto end;
}
if (sc->qfullmsk != 0) {
error = ENOBUFS;
goto end;
}
if (params == NULL) {
/*
* Legacy path; interpret frame contents to decide
* precisely how to send the frame.
*/
error = rtwn_tx_data(sc, ni, m);
} else {
/*
* Caller supplied explicit parameters to use in
* sending the frame.
*/
error = rtwn_tx_raw(sc, ni, m, params);
}
end:
if (error != 0) {
if (m->m_flags & M_TXCB)
ieee80211_process_callback(ni, m, 1);
m_freem(m);
}
RTWN_UNLOCK(sc);
return (error);
}
@@ -0,0 +1,31 @@
/*-
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $FreeBSD: releng/12.0/sys/dev/rtwn/if_rtwn_tx.h 308575 2016-11-12 17:58:37Z avos $
*/
#ifndef IF_RTWN_TX_H
#define IF_RTWN_TX_H
void rtwn_drain_mbufq(struct rtwn_softc *);
#ifdef IEEE80211_SUPPORT_SUPERG
void rtwn_ff_flush_all(struct rtwn_softc *, union sec_param *);
#endif
int rtwn_transmit(struct ieee80211com *, struct mbuf *);
void rtwn_start(struct rtwn_softc *);
int rtwn_raw_xmit(struct ieee80211_node *, struct mbuf *,
const struct ieee80211_bpf_params *);
#endif /* IF_RTWN_TX_H */
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,635 @@
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $
* $FreeBSD: releng/12.0/sys/dev/rtwn/if_rtwnvar.h 320640 2017-07-04 07:07:08Z avos $
*/
#ifndef IF_RTWNVAR_H
#define IF_RTWNVAR_H
#define RTWN_TX_DESC_SIZE 64
#define RTWN_BCN_MAX_SIZE 512
#define RTWN_CAM_ENTRY_LIMIT 64
#define RTWN_MACID_BC 1 /* Broadcast. */
#define RTWN_MACID_UNDEFINED 0x7fff
#define RTWN_MACID_VALID 0x8000
#define RTWN_MACID_LIMIT 128
#define RTWN_TX_TIMEOUT 5000 /* ms */
#define RTWN_MAX_EPOUT 4
#define RTWN_PORT_COUNT 2
#define RTWN_LED_LINK 0
#define RTWN_LED_DATA 1
struct rtwn_rx_radiotap_header {
struct ieee80211_radiotap_header wr_ihdr;
uint64_t wr_tsft;
uint8_t wr_flags;
uint8_t wr_rate;
uint16_t wr_chan_freq;
uint16_t wr_chan_flags;
int8_t wr_dbm_antsignal;
int8_t wr_dbm_antnoise;
} __packed __aligned(8);
#define RTWN_RX_RADIOTAP_PRESENT \
(1 << IEEE80211_RADIOTAP_TSFT | \
1 << IEEE80211_RADIOTAP_FLAGS | \
1 << IEEE80211_RADIOTAP_RATE | \
1 << IEEE80211_RADIOTAP_CHANNEL | \
1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL | \
1 << IEEE80211_RADIOTAP_DBM_ANTNOISE)
struct rtwn_tx_radiotap_header {
struct ieee80211_radiotap_header wt_ihdr;
uint8_t wt_flags;
uint16_t wt_chan_freq;
uint16_t wt_chan_flags;
} __packed __aligned(8);
#define RTWN_TX_RADIOTAP_PRESENT \
(1 << IEEE80211_RADIOTAP_FLAGS | \
1 << IEEE80211_RADIOTAP_CHANNEL)
struct rtwn_tx_buf {
uint8_t txd[RTWN_TX_DESC_SIZE];
} __attribute__((aligned(4)));
#define RTWN_PHY_STATUS_SIZE 32
struct rtwn_tx_phystat {
uint32_t phydw[RTWN_PHY_STATUS_SIZE / sizeof(uint32_t)];
};
struct rtwn_softc;
union sec_param {
struct ieee80211_key key;
int macid;
};
#define CMD_FUNC_PROTO void (*func)(struct rtwn_softc *, \
union sec_param *)
struct rtwn_cmdq {
union sec_param data;
CMD_FUNC_PROTO;
};
#define RTWN_CMDQ_SIZE 16
struct rtwn_node {
struct ieee80211_node ni; /* must be the first */
int id;
struct rtwn_tx_phystat last_physt;
int avg_pwdb;
};
#define RTWN_NODE(ni) ((struct rtwn_node *)(ni))
struct rtwn_vap {
struct ieee80211vap vap;
int id;
#define RTWN_VAP_ID_INVALID -1
int curr_mode;
struct rtwn_tx_buf bcn_desc;
struct mbuf *bcn_mbuf;
struct timeout_task tx_beacon_csa;
struct callout tsf_sync_adhoc;
struct task tsf_sync_adhoc_task;
const struct ieee80211_key *keys[IEEE80211_WEP_NKID];
int (*newstate)(struct ieee80211vap *,
enum ieee80211_state, int);
void (*recv_mgmt)(struct ieee80211_node *,
struct mbuf *, int,
const struct ieee80211_rx_stats *,
int, int);
};
#define RTWN_VAP(vap) ((struct rtwn_vap *)(vap))
/*
* Rx data types.
*/
enum {
RTWN_RX_DATA,
RTWN_RX_TX_REPORT,
RTWN_RX_OTHER
};
/*
* Firmware reset reasons.
*/
enum {
RTWN_FW_RESET_DOWNLOAD,
RTWN_FW_RESET_CHECKSUM,
RTWN_FW_RESET_SHUTDOWN
};
/*
* Rate control algorithm selection.
*/
enum {
RTWN_RATECTL_NONE,
RTWN_RATECTL_NET80211,
RTWN_RATECTL_FW,
RTWN_RATECTL_MAX
};
/*
* Control h/w crypto usage.
*/
enum {
RTWN_CRYPTO_SW,
RTWN_CRYPTO_PAIR,
RTWN_CRYPTO_FULL,
RTWN_CRYPTO_MAX,
};
struct rtwn_softc {
struct ieee80211com sc_ic;
struct mbufq sc_snd;
device_t sc_dev;
#if 1
int sc_ht40;
#endif
uint32_t sc_debug;
int sc_hwcrypto;
int sc_ratectl_sysctl;
int sc_ratectl;
uint8_t sc_detached;
uint8_t sc_flags;
/* Device flags */
#define RTWN_FLAG_CCK_HIPWR 0x01
#define RTWN_FLAG_EXT_HDR 0x02
#define RTWN_FLAG_CAM_FIXED 0x04
/* Driver state */
#define RTWN_STARTED 0x08
#define RTWN_RUNNING 0x10
#define RTWN_FW_LOADED 0x20
#define RTWN_TEMP_MEASURED 0x40
#define RTWN_RCR_LOCKED 0x80
#define RTWN_CHIP_HAS_BCNQ1(_sc) \
((_sc)->bcn_status_reg[0] != (_sc)->bcn_status_reg[1])
void *sc_priv;
const char *name;
int sc_ant;
struct rtwn_tx_phystat last_physt;
uint8_t thcal_temp;
int cur_bcnq_id;
int nvaps;
int ap_vaps;
int bcn_vaps;
int mon_vaps;
int vaps_running;
int monvaps_running;
uint16_t next_rom_addr;
uint8_t keys_bmap[howmany(RTWN_CAM_ENTRY_LIMIT, NBBY)];
struct rtwn_vap *vaps[RTWN_PORT_COUNT];
struct ieee80211_node *node_list[RTWN_MACID_LIMIT];
struct mtx nt_mtx;
struct callout sc_calib_to;
struct callout sc_pwrmode_init;
#ifndef D4054
struct callout sc_watchdog_to;
int sc_tx_timer;
#endif
struct mtx sc_mtx;
struct rtwn_cmdq cmdq[RTWN_CMDQ_SIZE];
struct mtx cmdq_mtx;
struct task cmdq_task;
uint8_t cmdq_first;
uint8_t cmdq_last;
struct wmeParams cap_wmeParams[WME_NUM_AC];
struct rtwn_rx_radiotap_header sc_rxtap;
struct rtwn_tx_radiotap_header sc_txtap;
int ntxchains;
int nrxchains;
int ledlink;
uint8_t thermal_meter;
int sc_tx_n_active;
uint8_t qfullmsk;
/* Firmware-specific */
const char *fwname;
uint16_t fwver;
uint16_t fwsig;
int fwcur;
void (*sc_node_free)(struct ieee80211_node *);
void (*sc_scan_curchan)(struct ieee80211_scan_state *,
unsigned long);
/* Interface-specific. */
int (*sc_write_1)(struct rtwn_softc *, uint16_t,
uint8_t);
int (*sc_write_2)(struct rtwn_softc *, uint16_t,
uint16_t);
int (*sc_write_4)(struct rtwn_softc *, uint16_t,
uint32_t);
uint8_t (*sc_read_1)(struct rtwn_softc *, uint16_t);
uint16_t (*sc_read_2)(struct rtwn_softc *, uint16_t);
uint32_t (*sc_read_4)(struct rtwn_softc *, uint16_t);
/* XXX eliminate */
void (*sc_delay)(struct rtwn_softc *, int);
int (*sc_tx_start)(struct rtwn_softc *,
struct ieee80211_node *, struct mbuf *, uint8_t *,
uint8_t, int);
void (*sc_start_xfers)(struct rtwn_softc *);
void (*sc_reset_lists)(struct rtwn_softc *,
struct ieee80211vap *);
void (*sc_abort_xfers)(struct rtwn_softc *);
int (*sc_fw_write_block)(struct rtwn_softc *,
const uint8_t *, uint16_t, int);
uint16_t (*sc_get_qmap)(struct rtwn_softc *);
void (*sc_set_desc_addr)(struct rtwn_softc *);
void (*sc_drop_incorrect_tx)(struct rtwn_softc *);
void (*sc_beacon_update_begin)(struct rtwn_softc *,
struct ieee80211vap *);
void (*sc_beacon_update_end)(struct rtwn_softc *,
struct ieee80211vap *);
void (*sc_beacon_unload)(struct rtwn_softc *, int);
/* XXX drop checks for PCIe? */
int bcn_check_interval;
/* Device-specific. */
uint32_t (*sc_rf_read)(struct rtwn_softc *, int, uint8_t);
void (*sc_rf_write)(struct rtwn_softc *, int, uint8_t,
uint32_t);
int (*sc_check_condition)(struct rtwn_softc *,
const uint8_t[]);
void (*sc_efuse_postread)(struct rtwn_softc *);
void (*sc_parse_rom)(struct rtwn_softc *, uint8_t *);
void (*sc_set_led)(struct rtwn_softc *, int, int);
int (*sc_power_on)(struct rtwn_softc *);
void (*sc_power_off)(struct rtwn_softc *);
#ifndef RTWN_WITHOUT_UCODE
void (*sc_fw_reset)(struct rtwn_softc *, int);
void (*sc_fw_download_enable)(struct rtwn_softc *, int);
#endif
int (*sc_llt_init)(struct rtwn_softc *);
int (*sc_set_page_size)(struct rtwn_softc *);
void (*sc_lc_calib)(struct rtwn_softc *);
void (*sc_iq_calib)(struct rtwn_softc *);
void (*sc_read_chipid_vendor)(struct rtwn_softc *,
uint32_t);
void (*sc_adj_devcaps)(struct rtwn_softc *);
void (*sc_vap_preattach)(struct rtwn_softc *,
struct ieee80211vap *);
void (*sc_postattach)(struct rtwn_softc *);
void (*sc_detach_private)(struct rtwn_softc *);
void (*sc_fill_tx_desc)(struct rtwn_softc *,
struct ieee80211_node *, struct mbuf *,
void *, uint8_t, int);
void (*sc_fill_tx_desc_raw)(struct rtwn_softc *,
struct ieee80211_node *, struct mbuf *,
void *, const struct ieee80211_bpf_params *);
void (*sc_fill_tx_desc_null)(struct rtwn_softc *,
void *, int, int, int);
void (*sc_dump_tx_desc)(struct rtwn_softc *, const void *);
uint8_t (*sc_tx_radiotap_flags)(const void *);
uint8_t (*sc_rx_radiotap_flags)(const void *);
void (*sc_beacon_init)(struct rtwn_softc *, void *, int);
void (*sc_beacon_enable)(struct rtwn_softc *, int, int);
void (*sc_beacon_set_rate)(void *, int);
void (*sc_beacon_select)(struct rtwn_softc *, int);
void (*sc_set_chan)(struct rtwn_softc *,
struct ieee80211_channel *);
void (*sc_set_media_status)(struct rtwn_softc *, int);
#ifndef RTWN_WITHOUT_UCODE
int (*sc_set_rsvd_page)(struct rtwn_softc *, int, int,
int);
int (*sc_set_pwrmode)(struct rtwn_softc *,
struct ieee80211vap *, int);
void (*sc_set_rssi)(struct rtwn_softc *);
#endif
void (*sc_get_rx_stats)(struct rtwn_softc *,
struct ieee80211_rx_stats *, const void *,
const void *);
int8_t (*sc_get_rssi_cck)(struct rtwn_softc *, void *);
int8_t (*sc_get_rssi_ofdm)(struct rtwn_softc *, void *);
int (*sc_classify_intr)(struct rtwn_softc *, void *, int);
void (*sc_handle_tx_report)(struct rtwn_softc *, uint8_t *,
int);
void (*sc_handle_c2h_report)(struct rtwn_softc *,
uint8_t *, int);
int (*sc_check_frame)(struct rtwn_softc *, struct mbuf *);
void (*sc_temp_measure)(struct rtwn_softc *);
uint8_t (*sc_temp_read)(struct rtwn_softc *);
void (*sc_init_tx_agg)(struct rtwn_softc *);
void (*sc_init_rx_agg)(struct rtwn_softc *);
void (*sc_init_intr)(struct rtwn_softc *);
void (*sc_init_ampdu)(struct rtwn_softc *);
void (*sc_init_edca)(struct rtwn_softc *);
void (*sc_init_bb)(struct rtwn_softc *);
void (*sc_init_rf)(struct rtwn_softc *);
void (*sc_init_antsel)(struct rtwn_softc *);
void (*sc_post_init)(struct rtwn_softc *);
int (*sc_init_bcnq1_boundary)(struct rtwn_softc *);
const uint8_t *chan_list_5ghz[3];
int chan_num_5ghz[3];
const struct rtwn_mac_prog *mac_prog;
int mac_size;
const struct rtwn_bb_prog *bb_prog;
int bb_size;
const struct rtwn_agc_prog *agc_prog;
int agc_size;
const struct rtwn_rf_prog *rf_prog;
int page_count;
int pktbuf_count;
int ackto;
int npubqpages;
int nhqpages;
int nnqpages;
int nlqpages;
int page_size;
int txdesc_len;
int efuse_maxlen;
int efuse_maplen;
uint16_t rx_dma_size;
int macid_limit;
int cam_entry_limit;
int fwsize_limit;
int temp_delta;
uint16_t bcn_status_reg[RTWN_PORT_COUNT];
uint32_t rcr; /* Rx filter */
};
MALLOC_DECLARE(M_RTWN_PRIV);
#define RTWN_LOCK(sc) mtx_lock(&(sc)->sc_mtx)
#define RTWN_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx)
#define RTWN_ASSERT_LOCKED(sc) mtx_assert(&(sc)->sc_mtx, MA_OWNED)
#define RTWN_CMDQ_LOCK_INIT(sc) \
mtx_init(&(sc)->cmdq_mtx, "cmdq lock", NULL, MTX_DEF)
#define RTWN_CMDQ_LOCK(sc) mtx_lock(&(sc)->cmdq_mtx)
#define RTWN_CMDQ_UNLOCK(sc) mtx_unlock(&(sc)->cmdq_mtx)
#define RTWN_CMDQ_LOCK_INITIALIZED(sc) mtx_initialized(&(sc)->cmdq_mtx)
#define RTWN_CMDQ_LOCK_DESTROY(sc) mtx_destroy(&(sc)->cmdq_mtx)
#define RTWN_NT_LOCK_INIT(sc) \
mtx_init(&(sc)->nt_mtx, "node table lock", NULL, MTX_DEF)
#define RTWN_NT_LOCK(sc) mtx_lock(&(sc)->nt_mtx)
#define RTWN_NT_UNLOCK(sc) mtx_unlock(&(sc)->nt_mtx)
#define RTWN_NT_LOCK_INITIALIZED(sc) mtx_initialized(&(sc)->nt_mtx)
#define RTWN_NT_LOCK_DESTROY(sc) mtx_destroy(&(sc)->nt_mtx)
void rtwn_sysctlattach(struct rtwn_softc *);
int rtwn_attach(struct rtwn_softc *);
void rtwn_detach(struct rtwn_softc *);
void rtwn_resume(struct rtwn_softc *);
void rtwn_suspend(struct rtwn_softc *);
/* Interface-specific. */
#define rtwn_write_1(_sc, _addr, _val) \
(((_sc)->sc_write_1)((_sc), (_addr), (_val)))
#define rtwn_write_2(_sc, _addr, _val) \
(((_sc)->sc_write_2)((_sc), (_addr), (_val)))
#define rtwn_write_4(_sc, _addr, _val) \
(((_sc)->sc_write_4)((_sc), (_addr), (_val)))
#define rtwn_read_1(_sc, _addr) \
(((_sc)->sc_read_1)((_sc), (_addr)))
#define rtwn_read_2(_sc, _addr) \
(((_sc)->sc_read_2)((_sc), (_addr)))
#define rtwn_read_4(_sc, _addr) \
(((_sc)->sc_read_4)((_sc), (_addr)))
#define rtwn_delay(_sc, _usec) \
(((_sc)->sc_delay)((_sc), (_usec)))
#define rtwn_tx_start(_sc, _ni, _m, _desc, _type, _id) \
(((_sc)->sc_tx_start)((_sc), (_ni), (_m), (_desc), (_type), (_id)))
#define rtwn_start_xfers(_sc) \
(((_sc)->sc_start_xfers)((_sc)))
#define rtwn_reset_lists(_sc, _vap) \
(((_sc)->sc_reset_lists)((_sc), (_vap)))
#define rtwn_abort_xfers(_sc) \
(((_sc)->sc_abort_xfers)((_sc)))
#define rtwn_fw_write_block(_sc, _buf, _reg, _len) \
(((_sc)->sc_fw_write_block)((_sc), (_buf), (_reg), (_len)))
#define rtwn_get_qmap(_sc) \
(((_sc)->sc_get_qmap)((_sc)))
#define rtwn_set_desc_addr(_sc) \
(((_sc)->sc_set_desc_addr)((_sc)))
#define rtwn_drop_incorrect_tx(_sc) \
(((_sc)->sc_drop_incorrect_tx)((_sc)))
#define rtwn_beacon_update_begin(_sc, _vap) \
(((_sc)->sc_beacon_update_begin)((_sc), (_vap)))
#define rtwn_beacon_update_end(_sc, _vap) \
(((_sc)->sc_beacon_update_end)((_sc), (_vap)))
#define rtwn_beacon_unload(_sc, _id) \
(((_sc)->sc_beacon_unload)((_sc), (_id)))
/* Aliases. */
#define rtwn_bb_write rtwn_write_4
#define rtwn_bb_read rtwn_read_4
#define rtwn_bb_setbits rtwn_setbits_4
/* Device-specific. */
#define rtwn_rf_read(_sc, _chain, _addr) \
(((_sc)->sc_rf_read)((_sc), (_chain), (_addr)))
#define rtwn_rf_write(_sc, _chain, _addr, _val) \
(((_sc)->sc_rf_write)((_sc), (_chain), (_addr), (_val)))
#define rtwn_check_condition(_sc, _cond) \
(((_sc)->sc_check_condition)((_sc), (_cond)))
#define rtwn_efuse_postread(_sc) \
(((_sc)->sc_efuse_postread)((_sc)))
#define rtwn_parse_rom(_sc, _rom) \
(((_sc)->sc_parse_rom)((_sc), (_rom)))
#define rtwn_set_led(_sc, _led, _on) \
(((_sc)->sc_set_led)((_sc), (_led), (_on)))
#define rtwn_get_rx_stats(_sc, _rxs, _desc, _physt) \
(((_sc)->sc_get_rx_stats((_sc), (_rxs), (_desc), (_physt))))
#define rtwn_get_rssi_cck(_sc, _physt) \
(((_sc)->sc_get_rssi_cck)((_sc), (_physt)))
#define rtwn_get_rssi_ofdm(_sc, _physt) \
(((_sc)->sc_get_rssi_ofdm)((_sc), (_physt)))
#define rtwn_power_on(_sc) \
(((_sc)->sc_power_on)((_sc)))
#define rtwn_power_off(_sc) \
(((_sc)->sc_power_off)((_sc)))
#ifndef RTWN_WITHOUT_UCODE
#define rtwn_fw_reset(_sc, _reason) \
(((_sc)->sc_fw_reset)((_sc), (_reason)))
#define rtwn_fw_download_enable(_sc, _enable) \
(((_sc)->sc_fw_download_enable)((_sc), (_enable)))
#endif
#define rtwn_llt_init(_sc) \
(((_sc)->sc_llt_init)((_sc)))
#define rtwn_set_page_size(_sc) \
(((_sc)->sc_set_page_size)((_sc)))
#define rtwn_lc_calib(_sc) \
(((_sc)->sc_lc_calib)((_sc)))
#define rtwn_iq_calib(_sc) \
(((_sc)->sc_iq_calib)((_sc)))
#define rtwn_read_chipid_vendor(_sc, _reg) \
(((_sc)->sc_read_chipid_vendor)((_sc), (_reg)))
#define rtwn_adj_devcaps(_sc) \
(((_sc)->sc_adj_devcaps)((_sc)))
#define rtwn_vap_preattach(_sc, _vap) \
(((_sc)->sc_vap_preattach)((_sc), (_vap)))
#define rtwn_postattach(_sc) \
(((_sc)->sc_postattach)((_sc)))
#define rtwn_detach_private(_sc) \
(((_sc)->sc_detach_private)((_sc)))
#define rtwn_fill_tx_desc(_sc, _ni, _m, \
_buf, _ridx, _maxretry) \
(((_sc)->sc_fill_tx_desc)((_sc), (_ni), \
(_m), (_buf), (_ridx), (_maxretry)))
#define rtwn_fill_tx_desc_raw(_sc, _ni, _m, \
_buf, _params) \
(((_sc)->sc_fill_tx_desc_raw)((_sc), (_ni), \
(_m), (_buf), (_params)))
#define rtwn_fill_tx_desc_null(_sc, _buf, _11b, _qos, _id) \
(((_sc)->sc_fill_tx_desc_null)((_sc), \
(_buf), (_11b), (_qos), (_id)))
#define rtwn_dump_tx_desc(_sc, _desc) \
(((_sc)->sc_dump_tx_desc)((_sc), (_desc)))
#define rtwn_tx_radiotap_flags(_sc, _buf) \
(((_sc)->sc_tx_radiotap_flags)((_buf)))
#define rtwn_rx_radiotap_flags(_sc, _buf) \
(((_sc)->sc_rx_radiotap_flags)((_buf)))
#define rtwn_set_chan(_sc, _c) \
(((_sc)->sc_set_chan)((_sc), (_c)))
#ifndef RTWN_WITHOUT_UCODE
#define rtwn_set_rsvd_page(_sc, _resp, _null, _qos_null) \
(((_sc)->sc_set_rsvd_page)((_sc), \
(_resp), (_null), (_qos_null)))
#define rtwn_set_pwrmode(_sc, _vap, _off) \
(((_sc)->sc_set_pwrmode)((_sc), (_vap), (_off)))
#define rtwn_set_rssi(_sc) \
(((_sc)->sc_set_rssi)((_sc)))
#endif
#define rtwn_classify_intr(_sc, _buf, _len) \
(((_sc)->sc_classify_intr)((_sc), (_buf), (_len)))
#define rtwn_handle_tx_report(_sc, _buf, _len) \
(((_sc)->sc_handle_tx_report)((_sc), (_buf), (_len)))
#define rtwn_handle_c2h_report(_sc, _buf, _len) \
(((_sc)->sc_handle_c2h_report)((_sc), (_buf), (_len)))
#define rtwn_check_frame(_sc, _m) \
(((_sc)->sc_check_frame)((_sc), (_m)))
#define rtwn_beacon_init(_sc, _buf, _id) \
(((_sc)->sc_beacon_init)((_sc), (_buf), (_id)))
#define rtwn_beacon_enable(_sc, _id, _enable) \
(((_sc)->sc_beacon_enable)((_sc), (_id), (_enable)))
#define rtwn_beacon_set_rate(_sc, _buf, _is5ghz) \
(((_sc)->sc_beacon_set_rate)((_buf), (_is5ghz)))
#define rtwn_beacon_select(_sc, _id) \
(((_sc)->sc_beacon_select)((_sc), (_id)))
#define rtwn_temp_measure(_sc) \
(((_sc)->sc_temp_measure)((_sc)))
#define rtwn_temp_read(_sc) \
(((_sc)->sc_temp_read)((_sc)))
#define rtwn_init_tx_agg(_sc) \
(((_sc)->sc_init_tx_agg)((_sc)))
#define rtwn_init_rx_agg(_sc) \
(((_sc)->sc_init_rx_agg)((_sc)))
#define rtwn_init_intr(_sc) \
(((_sc)->sc_init_intr)((_sc)))
#define rtwn_init_ampdu(_sc) \
(((_sc)->sc_init_ampdu)((_sc)))
#define rtwn_init_edca(_sc) \
(((_sc)->sc_init_edca)((_sc)))
#define rtwn_init_bb(_sc) \
(((_sc)->sc_init_bb)((_sc)))
#define rtwn_init_rf(_sc) \
(((_sc)->sc_init_rf)((_sc)))
#define rtwn_init_antsel(_sc) \
(((_sc)->sc_init_antsel)((_sc)))
#define rtwn_post_init(_sc) \
(((_sc)->sc_post_init)((_sc)))
#define rtwn_init_bcnq1_boundary(_sc) \
(((_sc)->sc_init_bcnq1_boundary)((_sc)))
/*
* Methods to access subfields in registers.
*/
static __inline int
rtwn_setbits_1(struct rtwn_softc *sc, uint16_t addr, uint8_t clr,
uint8_t set)
{
return (rtwn_write_1(sc, addr,
(rtwn_read_1(sc, addr) & ~clr) | set));
}
static __inline int
rtwn_setbits_1_shift(struct rtwn_softc *sc, uint16_t addr, uint32_t clr,
uint32_t set, int shift)
{
return (rtwn_setbits_1(sc, addr + shift, clr >> shift * NBBY,
set >> shift * NBBY));
}
static __inline int
rtwn_setbits_2(struct rtwn_softc *sc, uint16_t addr, uint16_t clr,
uint16_t set)
{
return (rtwn_write_2(sc, addr,
(rtwn_read_2(sc, addr) & ~clr) | set));
}
static __inline int
rtwn_setbits_4(struct rtwn_softc *sc, uint16_t addr, uint32_t clr,
uint32_t set)
{
return (rtwn_write_4(sc, addr,
(rtwn_read_4(sc, addr) & ~clr) | set));
}
static __inline void
rtwn_rf_setbits(struct rtwn_softc *sc, int chain, uint8_t addr,
uint32_t clr, uint32_t set)
{
rtwn_rf_write(sc, chain, addr,
(rtwn_rf_read(sc, chain, addr) & ~clr) | set);
}
#endif /* IF_RTWNVAR_H */
@@ -0,0 +1,793 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/pci/rtwn_pci_attach.c 320725 2017-07-06 07:37:33Z avos $");
#include <sys/param.h>
#include <sys/sysctl.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/module.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <sys/kdb.h>
#include <machine/bus.h>
#include <machine/resource.h>
#include <sys/rman.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/if_rtwn_nop.h>
#include <dev/rtwn/if_rtwn_debug.h>
#include <dev/rtwn/pci/rtwn_pci_var.h>
#include <dev/rtwn/pci/rtwn_pci_attach.h>
#include <dev/rtwn/pci/rtwn_pci_reg.h>
#include <dev/rtwn/pci/rtwn_pci_rx.h>
#include <dev/rtwn/pci/rtwn_pci_tx.h>
#include <dev/rtwn/rtl8192c/pci/r92ce_reg.h>
static device_probe_t rtwn_pci_probe;
static device_attach_t rtwn_pci_attach;
static device_detach_t rtwn_pci_detach;
static device_shutdown_t rtwn_pci_shutdown;
static device_suspend_t rtwn_pci_suspend;
static device_resume_t rtwn_pci_resume;
static int rtwn_pci_alloc_rx_list(struct rtwn_softc *);
static void rtwn_pci_reset_rx_list(struct rtwn_softc *);
static void rtwn_pci_free_rx_list(struct rtwn_softc *);
static int rtwn_pci_alloc_tx_list(struct rtwn_softc *, int);
static void rtwn_pci_reset_tx_ring_stopped(struct rtwn_softc *, int);
static void rtwn_pci_reset_beacon_ring(struct rtwn_softc *, int);
static void rtwn_pci_reset_tx_list(struct rtwn_softc *,
struct ieee80211vap *, int);
static void rtwn_pci_free_tx_list(struct rtwn_softc *, int);
static void rtwn_pci_reset_lists(struct rtwn_softc *,
struct ieee80211vap *);
static int rtwn_pci_fw_write_block(struct rtwn_softc *,
const uint8_t *, uint16_t, int);
static uint16_t rtwn_pci_get_qmap(struct rtwn_softc *);
static void rtwn_pci_set_desc_addr(struct rtwn_softc *);
static void rtwn_pci_beacon_update_begin(struct rtwn_softc *,
struct ieee80211vap *);
static void rtwn_pci_beacon_update_end(struct rtwn_softc *,
struct ieee80211vap *);
static void rtwn_pci_attach_methods(struct rtwn_softc *);
static const struct rtwn_pci_ident *
rtwn_pci_probe_sub(device_t dev)
{
const struct rtwn_pci_ident *ident;
int vendor_id, device_id;
vendor_id = pci_get_vendor(dev);
device_id = pci_get_device(dev);
for (ident = rtwn_pci_ident_table; ident->name != NULL; ident++)
if (vendor_id == ident->vendor && device_id == ident->device)
return (ident);
return (NULL);
}
static int
rtwn_pci_probe(device_t dev)
{
const struct rtwn_pci_ident *ident;
ident = rtwn_pci_probe_sub(dev);
if (ident != NULL) {
device_set_desc(dev, ident->name);
return (BUS_PROBE_DEFAULT);
}
return (ENXIO);
}
static int
rtwn_pci_alloc_rx_list(struct rtwn_softc *sc)
{
struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
struct rtwn_rx_ring *rx_ring = &pc->rx_ring;
struct rtwn_rx_data *rx_data;
bus_size_t size;
int i, error;
/* Allocate Rx descriptors. */
size = sizeof(struct rtwn_rx_stat_pci) * RTWN_PCI_RX_LIST_COUNT;
error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 1, 0,
BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
size, 1, size, 0, NULL, NULL, &rx_ring->desc_dmat);
if (error != 0) {
device_printf(sc->sc_dev, "could not create rx desc DMA tag\n");
goto fail;
}
error = bus_dmamem_alloc(rx_ring->desc_dmat, (void **)&rx_ring->desc,
BUS_DMA_NOWAIT | BUS_DMA_ZERO | BUS_DMA_COHERENT,
&rx_ring->desc_map);
if (error != 0) {
device_printf(sc->sc_dev, "could not allocate rx desc\n");
goto fail;
}
error = bus_dmamap_load(rx_ring->desc_dmat, rx_ring->desc_map,
rx_ring->desc, size, rtwn_pci_dma_map_addr, &rx_ring->paddr, 0);
if (error != 0) {
device_printf(sc->sc_dev, "could not load rx desc DMA map\n");
goto fail;
}
bus_dmamap_sync(rx_ring->desc_dmat, rx_ring->desc_map,
BUS_DMASYNC_PREWRITE);
/* Create RX buffer DMA tag. */
error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 1, 0,
BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
MJUMPAGESIZE, 1, MJUMPAGESIZE, 0, NULL, NULL, &rx_ring->data_dmat);
if (error != 0) {
device_printf(sc->sc_dev, "could not create rx buf DMA tag\n");
goto fail;
}
/* Allocate Rx buffers. */
for (i = 0; i < RTWN_PCI_RX_LIST_COUNT; i++) {
rx_data = &rx_ring->rx_data[i];
error = bus_dmamap_create(rx_ring->data_dmat, 0, &rx_data->map);
if (error != 0) {
device_printf(sc->sc_dev,
"could not create rx buf DMA map\n");
goto fail;
}
rx_data->m = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR,
MJUMPAGESIZE);
if (rx_data->m == NULL) {
device_printf(sc->sc_dev,
"could not allocate rx mbuf\n");
error = ENOMEM;
goto fail;
}
error = bus_dmamap_load(rx_ring->data_dmat, rx_data->map,
mtod(rx_data->m, void *), MJUMPAGESIZE,
rtwn_pci_dma_map_addr, &rx_data->paddr, BUS_DMA_NOWAIT);
if (error != 0) {
device_printf(sc->sc_dev,
"could not load rx buf DMA map");
goto fail;
}
rtwn_pci_setup_rx_desc(pc, &rx_ring->desc[i], rx_data->paddr,
MJUMPAGESIZE, i);
}
rx_ring->cur = 0;
return (0);
fail:
rtwn_pci_free_rx_list(sc);
return (error);
}
static void
rtwn_pci_reset_rx_list(struct rtwn_softc *sc)
{
struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
struct rtwn_rx_ring *rx_ring = &pc->rx_ring;
struct rtwn_rx_data *rx_data;
int i;
for (i = 0; i < RTWN_PCI_RX_LIST_COUNT; i++) {
rx_data = &rx_ring->rx_data[i];
rtwn_pci_setup_rx_desc(pc, &rx_ring->desc[i],
rx_data->paddr, MJUMPAGESIZE, i);
}
rx_ring->cur = 0;
}
static void
rtwn_pci_free_rx_list(struct rtwn_softc *sc)
{
struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
struct rtwn_rx_ring *rx_ring = &pc->rx_ring;
struct rtwn_rx_data *rx_data;
int i;
if (rx_ring->desc_dmat != NULL) {
if (rx_ring->desc != NULL) {
bus_dmamap_sync(rx_ring->desc_dmat,
rx_ring->desc_map,
BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
bus_dmamap_unload(rx_ring->desc_dmat,
rx_ring->desc_map);
bus_dmamem_free(rx_ring->desc_dmat, rx_ring->desc,
rx_ring->desc_map);
rx_ring->desc = NULL;
}
bus_dma_tag_destroy(rx_ring->desc_dmat);
rx_ring->desc_dmat = NULL;
}
for (i = 0; i < RTWN_PCI_RX_LIST_COUNT; i++) {
rx_data = &rx_ring->rx_data[i];
if (rx_data->m != NULL) {
bus_dmamap_sync(rx_ring->data_dmat,
rx_data->map, BUS_DMASYNC_POSTREAD);
bus_dmamap_unload(rx_ring->data_dmat, rx_data->map);
m_freem(rx_data->m);
rx_data->m = NULL;
}
bus_dmamap_destroy(rx_ring->data_dmat, rx_data->map);
rx_data->map = NULL;
}
if (rx_ring->data_dmat != NULL) {
bus_dma_tag_destroy(rx_ring->data_dmat);
rx_ring->data_dmat = NULL;
}
}
static int
rtwn_pci_alloc_tx_list(struct rtwn_softc *sc, int qid)
{
struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
struct rtwn_tx_ring *tx_ring = &pc->tx_ring[qid];
bus_size_t size;
int i, error;
size = sc->txdesc_len * RTWN_PCI_TX_LIST_COUNT;
error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), PAGE_SIZE, 0,
BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
size, 1, size, 0, NULL, NULL, &tx_ring->desc_dmat);
if (error != 0) {
device_printf(sc->sc_dev, "could not create tx ring DMA tag\n");
goto fail;
}
error = bus_dmamem_alloc(tx_ring->desc_dmat, &tx_ring->desc,
BUS_DMA_NOWAIT | BUS_DMA_ZERO, &tx_ring->desc_map);
if (error != 0) {
device_printf(sc->sc_dev, "can't map tx ring DMA memory\n");
goto fail;
}
error = bus_dmamap_load(tx_ring->desc_dmat, tx_ring->desc_map,
tx_ring->desc, size, rtwn_pci_dma_map_addr, &tx_ring->paddr,
BUS_DMA_NOWAIT);
if (error != 0) {
device_printf(sc->sc_dev, "could not load desc DMA map\n");
goto fail;
}
bus_dmamap_sync(tx_ring->desc_dmat, tx_ring->desc_map,
BUS_DMASYNC_PREWRITE);
error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 1, 0,
BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
MJUMPAGESIZE, 1, MJUMPAGESIZE, 0, NULL, NULL, &tx_ring->data_dmat);
if (error != 0) {
device_printf(sc->sc_dev, "could not create tx buf DMA tag\n");
goto fail;
}
for (i = 0; i < RTWN_PCI_TX_LIST_COUNT; i++) {
struct rtwn_tx_data *tx_data = &tx_ring->tx_data[i];
void *tx_desc = (uint8_t *)tx_ring->desc + sc->txdesc_len * i;
uint32_t next_desc_addr = tx_ring->paddr +
sc->txdesc_len * ((i + 1) % RTWN_PCI_TX_LIST_COUNT);
rtwn_pci_setup_tx_desc(pc, tx_desc, next_desc_addr);
error = bus_dmamap_create(tx_ring->data_dmat, 0, &tx_data->map);
if (error != 0) {
device_printf(sc->sc_dev,
"could not create tx buf DMA map\n");
return (error);
}
tx_data->m = NULL;
tx_data->ni = NULL;
}
return (0);
fail:
rtwn_pci_free_tx_list(sc, qid);
return (error);
}
static void
rtwn_pci_reset_tx_ring_stopped(struct rtwn_softc *sc, int qid)
{
struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
struct rtwn_tx_ring *ring = &pc->tx_ring[qid];
int i;
for (i = 0; i < RTWN_PCI_TX_LIST_COUNT; i++) {
struct rtwn_tx_data *data = &ring->tx_data[i];
void *desc = (uint8_t *)ring->desc + sc->txdesc_len * i;
rtwn_pci_copy_tx_desc(pc, desc, NULL);
if (data->m != NULL) {
bus_dmamap_sync(ring->data_dmat, data->map,
BUS_DMASYNC_POSTWRITE);
bus_dmamap_unload(ring->data_dmat, data->map);
m_freem(data->m);
data->m = NULL;
}
if (data->ni != NULL) {
ieee80211_free_node(data->ni);
data->ni = NULL;
}
}
bus_dmamap_sync(ring->desc_dmat, ring->desc_map,
BUS_DMASYNC_POSTWRITE);
sc->qfullmsk &= ~(1 << qid);
ring->queued = 0;
ring->last = ring->cur = 0;
}
/*
* Clear entry 0 (or 1) in the beacon queue (other are not used).
*/
static void
rtwn_pci_reset_beacon_ring(struct rtwn_softc *sc, int id)
{
struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
struct rtwn_tx_ring *ring = &pc->tx_ring[RTWN_PCI_BEACON_QUEUE];
struct rtwn_tx_data *data = &ring->tx_data[id];
struct rtwn_tx_desc_common *txd = (struct rtwn_tx_desc_common *)
((uint8_t *)ring->desc + id * sc->txdesc_len);
bus_dmamap_sync(ring->desc_dmat, ring->desc_map, BUS_DMASYNC_POSTREAD);
if (txd->flags0 & RTWN_FLAGS0_OWN) {
/* Clear OWN bit. */
txd->flags0 &= ~RTWN_FLAGS0_OWN;
bus_dmamap_sync(ring->desc_dmat, ring->desc_map,
BUS_DMASYNC_PREWRITE);
/* Unload mbuf. */
bus_dmamap_sync(ring->data_dmat, data->map,
BUS_DMASYNC_POSTWRITE);
bus_dmamap_unload(ring->data_dmat, data->map);
}
}
/*
* Drop stale entries from Tx ring before the vap will be deleted.
* In case if vap is NULL just free everything and reset cur / last pointers.
*/
static void
rtwn_pci_reset_tx_list(struct rtwn_softc *sc, struct ieee80211vap *vap,
int qid)
{
int i;
if (vap == NULL) {
if (qid != RTWN_PCI_BEACON_QUEUE) {
/*
* Device was stopped; just clear all entries.
*/
rtwn_pci_reset_tx_ring_stopped(sc, qid);
} else {
for (i = 0; i < RTWN_PORT_COUNT; i++)
rtwn_pci_reset_beacon_ring(sc, i);
}
} else if (qid == RTWN_PCI_BEACON_QUEUE &&
(vap->iv_opmode == IEEE80211_M_HOSTAP ||
vap->iv_opmode == IEEE80211_M_IBSS)) {
struct rtwn_vap *uvp = RTWN_VAP(vap);
rtwn_pci_reset_beacon_ring(sc, uvp->id);
} else {
struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
struct rtwn_tx_ring *ring = &pc->tx_ring[qid];
for (i = 0; i < RTWN_PCI_TX_LIST_COUNT; i++) {
struct rtwn_tx_data *data = &ring->tx_data[i];
if (data->ni != NULL && data->ni->ni_vap == vap) {
/*
* NB: if some vap is still running
* rtwn_pci_tx_done() will free the mbuf;
* otherwise, rtwn_stop() will reset all rings
* after device shutdown.
*/
ieee80211_free_node(data->ni);
data->ni = NULL;
}
}
}
}
static void
rtwn_pci_free_tx_list(struct rtwn_softc *sc, int qid)
{
struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
struct rtwn_tx_ring *tx_ring = &pc->tx_ring[qid];
struct rtwn_tx_data *tx_data;
int i;
if (tx_ring->desc_dmat != NULL) {
if (tx_ring->desc != NULL) {
bus_dmamap_sync(tx_ring->desc_dmat,
tx_ring->desc_map, BUS_DMASYNC_POSTWRITE);
bus_dmamap_unload(tx_ring->desc_dmat,
tx_ring->desc_map);
bus_dmamem_free(tx_ring->desc_dmat, tx_ring->desc,
tx_ring->desc_map);
}
bus_dma_tag_destroy(tx_ring->desc_dmat);
}
for (i = 0; i < RTWN_PCI_TX_LIST_COUNT; i++) {
tx_data = &tx_ring->tx_data[i];
if (tx_data->m != NULL) {
bus_dmamap_sync(tx_ring->data_dmat, tx_data->map,
BUS_DMASYNC_POSTWRITE);
bus_dmamap_unload(tx_ring->data_dmat, tx_data->map);
m_freem(tx_data->m);
tx_data->m = NULL;
}
}
if (tx_ring->data_dmat != NULL) {
bus_dma_tag_destroy(tx_ring->data_dmat);
tx_ring->data_dmat = NULL;
}
sc->qfullmsk &= ~(1 << qid);
tx_ring->queued = 0;
tx_ring->last = tx_ring->cur = 0;
}
static void
rtwn_pci_reset_lists(struct rtwn_softc *sc, struct ieee80211vap *vap)
{
int i;
for (i = 0; i < RTWN_PCI_NTXQUEUES; i++)
rtwn_pci_reset_tx_list(sc, vap, i);
if (vap == NULL) {
sc->qfullmsk = 0;
rtwn_pci_reset_rx_list(sc);
}
}
static int
rtwn_pci_fw_write_block(struct rtwn_softc *sc, const uint8_t *buf,
uint16_t reg, int mlen)
{
int i;
for (i = 0; i < mlen; i++)
rtwn_pci_write_1(sc, reg++, buf[i]);
/* NB: cannot fail */
return (0);
}
static uint16_t
rtwn_pci_get_qmap(struct rtwn_softc *sc)
{
struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
KASSERT(pc->pc_qmap != 0, ("%s: qmap is not set!\n", __func__));
return (pc->pc_qmap);
}
static void
rtwn_pci_set_desc_addr(struct rtwn_softc *sc)
{
struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
RTWN_DPRINTF(sc, RTWN_DEBUG_RESET, "%s: addresses:\n"
"bk: %08jX, be: %08jX, vi: %08jX, vo: %08jX\n"
"bcn: %08jX, mgt: %08jX, high: %08jX, rx: %08jX\n",
__func__, (uintmax_t)pc->tx_ring[RTWN_PCI_BK_QUEUE].paddr,
(uintmax_t)pc->tx_ring[RTWN_PCI_BE_QUEUE].paddr,
(uintmax_t)pc->tx_ring[RTWN_PCI_VI_QUEUE].paddr,
(uintmax_t)pc->tx_ring[RTWN_PCI_VO_QUEUE].paddr,
(uintmax_t)pc->tx_ring[RTWN_PCI_BEACON_QUEUE].paddr,
(uintmax_t)pc->tx_ring[RTWN_PCI_MGNT_QUEUE].paddr,
(uintmax_t)pc->tx_ring[RTWN_PCI_HIGH_QUEUE].paddr,
(uintmax_t)pc->rx_ring.paddr);
/* Set Tx Configuration Register. */
rtwn_pci_write_4(sc, R92C_TCR, pc->tcr);
/* Configure Tx DMA. */
rtwn_pci_write_4(sc, R92C_BKQ_DESA,
pc->tx_ring[RTWN_PCI_BK_QUEUE].paddr);
rtwn_pci_write_4(sc, R92C_BEQ_DESA,
pc->tx_ring[RTWN_PCI_BE_QUEUE].paddr);
rtwn_pci_write_4(sc, R92C_VIQ_DESA,
pc->tx_ring[RTWN_PCI_VI_QUEUE].paddr);
rtwn_pci_write_4(sc, R92C_VOQ_DESA,
pc->tx_ring[RTWN_PCI_VO_QUEUE].paddr);
rtwn_pci_write_4(sc, R92C_BCNQ_DESA,
pc->tx_ring[RTWN_PCI_BEACON_QUEUE].paddr);
rtwn_pci_write_4(sc, R92C_MGQ_DESA,
pc->tx_ring[RTWN_PCI_MGNT_QUEUE].paddr);
rtwn_pci_write_4(sc, R92C_HQ_DESA,
pc->tx_ring[RTWN_PCI_HIGH_QUEUE].paddr);
/* Configure Rx DMA. */
rtwn_pci_write_4(sc, R92C_RX_DESA, pc->rx_ring.paddr);
}
static void
rtwn_pci_beacon_update_begin(struct rtwn_softc *sc, struct ieee80211vap *vap)
{
struct rtwn_vap *rvp = RTWN_VAP(vap);
RTWN_ASSERT_LOCKED(sc);
rtwn_beacon_enable(sc, rvp->id, 0);
}
static void
rtwn_pci_beacon_update_end(struct rtwn_softc *sc, struct ieee80211vap *vap)
{
struct rtwn_vap *rvp = RTWN_VAP(vap);
RTWN_ASSERT_LOCKED(sc);
if (rvp->curr_mode != R92C_MSR_NOLINK)
rtwn_beacon_enable(sc, rvp->id, 1);
}
static void
rtwn_pci_attach_methods(struct rtwn_softc *sc)
{
sc->sc_write_1 = rtwn_pci_write_1;
sc->sc_write_2 = rtwn_pci_write_2;
sc->sc_write_4 = rtwn_pci_write_4;
sc->sc_read_1 = rtwn_pci_read_1;
sc->sc_read_2 = rtwn_pci_read_2;
sc->sc_read_4 = rtwn_pci_read_4;
sc->sc_delay = rtwn_pci_delay;
sc->sc_tx_start = rtwn_pci_tx_start;
sc->sc_reset_lists = rtwn_pci_reset_lists;
sc->sc_abort_xfers = rtwn_nop_softc;
sc->sc_fw_write_block = rtwn_pci_fw_write_block;
sc->sc_get_qmap = rtwn_pci_get_qmap;
sc->sc_set_desc_addr = rtwn_pci_set_desc_addr;
sc->sc_drop_incorrect_tx = rtwn_nop_softc;
sc->sc_beacon_update_begin = rtwn_pci_beacon_update_begin;
sc->sc_beacon_update_end = rtwn_pci_beacon_update_end;
sc->sc_beacon_unload = rtwn_pci_reset_beacon_ring;
sc->bcn_check_interval = 25000;
}
static int
rtwn_pci_attach(device_t dev)
{
const struct rtwn_pci_ident *ident;
struct rtwn_pci_softc *pc = device_get_softc(dev);
struct rtwn_softc *sc = &pc->pc_sc;
struct ieee80211com *ic = &sc->sc_ic;
uint32_t lcsr;
int cap_off, i, error, rid;
ident = rtwn_pci_probe_sub(dev);
if (ident == NULL)
return (ENXIO);
/*
* Get the offset of the PCI Express Capability Structure in PCI
* Configuration Space.
*/
error = pci_find_cap(dev, PCIY_EXPRESS, &cap_off);
if (error != 0) {
device_printf(dev, "PCIe capability structure not found!\n");
return (error);
}
/* Enable bus-mastering. */
pci_enable_busmaster(dev);
rid = PCIR_BAR(2);
pc->mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
RF_ACTIVE);
if (pc->mem == NULL) {
device_printf(dev, "can't map mem space\n");
return (ENOMEM);
}
pc->pc_st = rman_get_bustag(pc->mem);
pc->pc_sh = rman_get_bushandle(pc->mem);
/* Install interrupt handler. */
rid = 1;
if (pci_alloc_msi(dev, &rid) == 0)
rid = 1;
else
rid = 0;
pc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE |
(rid != 0 ? 0 : RF_SHAREABLE));
if (pc->irq == NULL) {
device_printf(dev, "can't map interrupt\n");
goto detach;
}
/* Disable PCIe Active State Power Management (ASPM). */
lcsr = pci_read_config(dev, cap_off + PCIER_LINK_CTL, 4);
lcsr &= ~PCIEM_LINK_CTL_ASPMC;
pci_write_config(dev, cap_off + PCIER_LINK_CTL, lcsr, 4);
sc->sc_dev = dev;
ic->ic_name = device_get_nameunit(dev);
/* Need to be initialized early. */
rtwn_sysctlattach(sc);
mtx_init(&sc->sc_mtx, ic->ic_name, MTX_NETWORK_LOCK, MTX_DEF);
rtwn_pci_attach_methods(sc);
rtwn_pci_attach_private(pc, ident->chip);
/* Allocate Tx/Rx buffers. */
error = rtwn_pci_alloc_rx_list(sc);
if (error != 0) {
device_printf(dev,
"could not allocate Rx buffers, error %d\n",
error);
goto detach;
}
for (i = 0; i < RTWN_PCI_NTXQUEUES; i++) {
error = rtwn_pci_alloc_tx_list(sc, i);
if (error != 0) {
device_printf(dev,
"could not allocate Tx buffers, error %d\n",
error);
goto detach;
}
}
/* Generic attach. */
error = rtwn_attach(sc);
if (error != 0)
goto detach;
/*
* Hook our interrupt after all initialization is complete.
*/
error = bus_setup_intr(dev, pc->irq, INTR_TYPE_NET | INTR_MPSAFE,
NULL, rtwn_pci_intr, sc, &pc->pc_ih);
if (error != 0) {
device_printf(dev, "can't establish interrupt, error %d\n",
error);
goto detach;
}
return (0);
detach:
rtwn_pci_detach(dev); /* failure */
return (ENXIO);
}
static int
rtwn_pci_detach(device_t dev)
{
struct rtwn_pci_softc *pc = device_get_softc(dev);
struct rtwn_softc *sc = &pc->pc_sc;
int i;
/* Generic detach. */
rtwn_detach(sc);
/* Uninstall interrupt handler. */
if (pc->irq != NULL) {
bus_teardown_intr(dev, pc->irq, pc->pc_ih);
bus_release_resource(dev, SYS_RES_IRQ, rman_get_rid(pc->irq),
pc->irq);
pci_release_msi(dev);
}
/* Free Tx/Rx buffers. */
for (i = 0; i < RTWN_PCI_NTXQUEUES; i++)
rtwn_pci_free_tx_list(sc, i);
rtwn_pci_free_rx_list(sc);
if (pc->mem != NULL)
bus_release_resource(dev, SYS_RES_MEMORY,
rman_get_rid(pc->mem), pc->mem);
rtwn_detach_private(sc);
mtx_destroy(&sc->sc_mtx);
return (0);
}
static int
rtwn_pci_shutdown(device_t self)
{
struct rtwn_pci_softc *pc = device_get_softc(self);
ieee80211_stop_all(&pc->pc_sc.sc_ic);
return (0);
}
static int
rtwn_pci_suspend(device_t self)
{
struct rtwn_pci_softc *pc = device_get_softc(self);
rtwn_suspend(&pc->pc_sc);
return (0);
}
static int
rtwn_pci_resume(device_t self)
{
struct rtwn_pci_softc *pc = device_get_softc(self);
rtwn_resume(&pc->pc_sc);
return (0);
}
static device_method_t rtwn_pci_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, rtwn_pci_probe),
DEVMETHOD(device_attach, rtwn_pci_attach),
DEVMETHOD(device_detach, rtwn_pci_detach),
DEVMETHOD(device_shutdown, rtwn_pci_shutdown),
DEVMETHOD(device_suspend, rtwn_pci_suspend),
DEVMETHOD(device_resume, rtwn_pci_resume),
DEVMETHOD_END
};
static driver_t rtwn_pci_driver = {
"rtwn",
rtwn_pci_methods,
sizeof(struct rtwn_pci_softc)
};
static devclass_t rtwn_pci_devclass;
DRIVER_MODULE(rtwn_pci, pci, rtwn_pci_driver, rtwn_pci_devclass, NULL, NULL);
MODULE_VERSION(rtwn_pci, 1);
MODULE_DEPEND(rtwn_pci, pci, 1, 1, 1);
MODULE_DEPEND(rtwn_pci, wlan, 1, 1, 1);
MODULE_DEPEND(rtwn_pci, rtwn, 2, 2, 2);
@@ -0,0 +1,48 @@
/*-
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $FreeBSD: releng/12.0/sys/dev/rtwn/pci/rtwn_pci_attach.h 307529 2016-10-17 20:38:24Z avos $
*/
void r92ce_attach(struct rtwn_pci_softc *);
enum {
RTWN_CHIP_RTL8192CE,
RTWN_CHIP_MAX_PCI
};
struct rtwn_pci_ident {
uint16_t vendor;
uint16_t device;
const char *name;
int chip;
};
static const struct rtwn_pci_ident rtwn_pci_ident_table[] = {
{ 0x10ec, 0x8176, "Realtek RTL8188CE", RTWN_CHIP_RTL8192CE },
{ 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
};
static __inline void
rtwn_pci_attach_private(struct rtwn_pci_softc *pc, int chip)
{
rtwn_chip_pci_attach[chip](pc);
}
@@ -0,0 +1,123 @@
/* $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>
*
* 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: releng/12.0/sys/dev/rtwn/pci/rtwn_pci_reg.c 307529 2016-10-17 20:38:24Z avos $");
#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 <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/pci/rtwn_pci_reg.h>
int
rtwn_pci_write_1(struct rtwn_softc *sc, uint16_t addr, uint8_t val)
{
struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
bus_space_write_1(pc->pc_st, pc->pc_sh, addr, val);
return (0);
}
int
rtwn_pci_write_2(struct rtwn_softc *sc, uint16_t addr, uint16_t val)
{
struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
val = htole16(val);
bus_space_write_2(pc->pc_st, pc->pc_sh, addr, val);
return (0);
}
int
rtwn_pci_write_4(struct rtwn_softc *sc, uint16_t addr, uint32_t val)
{
struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
val = htole32(val);
bus_space_write_4(pc->pc_st, pc->pc_sh, addr, val);
return (0);
}
uint8_t
rtwn_pci_read_1(struct rtwn_softc *sc, uint16_t addr)
{
struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
return (bus_space_read_1(pc->pc_st, pc->pc_sh, addr));
}
uint16_t
rtwn_pci_read_2(struct rtwn_softc *sc, uint16_t addr)
{
struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
uint16_t val;
val = bus_space_read_2(pc->pc_st, pc->pc_sh, addr);
return le16toh(val);
}
uint32_t
rtwn_pci_read_4(struct rtwn_softc *sc, uint16_t addr)
{
struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
uint32_t val;
val = bus_space_read_4(pc->pc_st, pc->pc_sh, addr);
return le32toh(val);
}
void
rtwn_pci_delay(struct rtwn_softc *sc, int usec)
{
if (usec < 1000)
DELAY(usec);
else {
(void) mtx_sleep(sc, &sc->sc_mtx, 0, "rtwn_pci",
MAX(msecs_to_ticks(usec / 1000), 1));
}
}
@@ -0,0 +1,30 @@
/*-
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $FreeBSD: releng/12.0/sys/dev/rtwn/pci/rtwn_pci_reg.h 307529 2016-10-17 20:38:24Z avos $
*/
#ifndef RTWN_PCI_REG_H
#define RTWN_PCI_REG_H
int rtwn_pci_write_1(struct rtwn_softc *, uint16_t, uint8_t);
int rtwn_pci_write_2(struct rtwn_softc *, uint16_t, uint16_t);
int rtwn_pci_write_4(struct rtwn_softc *, uint16_t, uint32_t);
uint8_t rtwn_pci_read_1(struct rtwn_softc *, uint16_t);
uint16_t rtwn_pci_read_2(struct rtwn_softc *, uint16_t);
uint32_t rtwn_pci_read_4(struct rtwn_softc *, uint16_t);
void rtwn_pci_delay(struct rtwn_softc *, int);
#endif /* RTWN_PCI_REG_H */
@@ -0,0 +1,317 @@
/* $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>
*
* 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: releng/12.0/sys/dev/rtwn/pci/rtwn_pci_rx.c 320725 2017-07-06 07:37:33Z avos $");
#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 <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 <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/if_rtwn_debug.h>
#include <dev/rtwn/if_rtwn_rx.h>
#include <dev/rtwn/if_rtwn_task.h>
#include <dev/rtwn/if_rtwn_tx.h>
#include <dev/rtwn/pci/rtwn_pci_var.h>
#include <dev/rtwn/pci/rtwn_pci_rx.h>
void
rtwn_pci_dma_map_addr(void *arg, bus_dma_segment_t *segs, int nsegs,
int error)
{
if (error != 0)
return;
KASSERT(nsegs == 1, ("too many DMA segments, %d should be 1", nsegs));
*(bus_addr_t *)arg = segs[0].ds_addr;
}
void
rtwn_pci_setup_rx_desc(struct rtwn_pci_softc *pc,
struct rtwn_rx_stat_pci *desc, bus_addr_t addr, size_t len, int idx)
{
memset(desc, 0, sizeof(*desc));
desc->rxdw0 = htole32(SM(RTWN_RXDW0_PKTLEN, len) |
((idx == RTWN_PCI_RX_LIST_COUNT - 1) ? RTWN_RXDW0_EOR : 0));
desc->rxbufaddr = htole32(addr);
bus_space_barrier(pc->pc_st, pc->pc_sh, 0, pc->pc_mapsize,
BUS_SPACE_BARRIER_WRITE);
desc->rxdw0 |= htole32(RTWN_RXDW0_OWN);
}
static void
rtwn_pci_rx_frame(struct rtwn_softc *sc, struct rtwn_rx_stat_pci *rx_desc,
int desc_idx)
{
struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
struct rtwn_rx_ring *ring = &pc->rx_ring;
struct rtwn_rx_data *rx_data = &ring->rx_data[desc_idx];
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_node *ni;
uint32_t rxdw0;
struct mbuf *m, *m1;
int infosz, pktlen, shift, error;
/* Dump Rx descriptor. */
RTWN_DPRINTF(sc, RTWN_DEBUG_RECV_DESC,
"%s: dw: 0 %08X, 1 %08X, 2 %08X, 3 %08X, 4 %08X, tsfl %08X, "
"addr: %08X (64: %08X)\n",
__func__, le32toh(rx_desc->rxdw0), le32toh(rx_desc->rxdw1),
le32toh(rx_desc->rxdw2), le32toh(rx_desc->rxdw3),
le32toh(rx_desc->rxdw4), le32toh(rx_desc->tsf_low),
le32toh(rx_desc->rxbufaddr), le32toh(rx_desc->rxbufaddr64));
rxdw0 = le32toh(rx_desc->rxdw0);
if (__predict_false(rxdw0 & (RTWN_RXDW0_CRCERR | RTWN_RXDW0_ICVERR))) {
/*
* This should not happen since we setup our Rx filter
* to not receive these frames.
*/
RTWN_DPRINTF(sc, RTWN_DEBUG_RECV,
"%s: RX flags error (%s)\n", __func__,
rxdw0 & RTWN_RXDW0_CRCERR ? "CRC" : "ICV");
goto fail;
}
pktlen = MS(rxdw0, RTWN_RXDW0_PKTLEN);
if (__predict_false(pktlen < sizeof(struct ieee80211_frame_ack) ||
pktlen > MJUMPAGESIZE)) {
RTWN_DPRINTF(sc, RTWN_DEBUG_RECV,
"%s: frame is too short/long: %d\n", __func__, pktlen);
goto fail;
}
infosz = MS(rxdw0, RTWN_RXDW0_INFOSZ) * 8;
shift = MS(rxdw0, RTWN_RXDW0_SHIFT);
m1 = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, MJUMPAGESIZE);
if (__predict_false(m1 == NULL)) {
device_printf(sc->sc_dev, "%s: could not allocate RX mbuf\n",
__func__);
goto fail;
}
bus_dmamap_sync(ring->data_dmat, rx_data->map, BUS_DMASYNC_POSTREAD);
bus_dmamap_unload(ring->data_dmat, rx_data->map);
error = bus_dmamap_load(ring->data_dmat, rx_data->map, mtod(m1, void *),
MJUMPAGESIZE, rtwn_pci_dma_map_addr, &rx_data->paddr, 0);
if (error != 0) {
m_freem(m1);
error = bus_dmamap_load(ring->data_dmat, rx_data->map,
mtod(rx_data->m, void *), MJUMPAGESIZE,
rtwn_pci_dma_map_addr, &rx_data->paddr, BUS_DMA_NOWAIT);
if (error != 0)
panic("%s: could not load old RX mbuf",
device_get_name(sc->sc_dev));
/* Physical address may have changed. */
rtwn_pci_setup_rx_desc(pc, rx_desc, rx_data->paddr,
MJUMPAGESIZE, desc_idx);
goto fail;
}
/* Finalize mbuf. */
m = rx_data->m;
rx_data->m = m1;
m->m_pkthdr.len = m->m_len = pktlen + infosz + shift;
ni = rtwn_rx_common(sc, m, rx_desc);
RTWN_DPRINTF(sc, RTWN_DEBUG_RECV,
"%s: Rx frame len %d, infosz %d, shift %d\n",
__func__, pktlen, infosz, shift);
/* Update RX descriptor. */
rtwn_pci_setup_rx_desc(pc, rx_desc, rx_data->paddr, MJUMPAGESIZE,
desc_idx);
/* Send the frame to the 802.11 layer. */
RTWN_UNLOCK(sc);
if (ni != NULL) {
(void)ieee80211_input_mimo(ni, m);
/* Node is no longer needed. */
ieee80211_free_node(ni);
} else
(void)ieee80211_input_mimo_all(ic, m);
RTWN_LOCK(sc);
return;
fail:
counter_u64_add(ic->ic_ierrors, 1);
}
static void
rtwn_pci_tx_done(struct rtwn_softc *sc, int qid)
{
struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
struct rtwn_tx_ring *ring = &pc->tx_ring[qid];
struct rtwn_tx_desc_common *desc;
struct rtwn_tx_data *data;
RTWN_DPRINTF(sc, RTWN_DEBUG_INTR, "%s: qid %d, last %d, cur %d\n",
__func__, qid, ring->last, ring->cur);
bus_dmamap_sync(ring->desc_dmat, ring->desc_map, BUS_DMASYNC_POSTREAD);
while(ring->last != ring->cur) {
data = &ring->tx_data[ring->last];
desc = (struct rtwn_tx_desc_common *)
((uint8_t *)ring->desc + sc->txdesc_len * ring->last);
KASSERT(data->m != NULL, ("no mbuf"));
if (desc->flags0 & RTWN_FLAGS0_OWN)
break;
/* Unmap and free mbuf. */
bus_dmamap_sync(ring->data_dmat, data->map,
BUS_DMASYNC_POSTWRITE);
bus_dmamap_unload(ring->data_dmat, data->map);
if (data->ni != NULL) { /* not a beacon frame */
ieee80211_tx_complete(data->ni, data->m, 0);
data->ni = NULL;
ring->queued--;
KASSERT(ring->queued >= 0,
("ring->queued (qid %d) underflow!\n", qid));
} else
m_freem(data->m);
data->m = NULL;
ring->last = (ring->last + 1) % RTWN_PCI_TX_LIST_COUNT;
#ifndef D4054
if (ring->queued > 0)
sc->sc_tx_timer = 5;
else
sc->sc_tx_timer = 0;
#endif
}
if ((sc->qfullmsk & (1 << qid)) != 0 &&
ring->queued < (RTWN_PCI_TX_LIST_COUNT - 1)) {
sc->qfullmsk &= ~(1 << qid);
rtwn_start(sc);
}
#ifdef IEEE80211_SUPPORT_SUPERG
/*
* If the TX active queue drops below a certain
* threshold, ensure we age fast-frames out so they're
* transmitted.
*/
if (sc->sc_ratectl != RTWN_RATECTL_NET80211 && ring->queued <= 1) {
/*
* XXX TODO: just make this a callout timer schedule
* so we can flush the FF staging queue if we're
* approaching idle.
*/
rtwn_cmd_sleepable(sc, NULL, 0, rtwn_ff_flush_all);
}
#endif
}
static void
rtwn_pci_rx_done(struct rtwn_softc *sc)
{
struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
struct rtwn_rx_ring *ring = &pc->rx_ring;
bus_dmamap_sync(ring->desc_dmat, ring->desc_map, BUS_DMASYNC_POSTREAD);
for (;;) {
struct rtwn_rx_stat_pci *rx_desc = &ring->desc[ring->cur];
if (le32toh(rx_desc->rxdw0) & RTWN_RXDW0_OWN)
break;
rtwn_pci_rx_frame(sc, rx_desc, ring->cur);
if (!(sc->sc_flags & RTWN_RUNNING))
return;
ring->cur = (ring->cur + 1) % RTWN_PCI_RX_LIST_COUNT;
}
}
void
rtwn_pci_intr(void *arg)
{
struct rtwn_softc *sc = arg;
struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
int i, status, tx_rings;
RTWN_LOCK(sc);
#ifndef __HAIKU__
status = rtwn_classify_intr(sc, &tx_rings, 0);
RTWN_DPRINTF(sc, RTWN_DEBUG_INTR, "%s: status %08X, tx_rings %08X\n",
__func__, status, tx_rings);
if (status == 0 && tx_rings == 0)
goto unlock;
#else
status = atomic_get(&pc->pc_intr_status);
tx_rings = atomic_get(&pc->pc_intr_tx_rings);
#endif
if (status & RTWN_PCI_INTR_RX) {
rtwn_pci_rx_done(sc);
if (!(sc->sc_flags & RTWN_RUNNING))
goto unlock;
}
if (tx_rings != 0)
for (i = 0; i < RTWN_PCI_NTXQUEUES; i++)
if (tx_rings & (1 << i))
rtwn_pci_tx_done(sc, i);
if (sc->sc_flags & RTWN_RUNNING)
rtwn_pci_enable_intr(pc);
unlock:
RTWN_UNLOCK(sc);
}
@@ -0,0 +1,27 @@
/*-
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $FreeBSD: releng/12.0/sys/dev/rtwn/pci/rtwn_pci_rx.h 320725 2017-07-06 07:37:33Z avos $
*/
#ifndef RTWN_PCI_RX_H
#define RTWN_PCI_RX_H
void rtwn_pci_dma_map_addr(void *, bus_dma_segment_t *, int, int);
void rtwn_pci_setup_rx_desc(struct rtwn_pci_softc *,
struct rtwn_rx_stat_pci *, bus_addr_t, size_t, int);
void rtwn_pci_intr(void *);
#endif /* RTWN_PCI_RX_H */
@@ -0,0 +1,272 @@
/* $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>
*
* 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: releng/12.0/sys/dev/rtwn/pci/rtwn_pci_tx.c 308575 2016-11-12 17:58:37Z avos $");
#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 <machine/bus.h>
#include <machine/resource.h>
#include <sys/rman.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 <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/pci/rtwn_pci_tx.h>
#include <dev/rtwn/rtl8192c/pci/r92ce_reg.h>
static struct mbuf *
rtwn_mbuf_defrag(struct mbuf *m0, int how)
{
struct mbuf *m = NULL;
KASSERT(m0->m_flags & M_PKTHDR,
("M_PKTHDR flag is absent (m %p)!", m0));
/* NB: we need _exactly_ one mbuf (no less, no more). */
if (m0->m_pkthdr.len > MJUMPAGESIZE) {
/* XXX MJUM9BYTES? */
return (NULL);
} else if (m0->m_pkthdr.len > MCLBYTES) {
m = m_getjcl(how, MT_DATA, M_PKTHDR, MJUMPAGESIZE);
if (m == NULL)
return (NULL);
if (m_dup_pkthdr(m, m0, how) == 0) {
m_freem(m);
return (NULL);
}
m_copydata(m0, 0, m0->m_pkthdr.len, mtod(m, caddr_t));
m->m_len = m->m_pkthdr.len;
m_freem(m0);
return (m);
} else
return (m_defrag(m0, how));
}
static int
rtwn_pci_tx_start_frame(struct rtwn_softc *sc, struct ieee80211_node *ni,
struct mbuf *m, uint8_t *tx_desc, uint8_t type)
{
struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
struct rtwn_tx_ring *ring;
struct rtwn_tx_data *data;
struct rtwn_tx_desc_common *txd;
bus_dma_segment_t segs[1];
uint8_t qid;
int nsegs, error;
RTWN_ASSERT_LOCKED(sc);
switch (type) {
case IEEE80211_FC0_TYPE_CTL:
case IEEE80211_FC0_TYPE_MGT:
qid = RTWN_PCI_MGNT_QUEUE;
break;
default:
qid = M_WME_GETAC(m);
break;
}
ring = &pc->tx_ring[qid];
data = &ring->tx_data[ring->cur];
if (data->m != NULL) {
RTWN_DPRINTF(sc, RTWN_DEBUG_XMIT,
"%s: ring #%u is full (m %p)\n", __func__, qid, data->m);
return (ENOBUFS);
}
txd = (struct rtwn_tx_desc_common *)
((uint8_t *)ring->desc + sc->txdesc_len * ring->cur);
if (txd->flags0 & RTWN_FLAGS0_OWN) {
device_printf(sc->sc_dev,
"%s: OWN bit is set (tx desc %d, ring %u)!\n",
__func__, ring->cur, qid);
return (ENOBUFS);
}
/* Copy Tx descriptor. */
rtwn_pci_copy_tx_desc(pc, txd, tx_desc);
txd->pktlen = htole16(m->m_pkthdr.len);
txd->offset = sc->txdesc_len;
error = bus_dmamap_load_mbuf_sg(ring->data_dmat, data->map, m, segs,
&nsegs, BUS_DMA_NOWAIT);
if (error != 0 && error != EFBIG) {
device_printf(sc->sc_dev, "can't map mbuf (error %d)\n",
error);
return (error);
}
if (error != 0) {
struct mbuf *mnew;
mnew = rtwn_mbuf_defrag(m, M_NOWAIT);
if (mnew == NULL) {
device_printf(sc->sc_dev, "can't defragment mbuf\n");
return (ENOBUFS);
}
m = mnew;
error = bus_dmamap_load_mbuf_sg(ring->data_dmat, data->map, m,
segs, &nsegs, BUS_DMA_NOWAIT);
if (error != 0) {
device_printf(sc->sc_dev,
"can't map mbuf (error %d)\n", error);
if (ni != NULL) {
if_inc_counter(ni->ni_vap->iv_ifp,
IFCOUNTER_OERRORS, 1);
ieee80211_free_node(ni);
}
m_freem(m);
return (0); /* XXX */
}
}
rtwn_pci_tx_postsetup(pc, txd, segs);
txd->flags0 |= RTWN_FLAGS0_OWN;
/* Dump Tx descriptor. */
rtwn_dump_tx_desc(sc, txd);
bus_dmamap_sync(ring->desc_dmat, ring->desc_map,
BUS_DMASYNC_POSTWRITE);
bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_POSTWRITE);
data->m = m;
data->ni = ni;
ring->cur = (ring->cur + 1) % RTWN_PCI_TX_LIST_COUNT;
ring->queued++;
if (ring->queued >= (RTWN_PCI_TX_LIST_COUNT - 1))
sc->qfullmsk |= (1 << qid);
#ifndef D4054
sc->sc_tx_timer = 5;
#endif
/* Kick TX. */
rtwn_write_2(sc, R92C_PCIE_CTRL_REG, (1 << qid));
return (0);
}
static int
rtwn_pci_tx_start_beacon(struct rtwn_softc *sc, struct mbuf *m,
uint8_t *tx_desc, int id)
{
struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
struct rtwn_tx_ring *ring;
struct rtwn_tx_data *data;
struct rtwn_tx_desc_common *txd;
bus_dma_segment_t segs[1];
int nsegs, error, own;
RTWN_ASSERT_LOCKED(sc);
KASSERT(id == 0 || id == 1, ("bogus vap id %d\n", id));
ring = &pc->tx_ring[RTWN_PCI_BEACON_QUEUE];
data = &ring->tx_data[id];
txd = (struct rtwn_tx_desc_common *)
((uint8_t *)ring->desc + id * sc->txdesc_len);
bus_dmamap_sync(ring->desc_dmat, ring->desc_map,
BUS_DMASYNC_POSTREAD);
own = !!(txd->flags0 & RTWN_FLAGS0_OWN);
error = 0;
if (!own || txd->pktlen != htole16(m->m_pkthdr.len)) {
if (!own) {
/* Copy Tx descriptor. */
rtwn_pci_copy_tx_desc(pc, txd, tx_desc);
txd->offset = sc->txdesc_len;
} else {
/* Reload mbuf. */
bus_dmamap_unload(ring->data_dmat, data->map);
}
error = bus_dmamap_load_mbuf_sg(ring->data_dmat,
data->map, m, segs, &nsegs, BUS_DMA_NOWAIT);
if (error != 0) {
device_printf(sc->sc_dev,
"can't map beacon (error %d)\n", error);
txd->flags0 &= ~RTWN_FLAGS0_OWN;
goto end;
}
txd->pktlen = htole16(m->m_pkthdr.len);
rtwn_pci_tx_postsetup(pc, txd, segs);
txd->flags0 |= RTWN_FLAGS0_OWN;
end:
bus_dmamap_sync(ring->desc_dmat, ring->desc_map,
BUS_DMASYNC_PREWRITE);
}
/* Dump Tx descriptor. */
rtwn_dump_tx_desc(sc, txd);
bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_PREWRITE);
return (0);
}
int
rtwn_pci_tx_start(struct rtwn_softc *sc, struct ieee80211_node *ni,
struct mbuf *m, uint8_t *tx_desc, uint8_t type, int id)
{
int error = 0;
RTWN_ASSERT_LOCKED(sc);
if (ni == NULL) /* beacon frame */
error = rtwn_pci_tx_start_beacon(sc, m, tx_desc, id);
else
error = rtwn_pci_tx_start_frame(sc, ni, m, tx_desc, type);
return (error);
}
@@ -0,0 +1,25 @@
/*-
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $FreeBSD: releng/12.0/sys/dev/rtwn/pci/rtwn_pci_tx.h 307529 2016-10-17 20:38:24Z avos $
*/
#ifndef RTWN_PCI_TX_H
#define RTWN_PCI_TX_H
int rtwn_pci_tx_start(struct rtwn_softc *, struct ieee80211_node *,
struct mbuf *, uint8_t *, uint8_t, int);
#endif /* RTWN_PCI_TX_H */
@@ -0,0 +1,142 @@
/* $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>
*
* 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: releng/12.0/sys/dev/rtwn/pci/rtwn_pci_var.h 320725 2017-07-06 07:37:33Z avos $
*/
#ifndef RTWN_PCI_VAR_H
#define RTWN_PCI_VAR_H
#define RTWN_PCI_RX_LIST_COUNT 256
#define RTWN_PCI_TX_LIST_COUNT 256
struct rtwn_rx_data {
bus_dmamap_t map;
struct mbuf *m;
bus_addr_t paddr;
};
struct rtwn_rx_ring {
struct rtwn_rx_stat_pci *desc;
bus_addr_t paddr;
bus_dma_tag_t desc_dmat;
bus_dmamap_t desc_map;
bus_dma_tag_t data_dmat;
bus_dma_segment_t seg;
struct rtwn_rx_data rx_data[RTWN_PCI_RX_LIST_COUNT];
int cur;
};
struct rtwn_tx_data {
bus_dmamap_t map;
struct mbuf *m;
struct ieee80211_node *ni;
};
struct rtwn_tx_ring {
bus_addr_t paddr;
bus_dma_tag_t desc_dmat;
bus_dmamap_t desc_map;
bus_dma_tag_t data_dmat;
bus_dma_segment_t seg;
void *desc;
struct rtwn_tx_data tx_data[RTWN_PCI_TX_LIST_COUNT];
int queued;
int cur;
int last;
};
/*
* TX queue indices.
*/
enum {
RTWN_PCI_BK_QUEUE,
RTWN_PCI_BE_QUEUE,
RTWN_PCI_VI_QUEUE,
RTWN_PCI_VO_QUEUE,
RTWN_PCI_BEACON_QUEUE,
RTWN_PCI_TXCMD_QUEUE,
RTWN_PCI_MGNT_QUEUE,
RTWN_PCI_HIGH_QUEUE,
RTWN_PCI_HCCA_QUEUE,
RTWN_PCI_NTXQUEUES
};
/*
* Interrupt events.
*/
enum {
RTWN_PCI_INTR_RX_ERROR = 0x00000001,
RTWN_PCI_INTR_RX_OVERFLOW = 0x00000002,
RTWN_PCI_INTR_RX_DESC_UNAVAIL = 0x00000004,
RTWN_PCI_INTR_RX_DONE = 0x00000008,
RTWN_PCI_INTR_TX_ERROR = 0x00000010,
RTWN_PCI_INTR_TX_OVERFLOW = 0x00000020,
RTWN_PCI_INTR_TX_REPORT = 0x00000040,
RTWN_PCI_INTR_PS_TIMEOUT = 0x00000080
};
/* Shortcuts */
/* Vendor driver treats RX errors like ROK... */
#define RTWN_PCI_INTR_RX \
(RTWN_PCI_INTR_RX_OVERFLOW | RTWN_PCI_INTR_RX_DESC_UNAVAIL | \
RTWN_PCI_INTR_RX_DONE)
struct rtwn_pci_softc {
struct rtwn_softc pc_sc; /* must be the first */
struct resource *irq;
struct resource *mem;
bus_space_tag_t pc_st;
bus_space_handle_t pc_sh;
void *pc_ih;
bus_size_t pc_mapsize;
struct rtwn_rx_ring rx_ring;
struct rtwn_tx_ring tx_ring[RTWN_PCI_NTXQUEUES];
/* must be set by the driver. */
uint16_t pc_qmap;
uint32_t tcr;
void (*pc_setup_tx_desc)(struct rtwn_pci_softc *,
void *, uint32_t);
void (*pc_tx_postsetup)(struct rtwn_pci_softc *,
void *, bus_dma_segment_t *);
void (*pc_copy_tx_desc)(void *, const void *);
void (*pc_enable_intr)(struct rtwn_pci_softc *);
#ifdef __HAIKU__
int32 pc_intr_status;
int32 pc_intr_tx_rings;
#endif
};
#define RTWN_PCI_SOFTC(sc) ((struct rtwn_pci_softc *)(sc))
#define rtwn_pci_setup_tx_desc(_pc, _desc, _addr) \
(((_pc)->pc_setup_tx_desc)((_pc), (_desc), (_addr)))
#define rtwn_pci_tx_postsetup(_pc, _txd, _segs) \
(((_pc)->pc_tx_postsetup)((_pc), (_txd), (_segs)))
#define rtwn_pci_copy_tx_desc(_pc, _dest, _src) \
(((_pc)->pc_copy_tx_desc)((_dest), (_src)))
#define rtwn_pci_enable_intr(_pc) \
(((_pc)->pc_enable_intr)((_pc)))
#endif /* RTWN_PCI_VAR_H */
@@ -0,0 +1,96 @@
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $
* $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8188e/r88e.h 322949 2017-08-27 12:44:56Z avos $
*/
#ifndef RTL8188E_H
#define RTL8188E_H
/*
* Global definitions.
*/
#define R88E_PUBQ_NPAGES 142
#define R88E_TXPKTBUF_COUNT 177
#define R88E_TX_PAGE_COUNT 169
#define R88E_MACID_MAX 63
#define R88E_RX_DMA_BUFFER_SIZE 0x2400
#define R88E_INTR_MSG_LEN 60
#define R88E_CALIB_THRESHOLD 4
/*
* Function declarations.
*/
/* r88e_beacon.c */
void r88e_beacon_enable(struct rtwn_softc *, int, int);
/* r88e_calib.c */
void r88e_iq_calib(struct rtwn_softc *);
void r88e_temp_measure(struct rtwn_softc *);
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 r88e_set_bw20(struct rtwn_softc *, uint8_t);
void r88e_set_gain(struct rtwn_softc *, uint8_t);
/* r88e_fw.c */
#ifndef RTWN_WITHOUT_UCODE
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);
#endif
void r88e_macid_enable_link(struct rtwn_softc *, int, int);
void r88e_set_media_status(struct rtwn_softc *, int);
#ifndef RTWN_WITHOUT_UCODE
int r88e_set_rsvd_page(struct rtwn_softc *, int, int, int);
int r88e_set_pwrmode(struct rtwn_softc *, struct ieee80211vap *, int);
#endif
/* r88e_init.c */
void r88e_init_bb(struct rtwn_softc *);
void r88e_init_rf(struct rtwn_softc *);
int r88e_power_on(struct rtwn_softc *);
/* r88e_led.c */
void r88e_set_led(struct rtwn_softc *, int, int);
/* r88e_rf.c */
void r88e_rf_write(struct rtwn_softc *, int, uint8_t, uint32_t);
/* r88e_rom.c */
void r88e_parse_rom(struct rtwn_softc *, uint8_t *);
/* r88e_rx.c */
void r88e_ratectl_tx_complete(struct rtwn_softc *, uint8_t *, int);
void r88e_handle_c2h_report(struct rtwn_softc *, uint8_t *, int);
int8_t r88e_get_rssi_cck(struct rtwn_softc *, void *);
int8_t r88e_get_rssi_ofdm(struct rtwn_softc *, void *);
void r88e_get_rx_stats(struct rtwn_softc *, struct ieee80211_rx_stats *,
const void *, const void *);
/* r88e_tx.c */
void r88e_tx_enable_ampdu(void *, int);
void r88e_tx_setup_hwseq(void *);
void r88e_tx_setup_macid(void *, int);
#endif /* RTL8188E_H */
@@ -0,0 +1,62 @@
/*-
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8188e/r88e_beacon.c 307529 2016-10-17 20:38:24Z avos $");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/rtl8188e/r88e.h>
#include <dev/rtwn/rtl8188e/r88e_reg.h>
void
r88e_beacon_enable(struct rtwn_softc *sc, int id, int enable)
{
if (enable) {
rtwn_setbits_1(sc, R92C_MBID_NUM, 0, R88E_MBID_TXBCN_RPT(id));
rtwn_setbits_1(sc, R92C_BCN_CTRL(id),
0, R92C_BCN_CTRL_EN_BCN);
} else {
rtwn_setbits_1(sc, R92C_MBID_NUM, R88E_MBID_TXBCN_RPT(id), 0);
rtwn_setbits_1(sc, R92C_BCN_CTRL(id),
R92C_BCN_CTRL_EN_BCN, 0);
}
}
@@ -0,0 +1,67 @@
/*-
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8188e/r88e_calib.c 307529 2016-10-17 20:38:24Z avos $");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/rtl8188e/r88e.h>
#include <dev/rtwn/rtl8188e/r88e_reg.h>
void
r88e_iq_calib(struct rtwn_softc *sc)
{
/* XXX TODO */
}
void
r88e_temp_measure(struct rtwn_softc *sc)
{
rtwn_rf_write(sc, 0, R88E_RF_T_METER, R88E_RF_T_METER_START);
}
uint8_t
r88e_temp_read(struct rtwn_softc *sc)
{
return (MS(rtwn_rf_read(sc, 0, R88E_RF_T_METER),
R88E_RF_T_METER_VAL));
}
@@ -0,0 +1,153 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* 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: releng/12.0/sys/dev/rtwn/rtl8188e/r88e_chan.c 330750 2018-03-10 23:47:03Z avos $");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/if_rtwn_debug.h>
#include <dev/rtwn/if_rtwn_ridx.h>
#include <dev/rtwn/rtl8192c/r92c_var.h>
#include <dev/rtwn/rtl8188e/r88e.h>
#include <dev/rtwn/rtl8188e/r88e_priv.h>
#include <dev/rtwn/rtl8188e/r88e_reg.h>
static int
r88e_get_power_group(struct rtwn_softc *sc, struct ieee80211_channel *c)
{
uint8_t chan;
int group;
chan = rtwn_chan2centieee(c);
if (IEEE80211_IS_CHAN_2GHZ(c)) {
if (chan <= 2) group = 0;
else if (chan <= 5) group = 1;
else if (chan <= 8) group = 2;
else if (chan <= 11) group = 3;
else if (chan <= 13) group = 4;
else if (chan <= 14) group = 5;
else {
KASSERT(0, ("wrong 2GHz channel %d!\n", chan));
return (-1);
}
} else {
KASSERT(0, ("wrong channel band (flags %08X)\n", c->ic_flags));
return (-1);
}
return (group);
}
void
r88e_get_txpower(struct rtwn_softc *sc, int chain,
struct ieee80211_channel *c, uint8_t power[RTWN_RIDX_COUNT])
{
struct r92c_softc *rs = sc->sc_priv;
const struct rtwn_r88e_txpwr *rt = rs->rs_txpwr;
uint8_t cckpow, ofdmpow, bw20pow, htpow = 0;
int max_mcs, ridx, group;
/* Determine channel group. */
group = r88e_get_power_group(sc, c);
if (group == -1) { /* shouldn't happen */
device_printf(sc->sc_dev, "%s: incorrect channel\n", __func__);
return;
}
/* XXX net80211 regulatory */
max_mcs = RTWN_RIDX_HT_MCS(sc->ntxchains * 8 - 1);
KASSERT(max_mcs <= RTWN_RIDX_COUNT, ("increase ridx limit\n"));
/* Compute per-CCK rate Tx power. */
cckpow = rt->cck_tx_pwr[group];
for (ridx = RTWN_RIDX_CCK1; ridx <= RTWN_RIDX_CCK11; ridx++) {
power[ridx] = (ridx == RTWN_RIDX_CCK2) ? cckpow - 9 : cckpow;
}
if (group < 5)
htpow = rt->ht40_tx_pwr[group];
/* Compute per-OFDM rate Tx power. */
ofdmpow = htpow + rt->ofdm_tx_pwr_diff;
for (ridx = RTWN_RIDX_OFDM6; ridx <= RTWN_RIDX_OFDM54; ridx++)
power[ridx] = ofdmpow;
bw20pow = htpow + rt->bw20_tx_pwr_diff;
for (ridx = RTWN_RIDX_HT_MCS(0); ridx <= max_mcs; ridx++)
power[ridx] = bw20pow;
/* Apply max limit. */
for (ridx = RTWN_RIDX_CCK1; ridx <= max_mcs; ridx++) {
if (power[ridx] > R92C_MAX_TX_PWR)
power[ridx] = R92C_MAX_TX_PWR;
}
}
void
r88e_set_bw20(struct rtwn_softc *sc, uint8_t chan)
{
struct r92c_softc *rs = sc->sc_priv;
rtwn_setbits_1(sc, R92C_BWOPMODE, 0, R92C_BWOPMODE_20MHZ);
rtwn_bb_setbits(sc, R92C_FPGA0_RFMOD, R92C_RFMOD_40MHZ, 0);
rtwn_bb_setbits(sc, R92C_FPGA1_RFMOD, R92C_RFMOD_40MHZ, 0);
/* Select 20MHz bandwidth. */
rtwn_rf_write(sc, 0, R92C_RF_CHNLBW,
(rs->rf_chnlbw[0] & ~0xfff) | chan | R88E_RF_CHNLBW_BW20);
}
void
r88e_set_gain(struct rtwn_softc *sc, uint8_t gain)
{
rtwn_bb_setbits(sc, R92C_OFDM0_AGCCORE1(0),
R92C_OFDM0_AGCCORE1_GAIN_M, gain);
}
@@ -0,0 +1,225 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* 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: releng/12.0/sys/dev/rtwn/rtl8188e/r88e_fw.c 312002 2017-01-13 02:11:16Z kevlo $");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/if_rtwn_debug.h>
#include <dev/rtwn/rtl8188e/r88e.h>
#include <dev/rtwn/rtl8188e/r88e_reg.h>
#include <dev/rtwn/rtl8188e/r88e_fw_cmd.h>
#ifndef RTWN_WITHOUT_UCODE
int
r88e_fw_cmd(struct rtwn_softc *sc, uint8_t id, const void *buf, int len)
{
struct r88e_fw_cmd cmd;
int ntries, error;
if (!(sc->sc_flags & RTWN_FW_LOADED)) {
RTWN_DPRINTF(sc, RTWN_DEBUG_FIRMWARE, "%s: firmware "
"was not loaded; command (id %d) will be discarded\n",
__func__, id);
return (0);
}
/* Wait for current FW box to be empty. */
for (ntries = 0; ntries < 100; ntries++) {
if (!(rtwn_read_1(sc, R92C_HMETFR) & (1 << sc->fwcur)))
break;
rtwn_delay(sc, 2000);
}
if (ntries == 100) {
device_printf(sc->sc_dev,
"could not send firmware command\n");
return (ETIMEDOUT);
}
memset(&cmd, 0, sizeof(cmd));
cmd.id = id;
KASSERT(len <= sizeof(cmd.msg),
("%s: firmware command too long (%d > %zu)\n",
__func__, len, sizeof(cmd.msg)));
memcpy(cmd.msg, buf, len);
/* Write the first word last since that will trigger the FW. */
if (len > 3) {
error = rtwn_write_4(sc, R88E_HMEBOX_EXT(sc->fwcur),
*(uint32_t *)((uint8_t *)&cmd + 4));
if (error != 0)
return (error);
}
error = rtwn_write_4(sc, R92C_HMEBOX(sc->fwcur), *(uint32_t *)&cmd);
if (error != 0)
return (error);
sc->fwcur = (sc->fwcur + 1) % R92C_H2C_NBOX;
return (0);
}
void
r88e_fw_reset(struct rtwn_softc *sc, int reason)
{
uint16_t reg;
reg = rtwn_read_2(sc, R92C_SYS_FUNC_EN);
rtwn_write_2(sc, R92C_SYS_FUNC_EN, reg & ~R92C_SYS_FUNC_EN_CPUEN);
rtwn_write_2(sc, R92C_SYS_FUNC_EN, reg | R92C_SYS_FUNC_EN_CPUEN);
}
void
r88e_fw_download_enable(struct rtwn_softc *sc, int enable)
{
if (enable) {
/* MCU firmware download enable. */
rtwn_setbits_1(sc, R92C_MCUFWDL, 0, R92C_MCUFWDL_EN);
/* 8051 reset. */
rtwn_setbits_1_shift(sc, R92C_MCUFWDL, R92C_MCUFWDL_ROM_DLEN,
0, 2);
} else {
/* MCU download disable. */
rtwn_setbits_1(sc, R92C_MCUFWDL, R92C_MCUFWDL_EN, 0);
/* Reserved for f/w extension. */
rtwn_write_1(sc, R92C_MCUFWDL + 1, 0);
}
}
#endif
void
r88e_macid_enable_link(struct rtwn_softc *sc, int id, int enable)
{
uint32_t reg;
reg = R88E_MACID_NO_LINK;
if (id > 32)
reg += 4;
if (enable)
rtwn_setbits_4(sc, reg, 1 << (id % 32), 0);
else
rtwn_setbits_4(sc, reg, 0, 1 << (id % 32));
/* XXX max macid for tx reports */
}
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
status.msrb0 = R88E_MSRRPT_B0_DISASSOC;
status.macid = (macid & ~RTWN_MACID_VALID);
r88e_macid_enable_link(sc, status.macid,
(macid & RTWN_MACID_VALID) != 0);
#ifndef RTWN_WITHOUT_UCODE
if (r88e_fw_cmd(sc, R88E_CMD_MSR_RPT, &status, sizeof(status)) != 0) {
device_printf(sc->sc_dev, "%s: cannot change media status!\n",
__func__);
}
#endif
}
#ifndef RTWN_WITHOUT_UCODE
int
r88e_set_rsvd_page(struct rtwn_softc *sc, int probe_resp, int null,
int qos_null)
{
struct r88e_fw_cmd_rsvdpage rsvd;
rsvd.probe_resp = probe_resp;
rsvd.ps_poll = 0;
rsvd.null_data = null;
rsvd.null_data_qos = qos_null;
rsvd.null_data_qos_bt = 0;
return (r88e_fw_cmd(sc, R88E_CMD_RSVD_PAGE, &rsvd, sizeof(rsvd)));
}
int
r88e_set_pwrmode(struct rtwn_softc *sc, struct ieee80211vap *vap,
int off)
{
struct r88e_fw_cmd_pwrmode mode;
int error;
if (off && vap->iv_state == IEEE80211_S_RUN &&
(vap->iv_flags & IEEE80211_F_PMGTON)) {
mode.mode = R88E_PWRMODE_LEG;
/*
* TODO: switch to RFOFF state
* (something is missing here - Rx stops with it).
*/
#ifdef RTWN_TODO
mode.pwr_state = R88E_PWRMODE_STATE_RFOFF;
#else
mode.pwr_state = R88E_PWRMODE_STATE_RFON;
#endif
} else {
mode.mode = R88E_PWRMODE_CAM;
mode.pwr_state = R88E_PWRMODE_STATE_ALLON;
}
mode.pwrb1 =
SM(R88E_PWRMODE_B1_SMART_PS, R88E_PWRMODE_B1_LEG_NULLDATA) |
SM(R88E_PWRMODE_B1_RLBM, R88E_PWRMODE_B1_MODE_MIN);
/* XXX ignored */
mode.bcn_pass = 0;
mode.queue_uapsd = 0;
error = r88e_fw_cmd(sc, R88E_CMD_SET_PWRMODE, &mode, sizeof(mode));
if (error != 0) {
device_printf(sc->sc_dev,
"%s: CMD_SET_PWRMODE was not sent, error %d\n",
__func__, error);
}
return (error);
}
#endif
@@ -0,0 +1,84 @@
/*-
* Copyright (c) 2015 Kevin Lo <kevlo@FreeBSD.org>
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $
* $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8188e/r88e_fw_cmd.h 307529 2016-10-17 20:38:24Z avos $
*/
#ifndef R88E_FW_CMD_H
#define R88E_FW_CMD_H
/*
* Host to firmware commands.
*/
struct r88e_fw_cmd {
uint8_t id;
#define R88E_CMD_RSVD_PAGE 0x00
#define R88E_CMD_MSR_RPT 0x01
#define R88E_CMD_SET_PWRMODE 0x20
uint8_t msg[7];
} __packed __attribute__((aligned(4)));
/* Structure for R88E_CMD_RSVD_PAGE. */
struct r88e_fw_cmd_rsvdpage {
uint8_t probe_resp;
uint8_t ps_poll;
uint8_t null_data;
uint8_t null_data_qos;
uint8_t null_data_qos_bt;
} __packed;
/* Structure for R88E_CMD_MSR_RPT. */
struct r88e_fw_cmd_msrrpt {
uint8_t msrb0;
#define R88E_MSRRPT_B0_DISASSOC 0x00
#define R88E_MSRRPT_B0_ASSOC 0x01
uint8_t macid;
} __packed;
/* Structure for R88E_CMD_SET_PWRMODE. */
struct r88e_fw_cmd_pwrmode {
uint8_t mode;
#define R88E_PWRMODE_CAM 0
#define R88E_PWRMODE_LEG 1
#define R88E_PWRMODE_UAPSD 2
uint8_t pwrb1;
#define R88E_PWRMODE_B1_RLBM_M 0x0f
#define R88E_PWRMODE_B1_RLBM_S 0
#define R88E_PWRMODE_B1_MODE_MIN 0
#define R88E_PWRMODE_B1_MODE_MAX 1
#define R88E_PWRMODE_B1_MODE_DTIM 2
#define R88E_PWRMODE_B1_SMART_PS_M 0xf0
#define R88E_PWRMODE_B1_SMART_PS_S 4
#define R88E_PWRMODE_B1_LEG_PSPOLL0 0
#define R88E_PWRMODE_B1_LEG_PSPOLL1 1
#define R88E_PWRMODE_B1_LEG_NULLDATA 2
#define R88E_PWRMODE_B1_WMM_PSPOLL 0
#define R88E_PWRMODE_B1_WMM_NULLDATA 1
uint8_t bcn_pass;
uint8_t queue_uapsd;
uint8_t pwr_state;
#define R88E_PWRMODE_STATE_RFOFF 0x00
#define R88E_PWRMODE_STATE_RFON 0x04
#define R88E_PWRMODE_STATE_ALLON 0x0c
} __packed;
#endif /* R88E_FW_CMD_H */
@@ -0,0 +1,158 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* 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: releng/12.0/sys/dev/rtwn/rtl8188e/r88e_init.c 307529 2016-10-17 20:38:24Z avos $");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/if_rtwn_debug.h>
#include <dev/rtwn/rtl8192c/r92c.h>
#include <dev/rtwn/rtl8192c/r92c_var.h>
#include <dev/rtwn/rtl8188e/r88e.h>
#include <dev/rtwn/rtl8188e/r88e_reg.h>
static void
r88e_crystalcap_write(struct rtwn_softc *sc)
{
struct r92c_softc *rs = sc->sc_priv;
uint32_t reg;
uint8_t val;
val = rs->crystalcap & 0x3f;
reg = rtwn_bb_read(sc, R92C_AFE_XTAL_CTRL);
rtwn_bb_write(sc, R92C_AFE_XTAL_CTRL,
RW(reg, R92C_AFE_XTAL_CTRL_ADDR, val | val << 6));
}
void
r88e_init_bb(struct rtwn_softc *sc)
{
/* Enable BB and RF. */
rtwn_setbits_2(sc, R92C_SYS_FUNC_EN, 0,
R92C_SYS_FUNC_EN_BBRSTB | R92C_SYS_FUNC_EN_BB_GLB_RST |
R92C_SYS_FUNC_EN_DIO_RF);
rtwn_write_1(sc, R92C_RF_CTRL,
R92C_RF_CTRL_EN | R92C_RF_CTRL_RSTB | R92C_RF_CTRL_SDMRSTB);
rtwn_write_1(sc, R92C_SYS_FUNC_EN,
R92C_SYS_FUNC_EN_USBA | R92C_SYS_FUNC_EN_USBD |
R92C_SYS_FUNC_EN_BB_GLB_RST | R92C_SYS_FUNC_EN_BBRSTB);
r92c_init_bb_common(sc);
rtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(0), 0x69553422);
rtwn_delay(sc, 1);
rtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(0), 0x69553420);
rtwn_delay(sc, 1);
r88e_crystalcap_write(sc);
}
int
r88e_power_on(struct rtwn_softc *sc)
{
#define RTWN_CHK(res) do { \
if (res != 0) \
return (EIO); \
} while(0)
int ntries;
/* Wait for power ready bit. */
for (ntries = 0; ntries < 5000; ntries++) {
if (rtwn_read_4(sc, R92C_APS_FSMCO) & R92C_APS_FSMCO_SUS_HOST)
break;
rtwn_delay(sc, 10);
}
if (ntries == 5000) {
device_printf(sc->sc_dev,
"timeout waiting for chip power up\n");
return (ETIMEDOUT);
}
/* Reset BB. */
RTWN_CHK(rtwn_setbits_1(sc, R92C_SYS_FUNC_EN,
R92C_SYS_FUNC_EN_BBRSTB | R92C_SYS_FUNC_EN_BB_GLB_RST, 0));
RTWN_CHK(rtwn_setbits_1(sc, R92C_AFE_XTAL_CTRL + 2, 0, 0x80));
/* Disable HWPDN. */
RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO,
R92C_APS_FSMCO_APDM_HPDN, 0, 1));
/* Disable WL suspend. */
RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO,
R92C_APS_FSMCO_AFSM_HSUS | R92C_APS_FSMCO_AFSM_PCIE, 0, 1));
RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO,
0, R92C_APS_FSMCO_APFM_ONMAC, 1));
for (ntries = 0; ntries < 5000; ntries++) {
if (!(rtwn_read_2(sc, R92C_APS_FSMCO) &
R92C_APS_FSMCO_APFM_ONMAC))
break;
rtwn_delay(sc, 10);
}
if (ntries == 5000)
return (ETIMEDOUT);
/* Enable LDO normal mode. */
RTWN_CHK(rtwn_setbits_1(sc, R92C_LPLDO_CTRL,
R92C_LPLDO_CTRL_SLEEP, 0));
/* Enable MAC DMA/WMAC/SCHEDULE/SEC blocks. */
RTWN_CHK(rtwn_write_2(sc, R92C_CR, 0));
RTWN_CHK(rtwn_setbits_2(sc, R92C_CR, 0,
R92C_CR_HCI_TXDMA_EN | R92C_CR_TXDMA_EN |
R92C_CR_HCI_RXDMA_EN | R92C_CR_RXDMA_EN |
R92C_CR_PROTOCOL_EN | R92C_CR_SCHEDULE_EN |
((sc->sc_hwcrypto != RTWN_CRYPTO_SW) ? R92C_CR_ENSEC : 0) |
R92C_CR_CALTMR_EN));
return (0);
#undef RTWN_CHK
}
@@ -0,0 +1,68 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8188e/r88e_led.c 307529 2016-10-17 20:38:24Z avos $");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/rtl8188e/r88e.h>
#include <dev/rtwn/rtl8188e/r88e_reg.h>
void
r88e_set_led(struct rtwn_softc *sc, int led, int on)
{
if (led == RTWN_LED_LINK) {
if (!on) {
rtwn_setbits_1(sc, R92C_LEDCFG2, 0x6f,
R92C_LEDCFG0_DIS);
rtwn_setbits_1(sc, R92C_MAC_PINMUX_CFG, 0x01, 0);
} else
rtwn_setbits_1(sc, R92C_LEDCFG2, 0x0f, 0x60);
sc->ledlink = on; /* Save LED state. */
}
/* XXX led #1? */
}
@@ -0,0 +1,230 @@
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $
* $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8188e/r88e_priv.h 320055 2017-06-17 14:39:25Z kevlo $
*/
#ifndef R88E_PRIV_H
#define R88E_PRIV_H
#include <dev/rtwn/rtl8188e/r88e_rom_defs.h>
/*
* Parsed Tx power (diff) values.
*/
struct rtwn_r88e_txpwr {
uint8_t cck_tx_pwr[R88E_GROUP_2G];
uint8_t ht40_tx_pwr[R88E_GROUP_2G - 1];
int8_t ofdm_tx_pwr_diff;
int8_t bw20_tx_pwr_diff;
};
/*
* MAC initialization values.
*/
static const struct rtwn_mac_prog 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 },
{ 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 rtl8188eu_bb_regs[] = {
0x800, 0x804, 0x808, 0x80c, 0x810, 0x814, 0x818, 0x81c,
0x820, 0x824, 0x828, 0x82c, 0x830, 0x834, 0x838, 0x83c,
0x840, 0x844, 0x848, 0x84c, 0x850, 0x854, 0x858, 0x85c,
0x860, 0x864, 0x868, 0x86c, 0x870, 0x874, 0x878, 0x87c,
0x880, 0x884, 0x888, 0x88c, 0x890, 0x894, 0x898, 0x89c,
0x900, 0x904, 0x908, 0x90c, 0x910, 0x914, 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, 0xee8, 0xeec, 0xf14, 0xf4c, 0xf00
};
static const uint32_t rtl8188eu_bb_vals[] = {
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, 0x21555448, 0x01c00014, 0x00000003,
0x00000000, 0x00000300
};
static const struct rtwn_bb_prog rtl8188eu_bb[] = {
{
nitems(rtl8188eu_bb_regs),
rtl8188eu_bb_regs,
rtl8188eu_bb_vals,
{ 0 },
NULL
}
};
static const uint32_t rtl8188eu_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, 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_agc_prog rtl8188eu_agc[] = {
{
nitems(rtl8188eu_agc_vals),
rtl8188eu_agc_vals,
{ 0 },
NULL
}
};
/*
* RF initialization values.
*/
static const uint8_t rtl8188eu_rf_regs[] = {
0x00, 0x08, 0x18, 0x19, 0x1e, 0x1f, 0x2f, 0x3f, 0x42, 0x57,
0x58, 0x67, 0x83, 0xb0, 0xb1, 0xb2, 0xb4, 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, 0xb6, 0x18, 0x5a,
0x19, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34,
0x34, 0x34, 0x00, 0x84, 0x86, 0x87, 0x8e, 0x8f, 0xef, 0x3b,
0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0xef, 0x00, 0x18, 0xfe, 0xfe,
0x1f, 0xfe, 0xfe, 0x1e, 0x1f, 0x00
};
static const uint32_t rtl8188eu_rf_vals[] = {
0x30000, 0x84000, 0x00407, 0x00012, 0x80009, 0x00880, 0x1a060,
0x00000, 0x060c0, 0xd0000, 0xbe180, 0x01552, 0x00000, 0xff8fc,
0x54400, 0xccc19, 0x43003, 0x4953e, 0x1c718, 0x060ff, 0x80001,
0x40000, 0x00400, 0xc0000, 0x02400, 0x00009, 0x40c91, 0x99999,
0x000a3, 0x88820, 0x76c06, 0x00000, 0x80000, 0x00180, 0x001a0,
0x6b27d, 0x7e49d, 0x00073, 0x51ff3, 0x00086, 0x00186,
0x00286, 0x01c25, 0x09c25, 0x11c25, 0x19c25, 0x48538, 0x00c07,
0x4bd00, 0x739d0, 0x0adf3, 0x09df0, 0x08ded, 0x07dea, 0x06de7,
0x054ee, 0x044eb, 0x034e8, 0x0246b, 0x01468, 0x0006d, 0x30159,
0x68200, 0x000ce, 0x48a00, 0x65540, 0x88000, 0x020a0, 0xf02b0,
0xef7b0, 0xd4fb0, 0xcf060, 0xb0090, 0xa0080, 0x90080, 0x8f780,
0x722b0, 0x6f7b0, 0x54fb0, 0x4f060, 0x30090, 0x20080, 0x10080,
0x0f780, 0x000a0, 0x10159, 0x0f407, 0x0c350, 0x0c350, 0x80003,
0x0c350, 0x0c350, 0x00001, 0x80000, 0x33e60
};
static const struct rtwn_rf_prog rtl8188eu_rf[] = {
{
nitems(rtl8188eu_rf_regs),
rtl8188eu_rf_regs,
rtl8188eu_rf_vals,
{ 0 },
NULL
},
{ 0, NULL, NULL, { 0 }, NULL }
};
#endif /* R88E_PRIV_H */
@@ -0,0 +1,91 @@
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $
* $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8188e/r88e_reg.h 307529 2016-10-17 20:38:24Z avos $
*/
#ifndef R88E_REG_H
#define R88E_REG_H
#include <dev/rtwn/rtl8192c/r92c_reg.h>
/*
* MAC registers.
*/
/* System Configuration. */
#define R88E_BB_PAD_CTRL 0x064
#define R88E_HIMR 0x0b0
#define R88E_HISR 0x0b4
#define R88E_HIMRE 0x0b8
#define R88E_HISRE 0x0bc
/* MAC General Configuration. */
#define R88E_32K_CTRL 0x194
#define R88E_HMEBOX_EXT(idx) (0x1f0 + (idx) * 4)
/* Protocol Configuration. */
#define R88E_TXPKTBUF_BCNQ1_BDNY 0x457
#define R88E_MACID_NO_LINK 0x484
#define R88E_TX_RPT_CTRL 0x4ec
#define R88E_TX_RPT_MACID_MAX 0x4ed
#define R88E_TX_RPT_TIME 0x4f0
#define R88E_SCH_TXCMD 0x5f8
/* Bits for R88E_HIMR. */
#define R88E_HIMR_CPWM 0x00000100
#define R88E_HIMR_CPWM2 0x00000200
#define R88E_HIMR_TBDER 0x04000000
#define R88E_HIMR_PSTIMEOUT 0x20000000
/* Bits for R88E_HIMRE.*/
#define R88E_HIMRE_RXFOVW 0x00000100
#define R88E_HIMRE_TXFOVW 0x00000200
#define R88E_HIMRE_RXERR 0x00000400
#define R88E_HIMRE_TXERR 0x00000800
/* Bits for R88E_TX_RPT_CTRL. */
#define R88E_TX_RPT1_ENA 0x01
#define R88E_TX_RPT2_ENA 0x02
/* Bits for R92C_MBID_NUM. */
#define R88E_MBID_TXBCN_RPT(id) (0x08 << (id))
/* Bits for R92C_SECCFG. */
#define R88E_SECCFG_CHK_KEYID 0x0100
/*
* Baseband registers.
*/
/* Bits for R92C_LSSI_PARAM(i). */
#define R88E_LSSI_PARAM_ADDR_M 0x0ff00000
#define R88E_LSSI_PARAM_ADDR_S 20
/*
* RF (6052) registers.
*/
#define R88E_RF_T_METER 0x42
/* Bits for R92C_RF_CHNLBW. */
#define R88E_RF_CHNLBW_BW20 0x00c00
/* Bits for R88E_RF_T_METER. */
#define R88E_RF_T_METER_VAL_M 0x0fc00
#define R88E_RF_T_METER_VAL_S 10
#define R88E_RF_T_METER_START 0x30000
#endif /* R88E_REG_H */
@@ -0,0 +1,60 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8188e/r88e_rf.c 307529 2016-10-17 20:38:24Z avos $");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/rtl8188e/r88e.h>
#include <dev/rtwn/rtl8188e/r88e_reg.h>
void
r88e_rf_write(struct rtwn_softc *sc, int chain, uint8_t addr, uint32_t val)
{
rtwn_bb_write(sc, R92C_LSSI_PARAM(chain),
SM(R88E_LSSI_PARAM_ADDR, addr) |
SM(R92C_LSSI_PARAM_DATA, val));
}
@@ -0,0 +1,85 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* 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: releng/12.0/sys/dev/rtwn/rtl8188e/r88e_rom.c 307529 2016-10-17 20:38:24Z avos $");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/if_rtwn_debug.h>
#include <dev/rtwn/rtl8192c/r92c_var.h>
#include <dev/rtwn/rtl8188e/r88e.h>
#include <dev/rtwn/rtl8188e/r88e_priv.h>
#include <dev/rtwn/rtl8188e/r88e_rom_image.h>
void
r88e_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 r88e_rom *rom = (struct r88e_rom *)buf;
int i;
rt->bw20_tx_pwr_diff = RTWN_SIGN4TO8(MS(rom->tx_pwr_diff, HIGH_PART));
rt->ofdm_tx_pwr_diff = RTWN_SIGN4TO8(MS(rom->tx_pwr_diff, LOW_PART));
for (i = 0; i < nitems(rom->cck_tx_pwr); i++)
rt->cck_tx_pwr[i] = rom->cck_tx_pwr[i];
for (i = 0; i < nitems(rom->ht40_tx_pwr); i++)
rt->ht40_tx_pwr[i] = rom->ht40_tx_pwr[i];
rs->crystalcap = RTWN_GET_ROM_VAR(rom->crystalcap,
R88E_ROM_CRYSTALCAP_DEF);
rs->regulatory = MS(rom->rf_board_opt, R92C_ROM_RF1_REGULATORY);
rs->board_type =
MS(RTWN_GET_ROM_VAR(rom->rf_board_opt, R92C_BOARD_TYPE_DONGLE),
R92C_ROM_RF1_BOARD_TYPE);
RTWN_DPRINTF(sc, RTWN_DEBUG_ROM, "%s: regulatory type %d\n",
__func__,rs->regulatory);
sc->thermal_meter = rom->thermal_meter;
IEEE80211_ADDR_COPY(sc->sc_ic.ic_macaddr, rom->macaddr);
}
@@ -0,0 +1,29 @@
/*-
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8188e/r88e_rom_defs.h 319649 2017-06-07 09:10:24Z kevlo $
*/
#ifndef R88E_ROM_DEFS_H
#define R88E_ROM_DEFS_H
#include <dev/rtwn/rtl8192c/r92c_rom_defs.h>
#define R88E_GROUP_2G 6
#define R88E_EFUSE_MAX_LEN 256
#define R88E_EFUSE_MAP_LEN 512
#endif /* R88E_ROM_DEFS_H */
@@ -0,0 +1,60 @@
/*-
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8188e/r88e_rom_image.h 307529 2016-10-17 20:38:24Z avos $
*/
#ifndef R88E_ROM_IMAGE_H
#define R88E_ROM_IMAGE_H
#include <dev/rtwn/rtl8188e/r88e_rom_defs.h>
/*
* RTL8188EU ROM image.
*/
struct r88e_rom {
uint8_t reserved1[16];
uint8_t cck_tx_pwr[R88E_GROUP_2G];
uint8_t ht40_tx_pwr[R88E_GROUP_2G - 1];
uint8_t tx_pwr_diff;
uint8_t reserved2[156];
uint8_t channel_plan;
uint8_t crystalcap;
#define R88E_ROM_CRYSTALCAP_DEF 0x20
uint8_t thermal_meter;
uint8_t reserved3[6];
uint8_t rf_board_opt;
uint8_t rf_feature_opt;
uint8_t rf_bt_opt;
uint8_t version;
uint8_t customer_id;
uint8_t reserved4[3];
uint8_t rf_ant_opt;
uint8_t reserved5[6];
uint16_t vid;
uint16_t pid;
uint8_t usb_opt;
uint8_t reserved6[2];
uint8_t macaddr[IEEE80211_ADDR_LEN];
uint8_t reserved7[2];
uint8_t string[33]; /* "realtek 802.11n NIC" */
uint8_t reserved8[256];
} __packed;
_Static_assert(sizeof(struct r88e_rom) == R88E_EFUSE_MAP_LEN,
"R88E_EFUSE_MAP_LEN must be equal to sizeof(struct r88e_rom)!");
#endif /* R88E_ROM_IMAGE_H */
@@ -0,0 +1,229 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* 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: releng/12.0/sys/dev/rtwn/rtl8188e/r88e_rx.c 331043 2018-03-16 01:03:10Z avos $");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <net80211/ieee80211_ratectl.h>
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/if_rtwn_debug.h>
#include <dev/rtwn/if_rtwn_ridx.h>
#include <dev/rtwn/rtl8192c/r92c.h>
#include <dev/rtwn/rtl8188e/r88e.h>
#include <dev/rtwn/rtl8188e/r88e_rx_desc.h>
void
r88e_ratectl_tx_complete(struct rtwn_softc *sc, uint8_t *buf, int len)
{
#if __FreeBSD_version >= 1200012
struct ieee80211_ratectl_tx_status txs;
#endif
struct r88e_tx_rpt_ccx *rpt;
struct ieee80211_node *ni;
uint8_t macid;
int ntries;
/* Skip Rx descriptor. */
buf += sizeof(struct r92c_rx_stat);
len -= sizeof(struct r92c_rx_stat);
rpt = (struct r88e_tx_rpt_ccx *)buf;
if (len != sizeof(*rpt)) {
RTWN_DPRINTF(sc, RTWN_DEBUG_INTR,
"%s: wrong report size (%d, must be %zu)\n",
__func__, len, sizeof(*rpt));
return;
}
RTWN_DPRINTF(sc, RTWN_DEBUG_INTR,
"%s: ccx report dump: 0: %02X, 1: %02X, 2: %02X, queue time: "
"low %02X, high %02X, final ridx: %02X, 6: %02X, 7: %02X\n",
__func__, rpt->rptb0, rpt->rptb1, rpt->rptb2, rpt->queue_time_low,
rpt->queue_time_high, rpt->final_rate, rpt->rptb6, rpt->rptb7);
macid = MS(rpt->rptb1, R88E_RPTB1_MACID);
if (macid > sc->macid_limit) {
device_printf(sc->sc_dev,
"macid %u is too big; increase MACID_MAX limit\n",
macid);
return;
}
ntries = MS(rpt->rptb2, R88E_RPTB2_RETRY_CNT);
ni = sc->node_list[macid];
if (ni != NULL) {
RTWN_DPRINTF(sc, RTWN_DEBUG_INTR, "%s: frame for macid %u was"
"%s sent (%d retries)\n", __func__, macid,
(rpt->rptb1 & R88E_RPTB1_PKT_OK) ? "" : " not",
ntries);
#if __FreeBSD_version >= 1200012
txs.flags = IEEE80211_RATECTL_STATUS_LONG_RETRY |
IEEE80211_RATECTL_STATUS_FINAL_RATE;
txs.long_retries = ntries;
if (rpt->final_rate > RTWN_RIDX_OFDM54) { /* MCS */
txs.final_rate =
rpt->final_rate - RTWN_RIDX_HT_MCS_SHIFT;
txs.final_rate |= IEEE80211_RATE_MCS;
} else
txs.final_rate = ridx2rate[rpt->final_rate];
if (rpt->rptb1 & R88E_RPTB1_PKT_OK)
txs.status = IEEE80211_RATECTL_TX_SUCCESS;
else if (rpt->rptb2 & R88E_RPTB2_RETRY_OVER)
txs.status = IEEE80211_RATECTL_TX_FAIL_LONG;
else if (rpt->rptb2 & R88E_RPTB2_LIFE_EXPIRE)
txs.status = IEEE80211_RATECTL_TX_FAIL_EXPIRED;
else
txs.status = IEEE80211_RATECTL_TX_FAIL_UNSPECIFIED;
ieee80211_ratectl_tx_complete(ni, &txs);
#else
struct ieee80211vap *vap = ni->ni_vap;
if (rpt->rptb1 & R88E_RPTB1_PKT_OK) {
ieee80211_ratectl_tx_complete(vap, ni,
IEEE80211_RATECTL_TX_SUCCESS, &ntries, NULL);
} else {
ieee80211_ratectl_tx_complete(vap, ni,
IEEE80211_RATECTL_TX_FAILURE, &ntries, NULL);
}
#endif
} else {
RTWN_DPRINTF(sc, RTWN_DEBUG_INTR, "%s: macid %u, ni is NULL\n",
__func__, macid);
}
}
void
r88e_handle_c2h_report(struct rtwn_softc *sc, uint8_t *buf, int len)
{
/* Skip Rx descriptor. */
buf += sizeof(struct r92c_rx_stat);
len -= sizeof(struct r92c_rx_stat);
if (len != R88E_INTR_MSG_LEN) {
RTWN_DPRINTF(sc, RTWN_DEBUG_INTR,
"%s: wrong interrupt message size (%d, must be %d)\n",
__func__, len, R88E_INTR_MSG_LEN);
return;
}
/* XXX TODO */
}
int8_t
r88e_get_rssi_cck(struct rtwn_softc *sc, void *physt)
{
struct r88e_rx_phystat *phy = (struct r88e_rx_phystat *)physt;
int8_t lna_idx, vga_idx, rssi;
lna_idx = (phy->agc_rpt & 0xe0) >> 5;
vga_idx = (phy->agc_rpt & 0x1f);
rssi = 6 - 2 * vga_idx;
switch (lna_idx) {
case 7:
if (vga_idx > 27)
rssi = -100 + 6;
else
rssi += -100 + 2 * 27;
break;
case 6:
rssi += -48 + 2 * 2;
break;
case 5:
rssi += -42 + 2 * 7;
break;
case 4:
rssi += -36 + 2 * 7;
break;
case 3:
rssi += -24 + 2 * 7;
break;
case 2:
rssi += -6 + 2 * 5;
if (sc->sc_flags & RTWN_FLAG_CCK_HIPWR)
rssi -= 6;
break;
case 1:
rssi += 8;
break;
case 0:
rssi += 14;
break;
}
return (rssi);
}
int8_t
r88e_get_rssi_ofdm(struct rtwn_softc *sc, void *physt)
{
struct r88e_rx_phystat *phy = (struct r88e_rx_phystat *)physt;
int rssi;
/* Get average RSSI. */
rssi = ((phy->sig_qual >> 1) & 0x7f) - 110;
return (rssi);
}
void
r88e_get_rx_stats(struct rtwn_softc *sc, struct ieee80211_rx_stats *rxs,
const void *desc, const void *physt_ptr)
{
const struct r88e_rx_phystat *physt = physt_ptr;
r92c_get_rx_stats(sc, rxs, desc, physt_ptr);
if (!sc->sc_ht40) { /* XXX center channel */
rxs->r_flags |= IEEE80211_R_IEEE | IEEE80211_R_FREQ;
rxs->c_ieee = physt->chan;
rxs->c_freq = ieee80211_ieee2mhz(rxs->c_ieee,
IEEE80211_CHAN_2GHZ);
}
}
@@ -0,0 +1,100 @@
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $
* $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8188e/r88e_rx_desc.h 307529 2016-10-17 20:38:24Z avos $
*/
#ifndef R88E_RX_DESC_H
#define R88E_RX_DESC_H
#include <dev/rtwn/rtl8192c/r92c_rx_desc.h>
/* Rx MAC descriptor defines (chip-specific). */
/* Rx dword 3 */
#define R88E_RXDW3_RPT_M 0x0000c000
#define R88E_RXDW3_RPT_S 14
#define R88E_RXDW3_RPT_RX 0
#define R88E_RXDW3_RPT_TX1 1
#define R88E_RXDW3_RPT_TX2 2
#define R88E_RXDW3_RPT_HIS 3
/* Rx PHY descriptor. */
struct r88e_rx_phystat {
uint8_t path_agc[2];
uint8_t chan;
uint8_t reserved1;
uint8_t sig_qual;
uint8_t agc_rpt;
uint8_t rpt_b;
uint8_t reserved2;
uint8_t noise_power;
uint8_t path_cfotail[2];
uint8_t pcts_mask[2];
uint8_t stream_rxevm[2];
uint8_t path_rxsnr[2];
uint8_t noise_power_db_lsb;
uint8_t reserved3[3];
uint8_t stream_csi[2];
uint8_t stream_target_csi[2];
uint8_t sig_evm;
} __packed;
/* Tx report (type 1). */
struct r88e_tx_rpt_ccx {
uint8_t rptb0;
#define R88E_RPTB6_PKT_NUM_M 0x0e
#define R88E_RPTB6_PKT_NUM_S 1
#define R88E_RPTB0_INT_CCX 0x80
uint8_t rptb1;
#define R88E_RPTB1_MACID_M 0x3f
#define R88E_RPTB1_MACID_S 0
#define R88E_RPTB1_PKT_OK 0x40
#define R88E_RPTB1_BMC 0x80
uint8_t rptb2;
#define R88E_RPTB2_RETRY_CNT_M 0x3f
#define R88E_RPTB2_RETRY_CNT_S 0
#define R88E_RPTB2_LIFE_EXPIRE 0x40
#define R88E_RPTB2_RETRY_OVER 0x80
uint8_t queue_time_low;
uint8_t queue_time_high;
uint8_t final_rate;
uint8_t rptb6;
#define R88E_RPTB6_QSEL_M 0xf0
#define R88E_RPTB6_QSEL_S 4
uint8_t rptb7;
} __packed;
/* Interrupt message format. */
/* XXX recheck */
struct r88e_intr_msg {
uint8_t c2h_id;
uint8_t c2h_seq;
uint8_t c2h_evt;
uint8_t reserved1[13];
uint8_t cpwm1;
uint8_t reserved2[3];
uint8_t cpwm2;
uint8_t reserved3[27];
uint32_t hisr;
uint32_t hisr_ex;
};
#endif /* R88E_RX_DESC_H */
@@ -0,0 +1,79 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* 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: releng/12.0/sys/dev/rtwn/rtl8188e/r88e_tx.c 307529 2016-10-17 20:38:24Z avos $");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/rtl8188e/r88e.h>
#include <dev/rtwn/rtl8188e/r88e_tx_desc.h>
void
r88e_tx_enable_ampdu(void *buf, int enable)
{
struct r92c_tx_desc *txd = (struct r92c_tx_desc *)buf;
if (enable)
txd->txdw2 |= htole32(R88E_TXDW2_AGGEN);
else
txd->txdw2 |= htole32(R88E_TXDW2_AGGBK);
}
void
r88e_tx_setup_hwseq(void *buf)
{
struct r92c_tx_desc *txd = (struct r92c_tx_desc *)buf;
txd->txdseq |= htole16(R88E_TXDSEQ_HWSEQ_EN);
}
void
r88e_tx_setup_macid(void *buf, int id)
{
struct r92c_tx_desc *txd = (struct r92c_tx_desc *)buf;
txd->txdw1 |= htole32(SM(R88E_TXDW1_MACID, id));
}
@@ -0,0 +1,38 @@
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $
* $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8188e/r88e_tx_desc.h 307529 2016-10-17 20:38:24Z avos $
*/
#ifndef R88E_TX_DESC_H
#define R88E_TX_DESC_H
#include <dev/rtwn/rtl8192c/r92c_tx_desc.h>
/* Tx MAC descriptor defines (chip-specific). */
/* Tx dword 1. */
#define R88E_TXDW1_MACID_M 0x0000003f
#define R88E_TXDW1_MACID_S 0
/* Tx dword 2. */
#define R88E_TXDW2_AGGEN 0x00001000
#define R88E_TXDW2_AGGBK 0x00010000
/* Tx dword 3. */
#define R88E_TXDSEQ_HWSEQ_EN 0x8000
#endif /* R88E_TX_DESC_H */
@@ -0,0 +1,39 @@
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $
* $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8188e/usb/r88eu.h 307529 2016-10-17 20:38:24Z avos $
*/
#ifndef RTL8188EU_H
#define RTL8188EU_H
#include <dev/rtwn/rtl8188e/r88e.h>
/*
* Function declarations.
*/
/* r88eu_init.c */
void r88eu_power_off(struct rtwn_softc *);
void r88eu_init_intr(struct rtwn_softc *);
void r88eu_init_rx_agg(struct rtwn_softc *);
void r88eu_post_init(struct rtwn_softc *);
/* r88eu_rx.c */
int r88eu_classify_intr(struct rtwn_softc *, void *, int);
#endif /* RTL8188EU_H */
@@ -0,0 +1,218 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* 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: releng/12.0/sys/dev/rtwn/rtl8188e/usb/r88eu_attach.c 320055 2017-06-17 14:39:25Z kevlo $");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/if_rtwn_nop.h>
#include <dev/rtwn/usb/rtwn_usb_var.h>
#include <dev/rtwn/rtl8192c/r92c_reg.h>
#include <dev/rtwn/rtl8192c/r92c_var.h>
#include <dev/rtwn/rtl8192c/usb/r92cu.h>
#include <dev/rtwn/rtl8192c/usb/r92cu_tx_desc.h>
#include <dev/rtwn/rtl8188e/r88e_priv.h>
#include <dev/rtwn/rtl8188e/usb/r88eu.h>
static struct rtwn_r88e_txpwr r88e_txpwr;
void r88eu_attach(struct rtwn_usb_softc *);
static void
r88e_postattach(struct rtwn_softc *sc)
{
struct r92c_softc *rs = sc->sc_priv;
struct ieee80211com *ic = &sc->sc_ic;
rs->rs_scan_start = ic->ic_scan_start;
ic->ic_scan_start = r92c_scan_start;
rs->rs_scan_end = ic->ic_scan_end;
ic->ic_scan_end = r92c_scan_end;
}
static void
r88eu_attach_private(struct rtwn_softc *sc)
{
struct r92c_softc *rs;
rs = malloc(sizeof(struct r92c_softc), M_RTWN_PRIV, M_WAITOK | M_ZERO);
rs->rs_txpwr = &r88e_txpwr;
rs->rs_txagc = NULL;
rs->rs_set_bw20 = r88e_set_bw20;
rs->rs_get_txpower = 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 = rtwn_nop_softc; /* not used */
rs->rf_read_delay[0] = 10;
rs->rf_read_delay[1] = 100;
rs->rf_read_delay[2] = 10;
sc->sc_priv = rs;
}
static void
r88eu_adj_devcaps(struct rtwn_softc *sc)
{
/* XXX TODO? */
}
void
r88eu_attach(struct rtwn_usb_softc *uc)
{
struct rtwn_softc *sc = &uc->uc_sc;
/* USB part. */
uc->uc_align_rx = r92cu_align_rx;
uc->tx_agg_desc_num = 6;
/* Common part. */
sc->sc_flags = RTWN_FLAG_EXT_HDR;
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;
sc->sc_dump_tx_desc = r92cu_dump_tx_desc;
sc->sc_tx_radiotap_flags = r92c_tx_radiotap_flags;
sc->sc_rx_radiotap_flags = r92c_rx_radiotap_flags;
sc->sc_get_rx_stats = r88e_get_rx_stats;
sc->sc_get_rssi_cck = r88e_get_rssi_cck;
sc->sc_get_rssi_ofdm = r88e_get_rssi_ofdm;
sc->sc_classify_intr = r88eu_classify_intr;
sc->sc_handle_tx_report = r88e_ratectl_tx_complete;
sc->sc_handle_c2h_report = r88e_handle_c2h_report;
sc->sc_check_frame = rtwn_nop_int_softc_mbuf;
sc->sc_rf_read = r92c_rf_read;
sc->sc_rf_write = r88e_rf_write;
sc->sc_check_condition = r92c_check_condition;
sc->sc_efuse_postread = rtwn_nop_softc;
sc->sc_parse_rom = r88e_parse_rom;
sc->sc_set_led = r88e_set_led;
sc->sc_power_on = r88e_power_on;
sc->sc_power_off = r88eu_power_off;
#ifndef RTWN_WITHOUT_UCODE
sc->sc_fw_reset = r88e_fw_reset;
sc->sc_fw_download_enable = r88e_fw_download_enable;
#endif
sc->sc_llt_init = r92c_llt_init;
sc->sc_set_page_size = r92c_set_page_size;
sc->sc_lc_calib = r92c_lc_calib;
sc->sc_iq_calib = r88e_iq_calib; /* XXX TODO */
sc->sc_read_chipid_vendor = rtwn_nop_softc_uint32;
sc->sc_adj_devcaps = r88eu_adj_devcaps;
sc->sc_vap_preattach = rtwn_nop_softc_vap;
sc->sc_postattach = r88e_postattach;
sc->sc_detach_private = r92c_detach_private;
sc->sc_set_media_status = r88e_set_media_status;
#ifndef RTWN_WITHOUT_UCODE
sc->sc_set_rsvd_page = r88e_set_rsvd_page;
sc->sc_set_pwrmode = r88e_set_pwrmode;
sc->sc_set_rssi = rtwn_nop_softc; /* XXX TODO? */
#endif
sc->sc_beacon_init = r92c_beacon_init;
sc->sc_beacon_enable = r88e_beacon_enable;
sc->sc_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 = r92cu_init_tx_agg;
sc->sc_init_rx_agg = r88eu_init_rx_agg;
sc->sc_init_ampdu = rtwn_nop_softc;
sc->sc_init_intr = r88eu_init_intr;
sc->sc_init_edca = r92c_init_edca;
sc->sc_init_bb = r88e_init_bb;
sc->sc_init_rf = r92c_init_rf;
sc->sc_init_antsel = rtwn_nop_softc;
sc->sc_post_init = r88eu_post_init;
sc->sc_init_bcnq1_boundary = rtwn_nop_int_softc;
sc->mac_prog = &rtl8188eu_mac[0];
sc->mac_size = nitems(rtl8188eu_mac);
sc->bb_prog = &rtl8188eu_bb[0];
sc->bb_size = nitems(rtl8188eu_bb);
sc->agc_prog = &rtl8188eu_agc[0];
sc->agc_size = nitems(rtl8188eu_agc);
sc->rf_prog = &rtl8188eu_rf[0];
sc->name = "RTL8188EU";
sc->fwname = "rtwn-rtl8188eufw";
sc->fwsig = 0x88e;
sc->page_count = R88E_TX_PAGE_COUNT;
sc->pktbuf_count = R88E_TXPKTBUF_COUNT;
sc->ackto = 0x40;
sc->npubqpages = R88E_PUBQ_NPAGES;
sc->page_size = R92C_TX_PAGE_SIZE;
sc->txdesc_len = sizeof(struct r92cu_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 = R92C_MAX_FW_SIZE;
sc->temp_delta = R88E_CALIB_THRESHOLD;
sc->bcn_status_reg[0] = R92C_TDECTRL;
sc->bcn_status_reg[1] = R92C_TDECTRL;
sc->rcr = 0;
sc->ntxchains = 1;
sc->nrxchains = 1;
r88eu_attach_private(sc);
}
@@ -0,0 +1,224 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* 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: releng/12.0/sys/dev/rtwn/rtl8188e/usb/r88eu_init.c 310305 2016-12-20 01:13:11Z kevlo $");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/rtl8192c/r92c.h>
#include <dev/rtwn/rtl8192c/r92c_var.h>
#include <dev/rtwn/rtl8188e/usb/r88eu.h>
#include <dev/rtwn/rtl8188e/usb/r88eu_reg.h>
void
r88eu_power_off(struct rtwn_softc *sc)
{
uint8_t reg;
int error, ntries;
/* Disable any kind of TX reports. */
error = rtwn_setbits_1(sc, R88E_TX_RPT_CTRL,
R88E_TX_RPT1_ENA | R88E_TX_RPT2_ENA, 0);
if (error == ENXIO) /* hardware gone */
return;
/* Stop Rx. */
rtwn_write_1(sc, R92C_CR, 0);
/* Move card to Low Power State. */
/* Block all Tx queues. */
rtwn_write_1(sc, R92C_TXPAUSE, R92C_TX_QUEUE_ALL);
for (ntries = 0; ntries < 10; ntries++) {
/* Should be zero if no packet is transmitting. */
if (rtwn_read_4(sc, R88E_SCH_TXCMD) == 0)
break;
rtwn_delay(sc, 5000);
}
if (ntries == 10) {
device_printf(sc->sc_dev, "%s: failed to block Tx queues\n",
__func__);
return;
}
/* CCK and OFDM are disabled, and clock are gated. */
rtwn_setbits_1(sc, R92C_SYS_FUNC_EN, R92C_SYS_FUNC_EN_BBRSTB, 0);
rtwn_delay(sc, 1);
/* Reset MAC TRX */
rtwn_write_1(sc, R92C_CR,
R92C_CR_HCI_TXDMA_EN | R92C_CR_HCI_RXDMA_EN |
R92C_CR_TXDMA_EN | R92C_CR_RXDMA_EN |
R92C_CR_PROTOCOL_EN | R92C_CR_SCHEDULE_EN);
/* check if removed later */
rtwn_setbits_1_shift(sc, R92C_CR, R92C_CR_ENSEC, 0, 1);
/* Respond TxOK to scheduler */
rtwn_setbits_1(sc, R92C_DUAL_TSF_RST, 0, 0x20);
/* If firmware in ram code, do reset. */
#ifndef RTWN_WITHOUT_UCODE
if (rtwn_read_1(sc, R92C_MCUFWDL) & R92C_MCUFWDL_RDY)
r88e_fw_reset(sc, RTWN_FW_RESET_SHUTDOWN);
#endif
/* Reset MCU ready status. */
rtwn_write_1(sc, R92C_MCUFWDL, 0);
/* Disable 32k. */
rtwn_setbits_1(sc, R88E_32K_CTRL, 0x01, 0);
/* Move card to Disabled state. */
/* Turn off RF. */
rtwn_write_1(sc, R92C_RF_CTRL, 0);
/* LDO Sleep mode. */
rtwn_setbits_1(sc, R92C_LPLDO_CTRL, 0, R92C_LPLDO_CTRL_SLEEP);
/* Turn off MAC by HW state machine */
rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, 0,
R92C_APS_FSMCO_APFM_OFF, 1);
for (ntries = 0; ntries < 10; ntries++) {
/* Wait until it will be disabled. */
if ((rtwn_read_2(sc, R92C_APS_FSMCO) &
R92C_APS_FSMCO_APFM_OFF) == 0)
break;
rtwn_delay(sc, 5000);
}
if (ntries == 10) {
device_printf(sc->sc_dev, "%s: could not turn off MAC\n",
__func__);
return;
}
/* schmit trigger */
rtwn_setbits_1(sc, R92C_AFE_XTAL_CTRL + 2, 0, 0x80);
/* Enable WL suspend. */
rtwn_setbits_1_shift(sc, R92C_APS_FSMCO,
R92C_APS_FSMCO_AFSM_PCIE, R92C_APS_FSMCO_AFSM_HSUS, 1);
/* Enable bandgap mbias in suspend. */
rtwn_write_1(sc, R92C_APS_FSMCO + 3, 0);
/* Clear SIC_EN register. */
rtwn_setbits_1(sc, R92C_GPIO_MUXCFG + 1, 0x10, 0);
/* Set USB suspend enable local register */
rtwn_setbits_1(sc, R92C_USB_SUSPEND, 0, 0x10);
/* Reset MCU IO Wrapper. */
reg = rtwn_read_1(sc, R92C_RSV_CTRL + 1);
rtwn_write_1(sc, R92C_RSV_CTRL + 1, reg & ~0x08);
rtwn_write_1(sc, R92C_RSV_CTRL + 1, reg | 0x08);
/* marked as 'For Power Consumption' code. */
rtwn_write_1(sc, R92C_GPIO_OUT, rtwn_read_1(sc, R92C_GPIO_IN));
rtwn_write_1(sc, R92C_GPIO_IOSEL, 0xff);
rtwn_write_1(sc, R92C_GPIO_IO_SEL,
rtwn_read_1(sc, R92C_GPIO_IO_SEL) << 4);
rtwn_setbits_1(sc, R92C_GPIO_MOD, 0, 0x0f);
/* Set LNA, TRSW, EX_PA Pin to output mode. */
rtwn_write_4(sc, R88E_BB_PAD_CTRL, 0x00080808);
}
void
r88eu_init_intr(struct rtwn_softc *sc)
{
/* TODO: adjust */
rtwn_write_4(sc, R88E_HISR, 0xffffffff);
rtwn_write_4(sc, R88E_HIMR, R88E_HIMR_CPWM | R88E_HIMR_CPWM2 |
R88E_HIMR_TBDER | R88E_HIMR_PSTIMEOUT);
rtwn_write_4(sc, R88E_HIMRE, R88E_HIMRE_RXFOVW |
R88E_HIMRE_TXFOVW | R88E_HIMRE_RXERR | R88E_HIMRE_TXERR);
rtwn_setbits_1(sc, R92C_USB_SPECIAL_OPTION, 0,
R92C_USB_SPECIAL_OPTION_INT_BULK_SEL);
}
void
r88eu_init_rx_agg(struct rtwn_softc *sc)
{
/* XXX merge? */
rtwn_setbits_1(sc, R92C_TRXDMA_CTRL, 0,
R92C_TRXDMA_CTRL_RXDMA_AGG_EN);
/* XXX dehardcode */
rtwn_write_1(sc, R92C_RXDMA_AGG_PG_TH, 48);
rtwn_write_1(sc, R92C_RXDMA_AGG_PG_TH + 1, 4);
}
void
r88eu_post_init(struct rtwn_softc *sc)
{
/* Enable per-packet TX report. */
rtwn_setbits_1(sc, R88E_TX_RPT_CTRL, 0, R88E_TX_RPT1_ENA);
/* Disable Tx if MACID is not associated. */
rtwn_write_4(sc, R88E_MACID_NO_LINK, 0xffffffff);
rtwn_write_4(sc, R88E_MACID_NO_LINK + 4, 0xffffffff);
r88e_macid_enable_link(sc, RTWN_MACID_BC, 1);
/* Perform LO and IQ calibrations. */
r88e_iq_calib(sc);
/* Perform LC calibration. */
r92c_lc_calib(sc);
rtwn_write_1(sc, R92C_USB_HRPWM, 0);
if (sc->sc_ratectl_sysctl == RTWN_RATECTL_FW) {
/* No support (yet?) for f/w rate adaptation. */
sc->sc_ratectl = RTWN_RATECTL_NET80211;
} else
sc->sc_ratectl = sc->sc_ratectl_sysctl;
}
@@ -0,0 +1,27 @@
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $
* $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8188e/usb/r88eu_reg.h 307529 2016-10-17 20:38:24Z avos $
*/
#ifndef R88EU_REG_H
#define R88EU_REG_H
#include <dev/rtwn/rtl8192c/usb/r92cu_reg.h>
#include <dev/rtwn/rtl8188e/r88e_reg.h>
#endif /* R88EU_REG_H */
@@ -0,0 +1,74 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* 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: releng/12.0/sys/dev/rtwn/rtl8188e/usb/r88eu_rx.c 307529 2016-10-17 20:38:24Z avos $");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/if_rtwn_debug.h>
#include <dev/rtwn/rtl8188e/r88e_rx_desc.h>
#include <dev/rtwn/rtl8188e/usb/r88eu.h>
int
r88eu_classify_intr(struct rtwn_softc *sc, void *buf, int len)
{
struct r92c_rx_stat *stat = buf;
int report_sel = MS(le32toh(stat->rxdw3), R88E_RXDW3_RPT);
switch (report_sel) {
case R88E_RXDW3_RPT_RX:
return (RTWN_RX_DATA);
case R88E_RXDW3_RPT_TX1: /* per-packet Tx report */
case R88E_RXDW3_RPT_TX2: /* periodical Tx report */
return (RTWN_RX_TX_REPORT);
case R88E_RXDW3_RPT_HIS:
return (RTWN_RX_OTHER);
default: /* shut up the compiler */
return (RTWN_RX_DATA);
}
}
@@ -0,0 +1,74 @@
/* $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>
*
* 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: releng/12.0/sys/dev/rtwn/rtl8192c/pci/r92ce.h 307529 2016-10-17 20:38:24Z avos $
*/
#ifndef RTL8192CE_H
#define RTL8192CE_H
#include <dev/rtwn/rtl8192c/r92c.h>
/*
* Global definitions.
*/
#define R92CE_PUBQ_NPAGES 176
#define R92CE_HPQ_NPAGES 41
#define R92CE_LPQ_NPAGES 28
#define R92CE_TX_PAGE_COUNT \
(R92CE_PUBQ_NPAGES + R92CE_HPQ_NPAGES + R92CE_LPQ_NPAGES)
/*
* Function declarations.
*/
/* r92ce_calib.c */
void r92ce_iq_calib(struct rtwn_softc *);
/* r92ce_fw.c */
#ifndef RTWN_WITHOUT_UCODE
void r92ce_fw_reset(struct rtwn_softc *, int);
#endif
/* r92ce_init.c */
void r92ce_init_intr(struct rtwn_softc *);
void r92ce_init_edca(struct rtwn_softc *);
void r92ce_init_bb(struct rtwn_softc *);
int r92ce_power_on(struct rtwn_softc *);
void r92ce_power_off(struct rtwn_softc *);
void r92ce_init_ampdu(struct rtwn_softc *);
void r92ce_post_init(struct rtwn_softc *);
/* r92ce_led.c */
void r92ce_set_led(struct rtwn_softc *, int, int);
/* r92ce_rx.c */
int r92ce_classify_intr(struct rtwn_softc *, void *, int);
void r92ce_enable_intr(struct rtwn_pci_softc *);
void r92ce_start_xfers(struct rtwn_softc *);
/* r92ce_tx.c */
void r92ce_setup_tx_desc(struct rtwn_pci_softc *, void *, uint32_t);
void r92ce_tx_postsetup(struct rtwn_pci_softc *, void *,
bus_dma_segment_t[]);
void r92ce_copy_tx_desc(void *, const void *);
void r92ce_dump_tx_desc(struct rtwn_softc *, const void *);
#endif /* RTL8192CE_H */
@@ -0,0 +1,265 @@
/* $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>
*
* 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: releng/12.0/sys/dev/rtwn/rtl8192c/pci/r92ce_attach.c 312680 2017-01-24 02:35:38Z kevlo $");
#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/pci/rtwn_pci_var.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>
static struct rtwn_r92c_txpwr r92c_txpwr;
void r92ce_attach(struct rtwn_pci_softc *);
static void
r92ce_postattach(struct rtwn_softc *sc)
{
struct r92c_softc *rs = sc->sc_priv;
struct ieee80211com *ic = &sc->sc_ic;
if (!(rs->chip & R92C_CHIP_92C) &&
rs->board_type == R92C_BOARD_TYPE_HIGHPA)
rs->rs_txagc = &rtl8188ru_txagc[0];
else
rs->rs_txagc = &rtl8192cu_txagc[0];
if ((rs->chip & (R92C_CHIP_UMC_A_CUT | R92C_CHIP_92C)) ==
R92C_CHIP_UMC_A_CUT)
sc->fwname = "rtwn-rtl8192cfwE";
else
sc->fwname = "rtwn-rtl8192cfwE_B";
sc->fwsig = 0x88c;
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
r92ce_set_name(struct rtwn_softc *sc)
{
struct r92c_softc *rs = sc->sc_priv;
if (rs->chip & R92C_CHIP_92C)
sc->name = "RTL8192CE";
else
sc->name = "RTL8188CE";
}
static void
r92ce_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 = &r92c_txpwr;
rs->rs_set_bw20 = r92c_set_bw20;
rs->rs_get_txpower = r92c_get_txpower;
rs->rs_set_gain = r92c_set_gain;
rs->rs_tx_enable_ampdu = r92c_tx_enable_ampdu;
rs->rs_tx_setup_hwseq = r92c_tx_setup_hwseq;
rs->rs_tx_setup_macid = r92c_tx_setup_macid;
rs->rs_set_name = r92ce_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
r92ce_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
r92ce_attach(struct rtwn_pci_softc *pc)
{
struct rtwn_softc *sc = &pc->pc_sc;
/* PCIe part. */
pc->pc_setup_tx_desc = r92ce_setup_tx_desc;
pc->pc_tx_postsetup = r92ce_tx_postsetup;
pc->pc_copy_tx_desc = r92ce_copy_tx_desc;
pc->pc_enable_intr = r92ce_enable_intr;
pc->pc_qmap = 0xf771;
pc->tcr =
R92C_TCR_CFENDFORM | (1 << 12) | (1 << 13);
/* Common part. */
/* RTL8192C* cannot use pairwise keys from first 4 slots */
sc->sc_flags = RTWN_FLAG_CAM_FIXED;
sc->sc_start_xfers = r92ce_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 = r92ce_dump_tx_desc;
sc->sc_tx_radiotap_flags = r92c_tx_radiotap_flags;
sc->sc_rx_radiotap_flags = r92c_rx_radiotap_flags;
sc->sc_get_rx_stats = r92c_get_rx_stats;
sc->sc_get_rssi_cck = r92c_get_rssi_cck;
sc->sc_get_rssi_ofdm = r92c_get_rssi_ofdm;
sc->sc_classify_intr = r92ce_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 = r92c_rf_write;
sc->sc_check_condition = r92c_check_condition;
sc->sc_efuse_postread = r92c_efuse_postread;
sc->sc_parse_rom = r92c_parse_rom;
sc->sc_set_led = r92ce_set_led;
sc->sc_power_on = r92ce_power_on;
sc->sc_power_off = r92ce_power_off;
#ifndef RTWN_WITHOUT_UCODE
sc->sc_fw_reset = r92ce_fw_reset;
sc->sc_fw_download_enable = r92c_fw_download_enable;
#endif
sc->sc_llt_init = r92c_llt_init;
sc->sc_set_page_size = r92c_set_page_size;
sc->sc_lc_calib = r92c_lc_calib;
sc->sc_iq_calib = r92ce_iq_calib;
sc->sc_read_chipid_vendor = r92c_read_chipid_vendor;
sc->sc_adj_devcaps = r92ce_adj_devcaps;
sc->sc_vap_preattach = rtwn_nop_softc_vap;
sc->sc_postattach = r92ce_postattach;
sc->sc_detach_private = r92c_detach_private;
sc->sc_set_media_status = r92c_joinbss_rpt;
#ifndef RTWN_WITHOUT_UCODE
sc->sc_set_rsvd_page = r92c_set_rsvd_page;
sc->sc_set_pwrmode = r92c_set_pwrmode;
sc->sc_set_rssi = r92c_set_rssi;
#endif
sc->sc_beacon_init = r92c_beacon_init;
sc->sc_beacon_enable = r92c_beacon_enable;
sc->sc_beacon_set_rate = rtwn_nop_void_int;
sc->sc_beacon_select = rtwn_nop_softc_int;
sc->sc_temp_measure = r92c_temp_measure;
sc->sc_temp_read = r92c_temp_read;
sc->sc_init_tx_agg = rtwn_nop_softc;
sc->sc_init_rx_agg = rtwn_nop_softc;
sc->sc_init_ampdu = r92ce_init_ampdu;
sc->sc_init_intr = r92ce_init_intr;
sc->sc_init_edca = r92ce_init_edca;
sc->sc_init_bb = r92ce_init_bb;
sc->sc_init_rf = r92c_init_rf;
sc->sc_init_antsel = rtwn_nop_softc;
sc->sc_post_init = r92ce_post_init;
sc->sc_init_bcnq1_boundary = rtwn_nop_int_softc;
sc->mac_prog = &rtl8192ce_mac[0];
sc->mac_size = nitems(rtl8192ce_mac);
sc->bb_prog = &rtl8192ce_bb[0];
sc->bb_size = nitems(rtl8192ce_bb);
sc->agc_prog = &rtl8192ce_agc[0];
sc->agc_size = nitems(rtl8192ce_agc);
sc->rf_prog = &rtl8192c_rf[0];
sc->page_count = R92CE_TX_PAGE_COUNT;
sc->pktbuf_count = R92C_TXPKTBUF_COUNT;
sc->ackto = 0x40;
sc->npubqpages = R92CE_PUBQ_NPAGES;
sc->nhqpages = R92CE_HPQ_NPAGES;
sc->nnqpages = 0;
sc->nlqpages = R92CE_LPQ_NPAGES;
sc->page_size = R92C_TX_PAGE_SIZE;
sc->txdesc_len = sizeof(struct r92ce_tx_desc);
sc->efuse_maxlen = R92C_EFUSE_MAX_LEN;
sc->efuse_maplen = R92C_EFUSE_MAP_LEN;
sc->rx_dma_size = R92C_RX_DMA_BUFFER_SIZE;
sc->macid_limit = R92C_MACID_MAX + 1;
sc->cam_entry_limit = R92C_CAM_ENTRY_COUNT;
sc->fwsize_limit = R92C_MAX_FW_SIZE;
sc->temp_delta = R92C_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 = 0;
r92ce_attach_private(sc);
}
@@ -0,0 +1,386 @@
/* $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>
*
* 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: releng/12.0/sys/dev/rtwn/rtl8192c/pci/r92ce_calib.c 307529 2016-10-17 20:38:24Z avos $");
#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/rtl8192c/pci/r92ce.h>
#include <dev/rtwn/rtl8192c/pci/r92ce_reg.h>
/* Registers to save and restore during IQ calibration. */
struct r92ce_iq_cal_reg_vals {
uint32_t adda[16];
uint8_t txpause;
uint8_t bcn_ctrl[2];
uint32_t gpio_muxcfg;
uint32_t ofdm0_trxpathena;
uint32_t ofdm0_trmuxpar;
uint32_t fpga0_rfifacesw1;
};
/* XXX 92CU? */
static int
r92ce_iq_calib_chain(struct rtwn_softc *sc, int chain, uint16_t tx[2],
uint16_t rx[2])
{
uint32_t status;
int offset = chain * 0x20;
if (chain == 0) { /* IQ calibration for chain 0. */
/* IQ calibration settings for chain 0. */
rtwn_bb_write(sc, 0xe30, 0x10008c1f);
rtwn_bb_write(sc, 0xe34, 0x10008c1f);
rtwn_bb_write(sc, 0xe38, 0x82140102);
if (sc->ntxchains > 1) {
rtwn_bb_write(sc, 0xe3c, 0x28160202); /* 2T */
/* IQ calibration settings for chain 1. */
rtwn_bb_write(sc, 0xe50, 0x10008c22);
rtwn_bb_write(sc, 0xe54, 0x10008c22);
rtwn_bb_write(sc, 0xe58, 0x82140102);
rtwn_bb_write(sc, 0xe5c, 0x28160202);
} else
rtwn_bb_write(sc, 0xe3c, 0x28160502); /* 1T */
/* LO calibration settings. */
rtwn_bb_write(sc, 0xe4c, 0x001028d1);
/* We're doing LO and IQ calibration in one shot. */
rtwn_bb_write(sc, 0xe48, 0xf9000000);
rtwn_bb_write(sc, 0xe48, 0xf8000000);
} else { /* IQ calibration for chain 1. */
/* We're doing LO and IQ calibration in one shot. */
rtwn_bb_write(sc, 0xe60, 0x00000002);
rtwn_bb_write(sc, 0xe60, 0x00000000);
}
/* Give LO and IQ calibrations the time to complete. */
rtwn_delay(sc, 1000);
/* Read IQ calibration status. */
status = rtwn_bb_read(sc, 0xeac);
if (status & (1 << (28 + chain * 3)))
return (0); /* Tx failed. */
/* Read Tx IQ calibration results. */
tx[0] = (rtwn_bb_read(sc, 0xe94 + offset) >> 16) & 0x3ff;
tx[1] = (rtwn_bb_read(sc, 0xe9c + offset) >> 16) & 0x3ff;
if (tx[0] == 0x142 || tx[1] == 0x042)
return (0); /* Tx failed. */
if (status & (1 << (27 + chain * 3)))
return (1); /* Rx failed. */
/* Read Rx IQ calibration results. */
rx[0] = (rtwn_bb_read(sc, 0xea4 + offset) >> 16) & 0x3ff;
rx[1] = (rtwn_bb_read(sc, 0xeac + offset) >> 16) & 0x3ff;
if (rx[0] == 0x132 || rx[1] == 0x036)
return (1); /* Rx failed. */
return (3); /* Both Tx and Rx succeeded. */
}
static void
r92ce_iq_calib_run(struct rtwn_softc *sc, int n, uint16_t tx[2][2],
uint16_t rx[2][2], struct r92ce_iq_cal_reg_vals *vals)
{
/* Registers to save and restore during IQ calibration. */
static const uint16_t reg_adda[16] = {
0x85c, 0xe6c, 0xe70, 0xe74,
0xe78, 0xe7c, 0xe80, 0xe84,
0xe88, 0xe8c, 0xed0, 0xed4,
0xed8, 0xedc, 0xee0, 0xeec
};
int i, chain;
uint32_t hssi_param1;
if (n == 0) {
for (i = 0; i < nitems(reg_adda); i++)
vals->adda[i] = rtwn_bb_read(sc, reg_adda[i]);
vals->txpause = rtwn_read_1(sc, R92C_TXPAUSE);
vals->bcn_ctrl[0] = rtwn_read_1(sc, R92C_BCN_CTRL(0));
vals->bcn_ctrl[1] = rtwn_read_1(sc, R92C_BCN_CTRL(1));
vals->gpio_muxcfg = rtwn_read_4(sc, R92C_GPIO_MUXCFG);
}
if (sc->ntxchains == 1) {
rtwn_bb_write(sc, reg_adda[0], 0x0b1b25a0);
for (i = 1; i < nitems(reg_adda); i++)
rtwn_bb_write(sc, reg_adda[i], 0x0bdb25a0);
} else {
for (i = 0; i < nitems(reg_adda); i++)
rtwn_bb_write(sc, reg_adda[i], 0x04db25a4);
}
hssi_param1 = rtwn_bb_read(sc, R92C_HSSI_PARAM1(0));
if (!(hssi_param1 & R92C_HSSI_PARAM1_PI)) {
rtwn_bb_write(sc, R92C_HSSI_PARAM1(0),
hssi_param1 | R92C_HSSI_PARAM1_PI);
rtwn_bb_write(sc, R92C_HSSI_PARAM1(1),
hssi_param1 | R92C_HSSI_PARAM1_PI);
}
if (n == 0) {
vals->ofdm0_trxpathena =
rtwn_bb_read(sc, R92C_OFDM0_TRXPATHENA);
vals->ofdm0_trmuxpar = rtwn_bb_read(sc, R92C_OFDM0_TRMUXPAR);
vals->fpga0_rfifacesw1 =
rtwn_bb_read(sc, R92C_FPGA0_RFIFACESW(1));
}
rtwn_bb_write(sc, R92C_OFDM0_TRXPATHENA, 0x03a05600);
rtwn_bb_write(sc, R92C_OFDM0_TRMUXPAR, 0x000800e4);
rtwn_bb_write(sc, R92C_FPGA0_RFIFACESW(1), 0x22204000);
if (sc->ntxchains > 1) {
rtwn_bb_write(sc, R92C_LSSI_PARAM(0), 0x00010000);
rtwn_bb_write(sc, R92C_LSSI_PARAM(1), 0x00010000);
}
rtwn_write_1(sc, R92C_TXPAUSE,
R92C_TX_QUEUE_AC | R92C_TX_QUEUE_MGT | R92C_TX_QUEUE_HIGH);
rtwn_write_1(sc, R92C_BCN_CTRL(0),
vals->bcn_ctrl[0] & ~R92C_BCN_CTRL_EN_BCN);
rtwn_write_1(sc, R92C_BCN_CTRL(1),
vals->bcn_ctrl[1] & ~R92C_BCN_CTRL_EN_BCN);
rtwn_write_1(sc, R92C_GPIO_MUXCFG,
vals->gpio_muxcfg & ~R92C_GPIO_MUXCFG_ENBT);
rtwn_bb_write(sc, 0x0b68, 0x00080000);
if (sc->ntxchains > 1)
rtwn_bb_write(sc, 0x0b6c, 0x00080000);
rtwn_bb_write(sc, 0x0e28, 0x80800000);
rtwn_bb_write(sc, 0x0e40, 0x01007c00);
rtwn_bb_write(sc, 0x0e44, 0x01004800);
rtwn_bb_write(sc, 0x0b68, 0x00080000);
for (chain = 0; chain < sc->ntxchains; chain++) {
if (chain > 0) {
/* Put chain 0 on standby. */
rtwn_bb_write(sc, 0x0e28, 0x00);
rtwn_bb_write(sc, R92C_LSSI_PARAM(0), 0x00010000);
rtwn_bb_write(sc, 0x0e28, 0x80800000);
/* Enable chain 1. */
for (i = 0; i < nitems(reg_adda); i++)
rtwn_bb_write(sc, reg_adda[i], 0x0b1b25a4);
}
/* Run IQ calibration twice. */
for (i = 0; i < 2; i++) {
int ret;
ret = r92ce_iq_calib_chain(sc, chain,
tx[chain], rx[chain]);
if (ret == 0) {
RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB,
"%s: chain %d: Tx failed.\n",
__func__, chain);
tx[chain][0] = 0xff;
tx[chain][1] = 0xff;
rx[chain][0] = 0xff;
rx[chain][1] = 0xff;
} else if (ret == 1) {
RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB,
"%s: chain %d: Rx failed.\n",
__func__, chain);
rx[chain][0] = 0xff;
rx[chain][1] = 0xff;
} else if (ret == 3) {
RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB,
"%s: chain %d: Both Tx and Rx "
"succeeded.\n", __func__, chain);
}
}
RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB,
"%s: results for run %d chain %d: tx[0] 0x%x, "
"tx[1] 0x%x, rx[0] 0x%x, rx[1] 0x%x\n", __func__, n, chain,
tx[chain][0], tx[chain][1], rx[chain][0], rx[chain][1]);
}
rtwn_bb_write(sc, R92C_OFDM0_TRXPATHENA,
vals->ofdm0_trxpathena);
rtwn_bb_write(sc, R92C_FPGA0_RFIFACESW(1),
vals->fpga0_rfifacesw1);
rtwn_bb_write(sc, R92C_OFDM0_TRMUXPAR, vals->ofdm0_trmuxpar);
rtwn_bb_write(sc, 0x0e28, 0x00);
rtwn_bb_write(sc, R92C_LSSI_PARAM(0), 0x00032ed3);
if (sc->ntxchains > 1)
rtwn_bb_write(sc, R92C_LSSI_PARAM(1), 0x00032ed3);
if (n != 0) {
if (!(hssi_param1 & R92C_HSSI_PARAM1_PI)) {
rtwn_bb_write(sc, R92C_HSSI_PARAM1(0), hssi_param1);
rtwn_bb_write(sc, R92C_HSSI_PARAM1(1), hssi_param1);
}
for (i = 0; i < nitems(reg_adda); i++)
rtwn_bb_write(sc, reg_adda[i], vals->adda[i]);
rtwn_write_1(sc, R92C_TXPAUSE, vals->txpause);
rtwn_write_1(sc, R92C_BCN_CTRL(0), vals->bcn_ctrl[0]);
rtwn_write_1(sc, R92C_BCN_CTRL(1), vals->bcn_ctrl[1]);
rtwn_write_4(sc, R92C_GPIO_MUXCFG, vals->gpio_muxcfg);
}
}
#define RTWN_IQ_CAL_MAX_TOLERANCE 5
static int
r92ce_iq_calib_compare_results(struct rtwn_softc *sc, uint16_t tx1[2][2],
uint16_t rx1[2][2], uint16_t tx2[2][2], uint16_t rx2[2][2])
{
int chain, i, tx_ok[2], rx_ok[2];
tx_ok[0] = tx_ok[1] = rx_ok[0] = rx_ok[1] = 0;
for (chain = 0; chain < sc->ntxchains; chain++) {
for (i = 0; i < 2; i++) {
if (tx1[chain][i] == 0xff || tx2[chain][i] == 0xff ||
rx1[chain][i] == 0xff || rx2[chain][i] == 0xff)
continue;
tx_ok[chain] = (abs(tx1[chain][i] - tx2[chain][i]) <=
RTWN_IQ_CAL_MAX_TOLERANCE);
rx_ok[chain] = (abs(rx1[chain][i] - rx2[chain][i]) <=
RTWN_IQ_CAL_MAX_TOLERANCE);
}
}
if (sc->ntxchains > 1)
return (tx_ok[0] && tx_ok[1] && rx_ok[0] && rx_ok[1]);
else
return (tx_ok[0] && rx_ok[0]);
}
#undef RTWN_IQ_CAL_MAX_TOLERANCE
static void
r92ce_iq_calib_write_results(struct rtwn_softc *sc, uint16_t tx[2],
uint16_t rx[2], int chain)
{
uint32_t reg, val, x;
long y, tx_c;
if (tx[0] == 0xff || tx[1] == 0xff)
return;
reg = rtwn_bb_read(sc, R92C_OFDM0_TXIQIMBALANCE(chain));
val = ((reg >> 22) & 0x3ff);
x = tx[0];
if (x & 0x00000200)
x |= 0xfffffc00;
reg = (((x * val) >> 8) & 0x3ff);
rtwn_bb_setbits(sc, R92C_OFDM0_TXIQIMBALANCE(chain), 0x3ff, reg);
rtwn_bb_setbits(sc, R92C_OFDM0_ECCATHRESHOLD, 0x80000000,
((x * val) & 0x80) << 24);
y = tx[1];
if (y & 0x00000200)
y |= 0xfffffc00;
tx_c = (y * val) >> 8;
rtwn_bb_setbits(sc, R92C_OFDM0_TXAFE(chain), 0xf0000000,
(tx_c & 0x3c0) << 22);
rtwn_bb_setbits(sc, R92C_OFDM0_TXIQIMBALANCE(chain), 0x003f0000,
(tx_c & 0x3f) << 16);
rtwn_bb_setbits(sc, R92C_OFDM0_ECCATHRESHOLD, 0x20000000,
((y * val) & 0x80) << 22);
if (rx[0] == 0xff || rx[1] == 0xff)
return;
rtwn_bb_setbits(sc, R92C_OFDM0_RXIQIMBALANCE(chain), 0x3ff,
rx[0] & 0x3ff);
rtwn_bb_setbits(sc, R92C_OFDM0_RXIQIMBALANCE(chain), 0xfc00,
(rx[1] & 0x3f) << 10);
if (chain == 0) {
rtwn_bb_setbits(sc, R92C_OFDM0_RXIQEXTANTA, 0xf0000000,
(rx[1] & 0x3c0) << 22);
} else {
rtwn_bb_setbits(sc, R92C_OFDM0_AGCRSSITABLE, 0xf000,
(rx[1] & 0x3c0) << 6);
}
}
#define RTWN_IQ_CAL_NRUN 3
void
r92ce_iq_calib(struct rtwn_softc *sc)
{
struct r92ce_iq_cal_reg_vals vals;
uint16_t tx[RTWN_IQ_CAL_NRUN][2][2], rx[RTWN_IQ_CAL_NRUN][2][2];
int n, valid;
valid = 0;
for (n = 0; n < RTWN_IQ_CAL_NRUN; n++) {
r92ce_iq_calib_run(sc, n, tx[n], rx[n], &vals);
if (n == 0)
continue;
/* Valid results remain stable after consecutive runs. */
valid = r92ce_iq_calib_compare_results(sc, tx[n - 1],
rx[n - 1], tx[n], rx[n]);
if (valid)
break;
}
if (valid) {
r92ce_iq_calib_write_results(sc, tx[n][0], rx[n][0], 0);
if (sc->ntxchains > 1)
r92ce_iq_calib_write_results(sc, tx[n][1], rx[n][1], 1);
}
}
#undef RTWN_IQ_CAL_NRUN
@@ -0,0 +1,75 @@
/* $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>
*
* 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: releng/12.0/sys/dev/rtwn/rtl8192c/pci/r92ce_fw.c 308380 2016-11-06 17:24:16Z avos $");
#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/rtl8192c/pci/r92ce.h>
#ifndef RTWN_WITHOUT_UCODE
void
r92ce_fw_reset(struct rtwn_softc *sc, int reason)
{
if (reason == RTWN_FW_RESET_CHECKSUM)
return;
r92c_fw_reset(sc, reason);
/*
* We must sleep for one second to let the firmware settle.
* Accessing registers too early will hang the whole system.
*/
if (reason == RTWN_FW_RESET_DOWNLOAD)
rtwn_delay(sc, 1000 * 1000);
}
#endif
@@ -0,0 +1,323 @@
/* $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>
*
* 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: releng/12.0/sys/dev/rtwn/rtl8192c/pci/r92ce_init.c 311347 2017-01-05 02:04:53Z kevlo $");
#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/rtl8192c/r92c_var.h>
#include <dev/rtwn/rtl8192c/pci/r92ce.h>
#include <dev/rtwn/rtl8192c/pci/r92ce_reg.h>
void
r92ce_init_intr(struct rtwn_softc *sc)
{
/* Disable interrupts. */
rtwn_write_4(sc, R92C_HISR, 0x00000000);
rtwn_write_4(sc, R92C_HIMR, 0x00000000);
}
void
r92ce_init_edca(struct rtwn_softc *sc)
{
/* SIFS */
rtwn_write_2(sc, R92C_SPEC_SIFS, 0x1010);
rtwn_write_2(sc, R92C_MAC_SPEC_SIFS, 0x1010);
rtwn_write_2(sc, R92C_SIFS_CCK, 0x1010);
rtwn_write_2(sc, R92C_SIFS_OFDM, 0x0e0e);
/* TXOP */
rtwn_write_4(sc, R92C_EDCA_BE_PARAM, 0x005ea42b);
rtwn_write_4(sc, R92C_EDCA_BK_PARAM, 0x0000a44f);
rtwn_write_4(sc, R92C_EDCA_VI_PARAM, 0x005e4322);
rtwn_write_4(sc, R92C_EDCA_VO_PARAM, 0x002f3222);
}
void
r92ce_init_bb(struct rtwn_softc *sc)
{
/* Enable BB and RF. */
rtwn_setbits_2(sc, R92C_SYS_FUNC_EN, 0,
R92C_SYS_FUNC_EN_BBRSTB | R92C_SYS_FUNC_EN_BB_GLB_RST |
R92C_SYS_FUNC_EN_DIO_RF);
rtwn_write_2(sc, R92C_AFE_PLL_CTRL, 0xdb83);
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_DIO_PCIE | R92C_SYS_FUNC_EN_PCIEA |
R92C_SYS_FUNC_EN_PPLL | R92C_SYS_FUNC_EN_BB_GLB_RST |
R92C_SYS_FUNC_EN_BBRSTB);
rtwn_write_1(sc, R92C_AFE_XTAL_CTRL + 1, 0x80);
rtwn_setbits_4(sc, R92C_LEDCFG0, 0, 0x00800000);
r92c_init_bb_common(sc);
}
int
r92ce_power_on(struct rtwn_softc *sc)
{
struct r92c_softc *rs = sc->sc_priv;
uint32_t reg;
int ntries;
/* Wait for autoload done bit. */
for (ntries = 0; ntries < 1000; ntries++) {
if (rtwn_read_1(sc, R92C_APS_FSMCO) & R92C_APS_FSMCO_PFM_ALDN)
break;
DELAY(5);
}
if (ntries == 1000) {
device_printf(sc->sc_dev,
"timeout waiting for chip autoload\n");
return (ETIMEDOUT);
}
/* Unlock ISO/CLK/Power control register. */
rtwn_write_1(sc, R92C_RSV_CTRL, 0);
if (rs->board_type != R92C_BOARD_TYPE_DONGLE) {
/* bt coex */
rtwn_setbits_4(sc, R92C_APS_FSMCO, 0,
R92C_APS_FSMCO_SOP_ABG |
R92C_APS_FSMCO_SOP_AMB |
R92C_APS_FSMCO_XOP_BTCK);
}
/* Move SPS into PWM mode. */
rtwn_write_1(sc, R92C_SPS0_CTRL, 0x2b);
/* Set low byte to 0x0f, leave others unchanged. */
rtwn_write_1(sc, R92C_AFE_XTAL_CTRL, 0x0f);
/* TODO: check if we need this for 8188CE */
if (rs->board_type != R92C_BOARD_TYPE_DONGLE) {
/* bt coex */
/* XXX magic from linux */
rtwn_setbits_4(sc, R92C_AFE_XTAL_CTRL, 0x024800, 0);
}
rtwn_setbits_2(sc, R92C_SYS_ISO_CTRL, 0xff00,
R92C_SYS_ISO_CTRL_PWC_EV12V | R92C_SYS_ISO_CTRL_DIOR);
DELAY(200);
/* TODO: linux does additional btcoex stuff here */
/* Auto enable WLAN. */
rtwn_setbits_2(sc, R92C_APS_FSMCO, 0, R92C_APS_FSMCO_APFM_ONMAC);
for (ntries = 0; ntries < 1000; ntries++) {
if (!(rtwn_read_2(sc, R92C_APS_FSMCO) &
R92C_APS_FSMCO_APFM_ONMAC))
break;
DELAY(5);
}
if (ntries == 1000) {
device_printf(sc->sc_dev, "timeout waiting for MAC auto ON\n");
return (ETIMEDOUT);
}
/* Enable radio, GPIO and LED functions. */
rtwn_write_2(sc, R92C_APS_FSMCO,
R92C_APS_FSMCO_AFSM_PCIE |
R92C_APS_FSMCO_PDN_EN |
R92C_APS_FSMCO_PFM_ALDN);
/* Release RF digital isolation. */
rtwn_setbits_2(sc, R92C_SYS_ISO_CTRL, R92C_SYS_ISO_CTRL_DIOR, 0);
if (rs->chip & R92C_CHIP_92C)
rtwn_write_1(sc, R92C_PCIE_CTRL_REG + 3, 0x77);
else
rtwn_write_1(sc, R92C_PCIE_CTRL_REG + 3, 0x22);
rtwn_write_4(sc, R92C_INT_MIG, 0);
if (rs->board_type != R92C_BOARD_TYPE_DONGLE) {
/* bt coex */
/* XXX magic from linux */
rtwn_setbits_1(sc, R92C_AFE_XTAL_CTRL + 2, 0x02, 0);
}
rtwn_setbits_1(sc, R92C_GPIO_MUXCFG, R92C_GPIO_MUXCFG_RFKILL, 0);
reg = rtwn_read_1(sc, R92C_GPIO_IO_SEL);
if (!(reg & R92C_GPIO_IO_SEL_RFKILL)) {
device_printf(sc->sc_dev,
"radio is disabled by hardware switch\n");
/* XXX how driver will know when radio will be enabled? */
return (EPERM);
}
/* Initialize MAC. */
rtwn_setbits_1(sc, R92C_APSD_CTRL, R92C_APSD_CTRL_OFF, 0);
for (ntries = 0; ntries < 200; ntries++) {
if (!(rtwn_read_1(sc, R92C_APSD_CTRL) &
R92C_APSD_CTRL_OFF_STATUS))
break;
DELAY(500);
}
if (ntries == 200) {
device_printf(sc->sc_dev,
"timeout waiting for MAC initialization\n");
return (ETIMEDOUT);
}
/* Enable MAC DMA/WMAC/SCHEDULE/SEC blocks. */
rtwn_setbits_2(sc, R92C_CR, 0,
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_MACTXEN | R92C_CR_MACRXEN |
((sc->sc_hwcrypto != RTWN_CRYPTO_SW) ? R92C_CR_ENSEC : 0));
rtwn_write_4(sc, R92C_MCUTST_1, 0x0);
return (0);
}
void
r92ce_power_off(struct rtwn_softc *sc)
{
#ifndef RTWN_WITHOUT_UCODE
struct r92c_softc *rs = sc->sc_priv;
/* Deinit C2H event handler. */
callout_stop(&rs->rs_c2h_report);
rs->rs_c2h_paused = 0;
rs->rs_c2h_pending = 0;
rs->rs_c2h_timeout = hz;
#endif
/* Stop hardware. */
/* Disable interrupts. */
rtwn_write_4(sc, R92C_HISR, 0);
rtwn_write_4(sc, R92C_HIMR, 0);
/* Stop hardware. */
rtwn_write_1(sc, R92C_TXPAUSE, R92C_TX_QUEUE_ALL);
/* Turn off RF. */
rtwn_write_1(sc, R92C_RF_CTRL, 0);
/* Reset BB state machine */
rtwn_setbits_1(sc, R92C_SYS_FUNC_EN, 0, R92C_SYS_FUNC_EN_BB_GLB_RST);
rtwn_setbits_1(sc, R92C_SYS_FUNC_EN, R92C_SYS_FUNC_EN_BB_GLB_RST, 0);
/* Disable MAC DMA/WMAC/SCHEDULE/SEC blocks. */
rtwn_setbits_2(sc, R92C_CR,
R92C_CR_HCI_TXDMA_EN | R92C_CR_HCI_RXDMA_EN |
R92C_CR_TXDMA_EN | R92C_CR_RXDMA_EN | R92C_CR_PROTOCOL_EN |
R92C_CR_SCHEDULE_EN | R92C_CR_MACTXEN | R92C_CR_MACRXEN |
R92C_CR_ENSEC,
0);
/* If firmware in ram code, do reset. */
#ifndef RTWN_WITHOUT_UCODE
if (rtwn_read_1(sc, R92C_MCUFWDL) & R92C_MCUFWDL_RAM_DL_SEL)
r92ce_fw_reset(sc, RTWN_FW_RESET_SHUTDOWN);
#endif
/* TODO: linux does additional btcoex stuff here */
rtwn_write_2(sc, R92C_AFE_PLL_CTRL, 0x80); /* linux magic number */
rtwn_write_1(sc, R92C_SPS0_CTRL, 0x23); /* ditto */
rtwn_write_1(sc, R92C_AFE_XTAL_CTRL, 0x0e); /* different with btcoex */
rtwn_write_1(sc, R92C_RSV_CTRL, 0x0e);
rtwn_write_1(sc, R92C_APS_FSMCO, R92C_APS_FSMCO_PDN_EN);
}
void
r92ce_init_ampdu(struct rtwn_softc *sc)
{
/* Setup AMPDU aggregation. */
rtwn_write_4(sc, R92C_AGGLEN_LMT, 0x99997631); /* MCS7~0 */
rtwn_write_1(sc, R92C_AGGR_BREAK_TIME, 0x16);
}
void
r92ce_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. */
r92ce_iq_calib(sc);
/* Perform LC calibration. */
r92c_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;
}
@@ -0,0 +1,67 @@
/* $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>
*
* 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: releng/12.0/sys/dev/rtwn/rtl8192c/pci/r92ce_led.c 307529 2016-10-17 20:38:24Z avos $");
#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/rtl8192c/pci/r92ce.h>
#include <dev/rtwn/rtl8192c/pci/r92ce_reg.h>
void
r92ce_set_led(struct rtwn_softc *sc, int led, int on)
{
if (led == RTWN_LED_LINK) {
rtwn_setbits_1(sc, R92C_LEDCFG2, 0x0f,
on ? R92C_LEDCFG2_EN : R92C_LEDCFG2_DIS);
sc->ledlink = on; /* Save LED state. */
}
}
@@ -0,0 +1,182 @@
/* $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>
*
* 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: releng/12.0/sys/dev/rtwn/rtl8192c/pci/r92ce_priv.h 307529 2016-10-17 20:38:24Z avos $
*/
#ifndef R92CE_PRIV_H
#define R92CE_PRIV_H
#include <dev/rtwn/rtl8192c/r92c_priv.h>
/*
* MAC initialization values.
*/
static const struct rtwn_mac_prog rtl8192ce_mac[] = {
{ 0x420, 0x80 }, { 0x423, 0x00 }, { 0x430, 0x00 }, { 0x431, 0x00 },
{ 0x432, 0x00 }, { 0x433, 0x01 }, { 0x434, 0x04 }, { 0x435, 0x05 },
{ 0x436, 0x06 }, { 0x437, 0x07 }, { 0x438, 0x00 }, { 0x439, 0x00 },
{ 0x43a, 0x00 }, { 0x43b, 0x01 }, { 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, 0x88 }, { 0x461, 0x88 }, { 0x462, 0x06 },
{ 0x463, 0x03 }, { 0x4c8, 0x04 }, { 0x4c9, 0x08 }, { 0x4cc, 0x02 },
{ 0x4cd, 0x28 }, { 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 },
{ 0x515, 0x10 }, { 0x516, 0x0a }, { 0x517, 0x10 }, { 0x51a, 0x16 },
{ 0x524, 0x0f }, { 0x525, 0x4f }, { 0x546, 0x20 }, { 0x547, 0x00 },
{ 0x559, 0x02 }, { 0x55a, 0x02 }, { 0x55d, 0xff }, { 0x605, 0x30 },
{ 0x608, 0x0e }, { 0x609, 0x2a }, { 0x652, 0x20 }, { 0x63c, 0x0a },
{ 0x63d, 0x0e }, { 0x700, 0x21 }, { 0x701, 0x43 }, { 0x702, 0x65 },
{ 0x703, 0x87 }, { 0x708, 0x21 }, { 0x709, 0x43 }, { 0x70a, 0x65 },
{ 0x70b, 0x87 }
};
/*
* Baseband initialization values.
*/
static const uint16_t rtl8192ce_bb_regs0[] = {
0x024, 0x028, 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, 0xa00, 0xa04, 0xa08, 0xa0c, 0xa10, 0xa14, 0xa18, 0xa1c,
0xa20, 0xa24, 0xa28, 0xa2c, 0xa70, 0xa74, 0xc00, 0xc04
}, rtl8192ce_bb_regs1[] = {
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
};
static const uint32_t rtl8192ce_bb_vals0_2t[] = {
0x0011800f, 0x00ffdb83, 0x80040002, 0x00000003, 0x0000fc00,
0x0000000a, 0x10005388, 0x020c3d10, 0x02200385, 0x00000000,
0x01000100, 0x00390004, 0x01000100, 0x00390004, 0x27272727,
0x27272727, 0x27272727, 0x27272727, 0x00010000, 0x00010000,
0x27272727, 0x27272727, 0x00000000, 0x00000000, 0x569a569a,
0x0c1b25a4, 0x66e60230, 0x061f0130, 0x27272727, 0x2b2b2b27,
0x07000700, 0x22184000, 0x08080808, 0x00000000, 0xc0083070,
0x000004d5, 0x00000000, 0xcc0000c0, 0x00000800, 0xfffffffe,
0x40302010, 0x00706050, 0x00000000, 0x00000023, 0x00000000,
0x81121313, 0x00d047c8, 0x80ff000c, 0x8c838300, 0x2e68120f,
0x9500bb78, 0x11144028, 0x00881117, 0x89140f00, 0x1a1b0000,
0x090e1317, 0x00000204, 0x00d30000, 0x101fbf00, 0x00000007,
0x48071d40, 0x03a05633
}, rtl8192ce_bb_vals0_1t[] = {
0x0011800f, 0x00ffdb83, 0x80040000, 0x00000001, 0x0000fc00,
0x0000000a, 0x10005388, 0x020c3d10, 0x02200385, 0x00000000,
0x01000100, 0x00390004, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00010000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x569a569a,
0x001b25a4, 0x66e60230, 0x061f0130, 0x00000000, 0x32323200,
0x07000700, 0x22004000, 0x00000808, 0x00000000, 0xc0083070,
0x000004d5, 0x00000000, 0xccc000c0, 0x00000800, 0xfffffffe,
0x40302010, 0x00706050, 0x00000000, 0x00000023, 0x00000000,
0x81121111, 0x00d047c8, 0x80ff000c, 0x8c838300, 0x2e68120f,
0x9500bb78, 0x11144028, 0x00881117, 0x89140f00, 0x1a1b0000,
0x090e1317, 0x00000204, 0x00d30000, 0x101fbf00, 0x00000007,
0x48071d40, 0x03a05611
}, rtl8192ce_bb_vals1[] = {
0x000000e4, 0x6c6c6c6c, 0x08800000, 0x40000100, 0x08800000,
0x40000100, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x69e9ac44, 0x469652cf, 0x49795994, 0x0a97971c, 0x1f7c403f,
0x000100b7, 0xec020107, 0x007f037f, 0x69543420, 0x43bc0094,
0x69543420, 0x433c0094, 0x00000000, 0x5116848b, 0x47c00bff,
0x00000036, 0x2c7f000d, 0x018610db, 0x0000001f, 0x00b91612,
0x40000100, 0x20f60000, 0x40000100, 0x20200000, 0x00121820,
0x00000000, 0x00121820, 0x00007f7f, 0x00000000, 0x00000080,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x28000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x64b22427, 0x00766932, 0x00222222,
0x00000000, 0x37644302, 0x2f97d40c, 0x00080740
}, rtl8192ce_bb_vals4_1t[] = {
0x00000010, 0x001b25a4, 0x631b25a0, 0x631b25a0, 0x081b25a0,
0x081b25a0, 0x081b25a0, 0x081b25a0, 0x631b25a0, 0x081b25a0,
0x631b25a0, 0x631b25a0, 0x631b25a0, 0x631b25a0, 0x001b25a0,
0x001b25a0, 0x6b1b25a0, 0x00000003, 0x00000000, 0x00000300
};
static const struct rtwn_bb_prog rtl8192ce_bb[] = {
{
nitems(rtl8192ce_bb_regs0),
rtl8192ce_bb_regs0,
rtl8192ce_bb_vals0_2t,
{ R92C_COND_RTL8192C },
&(const struct rtwn_bb_prog){
nitems(rtl8192ce_bb_regs0),
rtl8192ce_bb_regs0,
rtl8192ce_bb_vals0_1t,
{ 0 },
NULL
}
},
{
nitems(rtl8192ce_bb_regs1),
rtl8192ce_bb_regs1,
rtl8192ce_bb_vals1,
{ 0 },
NULL
},
{
nitems(rtl8192c_bb_regs3),
rtl8192c_bb_regs3,
rtl8192c_bb_vals3_92ce_92cu,
{ R92C_COND_RTL8192C },
&(const struct rtwn_bb_prog){
nitems(rtl8192c_bb_regs3),
rtl8192c_bb_regs3,
rtl8192c_bb_vals3_88cu_88ru,
{ 0 },
NULL
}
},
{
nitems(rtl8192c_bb_regs4),
rtl8192c_bb_regs4,
rtl8192c_bb_vals4,
{ 0 },
NULL
},
{
nitems(rtl8192c_bb_regs5),
rtl8192c_bb_regs5,
rtl8192c_bb_vals5_92ce_92cu,
{ R92C_COND_RTL8192C },
&(const struct rtwn_bb_prog){
nitems(rtl8192c_bb_regs5),
rtl8192c_bb_regs5,
rtl8192ce_bb_vals4_1t,
{ 0 },
NULL
}
}
};
#endif /* R92CE_PRIV_H */
@@ -0,0 +1,103 @@
/* $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>
*
* 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: releng/12.0/sys/dev/rtwn/rtl8192c/pci/r92ce_reg.h 307529 2016-10-17 20:38:24Z avos $
*/
#ifndef R92CE_REG_H
#define R92CE_REG_H
#include <dev/rtwn/rtl8192c/r92c_reg.h>
/*
* MAC registers.
*/
/* System Configuration. */
#define R92C_PCIE_MIO_INTF 0x0e4
#define R92C_PCIE_MIO_INTD 0x0e8
/* PCIe Configuration. */
#define R92C_PCIE_CTRL_REG 0x300
#define R92C_INT_MIG 0x304
#define R92C_BCNQ_DESA 0x308
#define R92C_HQ_DESA 0x310
#define R92C_MGQ_DESA 0x318
#define R92C_VOQ_DESA 0x320
#define R92C_VIQ_DESA 0x328
#define R92C_BEQ_DESA 0x330
#define R92C_BKQ_DESA 0x338
#define R92C_RX_DESA 0x340
#define R92C_DBI 0x348
#define R92C_MDIO 0x354
#define R92C_DBG_SEL 0x360
#define R92C_PCIE_HRPWM 0x361
#define R92C_PCIE_HCPWM 0x363
#define R92C_UART_CTRL 0x364
#define R92C_UART_TX_DES 0x370
#define R92C_UART_RX_DES 0x378
/* Bits for R92C_GPIO_MUXCFG. */
#define R92C_GPIO_MUXCFG_RFKILL 0x0008
/* Bits for R92C_GPIO_IO_SEL. */
#define R92C_GPIO_IO_SEL_RFKILL 0x0008
/* Bits for R92C_LEDCFG2. */
#define R92C_LEDCFG2_EN 0x60
#define R92C_LEDCFG2_DIS 0x68
/* Bits for R92C_HIMR. */
#define R92C_IMR_ROK 0x00000001 /* receive DMA OK */
#define R92C_IMR_VODOK 0x00000002 /* AC_VO DMA OK */
#define R92C_IMR_VIDOK 0x00000004 /* AC_VI DMA OK */
#define R92C_IMR_BEDOK 0x00000008 /* AC_BE DMA OK */
#define R92C_IMR_BKDOK 0x00000010 /* AC_BK DMA OK */
#define R92C_IMR_TXBDER 0x00000020 /* beacon transmit error */
#define R92C_IMR_MGNTDOK 0x00000040 /* management queue DMA OK */
#define R92C_IMR_TBDOK 0x00000080 /* beacon transmit OK */
#define R92C_IMR_HIGHDOK 0x00000100 /* high queue DMA OK */
#define R92C_IMR_BDOK 0x00000200 /* beacon queue DMA OK */
#define R92C_IMR_ATIMEND 0x00000400 /* ATIM window end interrupt */
#define R92C_IMR_RDU 0x00000800 /* Rx descriptor unavailable */
#define R92C_IMR_RXFOVW 0x00001000 /* receive FIFO overflow */
#define R92C_IMR_BCNINT 0x00002000 /* beacon DMA interrupt 0 */
#define R92C_IMR_PSTIMEOUT 0x00004000 /* powersave timeout */
#define R92C_IMR_TXFOVW 0x00008000 /* transmit FIFO overflow */
#define R92C_IMR_TIMEOUT1 0x00010000 /* timeout interrupt 1 */
#define R92C_IMR_TIMEOUT2 0x00020000 /* timeout interrupt 2 */
#define R92C_IMR_BCNDOK1 0x00040000 /* beacon queue DMA OK (1) */
#define R92C_IMR_BCNDOK2 0x00080000 /* beacon queue DMA OK (2) */
#define R92C_IMR_BCNDOK3 0x00100000 /* beacon queue DMA OK (3) */
#define R92C_IMR_BCNDOK4 0x00200000 /* beacon queue DMA OK (4) */
#define R92C_IMR_BCNDOK5 0x00400000 /* beacon queue DMA OK (5) */
#define R92C_IMR_BCNDOK6 0x00800000 /* beacon queue DMA OK (6) */
#define R92C_IMR_BCNDOK7 0x01000000 /* beacon queue DMA OK (7) */
#define R92C_IMR_BCNDOK8 0x02000000 /* beacon queue DMA OK (8) */
#define R92C_IMR_BCNDMAINT1 0x04000000 /* beacon DMA interrupt 1 */
#define R92C_IMR_BCNDMAINT2 0x08000000 /* beacon DMA interrupt 2 */
#define R92C_IMR_BCNDMAINT3 0x10000000 /* beacon DMA interrupt 3 */
#define R92C_IMR_BCNDMAINT4 0x20000000 /* beacon DMA interrupt 4 */
#define R92C_IMR_BCNDMAINT5 0x40000000 /* beacon DMA interrupt 5 */
#define R92C_IMR_BCNDMAINT6 0x80000000 /* beacon DMA interrupt 6 */
/* Shortcut. */
#define R92C_IBSS_INT_MASK \
(R92C_IMR_BCNINT | R92C_IMR_TBDOK | R92C_IMR_TBDER)
#endif /* R92CE_REG_H */
@@ -0,0 +1,132 @@
/* $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>
*
* 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: releng/12.0/sys/dev/rtwn/rtl8192c/pci/r92ce_rx.c 307529 2016-10-17 20:38:24Z avos $");
#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/rtl8192c/pci/r92ce.h>
#include <dev/rtwn/rtl8192c/pci/r92ce_reg.h>
int
r92ce_classify_intr(struct rtwn_softc *sc, void *arg, int len __unused)
{
uint32_t status;
int *rings = arg;
int ret;
*rings = 0;
status = rtwn_read_4(sc, R92C_HISR);
RTWN_DPRINTF(sc, RTWN_DEBUG_INTR, "%s: HISR %08X, HISRE %04X\n",
__func__, status, rtwn_read_2(sc, R92C_HISRE));
if (status == 0 || status == 0xffffffff)
return (0);
/* Disable interrupts. */
rtwn_write_4(sc, R92C_HIMR, 0);
/* Ack interrupts. */
rtwn_write_4(sc, R92C_HISR, status);
if (status & R92C_IMR_BDOK)
*rings |= (1 << RTWN_PCI_BEACON_QUEUE);
if (status & R92C_IMR_HIGHDOK)
*rings |= (1 << RTWN_PCI_HIGH_QUEUE);
if (status & R92C_IMR_MGNTDOK)
*rings |= (1 << RTWN_PCI_MGNT_QUEUE);
if (status & R92C_IMR_BKDOK)
*rings |= (1 << RTWN_PCI_BK_QUEUE);
if (status & R92C_IMR_BEDOK)
*rings |= (1 << RTWN_PCI_BE_QUEUE);
if (status & R92C_IMR_VIDOK)
*rings |= (1 << RTWN_PCI_VI_QUEUE);
if (status & 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);
}
#define R92C_INT_ENABLE (R92C_IMR_ROK | R92C_IMR_VODOK | R92C_IMR_VIDOK | \
R92C_IMR_BEDOK | R92C_IMR_BKDOK | R92C_IMR_MGNTDOK | \
R92C_IMR_HIGHDOK | R92C_IMR_BDOK | R92C_IMR_RDU | \
R92C_IMR_RXFOVW)
void
r92ce_enable_intr(struct rtwn_pci_softc *pc)
{
struct rtwn_softc *sc = &pc->pc_sc;
/* Enable interrupts. */
rtwn_write_4(sc, R92C_HIMR, R92C_INT_ENABLE);
}
void
r92ce_start_xfers(struct rtwn_softc *sc)
{
/* Clear pending interrupts. */
rtwn_write_4(sc, R92C_HISR, 0xffffffff);
/* Enable interrupts. */
rtwn_write_4(sc, R92C_HIMR, R92C_INT_ENABLE);
}
#undef R92C_INT_ENABLE
@@ -0,0 +1,41 @@
/* $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>
*
* 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: releng/12.0/sys/dev/rtwn/rtl8192c/pci/r92ce_rx_desc.h 307529 2016-10-17 20:38:24Z avos $
*/
#ifndef R92CE_RX_DESC_H
#define R92CE_RX_DESC_H
#include <dev/rtwn/rtl8192c/r92c_rx_desc.h>
/* Rx MAC descriptor (PCIe). */
struct r92ce_rx_stat {
uint32_t rxdw0;
uint32_t rxdw1;
uint32_t rxdw2;
uint32_t rxdw3;
uint32_t rxdw4;
uint32_t tsf_low;
uint32_t rxbufaddr;
uint32_t rxbufaddr64;
} __packed __attribute__((aligned(4)));
#endif /* R92CE_RX_DESC_H */
@@ -0,0 +1,115 @@
/* $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>
*
* 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: releng/12.0/sys/dev/rtwn/rtl8192c/pci/r92ce_tx.c 307529 2016-10-17 20:38:24Z avos $");
#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/rtl8192c/pci/r92ce.h>
#include <dev/rtwn/rtl8192c/pci/r92ce_tx_desc.h>
void
r92ce_setup_tx_desc(struct rtwn_pci_softc *pc, void *desc,
uint32_t next_desc_addr)
{
struct r92ce_tx_desc *txd = desc;
/* setup tx desc */
txd->nextdescaddr = htole32(next_desc_addr);
}
void
r92ce_tx_postsetup(struct rtwn_pci_softc *pc, void *desc,
bus_dma_segment_t segs[])
{
struct r92ce_tx_desc *txd = desc;
txd->txbufaddr = htole32(segs[0].ds_addr);
txd->txbufsize = txd->pktlen;
bus_space_barrier(pc->pc_st, pc->pc_sh, 0, pc->pc_mapsize,
BUS_SPACE_BARRIER_WRITE);
}
void
r92ce_copy_tx_desc(void *dest, const void *src)
{
struct r92ce_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
r92ce_dump_tx_desc(struct rtwn_softc *sc, const void *desc)
{
#ifdef RTWN_DEBUG
const struct r92ce_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
}
@@ -0,0 +1,55 @@
/* $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>
*
* 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: releng/12.0/sys/dev/rtwn/rtl8192c/pci/r92ce_tx_desc.h 307529 2016-10-17 20:38:24Z avos $
*/
#ifndef R92CE_TX_DESC_H
#define R92CE_TX_DESC_H
#include <dev/rtwn/rtl8192c/r92c_tx_desc.h>
/* Tx MAC descriptor (PCIe). */
struct r92ce_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 /* R92CE_TX_DESC_H */
@@ -0,0 +1,122 @@
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $
* $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/r92c.h 322950 2017-08-27 13:02:51Z avos $
*/
#ifndef RTL8192C_H
#define RTL8192C_H
/*
* Global definitions.
*/
#define R92C_TXPKTBUF_COUNT 256
#define R92C_TX_PAGE_SIZE 128
#define R92C_RX_DMA_BUFFER_SIZE 0x2800
#define R92C_MAX_FW_SIZE 0x4000
#define R92C_MACID_MAX 31
#define R92C_CAM_ENTRY_COUNT 32
#define R92C_CALIB_THRESHOLD 2
/*
* Function declarations.
*/
/* r92c_attach.c */
void r92c_detach_private(struct rtwn_softc *);
void r92c_read_chipid_vendor(struct rtwn_softc *, uint32_t);
/* r92c_beacon.c */
void r92c_beacon_init(struct rtwn_softc *, void *, int);
void r92c_beacon_enable(struct rtwn_softc *, int, int);
/* r92c_calib.c */
void r92c_iq_calib(struct rtwn_softc *);
void r92c_lc_calib(struct rtwn_softc *);
void r92c_temp_measure(struct rtwn_softc *);
uint8_t r92c_temp_read(struct rtwn_softc *);
/* r92c_chan.c */
void r92c_get_txpower(struct rtwn_softc *, int,
struct ieee80211_channel *, uint8_t[]);
void r92c_write_txpower(struct rtwn_softc *, int,
uint8_t power[]);
void r92c_set_bw20(struct rtwn_softc *, uint8_t);
void r92c_set_chan(struct rtwn_softc *, struct ieee80211_channel *);
void r92c_set_gain(struct rtwn_softc *, uint8_t);
void r92c_scan_start(struct ieee80211com *);
void r92c_scan_end(struct ieee80211com *);
/* r92c_fw.c */
#ifndef RTWN_WITHOUT_UCODE
void r92c_fw_reset(struct rtwn_softc *, int);
void r92c_fw_download_enable(struct rtwn_softc *, int);
#endif
void r92c_joinbss_rpt(struct rtwn_softc *, int);
#ifndef RTWN_WITHOUT_UCODE
int r92c_set_rsvd_page(struct rtwn_softc *, int, int, int);
int r92c_set_pwrmode(struct rtwn_softc *, struct ieee80211vap *, int);
void r92c_set_rssi(struct rtwn_softc *);
void r92c_handle_c2h_report(void *);
#endif
/* r92c_init.c */
int r92c_check_condition(struct rtwn_softc *, const uint8_t[]);
int r92c_llt_init(struct rtwn_softc *);
int r92c_set_page_size(struct rtwn_softc *);
void r92c_init_bb_common(struct rtwn_softc *);
int r92c_init_rf_chain(struct rtwn_softc *,
const struct rtwn_rf_prog *, int);
void r92c_init_rf(struct rtwn_softc *);
void r92c_init_edca(struct rtwn_softc *);
void r92c_init_ampdu(struct rtwn_softc *);
void r92c_init_antsel(struct rtwn_softc *);
void r92c_pa_bias_init(struct rtwn_softc *);
/* r92c_llt.c */
int r92c_llt_write(struct rtwn_softc *, uint32_t, uint32_t);
/* r92c_rf.c */
uint32_t r92c_rf_read(struct rtwn_softc *, int, uint8_t);
void r92c_rf_write(struct rtwn_softc *, int, uint8_t, uint32_t);
/* r92c_rom.c */
void r92c_efuse_postread(struct rtwn_softc *);
void r92c_parse_rom(struct rtwn_softc *, uint8_t *);
/* r92c_rx.c */
int8_t r92c_get_rssi_cck(struct rtwn_softc *, void *);
int8_t r92c_get_rssi_ofdm(struct rtwn_softc *, void *);
uint8_t r92c_rx_radiotap_flags(const void *);
void r92c_get_rx_stats(struct rtwn_softc *, struct ieee80211_rx_stats *,
const void *, const void *);
/* r92c_tx.c */
void r92c_tx_enable_ampdu(void *, int);
void r92c_tx_setup_hwseq(void *);
void r92c_tx_setup_macid(void *, int);
void r92c_fill_tx_desc(struct rtwn_softc *, struct ieee80211_node *,
struct mbuf *, void *, uint8_t, int);
void r92c_fill_tx_desc_raw(struct rtwn_softc *, struct ieee80211_node *,
struct mbuf *, void *, const struct ieee80211_bpf_params *);
void r92c_fill_tx_desc_null(struct rtwn_softc *, void *, int, int, int);
uint8_t r92c_tx_radiotap_flags(const void *);
#endif /* RTL8192C_H */
@@ -0,0 +1,80 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/r92c_attach.c 307529 2016-10-17 20:38:24Z avos $");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/rtl8192c/r92c.h>
#include <dev/rtwn/rtl8192c/r92c_reg.h>
#include <dev/rtwn/rtl8192c/r92c_var.h>
void
r92c_detach_private(struct rtwn_softc *sc)
{
struct r92c_softc *rs = sc->sc_priv;
free(rs, M_RTWN_PRIV);
}
void
r92c_read_chipid_vendor(struct rtwn_softc *sc, uint32_t reg_sys_cfg)
{
struct r92c_softc *rs = sc->sc_priv;
if (reg_sys_cfg & R92C_SYS_CFG_TYPE_92C) {
rs->chip |= R92C_CHIP_92C;
/* Check if it is a castrated 8192C. */
if (MS(rtwn_read_4(sc, R92C_HPON_FSM),
R92C_HPON_FSM_CHIP_BONDING_ID) ==
R92C_HPON_FSM_CHIP_BONDING_ID_92C_1T2R)
rs->chip |= R92C_CHIP_92C_1T2R;
}
if (reg_sys_cfg & R92C_SYS_CFG_VENDOR_UMC) {
if (MS(reg_sys_cfg, R92C_SYS_CFG_CHIP_VER_RTL) == 0)
rs->chip |= R92C_CHIP_UMC_A_CUT;
}
}
@@ -0,0 +1,86 @@
/*-
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/r92c_beacon.c 308389 2016-11-06 23:13:13Z avos $");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwn_ridx.h>
#include <dev/rtwn/rtl8192c/r92c.h>
#include <dev/rtwn/rtl8192c/r92c_var.h>
#include <dev/rtwn/rtl8192c/r92c_reg.h>
#include <dev/rtwn/rtl8192c/r92c_tx_desc.h>
void
r92c_beacon_init(struct rtwn_softc *sc, void *buf, int id)
{
struct r92c_tx_desc *txd = (struct r92c_tx_desc *)buf;
/*
* NB: there is no need to setup HWSEQ_EN bit;
* QSEL_BEACON already implies it.
*/
txd->flags0 |= R92C_FLAGS0_BMCAST | R92C_FLAGS0_FSG | R92C_FLAGS0_LSG;
txd->txdw1 |= htole32(
SM(R92C_TXDW1_QSEL, R92C_TXDW1_QSEL_BEACON) |
SM(R92C_TXDW1_RAID, R92C_RAID_11B));
rtwn_r92c_tx_setup_macid(sc, buf, id);
txd->txdw4 |= htole32(R92C_TXDW4_DRVRATE);
txd->txdw4 |= htole32(SM(R92C_TXDW4_SEQ_SEL, id));
txd->txdw4 |= htole32(SM(R92C_TXDW4_PORT_ID, id));
txd->txdw5 |= htole32(SM(R92C_TXDW5_DATARATE, RTWN_RIDX_CCK1));
}
void
r92c_beacon_enable(struct rtwn_softc *sc, int id, int enable)
{
if (enable) {
rtwn_setbits_1(sc, R92C_BCN_CTRL(id),
0, R92C_BCN_CTRL_EN_BCN);
} else {
rtwn_setbits_1(sc, R92C_BCN_CTRL(id),
R92C_BCN_CTRL_EN_BCN, 0);
}
}
@@ -0,0 +1,113 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/r92c_calib.c 307529 2016-10-17 20:38:24Z avos $");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/rtl8192c/r92c.h>
#include <dev/rtwn/rtl8192c/r92c_reg.h>
void
r92c_iq_calib(struct rtwn_softc *sc)
{
/* XXX TODO */
}
void
r92c_lc_calib(struct rtwn_softc *sc)
{
uint32_t rf_ac[2];
uint8_t txmode;
int i;
txmode = rtwn_read_1(sc, R92C_OFDM1_LSTF + 3);
if ((txmode & 0x70) != 0) {
/* Disable all continuous Tx. */
rtwn_write_1(sc, R92C_OFDM1_LSTF + 3, txmode & ~0x70);
/* Set RF mode to standby mode. */
for (i = 0; i < sc->nrxchains; i++) {
rf_ac[i] = rtwn_rf_read(sc, i, R92C_RF_AC);
rtwn_rf_write(sc, i, R92C_RF_AC,
RW(rf_ac[i], R92C_RF_AC_MODE,
R92C_RF_AC_MODE_STANDBY));
}
} else {
/* Block all Tx queues. */
rtwn_write_1(sc, R92C_TXPAUSE, R92C_TX_QUEUE_ALL);
}
/* Start calibration. */
rtwn_rf_setbits(sc, 0, R92C_RF_CHNLBW, 0, R92C_RF_CHNLBW_LCSTART);
/* Give calibration the time to complete. */
rtwn_delay(sc, 100000); /* 100ms */
/* Restore configuration. */
if ((txmode & 0x70) != 0) {
/* Restore Tx mode. */
rtwn_write_1(sc, R92C_OFDM1_LSTF + 3, txmode);
/* Restore RF mode. */
for (i = 0; i < sc->nrxchains; i++)
rtwn_rf_write(sc, i, R92C_RF_AC, rf_ac[i]);
} else {
/* Unblock all Tx queues. */
rtwn_write_1(sc, R92C_TXPAUSE, 0x00);
}
}
void
r92c_temp_measure(struct rtwn_softc *sc)
{
rtwn_rf_write(sc, 0, R92C_RF_T_METER, R92C_RF_T_METER_START);
}
uint8_t
r92c_temp_read(struct rtwn_softc *sc)
{
return (MS(rtwn_rf_read(sc, 0, R92C_RF_T_METER),
R92C_RF_T_METER_VAL));
}
@@ -0,0 +1,351 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/r92c_chan.c 330750 2018-03-10 23:47:03Z avos $");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/if_rtwn_debug.h>
#include <dev/rtwn/if_rtwn_ridx.h>
#include <dev/rtwn/rtl8192c/r92c.h>
#include <dev/rtwn/rtl8192c/r92c_priv.h>
#include <dev/rtwn/rtl8192c/r92c_reg.h>
#include <dev/rtwn/rtl8192c/r92c_var.h>
static int
r92c_get_power_group(struct rtwn_softc *sc, struct ieee80211_channel *c)
{
uint8_t chan;
int group;
chan = rtwn_chan2centieee(c);
if (IEEE80211_IS_CHAN_2GHZ(c)) {
if (chan <= 3) group = 0;
else if (chan <= 9) group = 1;
else if (chan <= 14) group = 2;
else {
KASSERT(0, ("wrong 2GHz channel %d!\n", chan));
return (-1);
}
} else {
KASSERT(0, ("wrong channel band (flags %08X)\n", c->ic_flags));
return (-1);
}
return (group);
}
/* XXX recheck */
void
r92c_get_txpower(struct rtwn_softc *sc, int chain,
struct ieee80211_channel *c, uint8_t power[RTWN_RIDX_COUNT])
{
struct r92c_softc *rs = sc->sc_priv;
struct rtwn_r92c_txpwr *rt = rs->rs_txpwr;
const struct rtwn_r92c_txagc *base = rs->rs_txagc;
uint8_t ofdmpow, htpow, diff, max;
int max_mcs, ridx, group;
/* Determine channel group. */
group = r92c_get_power_group(sc, c);
if (group == -1) { /* shouldn't happen */
device_printf(sc->sc_dev, "%s: incorrect channel\n", __func__);
return;
}
/* XXX net80211 regulatory */
max_mcs = RTWN_RIDX_HT_MCS(sc->ntxchains * 8 - 1);
KASSERT(max_mcs <= RTWN_RIDX_COUNT, ("increase ridx limit\n"));
if (rs->regulatory == 0) {
for (ridx = RTWN_RIDX_CCK1; ridx <= RTWN_RIDX_CCK11; ridx++)
power[ridx] = base[chain].pwr[0][ridx];
}
for (ridx = RTWN_RIDX_OFDM6; ridx < RTWN_RIDX_COUNT; ridx++) {
if (rs->regulatory == 3) {
power[ridx] = base[chain].pwr[0][ridx];
/* Apply vendor limits. */
if (IEEE80211_IS_CHAN_HT40(c))
max = rt->ht40_max_pwr[chain][group];
else
max = rt->ht20_max_pwr[chain][group];
if (power[ridx] > max)
power[ridx] = max;
} else if (rs->regulatory == 1) {
if (!IEEE80211_IS_CHAN_HT40(c))
power[ridx] = base[chain].pwr[group][ridx];
} else if (rs->regulatory != 2)
power[ridx] = base[chain].pwr[0][ridx];
}
/* Compute per-CCK rate Tx power. */
for (ridx = RTWN_RIDX_CCK1; ridx <= RTWN_RIDX_CCK11; ridx++)
power[ridx] += rt->cck_tx_pwr[chain][group];
htpow = rt->ht40_1s_tx_pwr[chain][group];
if (sc->ntxchains > 1) {
/* Apply reduction for 2 spatial streams. */
diff = rt->ht40_2s_tx_pwr_diff[chain][group];
htpow = (htpow > diff) ? htpow - diff : 0;
}
/* Compute per-OFDM rate Tx power. */
diff = rt->ofdm_tx_pwr_diff[chain][group];
ofdmpow = htpow + diff; /* HT->OFDM correction. */
for (ridx = RTWN_RIDX_OFDM6; ridx <= RTWN_RIDX_OFDM54; ridx++)
power[ridx] += ofdmpow;
/* Compute per-MCS Tx power. */
if (!IEEE80211_IS_CHAN_HT40(c)) {
diff = rt->ht20_tx_pwr_diff[chain][group];
htpow += diff; /* HT40->HT20 correction. */
}
for (ridx = RTWN_RIDX_HT_MCS(0); ridx <= max_mcs; ridx++)
power[ridx] += htpow;
/* Apply max limit. */
for (ridx = RTWN_RIDX_CCK1; ridx <= max_mcs; ridx++) {
if (power[ridx] > R92C_MAX_TX_PWR)
power[ridx] = R92C_MAX_TX_PWR;
}
}
void
r92c_write_txpower(struct rtwn_softc *sc, int chain,
uint8_t power[RTWN_RIDX_COUNT])
{
uint32_t reg;
/* Write per-CCK rate Tx power. */
if (chain == 0) {
reg = rtwn_bb_read(sc, R92C_TXAGC_A_CCK1_MCS32);
reg = RW(reg, R92C_TXAGC_A_CCK1, power[RTWN_RIDX_CCK1]);
rtwn_bb_write(sc, R92C_TXAGC_A_CCK1_MCS32, reg);
reg = rtwn_bb_read(sc, R92C_TXAGC_B_CCK11_A_CCK2_11);
reg = RW(reg, R92C_TXAGC_A_CCK2, power[RTWN_RIDX_CCK2]);
reg = RW(reg, R92C_TXAGC_A_CCK55, power[RTWN_RIDX_CCK55]);
reg = RW(reg, R92C_TXAGC_A_CCK11, power[RTWN_RIDX_CCK11]);
rtwn_bb_write(sc, R92C_TXAGC_B_CCK11_A_CCK2_11, reg);
} else {
reg = rtwn_bb_read(sc, R92C_TXAGC_B_CCK1_55_MCS32);
reg = RW(reg, R92C_TXAGC_B_CCK1, power[RTWN_RIDX_CCK1]);
reg = RW(reg, R92C_TXAGC_B_CCK2, power[RTWN_RIDX_CCK2]);
reg = RW(reg, R92C_TXAGC_B_CCK55, power[RTWN_RIDX_CCK55]);
rtwn_bb_write(sc, R92C_TXAGC_B_CCK1_55_MCS32, reg);
reg = rtwn_bb_read(sc, R92C_TXAGC_B_CCK11_A_CCK2_11);
reg = RW(reg, R92C_TXAGC_B_CCK11, power[RTWN_RIDX_CCK11]);
rtwn_bb_write(sc, R92C_TXAGC_B_CCK11_A_CCK2_11, reg);
}
/* Write per-OFDM rate Tx power. */
rtwn_bb_write(sc, R92C_TXAGC_RATE18_06(chain),
SM(R92C_TXAGC_RATE06, power[RTWN_RIDX_OFDM6]) |
SM(R92C_TXAGC_RATE09, power[RTWN_RIDX_OFDM9]) |
SM(R92C_TXAGC_RATE12, power[RTWN_RIDX_OFDM12]) |
SM(R92C_TXAGC_RATE18, power[RTWN_RIDX_OFDM18]));
rtwn_bb_write(sc, R92C_TXAGC_RATE54_24(chain),
SM(R92C_TXAGC_RATE24, power[RTWN_RIDX_OFDM24]) |
SM(R92C_TXAGC_RATE36, power[RTWN_RIDX_OFDM36]) |
SM(R92C_TXAGC_RATE48, power[RTWN_RIDX_OFDM48]) |
SM(R92C_TXAGC_RATE54, power[RTWN_RIDX_OFDM54]));
/* Write per-MCS Tx power. */
rtwn_bb_write(sc, R92C_TXAGC_MCS03_MCS00(chain),
SM(R92C_TXAGC_MCS00, power[RTWN_RIDX_HT_MCS(0)]) |
SM(R92C_TXAGC_MCS01, power[RTWN_RIDX_HT_MCS(1)]) |
SM(R92C_TXAGC_MCS02, power[RTWN_RIDX_HT_MCS(2)]) |
SM(R92C_TXAGC_MCS03, power[RTWN_RIDX_HT_MCS(3)]));
rtwn_bb_write(sc, R92C_TXAGC_MCS07_MCS04(chain),
SM(R92C_TXAGC_MCS04, power[RTWN_RIDX_HT_MCS(4)]) |
SM(R92C_TXAGC_MCS05, power[RTWN_RIDX_HT_MCS(5)]) |
SM(R92C_TXAGC_MCS06, power[RTWN_RIDX_HT_MCS(6)]) |
SM(R92C_TXAGC_MCS07, power[RTWN_RIDX_HT_MCS(7)]));
if (sc->ntxchains >= 2) {
rtwn_bb_write(sc, R92C_TXAGC_MCS11_MCS08(chain),
SM(R92C_TXAGC_MCS08, power[RTWN_RIDX_HT_MCS(8)]) |
SM(R92C_TXAGC_MCS09, power[RTWN_RIDX_HT_MCS(9)]) |
SM(R92C_TXAGC_MCS10, power[RTWN_RIDX_HT_MCS(10)]) |
SM(R92C_TXAGC_MCS11, power[RTWN_RIDX_HT_MCS(11)]));
rtwn_bb_write(sc, R92C_TXAGC_MCS15_MCS12(chain),
SM(R92C_TXAGC_MCS12, power[RTWN_RIDX_HT_MCS(12)]) |
SM(R92C_TXAGC_MCS13, power[RTWN_RIDX_HT_MCS(13)]) |
SM(R92C_TXAGC_MCS14, power[RTWN_RIDX_HT_MCS(14)]) |
SM(R92C_TXAGC_MCS15, power[RTWN_RIDX_HT_MCS(15)]));
}
}
static void
r92c_set_txpower(struct rtwn_softc *sc, struct ieee80211_channel *c)
{
uint8_t power[RTWN_RIDX_COUNT];
int i;
for (i = 0; i < sc->ntxchains; i++) {
memset(power, 0, sizeof(power));
/* Compute per-rate Tx power values. */
rtwn_r92c_get_txpower(sc, i, c, power);
#ifdef RTWN_DEBUG
if (sc->sc_debug & RTWN_DEBUG_TXPWR) {
int max_mcs, ridx;
max_mcs = RTWN_RIDX_HT_MCS(sc->ntxchains * 8 - 1);
/* Dump per-rate Tx power values. */
printf("Tx power for chain %d:\n", i);
for (ridx = RTWN_RIDX_CCK1; ridx <= max_mcs; ridx++)
printf("Rate %d = %u\n", ridx, power[ridx]);
}
#endif
/* Write per-rate Tx power values to hardware. */
r92c_write_txpower(sc, i, power);
}
}
static void
r92c_set_bw40(struct rtwn_softc *sc, uint8_t chan, int prichlo)
{
struct r92c_softc *rs = sc->sc_priv;
rtwn_setbits_1(sc, R92C_BWOPMODE, R92C_BWOPMODE_20MHZ, 0);
rtwn_setbits_1(sc, R92C_RRSR + 2, 0x6f, (prichlo ? 1 : 2) << 5);
rtwn_bb_setbits(sc, R92C_FPGA0_RFMOD, 0, R92C_RFMOD_40MHZ);
rtwn_bb_setbits(sc, R92C_FPGA1_RFMOD, 0, R92C_RFMOD_40MHZ);
/* Set CCK side band. */
rtwn_bb_setbits(sc, R92C_CCK0_SYSTEM, 0x10,
(prichlo ? 0 : 1) << 4);
rtwn_bb_setbits(sc, R92C_OFDM1_LSTF, 0x0c00,
(prichlo ? 1 : 2) << 10);
rtwn_bb_setbits(sc, R92C_FPGA0_ANAPARAM2,
R92C_FPGA0_ANAPARAM2_CBW20, 0);
rtwn_bb_setbits(sc, 0x818, 0x0c000000, (prichlo ? 2 : 1) << 26);
/* Select 40MHz bandwidth. */
rtwn_rf_write(sc, 0, R92C_RF_CHNLBW,
(rs->rf_chnlbw[0] & ~0xfff) | chan);
}
void
r92c_set_bw20(struct rtwn_softc *sc, uint8_t chan)
{
struct r92c_softc *rs = sc->sc_priv;
rtwn_setbits_1(sc, R92C_BWOPMODE, 0, R92C_BWOPMODE_20MHZ);
rtwn_bb_setbits(sc, R92C_FPGA0_RFMOD, R92C_RFMOD_40MHZ, 0);
rtwn_bb_setbits(sc, R92C_FPGA1_RFMOD, R92C_RFMOD_40MHZ, 0);
rtwn_bb_setbits(sc, R92C_FPGA0_ANAPARAM2, 0,
R92C_FPGA0_ANAPARAM2_CBW20);
/* Select 20MHz bandwidth. */
rtwn_rf_write(sc, 0, R92C_RF_CHNLBW,
(rs->rf_chnlbw[0] & ~0xfff) | chan | R92C_RF_CHNLBW_BW20);
}
void
r92c_set_chan(struct rtwn_softc *sc, struct ieee80211_channel *c)
{
struct r92c_softc *rs = sc->sc_priv;
u_int chan;
int i;
chan = rtwn_chan2centieee(c);
/* Set Tx power for this new channel. */
r92c_set_txpower(sc, c);
for (i = 0; i < sc->nrxchains; i++) {
rtwn_rf_write(sc, i, R92C_RF_CHNLBW,
RW(rs->rf_chnlbw[i], R92C_RF_CHNLBW_CHNL, chan));
}
if (IEEE80211_IS_CHAN_HT40(c))
r92c_set_bw40(sc, chan, IEEE80211_IS_CHAN_HT40U(c));
else
rtwn_r92c_set_bw20(sc, chan);
}
void
r92c_set_gain(struct rtwn_softc *sc, uint8_t gain)
{
rtwn_bb_setbits(sc, R92C_OFDM0_AGCCORE1(0),
R92C_OFDM0_AGCCORE1_GAIN_M, gain);
rtwn_bb_setbits(sc, R92C_OFDM0_AGCCORE1(1),
R92C_OFDM0_AGCCORE1_GAIN_M, gain);
}
void
r92c_scan_start(struct ieee80211com *ic)
{
struct rtwn_softc *sc = ic->ic_softc;
struct r92c_softc *rs = sc->sc_priv;
RTWN_LOCK(sc);
/* Set gain for scanning. */
rtwn_r92c_set_gain(sc, 0x20);
RTWN_UNLOCK(sc);
rs->rs_scan_start(ic);
}
void
r92c_scan_end(struct ieee80211com *ic)
{
struct rtwn_softc *sc = ic->ic_softc;
struct r92c_softc *rs = sc->sc_priv;
RTWN_LOCK(sc);
/* Set gain under link. */
rtwn_r92c_set_gain(sc, 0x32);
RTWN_UNLOCK(sc);
rs->rs_scan_end(ic);
}
@@ -0,0 +1,520 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* 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: releng/12.0/sys/dev/rtwn/rtl8192c/r92c_fw.c 322988 2017-08-28 22:14:16Z avos $");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <net80211/ieee80211_ratectl.h>
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/if_rtwn_debug.h>
#include <dev/rtwn/if_rtwn_ridx.h>
#include <dev/rtwn/if_rtwn_rx.h>
#include <dev/rtwn/if_rtwn_task.h>
#include <dev/rtwn/if_rtwn_tx.h>
#include <dev/rtwn/rtl8192c/r92c.h>
#include <dev/rtwn/rtl8192c/r92c_reg.h>
#include <dev/rtwn/rtl8192c/r92c_var.h>
#include <dev/rtwn/rtl8192c/r92c_fw_cmd.h>
#include <dev/rtwn/rtl8192c/r92c_tx_desc.h>
#ifndef RTWN_WITHOUT_UCODE
static int
r92c_fw_cmd(struct rtwn_softc *sc, uint8_t id, const void *buf, int len)
{
struct r92c_fw_cmd cmd;
int ntries, error;
KASSERT(len <= sizeof(cmd.msg),
("%s: firmware command too long (%d > %zu)\n",
__func__, len, sizeof(cmd.msg)));
if (!(sc->sc_flags & RTWN_FW_LOADED)) {
RTWN_DPRINTF(sc, RTWN_DEBUG_FIRMWARE, "%s: firmware "
"was not loaded; command (id %u) will be discarded\n",
__func__, id);
return (0);
}
/* Wait for current FW box to be empty. */
for (ntries = 0; ntries < 100; ntries++) {
if (!(rtwn_read_1(sc, R92C_HMETFR) & (1 << sc->fwcur)))
break;
rtwn_delay(sc, 2000);
}
if (ntries == 100) {
device_printf(sc->sc_dev,
"could not send firmware command\n");
return (ETIMEDOUT);
}
memset(&cmd, 0, sizeof(cmd));
cmd.id = id;
if (len > 3) {
/* Ext command: [id : byte2 : byte3 : byte4 : byte0 : byte1] */
cmd.id |= R92C_CMD_FLAG_EXT;
memcpy(cmd.msg, (const uint8_t *)buf + 2, len - 2);
memcpy(cmd.msg + 3, buf, 2);
} else
memcpy(cmd.msg, buf, len);
/* Write the first word last since that will trigger the FW. */
if (len > 3) {
error = rtwn_write_2(sc, R92C_HMEBOX_EXT(sc->fwcur),
*(uint16_t *)((uint8_t *)&cmd + 4));
if (error != 0)
return (error);
}
error = rtwn_write_4(sc, R92C_HMEBOX(sc->fwcur),
*(uint32_t *)&cmd);
if (error != 0)
return (error);
sc->fwcur = (sc->fwcur + 1) % R92C_H2C_NBOX;
return (0);
}
void
r92c_fw_reset(struct rtwn_softc *sc, int reason)
{
int ntries;
if (reason == RTWN_FW_RESET_CHECKSUM)
return;
/* Tell 8051 to reset itself. */
rtwn_write_1(sc, R92C_HMETFR + 3, 0x20);
/* Wait until 8051 resets by itself. */
for (ntries = 0; ntries < 100; ntries++) {
if ((rtwn_read_2(sc, R92C_SYS_FUNC_EN) &
R92C_SYS_FUNC_EN_CPUEN) == 0)
return;
rtwn_delay(sc, 50);
}
/* Force 8051 reset. */
rtwn_setbits_1_shift(sc, R92C_SYS_FUNC_EN,
R92C_SYS_FUNC_EN_CPUEN, 0, 1);
}
void
r92c_fw_download_enable(struct rtwn_softc *sc, int enable)
{
if (enable) {
/* 8051 enable. */
rtwn_setbits_1_shift(sc, R92C_SYS_FUNC_EN, 0,
R92C_SYS_FUNC_EN_CPUEN, 1);
/* MCU firmware download enable. */
rtwn_setbits_1(sc, R92C_MCUFWDL, 0, R92C_MCUFWDL_EN);
/* 8051 reset. */
rtwn_setbits_1_shift(sc, R92C_MCUFWDL, R92C_MCUFWDL_ROM_DLEN,
0, 2);
} else {
/* MCU download disable. */
rtwn_setbits_1(sc, R92C_MCUFWDL, R92C_MCUFWDL_EN, 0);
/* Reserved for f/w extension. */
rtwn_write_1(sc, R92C_MCUFWDL + 1, 0);
}
}
#endif
/*
* Initialize firmware rate adaptation.
*/
#ifndef RTWN_WITHOUT_UCODE
static int
r92c_send_ra_cmd(struct rtwn_softc *sc, int macid, uint32_t rates,
int maxrate)
{
struct r92c_fw_cmd_macid_cfg cmd;
uint8_t mode;
int error = 0;
/* XXX should be called directly from iv_newstate() for MACID_BC */
/* XXX joinbss, not send_ra_cmd() */
#ifdef RTWN_TODO
/* NB: group addressed frames are done at 11bg rates for now */
if (ic->ic_curmode == IEEE80211_MODE_11B)
mode = R92C_RAID_11B;
else
mode = R92C_RAID_11BG;
/* XXX misleading 'mode' value here for unicast frames */
RTWN_DPRINTF(sc, RTWN_DEBUG_RA,
"%s: mode 0x%x, rates 0x%08x, basicrates 0x%08x\n", __func__,
mode, rates, basicrates);
/* Set rates mask for group addressed frames. */
cmd.macid = RTWN_MACID_BC | R92C_CMD_MACID_VALID;
cmd.mask = htole32(mode << 28 | basicrates);
error = rtwn_fw_cmd(sc, R92C_CMD_MACID_CONFIG, &cmd, sizeof(cmd));
if (error != 0) {
device_printf(sc->sc_dev,
"could not set RA mask for broadcast station\n");
return (error);
}
#endif
/* Set rates mask for unicast frames. */
if (maxrate >= RTWN_RIDX_HT_MCS(0))
mode = R92C_RAID_11GN;
else if (maxrate >= RTWN_RIDX_OFDM6)
mode = R92C_RAID_11BG;
else
mode = R92C_RAID_11B;
cmd.macid = macid | R92C_CMD_MACID_VALID;
cmd.mask = htole32(mode << 28 | rates);
error = r92c_fw_cmd(sc, R92C_CMD_MACID_CONFIG, &cmd, sizeof(cmd));
if (error != 0) {
device_printf(sc->sc_dev,
"%s: could not set RA mask for %d station\n",
__func__, macid);
return (error);
}
return (0);
}
#endif
static void
r92c_init_ra(struct rtwn_softc *sc, int macid)
{
struct ieee80211_htrateset *rs_ht;
struct ieee80211_node *ni;
uint32_t rates;
int maxrate;
RTWN_NT_LOCK(sc);
if (sc->node_list[macid] == NULL) {
RTWN_DPRINTF(sc, RTWN_DEBUG_RA, "%s: macid %d, ni is NULL\n",
__func__, macid);
RTWN_NT_UNLOCK(sc);
return;
}
ni = ieee80211_ref_node(sc->node_list[macid]);
if (ni->ni_flags & IEEE80211_NODE_HT)
rs_ht = &ni->ni_htrates;
else
rs_ht = NULL;
/* XXX MACID_BC */
rtwn_get_rates(sc, &ni->ni_rates, rs_ht, &rates, &maxrate, 0);
RTWN_NT_UNLOCK(sc);
#ifndef RTWN_WITHOUT_UCODE
if (sc->sc_ratectl == RTWN_RATECTL_FW) {
r92c_send_ra_cmd(sc, macid, rates, maxrate);
}
#endif
rtwn_write_1(sc, R92C_INIDATA_RATE_SEL(macid), maxrate);
ieee80211_free_node(ni);
}
void
r92c_joinbss_rpt(struct rtwn_softc *sc, int macid)
{
#ifndef RTWN_WITHOUT_UCODE
struct r92c_softc *rs = sc->sc_priv;
struct ieee80211vap *vap;
struct r92c_fw_cmd_joinbss_rpt cmd;
if (sc->vaps[0] == NULL) /* XXX fix */
goto end;
vap = &sc->vaps[0]->vap;
if ((vap->iv_state == IEEE80211_S_RUN) ^
!(rs->rs_flags & R92C_FLAG_ASSOCIATED))
goto end;
if (rs->rs_flags & R92C_FLAG_ASSOCIATED) {
cmd.mstatus = R92C_MSTATUS_DISASSOC;
rs->rs_flags &= ~R92C_FLAG_ASSOCIATED;
} else {
cmd.mstatus = R92C_MSTATUS_ASSOC;
rs->rs_flags |= R92C_FLAG_ASSOCIATED;
}
if (r92c_fw_cmd(sc, R92C_CMD_JOINBSS_RPT, &cmd, sizeof(cmd)) != 0) {
device_printf(sc->sc_dev, "%s: cannot change media status!\n",
__func__);
}
end:
#endif
/* TODO: init rates for RTWN_MACID_BC. */
if (macid & RTWN_MACID_VALID)
r92c_init_ra(sc, macid & ~RTWN_MACID_VALID);
}
#ifndef RTWN_WITHOUT_UCODE
int
r92c_set_rsvd_page(struct rtwn_softc *sc, int probe_resp, int null,
int qos_null)
{
struct r92c_fw_cmd_rsvdpage rsvd;
rsvd.probe_resp = probe_resp;
rsvd.ps_poll = 0;
rsvd.null_data = null;
return (r92c_fw_cmd(sc, R92C_CMD_RSVD_PAGE, &rsvd, sizeof(rsvd)));
}
int
r92c_set_pwrmode(struct rtwn_softc *sc, struct ieee80211vap *vap,
int off)
{
struct r92c_fw_cmd_pwrmode mode;
int error;
/* XXX dm_RF_saving */
if (off && vap->iv_state == IEEE80211_S_RUN &&
(vap->iv_flags & IEEE80211_F_PMGTON))
mode.mode = R92C_PWRMODE_MIN;
else
mode.mode = R92C_PWRMODE_CAM;
mode.smart_ps = R92C_PWRMODE_SMARTPS_NULLDATA;
mode.bcn_pass = 1; /* XXX */
error = r92c_fw_cmd(sc, R92C_CMD_SET_PWRMODE, &mode, sizeof(mode));
if (error != 0) {
device_printf(sc->sc_dev,
"%s: CMD_SET_PWRMODE was not sent, error %d\n",
__func__, error);
}
return (error);
}
void
r92c_set_rssi(struct rtwn_softc *sc)
{
struct ieee80211_node *ni;
struct rtwn_node *rn;
struct r92c_fw_cmd_rssi cmd;
int i;
cmd.reserved = 0;
RTWN_NT_LOCK(sc);
for (i = 0; i < sc->macid_limit; i++) {
/* XXX optimize? */
ni = sc->node_list[i];
if (ni == NULL)
continue;
rn = RTWN_NODE(ni);
cmd.macid = i;
cmd.pwdb = rn->avg_pwdb;
RTWN_DPRINTF(sc, RTWN_DEBUG_RSSI,
"%s: sending RSSI command (macid %d, rssi %d)\n",
__func__, i, rn->avg_pwdb);
RTWN_NT_UNLOCK(sc);
r92c_fw_cmd(sc, R92C_CMD_RSSI_SETTING, &cmd, sizeof(cmd));
RTWN_NT_LOCK(sc);
}
RTWN_NT_UNLOCK(sc);
}
static void
r92c_ratectl_tx_complete(struct rtwn_softc *sc, uint8_t *buf, int len)
{
#if __FreeBSD_version >= 1200012
struct ieee80211_ratectl_tx_status txs;
#endif
struct r92c_c2h_tx_rpt *rpt;
struct ieee80211_node *ni;
uint8_t macid;
int ntries;
if (sc->sc_ratectl != RTWN_RATECTL_NET80211) {
/* shouldn't happen */
device_printf(sc->sc_dev, "%s called while ratectl = %d!\n",
__func__, sc->sc_ratectl);
return;
}
rpt = (struct r92c_c2h_tx_rpt *)buf;
if (len != sizeof(*rpt)) {
device_printf(sc->sc_dev,
"%s: wrong report size (%d, must be %zu)\n",
__func__, len, sizeof(*rpt));
return;
}
RTWN_DPRINTF(sc, RTWN_DEBUG_INTR,
"%s: ccx report dump: 0: %02X, 1: %02X, queue time: "
"low %02X, high %02X, 4: %02X, 5: %02X, 6: %02X, 7: %02X\n",
__func__, rpt->rptb0, rpt->rptb1, rpt->queue_time_low,
rpt->queue_time_high, rpt->rptb4, rpt->rptb5, rpt->rptb6,
rpt->rptb7);
macid = MS(rpt->rptb5, R92C_RPTB5_MACID);
if (macid > sc->macid_limit) {
device_printf(sc->sc_dev,
"macid %u is too big; increase MACID_MAX limit\n",
macid);
return;
}
ntries = MS(rpt->rptb0, R92C_RPTB0_RETRY_CNT);
RTWN_NT_LOCK(sc);
ni = sc->node_list[macid];
if (ni != NULL) {
RTWN_DPRINTF(sc, RTWN_DEBUG_INTR, "%s: frame for macid %u was"
"%s sent (%d retries)\n", __func__, macid,
(rpt->rptb7 & R92C_RPTB7_PKT_OK) ? "" : " not",
ntries);
#if __FreeBSD_version >= 1200012
txs.flags = IEEE80211_RATECTL_STATUS_LONG_RETRY;
txs.long_retries = ntries;
if (rpt->rptb7 & R92C_RPTB7_PKT_OK)
txs.status = IEEE80211_RATECTL_TX_SUCCESS;
else if (rpt->rptb6 & R92C_RPTB6_RETRY_OVER)
txs.status = IEEE80211_RATECTL_TX_FAIL_LONG; /* XXX */
else if (rpt->rptb6 & R92C_RPTB6_LIFE_EXPIRE)
txs.status = IEEE80211_RATECTL_TX_FAIL_EXPIRED;
else
txs.status = IEEE80211_RATECTL_TX_FAIL_UNSPECIFIED;
ieee80211_ratectl_tx_complete(ni, &txs);
#else
struct ieee80211vap *vap = ni->ni_vap;
if (rpt->rptb7 & R92C_RPTB7_PKT_OK) {
ieee80211_ratectl_tx_complete(vap, ni,
IEEE80211_RATECTL_TX_SUCCESS, &ntries, NULL);
} else {
ieee80211_ratectl_tx_complete(vap, ni,
IEEE80211_RATECTL_TX_FAILURE, &ntries, NULL);
}
#endif
} else {
RTWN_DPRINTF(sc, RTWN_DEBUG_INTR, "%s: macid %u, ni is NULL\n",
__func__, macid);
}
RTWN_NT_UNLOCK(sc);
#ifdef IEEE80211_SUPPORT_SUPERG
if (sc->sc_tx_n_active > 0 && --sc->sc_tx_n_active <= 1)
rtwn_cmd_sleepable(sc, NULL, 0, rtwn_ff_flush_all);
#endif
}
static void
r92c_handle_c2h_task(struct rtwn_softc *sc, union sec_param *data)
{
const uint16_t off = R92C_C2H_EVT_MSG + sizeof(struct r92c_c2h_evt);
struct r92c_softc *rs = sc->sc_priv;
uint16_t buf[R92C_C2H_MSG_MAX_LEN / 2 + 1];
uint8_t id, len, status;
int i;
/* Do not reschedule the task if device is not running. */
if (!(sc->sc_flags & RTWN_RUNNING))
return;
/* Read current status. */
status = rtwn_read_1(sc, R92C_C2H_EVT_CLEAR);
if (status == R92C_C2H_EVT_HOST_CLOSE)
goto end; /* nothing to do */
else if (status == R92C_C2H_EVT_FW_CLOSE) {
len = rtwn_read_1(sc, R92C_C2H_EVT_MSG);
id = MS(len, R92C_C2H_EVTB0_ID);
len = MS(len, R92C_C2H_EVTB0_LEN);
memset(buf, 0, sizeof(buf));
/* Try to optimize event reads. */
for (i = 0; i < len; i += 2)
buf[i / 2] = rtwn_read_2(sc, off + i);
KASSERT(i < sizeof(buf), ("%s: buffer overrun (%d >= %zu)!",
__func__, i, sizeof(buf)));
switch (id) {
case R92C_C2H_EVT_TX_REPORT:
r92c_ratectl_tx_complete(sc, (uint8_t *)buf, len);
break;
default:
device_printf(sc->sc_dev,
"%s: C2H report %u (len %u) was not handled\n",
__func__, id, len);
break;
}
}
/* Prepare for next event. */
rtwn_write_1(sc, R92C_C2H_EVT_CLEAR, R92C_C2H_EVT_HOST_CLOSE);
end:
/* Adjust timeout for next call. */
if (rs->rs_c2h_pending != 0) {
rs->rs_c2h_pending = 0;
rs->rs_c2h_paused = 0;
} else
rs->rs_c2h_paused++;
if (rs->rs_c2h_paused > R92C_TX_PAUSED_THRESHOLD)
rs->rs_c2h_timeout = hz;
else
rs->rs_c2h_timeout = MAX(hz / 100, 1);
/* Reschedule the task. */
callout_reset(&rs->rs_c2h_report, rs->rs_c2h_timeout,
r92c_handle_c2h_report, sc);
}
void
r92c_handle_c2h_report(void *arg)
{
struct rtwn_softc *sc = arg;
rtwn_cmd_sleepable(sc, NULL, 0, r92c_handle_c2h_task);
}
#endif /* RTWN_WITHOUT_UCODE */
@@ -0,0 +1,148 @@
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $
* $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/r92c_fw_cmd.h 307529 2016-10-17 20:38:24Z avos $
*/
#ifndef R92C_FW_CMD_H
#define R92C_FW_CMD_H
/*
* Host to firmware commands.
*/
struct r92c_fw_cmd {
uint8_t id;
#define R92C_CMD_SET_PWRMODE 1
#define R92C_CMD_JOINBSS_RPT 2
#define R92C_CMD_RSVD_PAGE 3
#define R92C_CMD_RSSI_SETTING 5
#define R92C_CMD_MACID_CONFIG 6
#define R92C_CMD_FLAG_EXT 0x80
uint8_t msg[5];
} __packed __attribute__((aligned(4)));
/* Structure for R92C_CMD_JOINBSS_RPT. */
struct r92c_fw_cmd_joinbss_rpt {
uint8_t mstatus;
#define R92C_MSTATUS_DISASSOC 0x00
#define R92C_MSTATUS_ASSOC 0x01
} __packed;
/* Structure for R92C_CMD_SET_PWRMODE. */
struct r92c_fw_cmd_pwrmode {
uint8_t mode;
#define R92C_PWRMODE_CAM 0
#define R92C_PWRMODE_MIN 1
#define R92C_PWRMODE_MAX 2
#define R92C_PWRMODE_DTIM 3
#define R92C_PWRMODE_UAPSD_WMM 5
#define R92C_PWRMODE_UAPSD 6
#define R92C_PWRMODE_IBSS 7
uint8_t smart_ps;
/* XXX undocumented */
#define R92C_PWRMODE_SMARTPS_NULLDATA 2
uint8_t bcn_pass; /* unit: beacon interval */
} __packed;
/* Structure for R92C_CMD_RSVD_PAGE. */
struct r92c_fw_cmd_rsvdpage {
uint8_t probe_resp;
uint8_t ps_poll;
uint8_t null_data;
} __packed;
/* Structure for R92C_CMD_RSSI_SETTING. */
struct r92c_fw_cmd_rssi {
uint8_t macid;
uint8_t reserved;
uint8_t pwdb;
} __packed;
/* Structure for R92C_CMD_MACID_CONFIG. */
struct r92c_fw_cmd_macid_cfg {
uint32_t mask;
uint8_t macid;
#define R92C_CMD_MACID_VALID 0x80
} __packed;
/*
* C2H event structure.
*/
/* Bigger value is used to prevent buffer overrun. */
#define R92C_C2H_MSG_MAX_LEN 16
struct r92c_c2h_evt {
uint8_t evtb0;
#define R92C_C2H_EVTB0_ID_M 0x0f
#define R92C_C2H_EVTB0_ID_S 0
#define R92C_C2H_EVTB0_LEN_M 0xf0
#define R92C_C2H_EVTB0_LEN_S 4
uint8_t seq;
/* Followed by payload (see below). */
} __packed;
/*
* C2H event types.
*/
#define R92C_C2H_EVT_DEBUG 0
#define R92C_C2H_EVT_TX_REPORT 3
#define R92C_C2H_EVT_EXT_RA_RPT 6
/* Structure for R92C_C2H_EVT_TX_REPORT event. */
struct r92c_c2h_tx_rpt {
uint8_t rptb0;
#define R92C_RPTB0_RETRY_CNT_M 0x3f
#define R92C_RPTB0_RETRY_CNT_S 0
uint8_t rptb1; /* XXX junk */
#define R92C_RPTB1_RTS_RETRY_CNT_M 0x3f
#define R92C_RPTB1_RTS_RETRY_CNT_S 0
uint8_t queue_time_low;
uint8_t queue_time_high;
uint8_t rptb4;
#define R92C_RPTB4_MISSED_PKT_NUM_M 0x1f
#define R92C_RPTB4_MISSED_PKT_NUM_S 0
uint8_t rptb5;
#define R92C_RPTB5_MACID_M 0x1f
#define R92C_RPTB5_MACID_S 0
#define R92C_RPTB5_DES1_FRAGSSN_M 0xe0
#define R92C_RPTB5_DES1_FRAGSSN_S 5
uint8_t rptb6;
#define R92C_RPTB6_RPT_PKT_NUM_M 0x1f
#define R92C_RPTB6_RPT_PKT_NUM_S 0
#define R92C_RPTB6_PKT_DROP 0x20
#define R92C_RPTB6_LIFE_EXPIRE 0x40
#define R92C_RPTB6_RETRY_OVER 0x80
uint8_t rptb7;
#define R92C_RPTB7_EDCA_M 0x0f
#define R92C_RPTB7_EDCA_S 0
#define R92C_RPTB7_BMC 0x20
#define R92C_RPTB7_PKT_OK 0x40
#define R92C_RPTB7_INT_CCX 0x80
} __packed;
#endif /* R92C_FW_CMD_H */
@@ -0,0 +1,343 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* 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: releng/12.0/sys/dev/rtwn/rtl8192c/r92c_init.c 312680 2017-01-24 02:35:38Z kevlo $");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/if_rtwn_debug.h>
#include <dev/rtwn/rtl8192c/r92c.h>
#include <dev/rtwn/rtl8192c/r92c_priv.h>
#include <dev/rtwn/rtl8192c/r92c_reg.h>
#include <dev/rtwn/rtl8192c/r92c_var.h>
int
r92c_check_condition(struct rtwn_softc *sc, const uint8_t cond[])
{
struct r92c_softc *rs = sc->sc_priv;
uint8_t mask;
int i;
if (cond[0] == 0)
return (1);
RTWN_DPRINTF(sc, RTWN_DEBUG_RESET,
"%s: condition byte 0: %02X; chip %02X, board %02X\n",
__func__, cond[0], rs->chip, rs->board_type);
if (!(rs->chip & R92C_CHIP_92C)) {
if (rs->board_type == R92C_BOARD_TYPE_HIGHPA)
mask = R92C_COND_RTL8188RU;
else if (rs->board_type == R92C_BOARD_TYPE_MINICARD)
mask = R92C_COND_RTL8188CE;
else
mask = R92C_COND_RTL8188CU;
} else {
if (rs->board_type == R92C_BOARD_TYPE_MINICARD)
mask = R92C_COND_RTL8192CE;
else
mask = R92C_COND_RTL8192CU;
}
for (i = 0; i < RTWN_MAX_CONDITIONS && cond[i] != 0; i++)
if ((cond[i] & mask) == mask)
return (1);
return (0);
}
int
r92c_llt_init(struct rtwn_softc *sc)
{
int i, error;
/* Reserve pages [0; page_count]. */
for (i = 0; i < sc->page_count; i++) {
if ((error = r92c_llt_write(sc, i, i + 1)) != 0)
return (error);
}
/* NB: 0xff indicates end-of-list. */
if ((error = r92c_llt_write(sc, i, 0xff)) != 0)
return (error);
/*
* Use pages [page_count + 1; pktbuf_count - 1]
* as ring buffer.
*/
for (++i; i < sc->pktbuf_count - 1; i++) {
if ((error = r92c_llt_write(sc, i, i + 1)) != 0)
return (error);
}
/* Make the last page point to the beginning of the ring buffer. */
error = r92c_llt_write(sc, i, sc->page_count + 1);
return (error);
}
int
r92c_set_page_size(struct rtwn_softc *sc)
{
return (rtwn_write_1(sc, R92C_PBP, SM(R92C_PBP_PSRX, R92C_PBP_128) |
SM(R92C_PBP_PSTX, R92C_PBP_128)) == 0);
}
void
r92c_init_bb_common(struct rtwn_softc *sc)
{
struct r92c_softc *rs = sc->sc_priv;
int i, j;
/* Write BB initialization values. */
for (i = 0; i < sc->bb_size; i++) {
const struct rtwn_bb_prog *bb_prog = &sc->bb_prog[i];
while (!rtwn_check_condition(sc, bb_prog->cond)) {
KASSERT(bb_prog->next != NULL,
("%s: wrong condition value (i %d)\n",
__func__, i));
bb_prog = bb_prog->next;
}
for (j = 0; j < bb_prog->count; j++) {
RTWN_DPRINTF(sc, RTWN_DEBUG_RESET,
"BB: reg 0x%03x, val 0x%08x\n",
bb_prog->reg[j], bb_prog->val[j]);
rtwn_bb_write(sc, bb_prog->reg[j], bb_prog->val[j]);
rtwn_delay(sc, 1);
}
}
if (rs->chip & R92C_CHIP_92C_1T2R) {
/* 8192C 1T only configuration. */
rtwn_bb_setbits(sc, R92C_FPGA0_TXINFO, 0x03, 0x02);
rtwn_bb_setbits(sc, R92C_FPGA1_TXINFO, 0x300033, 0x200022);
rtwn_bb_setbits(sc, R92C_CCK0_AFESETTING, 0xff000000,
0x45000000);
rtwn_bb_setbits(sc, R92C_OFDM0_TRXPATHENA, 0xff, 0x23);
rtwn_bb_setbits(sc, R92C_OFDM0_AGCPARAM1, 0x30, 0x10);
rtwn_bb_setbits(sc, 0xe74, 0x0c000000, 0x08000000);
rtwn_bb_setbits(sc, 0xe78, 0x0c000000, 0x08000000);
rtwn_bb_setbits(sc, 0xe7c, 0x0c000000, 0x08000000);
rtwn_bb_setbits(sc, 0xe80, 0x0c000000, 0x08000000);
rtwn_bb_setbits(sc, 0xe88, 0x0c000000, 0x08000000);
}
/* Write AGC values. */
for (i = 0; i < sc->agc_size; i++) {
const struct rtwn_agc_prog *agc_prog = &sc->agc_prog[i];
while (!rtwn_check_condition(sc, agc_prog->cond)) {
KASSERT(agc_prog->next != NULL,
("%s: wrong condition value (2) (i %d)\n",
__func__, i));
agc_prog = agc_prog->next;
}
for (j = 0; j < agc_prog->count; j++) {
RTWN_DPRINTF(sc, RTWN_DEBUG_RESET,
"AGC: val 0x%08x\n", agc_prog->val[j]);
rtwn_bb_write(sc, R92C_OFDM0_AGCRSSITABLE,
agc_prog->val[j]);
rtwn_delay(sc, 1);
}
}
if (rtwn_bb_read(sc, R92C_HSSI_PARAM2(0)) & R92C_HSSI_PARAM2_CCK_HIPWR)
sc->sc_flags |= RTWN_FLAG_CCK_HIPWR;
}
int
r92c_init_rf_chain(struct rtwn_softc *sc,
const struct rtwn_rf_prog *rf_prog, int chain)
{
int i, j;
RTWN_DPRINTF(sc, RTWN_DEBUG_RESET, "%s: chain %d\n",
__func__, chain);
for (i = 0; rf_prog[i].reg != NULL; i++) {
const struct rtwn_rf_prog *prog = &rf_prog[i];
while (!rtwn_check_condition(sc, prog->cond)) {
KASSERT(prog->next != NULL,
("%s: wrong condition value (i %d)\n",
__func__, i));
prog = prog->next;
}
for (j = 0; j < prog->count; j++) {
RTWN_DPRINTF(sc, RTWN_DEBUG_RESET,
"RF: reg 0x%02x, val 0x%05x\n",
prog->reg[j], prog->val[j]);
/*
* These are fake RF registers offsets that
* indicate a delay is required.
*/
/* NB: we are using 'value' to store required delay. */
if (prog->reg[j] > 0xf8) {
rtwn_delay(sc, prog->val[j]);
continue;
}
rtwn_rf_write(sc, chain, prog->reg[j], prog->val[j]);
rtwn_delay(sc, 1);
}
}
return (i);
}
void
r92c_init_rf(struct rtwn_softc *sc)
{
struct r92c_softc *rs = sc->sc_priv;
uint32_t reg, type;
int i, chain, idx, off;
for (chain = 0, i = 0; chain < sc->nrxchains; chain++, i++) {
/* Save RF_ENV control type. */
idx = chain / 2;
off = (chain % 2) * 16;
reg = rtwn_bb_read(sc, R92C_FPGA0_RFIFACESW(idx));
type = (reg >> off) & 0x10;
/* Set RF_ENV enable. */
rtwn_bb_setbits(sc, R92C_FPGA0_RFIFACEOE(chain),
0, 0x100000);
rtwn_delay(sc, 1);
/* Set RF_ENV output high. */
rtwn_bb_setbits(sc, R92C_FPGA0_RFIFACEOE(chain),
0, 0x10);
rtwn_delay(sc, 1);
/* Set address and data lengths of RF registers. */
rtwn_bb_setbits(sc, R92C_HSSI_PARAM2(chain),
R92C_HSSI_PARAM2_ADDR_LENGTH, 0);
rtwn_delay(sc, 1);
rtwn_bb_setbits(sc, R92C_HSSI_PARAM2(chain),
R92C_HSSI_PARAM2_DATA_LENGTH, 0);
rtwn_delay(sc, 1);
/* Write RF initialization values for this chain. */
i += r92c_init_rf_chain(sc, &sc->rf_prog[i], chain);
/* Restore RF_ENV control type. */
rtwn_bb_setbits(sc, R92C_FPGA0_RFIFACESW(idx),
0x10 << off, type << off);
/* Cache RF register CHNLBW. */
rs->rf_chnlbw[chain] = rtwn_rf_read(sc, chain,
R92C_RF_CHNLBW);
}
if ((rs->chip & (R92C_CHIP_UMC_A_CUT | R92C_CHIP_92C)) ==
R92C_CHIP_UMC_A_CUT) {
rtwn_rf_write(sc, 0, R92C_RF_RX_G1, 0x30255);
rtwn_rf_write(sc, 0, R92C_RF_RX_G2, 0x50a00);
}
/* Turn CCK and OFDM blocks on. */
rtwn_bb_setbits(sc, R92C_FPGA0_RFMOD, 0, R92C_RFMOD_CCK_EN);
rtwn_bb_setbits(sc, R92C_FPGA0_RFMOD, 0, R92C_RFMOD_OFDM_EN);
}
void
r92c_init_edca(struct rtwn_softc *sc)
{
/* SIFS */
rtwn_write_2(sc, R92C_SPEC_SIFS, 0x100a);
rtwn_write_2(sc, R92C_MAC_SPEC_SIFS, 0x100a);
rtwn_write_2(sc, R92C_SIFS_CCK, 0x100a);
rtwn_write_2(sc, R92C_SIFS_OFDM, 0x100a);
/* TXOP */
rtwn_write_4(sc, R92C_EDCA_BE_PARAM, 0x005ea42b);
rtwn_write_4(sc, R92C_EDCA_BK_PARAM, 0x0000a44f);
rtwn_write_4(sc, R92C_EDCA_VI_PARAM, 0x005ea324);
rtwn_write_4(sc, R92C_EDCA_VO_PARAM, 0x002fa226);
}
void
r92c_init_ampdu(struct rtwn_softc *sc)
{
/* Setup AMPDU aggregation. */
rtwn_write_4(sc, R92C_AGGLEN_LMT, 0x99997631); /* MCS7~0 */
rtwn_write_1(sc, R92C_AGGR_BREAK_TIME, 0x16);
rtwn_write_2(sc, R92C_MAX_AGGR_NUM, 0x0708);
}
void
r92c_init_antsel(struct rtwn_softc *sc)
{
uint32_t reg;
if (sc->ntxchains != 1 || sc->nrxchains != 1)
return;
rtwn_setbits_1(sc, R92C_LEDCFG2, 0, 0x80);
rtwn_bb_setbits(sc, R92C_FPGA0_RFPARAM(0), 0, 0x2000);
reg = rtwn_bb_read(sc, R92C_FPGA0_RFIFACEOE(0));
sc->sc_ant = MS(reg, R92C_FPGA0_RFIFACEOE0_ANT); /* XXX */
}
void
r92c_pa_bias_init(struct rtwn_softc *sc)
{
struct r92c_softc *rs = sc->sc_priv;
int i;
for (i = 0; i < sc->nrxchains; i++) {
if (rs->pa_setting & (1 << i))
continue;
r92c_rf_write(sc, i, R92C_RF_IPA, 0x0f406);
r92c_rf_write(sc, i, R92C_RF_IPA, 0x4f406);
r92c_rf_write(sc, i, R92C_RF_IPA, 0x8f406);
r92c_rf_write(sc, i, R92C_RF_IPA, 0xcf406);
}
if (!(rs->pa_setting & 0x10))
rtwn_setbits_1(sc, 0x16, 0xf0, 0x90);
}
@@ -0,0 +1,73 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* 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: releng/12.0/sys/dev/rtwn/rtl8192c/r92c_llt.c 312680 2017-01-24 02:35:38Z kevlo $");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/rtl8192c/r92c.h>
#include <dev/rtwn/rtl8192c/r92c_reg.h>
#include <dev/rtwn/rtl8192c/r92c_var.h>
int
r92c_llt_write(struct rtwn_softc *sc, uint32_t addr, uint32_t data)
{
int ntries, error;
error = rtwn_write_4(sc, R92C_LLT_INIT,
SM(R92C_LLT_INIT_OP, R92C_LLT_INIT_OP_WRITE) |
SM(R92C_LLT_INIT_ADDR, addr) |
SM(R92C_LLT_INIT_DATA, data));
if (error != 0)
return (error);
/* Wait for write operation to complete. */
for (ntries = 0; ntries < 20; ntries++) {
if (MS(rtwn_read_4(sc, R92C_LLT_INIT), R92C_LLT_INIT_OP) ==
R92C_LLT_INIT_OP_NO_ACTIVE)
return (0);
rtwn_delay(sc, 10);
}
return (ETIMEDOUT);
}
@@ -0,0 +1,408 @@
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $
* $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/r92c_priv.h 322988 2017-08-28 22:14:16Z avos $
*/
#ifndef R92C_PRIV_H
#define R92C_PRIV_H
#include <dev/rtwn/rtl8192c/r92c_rom_defs.h>
/*
* Parsed Tx power (diff) values.
*/
struct rtwn_r92c_txpwr {
uint8_t cck_tx_pwr[R92C_MAX_CHAINS][R92C_GROUP_2G];
uint8_t ht40_1s_tx_pwr[R92C_MAX_CHAINS][R92C_GROUP_2G];
int8_t ht40_2s_tx_pwr_diff[R92C_MAX_CHAINS][R92C_GROUP_2G];
int8_t ht20_tx_pwr_diff[R92C_MAX_CHAINS][R92C_GROUP_2G];
int8_t ofdm_tx_pwr_diff[R92C_MAX_CHAINS][R92C_GROUP_2G];
int8_t ht40_max_pwr[R92C_MAX_CHAINS][R92C_GROUP_2G];
int8_t ht20_max_pwr[R92C_MAX_CHAINS][R92C_GROUP_2G];
};
/*
* Baseband initialization values (shared parts).
*/
#define R92C_COND_RTL8188CE 0x01
#define R92C_COND_RTL8188CU 0x02
#define R92C_COND_RTL8188RU 0x04
#define R92C_COND_RTL8192CE 0x08
#define R92C_COND_RTL8192CU 0x10
/* Shortcut. */
#define R92C_COND_RTL8192C (R92C_COND_RTL8192CE | R92C_COND_RTL8192CU)
static const uint16_t rtl8192c_bb_regs3[] = {
0xd04
}, rtl8192c_bb_regs4[] = {
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
}, rtl8192c_bb_regs5[] = {
0xe60, 0xe68, 0xe6c, 0xe70, 0xe74, 0xe78, 0xe7c, 0xe80, 0xe84,
0xe88, 0xe8c, 0xed0, 0xed4, 0xed8, 0xedc, 0xee0, 0xeec, 0xf14,
0xf4c, 0xf00
};
static const uint32_t rtl8192c_bb_vals3_88cu_88ru[] = {
0x00020401
}, rtl8192c_bb_vals3_92ce_92cu[] = {
0x00020403
}, rtl8192c_bb_vals4[] = {
0x0000907f, 0x20010201, 0xa0633333, 0x3333bc43, 0x7a8f5b6b,
0xcc979975, 0x00000000, 0x80608000, 0x00000000, 0x00027293,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x6437140a,
0x00000000, 0x00000000, 0x30032064, 0x4653de68, 0x04518a3c,
0x00002101, 0x2a201c16, 0x1812362e, 0x322c2220, 0x000e3c24,
0x2a2a2a2a, 0x2a2a2a2a, 0x03902a2a, 0x2a2a2a2a, 0x2a2a2a2a,
0x2a2a2a2a, 0x2a2a2a2a, 0x00000000, 0x1000dc1f, 0x10008c1f,
0x02140102, 0x681604c2, 0x01007c00, 0x01004800, 0xfb000000,
0x000028d1, 0x1000dc1f, 0x10008c1f, 0x02140102, 0x28160d05
},rtl8192c_bb_vals5_92ce_92cu[] = {
0x00000010, 0x001b25a4, 0x63db25a4, 0x63db25a4, 0x0c1b25a4,
0x0c1b25a4, 0x0c1b25a4, 0x0c1b25a4, 0x63db25a4, 0x0c1b25a4,
0x63db25a4, 0x63db25a4, 0x63db25a4, 0x63db25a4, 0x001b25a4,
0x001b25a4, 0x6fdb25a4, 0x00000003, 0x00000000, 0x00000300
};
/*
* RTL8192CU and RTL8192CE-VAU.
*/
static const uint32_t rtl8192ce_agc_vals[] = {
0x7b000001, 0x7b010001, 0x7b020001, 0x7b030001, 0x7b040001,
0x7b050001, 0x7a060001, 0x79070001, 0x78080001, 0x77090001,
0x760a0001, 0x750b0001, 0x740c0001, 0x730d0001, 0x720e0001,
0x710f0001, 0x70100001, 0x6f110001, 0x6e120001, 0x6d130001,
0x6c140001, 0x6b150001, 0x6a160001, 0x69170001, 0x68180001,
0x67190001, 0x661a0001, 0x651b0001, 0x641c0001, 0x631d0001,
0x621e0001, 0x611f0001, 0x60200001, 0x49210001, 0x48220001,
0x47230001, 0x46240001, 0x45250001, 0x44260001, 0x43270001,
0x42280001, 0x41290001, 0x402a0001, 0x262b0001, 0x252c0001,
0x242d0001, 0x232e0001, 0x222f0001, 0x21300001, 0x20310001,
0x06320001, 0x05330001, 0x04340001, 0x03350001, 0x02360001,
0x01370001, 0x00380001, 0x00390001, 0x003a0001, 0x003b0001,
0x003c0001, 0x003d0001, 0x003e0001, 0x003f0001, 0x7b400001,
0x7b410001, 0x7b420001, 0x7b430001, 0x7b440001, 0x7b450001,
0x7a460001, 0x79470001, 0x78480001, 0x77490001, 0x764a0001,
0x754b0001, 0x744c0001, 0x734d0001, 0x724e0001, 0x714f0001,
0x70500001, 0x6f510001, 0x6e520001, 0x6d530001, 0x6c540001,
0x6b550001, 0x6a560001, 0x69570001, 0x68580001, 0x67590001,
0x665a0001, 0x655b0001, 0x645c0001, 0x635d0001, 0x625e0001,
0x615f0001, 0x60600001, 0x49610001, 0x48620001, 0x47630001,
0x46640001, 0x45650001, 0x44660001, 0x43670001, 0x42680001,
0x41690001, 0x406a0001, 0x266b0001, 0x256c0001, 0x246d0001,
0x236e0001, 0x226f0001, 0x21700001, 0x20710001, 0x06720001,
0x05730001, 0x04740001, 0x03750001, 0x02760001, 0x01770001,
0x00780001, 0x00790001, 0x007a0001, 0x007b0001, 0x007c0001,
0x007d0001, 0x007e0001, 0x007f0001, 0x3800001e, 0x3801001e,
0x3802001e, 0x3803001e, 0x3804001e, 0x3805001e, 0x3806001e,
0x3807001e, 0x3808001e, 0x3c09001e, 0x3e0a001e, 0x400b001e,
0x440c001e, 0x480d001e, 0x4c0e001e, 0x500f001e, 0x5210001e,
0x5611001e, 0x5a12001e, 0x5e13001e, 0x6014001e, 0x6015001e,
0x6016001e, 0x6217001e, 0x6218001e, 0x6219001e, 0x621a001e,
0x621b001e, 0x621c001e, 0x621d001e, 0x621e001e, 0x621f001e
};
static const struct rtwn_agc_prog rtl8192ce_agc[] = {
{
nitems(rtl8192ce_agc_vals),
rtl8192ce_agc_vals,
{ 0 },
NULL
}
};
/*
* RF initialization values.
*/
static const uint8_t rtl8192c_rf0_regs0[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
0x0f, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21
}, rtl8192c_rf0_regs1[] = {
0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28
}, rtl8192c_rf0_regs2[] = {
0x29, 0x2a, 0x2b, 0x2a, 0x2b, 0x2a, 0x2b, 0x2b, 0x2c, 0x2a, 0x2b,
0x2b, 0x2c, 0x2a, 0x2b, 0x2b, 0x2c, 0x2a, 0x2b, 0x2b, 0x2c, 0x2a,
0x2b, 0x2b, 0x2c, 0x2a, 0x2b, 0x2b, 0x2c, 0x2a, 0x2b, 0x2b, 0x2c,
0x2a, 0x2b, 0x2b, 0x2c, 0x2a, 0x2b, 0x2b, 0x2c, 0x2a, 0x2b, 0x2b,
0x2c, 0x2a, 0x2b, 0x2b, 0x2c, 0x2a, 0x2b, 0x2b, 0x2c, 0x2a, 0x2b,
0x2b, 0x2c, 0x2a, 0x2b, 0x2b, 0x2c, 0x2a, 0x10, 0x11, 0x10, 0x11,
0x10, 0x11, 0x10, 0x11, 0x10, 0x11, 0x10, 0x11, 0x10, 0x11
}, rtl8192c_rf0_regs3[] = {
0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13,
0x13, 0x13, 0x13, 0x13
}, rtl8192c_rf0_regs4[] = {
0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15
}, rtl8192c_rf0_regs5[] = {
0x16, 0x16, 0x16, 0x16, 0x00, 0x18, 0xfe, 0xfe, 0x1f, 0xfe, 0xfe,
0x1e, 0x1f, 0x00
};
static const uint32_t rtl8192c_rf0_vals0_88ce_88cu_92ce[] = {
0x30159, 0x31284, 0x98000, 0x18c63, 0x210e7, 0x2044f, 0x1adb1,
0x54867, 0x8992e, 0x0e52c, 0x39ce7, 0x00451, 0x00000, 0x10255,
0x60a00, 0xfc378, 0xa1250, 0x4445f, 0x80001, 0x0b614, 0x6c000
}, rtl8192c_rf0_vals0_88ru[] = {
0x30159, 0x31284, 0x98000, 0x18c63, 0x210e7, 0x2044f, 0x1adb0,
0x54867, 0x8992e, 0x0e529, 0x39ce7, 0x00451, 0x00000, 0x00255,
0x60a00, 0xfc378, 0xa1250, 0x4445f, 0x80001, 0x0b614, 0x6c000
}, rtl8192c_rf0_vals1_88ru[] = {
0x0083c, 0x01558, 0x00060, 0x00483, 0x4f000, 0xec7d9, 0x977c0
}, rtl8192c_rf0_vals1_88ce[] = {
0x00000, 0x01558, 0x00060, 0x00483, 0x4f200, 0xec7d9, 0x577c0
}, rtl8192c_rf0_vals1_88cu_92ce[] = {
0x00000, 0x01558, 0x00060, 0x00483, 0x4f000, 0xec7d9, 0x577c0
}, rtl8192c_rf0_vals2[] = {
0x04783, 0x00001, 0x21334, 0x00000, 0x00054, 0x00001, 0x00808,
0x53333, 0x0000c, 0x00002, 0x00808, 0x5b333, 0x0000d, 0x00003,
0x00808, 0x63333, 0x0000d, 0x00004, 0x00808, 0x6b333, 0x0000d,
0x00005, 0x00808, 0x73333, 0x0000d, 0x00006, 0x00709, 0x5b333,
0x0000d, 0x00007, 0x00709, 0x63333, 0x0000d, 0x00008, 0x0060a,
0x4b333, 0x0000d, 0x00009, 0x0060a, 0x53333, 0x0000d, 0x0000a,
0x0060a, 0x5b333, 0x0000d, 0x0000b, 0x0060a, 0x63333, 0x0000d,
0x0000c, 0x0060a, 0x6b333, 0x0000d, 0x0000d, 0x0060a, 0x73333,
0x0000d, 0x0000e, 0x0050b, 0x66666, 0x0001a, 0xe0000, 0x4000f,
0xe31fc, 0x6000f, 0xff9f8, 0x2000f, 0x203f9, 0x3000f, 0xff500,
0x00000, 0x00000, 0x8000f, 0x3f100, 0x9000f, 0x23100
}, rtl8192c_rf0_vals3_88ru[] = {
0xd8000, 0x90000, 0x51000, 0x12000, 0x28fb4, 0x24fa8, 0x207a4,
0x1c798, 0x183a4, 0x14398, 0x101a4, 0x0c198, 0x080a4, 0x04098,
0x00014
}, rtl8192c_rf0_vals3_92ce[] = {
0x32000, 0x71000, 0xb0000, 0xfc000, 0x287af, 0x244b7, 0x204ab,
0x1c49f, 0x18493, 0x14297, 0x10295, 0x0c298, 0x0819c, 0x040a8,
0x0001c
}, rtl8192c_rf0_vals3_88cu_88ce[] = {
0x32000, 0x71000, 0xb0000, 0xfc000, 0x287b3, 0x244b7, 0x204ab,
0x1c49f, 0x18493, 0x1429b, 0x10299, 0x0c29c, 0x081a0, 0x040ac,
0x00020
}, rtl8192c_rf0_vals4_92ce_88ce[] = {
0x1944c, 0x59444, 0x9944c, 0xd9444, 0x0f424, 0x4f424, 0x8f424,
0xcf424
}, rtl8192c_rf0_vals4_88cu_88ru[] = {
0x1944c, 0x59444, 0x9944c, 0xd9444, 0x0f405, 0x4f405, 0x8f405,
0xcf405
}, rtl8192c_rf0_vals5[] = {
0xe0330, 0xa0330, 0x60330, 0x20330, 0x10159, 0x0f401, 0x0c350,
0x0c350, 0x80003, 0x0c350, 0x0c350, 0x44457, 0x80000, 0x30159
};
static const struct rtwn_rf_prog rtl8192c_rf[] = {
/* RF chain 0 */
/* RTL8188RU. */
{
nitems(rtl8192c_rf0_regs0),
rtl8192c_rf0_regs0,
rtl8192c_rf0_vals0_88ru,
{ R92C_COND_RTL8188RU },
/* Others. */
&(const struct rtwn_rf_prog){
nitems(rtl8192c_rf0_regs0),
rtl8192c_rf0_regs0,
rtl8192c_rf0_vals0_88ce_88cu_92ce,
{ 0 },
NULL
}
},
/* RTL8188RU. */
{
nitems(rtl8192c_rf0_regs1),
rtl8192c_rf0_regs1,
rtl8192c_rf0_vals1_88ru,
{ R92C_COND_RTL8188RU },
/* RTL8188CE. */
&(const struct rtwn_rf_prog){
nitems(rtl8192c_rf0_regs1),
rtl8192c_rf0_regs1,
rtl8192c_rf0_vals1_88ce,
{ R92C_COND_RTL8188CE },
/* Others. */
&(const struct rtwn_rf_prog){
nitems(rtl8192c_rf0_regs1),
rtl8192c_rf0_regs1,
rtl8192c_rf0_vals1_88cu_92ce,
{ 0 },
NULL
}
}
},
{
nitems(rtl8192c_rf0_regs2),
rtl8192c_rf0_regs2,
rtl8192c_rf0_vals2,
{ 0 },
NULL
},
/* RTL8188RU. */
{
nitems(rtl8192c_rf0_regs3),
rtl8192c_rf0_regs3,
rtl8192c_rf0_vals3_88ru,
{ R92C_COND_RTL8188RU },
/* RTL8192C. */
&(const struct rtwn_rf_prog){
nitems(rtl8192c_rf0_regs3),
rtl8192c_rf0_regs3,
rtl8192c_rf0_vals3_92ce,
{ R92C_COND_RTL8192C },
/* Others. */
&(struct rtwn_rf_prog){
nitems(rtl8192c_rf0_regs3),
rtl8192c_rf0_regs3,
rtl8192c_rf0_vals3_88cu_88ce,
{ 0 },
NULL
}
}
},
/* RTL8188CE / RTL8192C. */
{
nitems(rtl8192c_rf0_regs4),
rtl8192c_rf0_regs4,
rtl8192c_rf0_vals4_92ce_88ce,
{ R92C_COND_RTL8188CE | R92C_COND_RTL8192C },
/* Others. */
&(const struct rtwn_rf_prog){
nitems(rtl8192c_rf0_regs4),
rtl8192c_rf0_regs4,
rtl8192c_rf0_vals4_88cu_88ru,
{ 0 },
NULL
}
},
{
nitems(rtl8192c_rf0_regs5),
rtl8192c_rf0_regs5,
rtl8192c_rf0_vals5,
{ 0 },
NULL
},
{ 0, NULL, NULL, { 0 }, NULL },
/* RF chain 1 (RTL8192C). */
{
12, /* 0x00 - 0x0f */
rtl8192c_rf0_regs0,
rtl8192c_rf0_vals0_88ce_88cu_92ce,
{ 0 },
NULL
},
{
nitems(rtl8192c_rf0_regs3), /* 0x12 - 0x13 */
rtl8192c_rf0_regs3,
rtl8192c_rf0_vals3_92ce,
{ 0 },
NULL
},
{
nitems(rtl8192c_rf0_regs4), /* 0x14 - 0x15 */
rtl8192c_rf0_regs4,
rtl8192c_rf0_vals4_92ce_88ce,
{ 0 },
NULL
},
{
4, /* 0x16 */
rtl8192c_rf0_regs5,
rtl8192c_rf0_vals5,
{ 0 },
NULL
},
{ 0, NULL, NULL, { 0 }, NULL }
};
struct rtwn_r92c_txagc {
uint8_t pwr[R92C_GROUP_2G][28]; /* RTWN_RIDX_HT_MCS(15) + 1 */
};
/*
* Per RF chain/group/rate Tx gain values.
*/
static const struct rtwn_r92c_txagc rtl8192cu_txagc[] = {
{ { /* Chain 0. */
{ /* Group 0. */
0x00, 0x00, 0x00, 0x00, /* CCK1~11. */
0x0c, 0x0c, 0x0c, 0x0a, 0x08, 0x06, 0x04, 0x02, /* OFDM6~54. */
0x0e, 0x0d, 0x0c, 0x0a, 0x08, 0x06, 0x04, 0x02, /* MCS0~7. */
0x0e, 0x0d, 0x0c, 0x0a, 0x08, 0x06, 0x04, 0x02 /* MCS8~15. */
},
{ /* Group 1. */
0x00, 0x00, 0x00, 0x00, /* CCK1~11. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* OFDM6~54. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MCS0~7. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* MCS8~15. */
},
{ /* Group 2. */
0x00, 0x00, 0x00, 0x00, /* CCK1~11. */
0x04, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x00, /* OFDM6~54. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MCS0~7. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* MCS8~15. */
}
} },
{ { /* Chain 1. */
{ /* Group 0. */
0x00, 0x00, 0x00, 0x00, /* CCK1~11. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* OFDM6~54. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MCS0~7. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* MCS8~15. */
},
{ /* Group 1. */
0x00, 0x00, 0x00, 0x00, /* CCK1~11. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* OFDM6~54. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MCS0~7. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* MCS8~15. */
},
{ /* Group 2. */
0x00, 0x00, 0x00, 0x00, /* CCK1~11. */
0x04, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x00, /* OFDM6~54. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MCS0~7. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* MCS8~15. */
}
} }
};
static const struct rtwn_r92c_txagc rtl8188ru_txagc[] = {
{ { /* Chain 0. */
{ /* Group 0. */
0x00, 0x00, 0x00, 0x00, /* CCK1~11. */
0x08, 0x08, 0x08, 0x06, 0x06, 0x04, 0x04, 0x00, /* OFDM6~54. */
0x08, 0x06, 0x06, 0x04, 0x04, 0x02, 0x02, 0x00, /* MCS0~7. */
0x08, 0x06, 0x06, 0x04, 0x04, 0x02, 0x02, 0x00 /* MCS8~15. */
},
{ /* Group 1. */
0x00, 0x00, 0x00, 0x00, /* CCK1~11. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* OFDM6~54. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MCS0~7. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* MCS8~15. */
},
{ /* Group 2. */
0x00, 0x00, 0x00, 0x00, /* CCK1~11. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* OFDM6~54. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MCS0~7. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* MCS8~15. */
}
} }
};
#endif /* R92C_PRIV_H */
@@ -0,0 +1,879 @@
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2015 Stefan Sperling <stsp@openbsd.org>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $
* $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/r92c_reg.h 312680 2017-01-24 02:35:38Z kevlo $
*/
#ifndef R92C_REG_H
#define R92C_REG_H
/*
* MAC registers.
*/
/* System Configuration. */
#define R92C_SYS_ISO_CTRL 0x000
#define R92C_SYS_FUNC_EN 0x002
#define R92C_APS_FSMCO 0x004
#define R92C_SYS_CLKR 0x008
#define R92C_AFE_MISC 0x010
#define R92C_SPS0_CTRL 0x011
#define R92C_SPS_OCP_CFG 0x018
#define R92C_RSV_CTRL 0x01c
#define R92C_RF_CTRL 0x01f
#define R92C_LDOA15_CTRL 0x020
#define R92C_LDOV12D_CTRL 0x021
#define R92C_LDOHCI12_CTRL 0x022
#define R92C_LPLDO_CTRL 0x023
#define R92C_AFE_XTAL_CTRL 0x024
#define R92C_AFE_PLL_CTRL 0x028
#define R92C_APE_PLL_CTRL_EXT 0x02c
#define R92C_MAC_PHY_CTRL R92C_APE_PLL_CTRL_EXT
#define R92C_EFUSE_CTRL 0x030
#define R92C_EFUSE_TEST 0x034
#define R92C_PWR_DATA 0x038
#define R92C_CAL_TIMER 0x03c
#define R92C_ACLK_MON 0x03e
#define R92C_GPIO_MUXCFG 0x040
#define R92C_GPIO_IO_SEL 0x042
#define R92C_MAC_PINMUX_CFG 0x043
#define R92C_GPIO_PIN_CTRL 0x044
#define R92C_GPIO_IN 0x044
#define R92C_GPIO_OUT 0x045
#define R92C_GPIO_IOSEL 0x046
#define R92C_GPIO_MOD 0x047
#define R92C_GPIO_INTM 0x048
#define R92C_LEDCFG0 0x04c
#define R92C_LEDCFG1 0x04d
#define R92C_LEDCFG2 0x04e
#define R92C_LEDCFG3 0x04f
#define R92C_FSIMR 0x050
#define R92C_FSISR 0x054
#define R92C_HSIMR 0x058
#define R92C_HSISR 0x05c
#define R92C_MULTI_FUNC_CTRL 0x068
#define R92C_LDO_SWR_CTRL 0x07c
#define R92C_MCUFWDL 0x080
#define R92C_HMEBOX_EXT(idx) (0x088 + (idx) * 2)
#define R92C_EFUSE_ACCESS 0x0cf
#define R92C_BIST_SCAN 0x0d0
#define R92C_BIST_RPT 0x0d4
#define R92C_BIST_ROM_RPT 0x0d8
#define R92C_HPON_FSM 0x0ec
#define R92C_SYS_CFG 0x0f0
#define R92C_TYPE_ID 0x0fc
/* MAC General Configuration. */
#define R92C_CR 0x100
#define R92C_MSR 0x102
#define R92C_PBP 0x104
#define R92C_TRXDMA_CTRL 0x10c
#define R92C_TRXFF_BNDY 0x114
#define R92C_TRXFF_STATUS 0x118
#define R92C_RXFF_PTR 0x11c
#define R92C_HIMR 0x120
#define R92C_HISR 0x124
#define R92C_HIMRE 0x128
#define R92C_HISRE 0x12c
#define R92C_CPWM 0x12f
#define R92C_FWIMR 0x130
#define R92C_FWISR 0x134
#define R92C_PKTBUF_DBG_CTRL 0x140
#define R92C_PKTBUF_DBG_DATA_L 0x144
#define R92C_PKTBUF_DBG_DATA_H 0x148
#define R92C_TC0_CTRL(i) (0x150 + (i) * 4)
#define R92C_TCUNIT_BASE 0x164
#define R92C_MBIST_START 0x174
#define R92C_MBIST_DONE 0x178
#define R92C_MBIST_FAIL 0x17c
#define R92C_C2H_EVT_MSG 0x1a0
#define R92C_C2H_EVT_CLEAR 0x1af
#define R92C_C2H_EVT_MSG_TEST 0x1b8
#define R92C_MCUTST_1 0x1c0
#define R92C_FMETHR 0x1c8
#define R92C_HMETFR 0x1cc
#define R92C_HMEBOX(idx) (0x1d0 + (idx) * 4)
#define R92C_LLT_INIT 0x1e0
#define R92C_BB_ACCESS_CTRL 0x1e8
#define R92C_BB_ACCESS_DATA 0x1ec
/* Tx DMA Configuration. */
#define R92C_RQPN 0x200
#define R92C_FIFOPAGE 0x204
#define R92C_TDECTRL 0x208
#define R92C_TXDMA_OFFSET_CHK 0x20c
#define R92C_TXDMA_STATUS 0x210
#define R92C_RQPN_NPQ 0x214
#define R92C_AUTO_LLT 0x224
/* Rx DMA Configuration. */
#define R92C_RXDMA_AGG_PG_TH 0x280
#define R92C_RXPKT_NUM 0x284
#define R92C_RXDMA_STATUS 0x288
/* Protocol Configuration. */
#define R92C_VOQ_INFORMATION 0x400
#define R92C_VIQ_INFORMATION 0x404
#define R92C_BEQ_INFORMATION 0x408
#define R92C_BKQ_INFORMATION 0x40c
#define R92C_MGQ_INFORMATION 0x410
#define R92C_HGQ_INFORMATION 0x414
#define R92C_BCNQ_INFORMATION 0x418
#define R92C_CPU_MGQ_INFORMATION 0x41c
#define R92C_FWHW_TXQ_CTRL 0x420
#define R92C_HWSEQ_CTRL 0x423
#define R92C_TXPKTBUF_BCNQ_BDNY 0x424
#define R92C_TXPKTBUF_MGQ_BDNY 0x425
#define R92C_SPEC_SIFS 0x428
#define R92C_RL 0x42a
#define R92C_DARFRC 0x430
#define R92C_RARFRC 0x438
#define R92C_RRSR 0x440
#define R92C_ARFR(i) (0x444 + (i) * 4)
#define R92C_AGGLEN_LMT 0x458
#define R92C_AMPDU_MIN_SPACE 0x45c
#define R92C_TXPKTBUF_WMAC_LBK_BF_HD 0x45d
#define R92C_FAST_EDCA_CTRL 0x460
#define R92C_RD_RESP_PKT_TH 0x463
#define R92C_INIRTS_RATE_SEL 0x480
#define R92C_INIDATA_RATE_SEL(macid) (0x484 + (macid))
#define R92C_QUEUE_CTRL 0x4c6
#define R92C_MAX_AGGR_NUM 0x4ca
#define R92C_BAR_MODE_CTRL 0x4cc
/* EDCA Configuration. */
#define R92C_EDCA_VO_PARAM 0x500
#define R92C_EDCA_VI_PARAM 0x504
#define R92C_EDCA_BE_PARAM 0x508
#define R92C_EDCA_BK_PARAM 0x50c
#define R92C_BCNTCFG 0x510
#define R92C_PIFS 0x512
#define R92C_RDG_PIFS 0x513
#define R92C_SIFS_CCK 0x514
#define R92C_SIFS_OFDM 0x516
#define R92C_AGGR_BREAK_TIME 0x51a
#define R92C_SLOT 0x51b
#define R92C_TX_PTCL_CTRL 0x520
#define R92C_TXPAUSE 0x522
#define R92C_DIS_TXREQ_CLR 0x523
#define R92C_RD_CTRL 0x524
#define R92C_TBTT_PROHIBIT 0x540
#define R92C_RD_NAV_NXT 0x544
#define R92C_NAV_PROT_LEN 0x546
#define R92C_BCN_CTRL(id) ((id) + 0x550)
/* WARNING: R92C_USTIME_TSF == 0x55c, not 0x551 */
#define R92C_MBID_NUM 0x552
#define R92C_DUAL_TSF_RST 0x553
#define R92C_BCN_INTERVAL(id) (0x554 + (id) * 2)
#define R92C_DRVERLYINT 0x558
#define R92C_BCNDMATIM 0x559
#define R92C_ATIMWND 0x55a
#define R92C_USTIME_TSF 0x55c
#define R92C_BCN_MAX_ERR 0x55d
#define R92C_RXTSF_OFFSET_CCK 0x55e
#define R92C_RXTSF_OFFSET_OFDM 0x55f
#define R92C_TSFTR(i) (0x560 + (i) * 8)
#define R92C_PSTIMER 0x580
#define R92C_TIMER0 0x584
#define R92C_TIMER1 0x588
#define R92C_ACMHWCTRL 0x5c0
#define R92C_ACMRSTCTRL 0x5c1
#define R92C_ACMAVG 0x5c2
#define R92C_VO_ADMTIME 0x5c4
#define R92C_VI_ADMTIME 0x5c6
#define R92C_BE_ADMTIME 0x5c8
#define R92C_EDCA_RANDOM_GEN 0x5cc
#define R92C_SCH_TXCMD 0x5d0
/* WMAC Configuration. */
#define R92C_APSD_CTRL 0x600
#define R92C_BWOPMODE 0x603
#define R92C_TCR 0x604
#define R92C_RCR 0x608
#define R92C_RX_PKT_LIMIT 0x60c
#define R92C_RX_DRVINFO_SZ 0x60f
#define R92C_MACID0 0x610
#define R92C_BSSID0 0x618
#define R92C_MAR 0x620
#define R92C_USTIME_EDCA 0x638
#define R92C_MAC_SPEC_SIFS 0x63a
#define R92C_R2T_SIFS 0x63c
#define R92C_T2T_SIFS 0x63e
#define R92C_ACKTO 0x640
#define R92C_NAV_UPPER 0x652
#define R92C_WMAC_TRXPTCL_CTL 0x668
#define R92C_CAMCMD 0x670
#define R92C_CAMWRITE 0x674
#define R92C_CAMREAD 0x678
#define R92C_CAMDBG 0x67c
#define R92C_SECCFG 0x680
#define R92C_RXFLTMAP0 0x6a0
#define R92C_RXFLTMAP1 0x6a2
#define R92C_RXFLTMAP2 0x6a4
#define R92C_BCN_PSR_RPT 0x6a8
#define R92C_MACID1 0x700
#define R92C_BSSID1 0x708
#define R92C_MACID(id) ((id) == 0 ? R92C_MACID0 : R92C_MACID1)
#define R92C_BSSID(id) ((id) == 0 ? R92C_BSSID0 : R92C_BSSID1)
/* Bits for R92C_SYS_ISO_CTRL. */
#define R92C_SYS_ISO_CTRL_MD2PP 0x0001
#define R92C_SYS_ISO_CTRL_UA2USB 0x0002
#define R92C_SYS_ISO_CTRL_UD2CORE 0x0004
#define R92C_SYS_ISO_CTRL_PA2PCIE 0x0008
#define R92C_SYS_ISO_CTRL_PD2CORE 0x0010
#define R92C_SYS_ISO_CTRL_IP2MAC 0x0020
#define R92C_SYS_ISO_CTRL_DIOP 0x0040
#define R92C_SYS_ISO_CTRL_DIOE 0x0080
#define R92C_SYS_ISO_CTRL_EB2CORE 0x0100
#define R92C_SYS_ISO_CTRL_DIOR 0x0200
#define R92C_SYS_ISO_CTRL_PWC_EV25V 0x4000
#define R92C_SYS_ISO_CTRL_PWC_EV12V 0x8000
/* Bits for R92C_SYS_FUNC_EN. */
#define R92C_SYS_FUNC_EN_BBRSTB 0x0001
#define R92C_SYS_FUNC_EN_BB_GLB_RST 0x0002
#define R92C_SYS_FUNC_EN_USBA 0x0004
#define R92C_SYS_FUNC_EN_UPLL 0x0008
#define R92C_SYS_FUNC_EN_USBD 0x0010
#define R92C_SYS_FUNC_EN_DIO_PCIE 0x0020
#define R92C_SYS_FUNC_EN_PCIEA 0x0040
#define R92C_SYS_FUNC_EN_PPLL 0x0080
#define R92C_SYS_FUNC_EN_PCIED 0x0100
#define R92C_SYS_FUNC_EN_DIOE 0x0200
#define R92C_SYS_FUNC_EN_CPUEN 0x0400
#define R92C_SYS_FUNC_EN_DCORE 0x0800
#define R92C_SYS_FUNC_EN_ELDR 0x1000
#define R92C_SYS_FUNC_EN_DIO_RF 0x2000
#define R92C_SYS_FUNC_EN_HWPDN 0x4000
#define R92C_SYS_FUNC_EN_MREGEN 0x8000
/* Bits for R92C_APS_FSMCO. */
#define R92C_APS_FSMCO_PFM_LDALL 0x00000001
#define R92C_APS_FSMCO_PFM_ALDN 0x00000002
#define R92C_APS_FSMCO_PFM_LDKP 0x00000004
#define R92C_APS_FSMCO_PFM_WOWL 0x00000008
#define R92C_APS_FSMCO_PDN_EN 0x00000010
#define R92C_APS_FSMCO_PDN_PL 0x00000020
#define R92C_APS_FSMCO_APFM_ONMAC 0x00000100
#define R92C_APS_FSMCO_APFM_OFF 0x00000200
#define R92C_APS_FSMCO_APFM_RSM 0x00000400
#define R92C_APS_FSMCO_AFSM_HSUS 0x00000800
#define R92C_APS_FSMCO_AFSM_PCIE 0x00001000
#define R92C_APS_FSMCO_APDM_MAC 0x00002000
#define R92C_APS_FSMCO_APDM_HOST 0x00004000
#define R92C_APS_FSMCO_APDM_HPDN 0x00008000
#define R92C_APS_FSMCO_RDY_MACON 0x00010000
#define R92C_APS_FSMCO_SUS_HOST 0x00020000
#define R92C_APS_FSMCO_ROP_ALD 0x00100000
#define R92C_APS_FSMCO_ROP_PWR 0x00200000
#define R92C_APS_FSMCO_ROP_SPS 0x00400000
#define R92C_APS_FSMCO_SOP_MRST 0x02000000
#define R92C_APS_FSMCO_SOP_FUSE 0x04000000
#define R92C_APS_FSMCO_SOP_ABG 0x08000000
#define R92C_APS_FSMCO_SOP_AMB 0x10000000
#define R92C_APS_FSMCO_SOP_RCK 0x20000000
#define R92C_APS_FSMCO_SOP_A8M 0x40000000
#define R92C_APS_FSMCO_XOP_BTCK 0x80000000
/* Bits for R92C_SYS_CLKR. */
#define R92C_SYS_CLKR_ANAD16V_EN 0x00000001
#define R92C_SYS_CLKR_ANA8M 0x00000002
#define R92C_SYS_CLKR_MACSLP 0x00000010
#define R92C_SYS_CLKR_LOADER_EN 0x00000020
#define R92C_SYS_CLKR_80M_SSC_DIS 0x00000080
#define R92C_SYS_CLKR_80M_SSC_EN_HO 0x00000100
#define R92C_SYS_CLKR_PHY_SSC_RSTB 0x00000200
#define R92C_SYS_CLKR_SEC_EN 0x00000400
#define R92C_SYS_CLKR_MAC_EN 0x00000800
#define R92C_SYS_CLKR_SYS_EN 0x00001000
#define R92C_SYS_CLKR_RING_EN 0x00002000
/* Bits for R92C_RSV_CTRL. */
#define R92C_RSV_CTRL_WLOCK_ALL 0x01
#define R92C_RSV_CTRL_WLOCK_00 0x02
#define R92C_RSV_CTRL_WLOCK_04 0x04
#define R92C_RSV_CTRL_WLOCK_08 0x08
#define R92C_RSV_CTRL_WLOCK_40 0x10
#define R92C_RSV_CTRL_R_DIS_PRST_0 0x20
#define R92C_RSV_CTRL_R_DIS_PRST_1 0x40
#define R92C_RSV_CTRL_LOCK_ALL_EN 0x80
/* Bits for R92C_RF_CTRL. */
#define R92C_RF_CTRL_EN 0x01
#define R92C_RF_CTRL_RSTB 0x02
#define R92C_RF_CTRL_SDMRSTB 0x04
/* Bits for R92C_LDOA15_CTRL. */
#define R92C_LDOA15_CTRL_EN 0x01
#define R92C_LDOA15_CTRL_STBY 0x02
#define R92C_LDOA15_CTRL_OBUF 0x04
#define R92C_LDOA15_CTRL_REG_VOS 0x08
/* Bits for R92C_LDOV12D_CTRL. */
#define R92C_LDOV12D_CTRL_LDV12_EN 0x01
/* Bits for R92C_LPLDO_CTRL. */
#define R92C_LPLDO_CTRL_SLEEP 0x10
/* Bits for R92C_AFE_XTAL_CTRL. */
#define R92C_AFE_XTAL_CTRL_ADDR_M 0x007ff800
#define R92C_AFE_XTAL_CTRL_ADDR_S 11
/* Bits for R92C_AFE_PLL_CTRL. */
#define R92C_AFE_PLL_CTRL_EN 0x0001
#define R92C_AFE_PLL_CTRL_320_EN 0x0002
#define R92C_AFE_PLL_CTRL_FREF_SEL 0x0004
#define R92C_AFE_PLL_CTRL_EDGE_SEL 0x0008
#define R92C_AFE_PLL_CTRL_WDOGB 0x0010
#define R92C_AFE_PLL_CTRL_LPFEN 0x0020
/* Bits for R92C_EFUSE_CTRL. */
#define R92C_EFUSE_CTRL_DATA_M 0x000000ff
#define R92C_EFUSE_CTRL_DATA_S 0
#define R92C_EFUSE_CTRL_ADDR_M 0x0003ff00
#define R92C_EFUSE_CTRL_ADDR_S 8
#define R92C_EFUSE_CTRL_VALID 0x80000000
/* Bits for R92C_GPIO_MUXCFG. */
#define R92C_GPIO_MUXCFG_ENBT 0x0020
/* Bits for R92C_LEDCFG0. */
#define R92C_LEDCFG0_DIS 0x08
/* Bits for R92C_LEDCFG1. */
#define R92C_LEDCFG1_DIS 0x80
/* Bits for R92C_MULTI_FUNC_CTRL. */
#define R92C_MULTI_BT_FUNC_EN 0x00040000
/* Bits for R92C_MCUFWDL. */
#define R92C_MCUFWDL_EN 0x00000001
#define R92C_MCUFWDL_RDY 0x00000002
#define R92C_MCUFWDL_CHKSUM_RPT 0x00000004
#define R92C_MCUFWDL_MACINI_RDY 0x00000008
#define R92C_MCUFWDL_BBINI_RDY 0x00000010
#define R92C_MCUFWDL_RFINI_RDY 0x00000020
#define R92C_MCUFWDL_WINTINI_RDY 0x00000040
#define R92C_MCUFWDL_RAM_DL_SEL 0x00000080 /* 1: RAM, 0: ROM */
#define R92C_MCUFWDL_PAGE_M 0x00070000
#define R92C_MCUFWDL_PAGE_S 16
#define R92C_MCUFWDL_ROM_DLEN 0x00080000
#define R92C_MCUFWDL_CPRST 0x00800000
/* Bits for R92C_EFUSE_ACCESS. */
#define R92C_EFUSE_ACCESS_OFF 0x00
#define R92C_EFUSE_ACCESS_ON 0x69
/* Bits for R92C_HPON_FSM. */
#define R92C_HPON_FSM_CHIP_BONDING_ID_S 22
#define R92C_HPON_FSM_CHIP_BONDING_ID_M 0x00c00000
#define R92C_HPON_FSM_CHIP_BONDING_ID_92C_1T2R 1
/* Bits for R92C_SYS_CFG. */
#define R92C_SYS_CFG_XCLK_VLD 0x00000001
#define R92C_SYS_CFG_ACLK_VLD 0x00000002
#define R92C_SYS_CFG_UCLK_VLD 0x00000004
#define R92C_SYS_CFG_PCLK_VLD 0x00000008
#define R92C_SYS_CFG_PCIRSTB 0x00000010
#define R92C_SYS_CFG_V15_VLD 0x00000020
#define R92C_SYS_CFG_TRP_B15V_EN 0x00000080
#define R92C_SYS_CFG_SIC_IDLE 0x00000100
#define R92C_SYS_CFG_BD_MAC2 0x00000200
#define R92C_SYS_CFG_BD_MAC1 0x00000400
#define R92C_SYS_CFG_IC_MACPHY_MODE 0x00000800
#define R92C_SYS_CFG_CHIP_VER_RTL_M 0x0000f000
#define R92C_SYS_CFG_CHIP_VER_RTL_S 12
#define R92C_SYS_CFG_BT_FUNC 0x00010000
#define R92C_SYS_CFG_VENDOR_UMC 0x00080000
#define R92C_SYS_CFG_PAD_HWPD_IDN 0x00400000
#define R92C_SYS_CFG_TRP_VAUX_EN 0x00800000
#define R92C_SYS_CFG_TRP_BT_EN 0x01000000
#define R92C_SYS_CFG_BD_PKG_SEL 0x02000000
#define R92C_SYS_CFG_BD_HCI_SEL 0x04000000
#define R92C_SYS_CFG_TYPE_92C 0x08000000
/* Bits for R92C_CR. */
#define R92C_CR_HCI_TXDMA_EN 0x0001
#define R92C_CR_HCI_RXDMA_EN 0x0002
#define R92C_CR_TXDMA_EN 0x0004
#define R92C_CR_RXDMA_EN 0x0008
#define R92C_CR_PROTOCOL_EN 0x0010
#define R92C_CR_SCHEDULE_EN 0x0020
#define R92C_CR_MACTXEN 0x0040
#define R92C_CR_MACRXEN 0x0080
#define R92C_CR_ENSWBCN 0x0100
#define R92C_CR_ENSEC 0x0200
#define R92C_CR_CALTMR_EN 0x0400
/* Bits for R92C_MSR. */
#define R92C_MSR_NOLINK 0x00
#define R92C_MSR_ADHOC 0x01
#define R92C_MSR_INFRA 0x02
#define R92C_MSR_AP 0x03
#define R92C_MSR_MASK (R92C_MSR_AP)
/* Bits for R92C_PBP. */
#define R92C_PBP_PSRX_M 0x0f
#define R92C_PBP_PSRX_S 0
#define R92C_PBP_PSTX_M 0xf0
#define R92C_PBP_PSTX_S 4
#define R92C_PBP_64 0
#define R92C_PBP_128 1
#define R92C_PBP_256 2
#define R92C_PBP_512 3
#define R92C_PBP_1024 4
/* Bits for R92C_TRXDMA_CTRL. */
#define R92C_TRXDMA_CTRL_RX_SHIFT_EN 0x0002
#define R92C_TRXDMA_CTRL_RXDMA_AGG_EN 0x0004
#define R92C_TRXDMA_CTRL_TXDMA_VOQ_MAP_M 0x0030
#define R92C_TRXDMA_CTRL_TXDMA_VOQ_MAP_S 4
#define R92C_TRXDMA_CTRL_TXDMA_VIQ_MAP_M 0x00c0
#define R92C_TRXDMA_CTRL_TXDMA_VIQ_MAP_S 6
#define R92C_TRXDMA_CTRL_TXDMA_BEQ_MAP_M 0x0300
#define R92C_TRXDMA_CTRL_TXDMA_BEQ_MAP_S 8
#define R92C_TRXDMA_CTRL_TXDMA_BKQ_MAP_M 0x0c00
#define R92C_TRXDMA_CTRL_TXDMA_BKQ_MAP_S 10
#define R92C_TRXDMA_CTRL_TXDMA_MGQ_MAP_M 0x3000
#define R92C_TRXDMA_CTRL_TXDMA_MGQ_MAP_S 12
#define R92C_TRXDMA_CTRL_TXDMA_HIQ_MAP_M 0xc000
#define R92C_TRXDMA_CTRL_TXDMA_HIQ_MAP_S 14
#define R92C_TRXDMA_CTRL_QUEUE_LOW 1
#define R92C_TRXDMA_CTRL_QUEUE_NORMAL 2
#define R92C_TRXDMA_CTRL_QUEUE_HIGH 3
#define R92C_TRXDMA_CTRL_QMAP_M 0xfff0
/* Shortcuts. */
#define R92C_TRXDMA_CTRL_QMAP_3EP 0xf5b0
#define R92C_TRXDMA_CTRL_QMAP_HQ_LQ 0xf5f0
#define R92C_TRXDMA_CTRL_QMAP_HQ_NQ 0xfaf0
#define R92C_TRXDMA_CTRL_QMAP_LQ 0x5550
#define R92C_TRXDMA_CTRL_QMAP_NQ 0xaaa0
#define R92C_TRXDMA_CTRL_QMAP_HQ 0xfff0
/* Bits for R92C_C2H_EVT_CLEAR. */
#define R92C_C2H_EVT_HOST_CLOSE 0x00
#define R92C_C2H_EVT_FW_CLOSE 0xff
/* Bits for R92C_LLT_INIT. */
#define R92C_LLT_INIT_DATA_M 0x000000ff
#define R92C_LLT_INIT_DATA_S 0
#define R92C_LLT_INIT_ADDR_M 0x0000ff00
#define R92C_LLT_INIT_ADDR_S 8
#define R92C_LLT_INIT_OP_M 0xc0000000
#define R92C_LLT_INIT_OP_S 30
#define R92C_LLT_INIT_OP_NO_ACTIVE 0
#define R92C_LLT_INIT_OP_WRITE 1
/* Bits for R92C_RQPN. */
#define R92C_RQPN_HPQ_M 0x000000ff
#define R92C_RQPN_HPQ_S 0
#define R92C_RQPN_LPQ_M 0x0000ff00
#define R92C_RQPN_LPQ_S 8
#define R92C_RQPN_PUBQ_M 0x00ff0000
#define R92C_RQPN_PUBQ_S 16
#define R92C_RQPN_LD 0x80000000
/* Bits for R92C_TDECTRL. */
#define R92C_TDECTRL_BLK_DESC_NUM_M 0x000000f0
#define R92C_TDECTRL_BLK_DESC_NUM_S 4
#define R92C_TDECTRL_BCN_VALID 0x00010000
/* Bits for R92C_TXDMA_OFFSET_CHK. */
#define R92C_TXDMA_OFFSET_DROP_DATA_EN 0x00000200
/* Bits for R92C_AUTO_LLT. */
#define R92C_AUTO_LLT_INIT 0x00010000
/* Bits for R92C_FWHW_TXQ_CTRL. */
#define R92C_FWHW_TXQ_CTRL_AMPDU_RTY_NEW 0x80
#define R92C_FWHW_TXQ_CTRL_REAL_BEACON 0x400000
/* Bits for R92C_SPEC_SIFS. */
#define R92C_SPEC_SIFS_CCK_M 0x00ff
#define R92C_SPEC_SIFS_CCK_S 0
#define R92C_SPEC_SIFS_OFDM_M 0xff00
#define R92C_SPEC_SIFS_OFDM_S 8
/* Bits for R92C_RL. */
#define R92C_RL_LRL_M 0x003f
#define R92C_RL_LRL_S 0
#define R92C_RL_SRL_M 0x3f00
#define R92C_RL_SRL_S 8
/* Size of R92C_DARFRC. */
#define R92C_DARFRC_SIZE 8
/* Bits for R92C_RRSR. */
#define R92C_RRSR_RATE_BITMAP_M 0x000fffff
#define R92C_RRSR_RATE_BITMAP_S 0
#define R92C_RRSR_RATE_CCK_ONLY_1M 0xffff1
#define R92C_RRSR_RATE_ALL 0xfffff
#define R92C_RRSR_RSC_LOWSUBCHNL 0x00200000
#define R92C_RRSR_RSC_UPSUBCHNL 0x00400000
#define R92C_RRSR_SHORT 0x00800000
/* Bits for R92C_EDCA_XX_PARAM. */
#define R92C_EDCA_PARAM_AIFS_M 0x000000ff
#define R92C_EDCA_PARAM_AIFS_S 0
#define R92C_EDCA_PARAM_ECWMIN_M 0x00000f00
#define R92C_EDCA_PARAM_ECWMIN_S 8
#define R92C_EDCA_PARAM_ECWMAX_M 0x0000f000
#define R92C_EDCA_PARAM_ECWMAX_S 12
#define R92C_EDCA_PARAM_TXOP_M 0xffff0000
#define R92C_EDCA_PARAM_TXOP_S 16
/* Bits for R92C_HWSEQ_CTRL / R92C_TXPAUSE. */
#define R92C_TX_QUEUE_VO 0x01
#define R92C_TX_QUEUE_VI 0x02
#define R92C_TX_QUEUE_BE 0x04
#define R92C_TX_QUEUE_BK 0x08
#define R92C_TX_QUEUE_MGT 0x10
#define R92C_TX_QUEUE_HIGH 0x20
#define R92C_TX_QUEUE_BCN 0x40
/* Shortcuts. */
#define R92C_TX_QUEUE_AC \
(R92C_TX_QUEUE_VO | R92C_TX_QUEUE_VI | \
R92C_TX_QUEUE_BE | R92C_TX_QUEUE_BK)
#define R92C_TX_QUEUE_ALL \
(R92C_TX_QUEUE_AC | R92C_TX_QUEUE_MGT | \
R92C_TX_QUEUE_HIGH | R92C_TX_QUEUE_BCN | 0x80) /* XXX */
/* Bits for R92C_BCN_CTRL. */
#define R92C_BCN_CTRL_EN_MBSSID 0x02
#define R92C_BCN_CTRL_TXBCN_RPT 0x04
#define R92C_BCN_CTRL_EN_BCN 0x08
#define R92C_BCN_CTRL_DIS_TSF_UDT0 0x10
/* Bits for R92C_DUAL_TSF_RST. */
#define R92C_DUAL_TSF_RESET(id) (0x01 << (id))
#define R92C_DUAL_TSF_RST_TXOK 0x20
/* Bits for R92C_ACMHWCTRL. */
#define R92C_ACMHWCTRL_EN 0x01
#define R92C_ACMHWCTRL_BE 0x02
#define R92C_ACMHWCTRL_VI 0x04
#define R92C_ACMHWCTRL_VO 0x08
#define R92C_ACMHWCTRL_ACM_MASK 0x0f
/* Bits for R92C_APSD_CTRL. */
#define R92C_APSD_CTRL_OFF 0x40
#define R92C_APSD_CTRL_OFF_STATUS 0x80
/* Bits for R92C_BWOPMODE. */
#define R92C_BWOPMODE_11J 0x01
#define R92C_BWOPMODE_5G 0x02
#define R92C_BWOPMODE_20MHZ 0x04
/* Bits for R92C_TCR. */
#define R92C_TCR_TSFRST 0x00000001
#define R92C_TCR_DIS_GCLK 0x00000002
#define R92C_TCR_PAD_SEL 0x00000004
#define R92C_TCR_PWR_ST 0x00000040
#define R92C_TCR_PWRBIT_OW_EN 0x00000080
#define R92C_TCR_ACRC 0x00000100
#define R92C_TCR_CFENDFORM 0x00000200
#define R92C_TCR_ICV 0x00000400
/* Bits for R92C_RCR. */
#define R92C_RCR_AAP 0x00000001
#define R92C_RCR_APM 0x00000002
#define R92C_RCR_AM 0x00000004
#define R92C_RCR_AB 0x00000008
#define R92C_RCR_ADD3 0x00000010
#define R92C_RCR_APWRMGT 0x00000020
#define R92C_RCR_CBSSID_DATA 0x00000040
#define R92C_RCR_CBSSID_BCN 0x00000080
#define R92C_RCR_ACRC32 0x00000100
#define R92C_RCR_AICV 0x00000200
#define R92C_RCR_ADF 0x00000800
#define R92C_RCR_ACF 0x00001000
#define R92C_RCR_AMF 0x00002000
#define R92C_RCR_HTC_LOC_CTRL 0x00004000
#define R92C_RCR_MFBEN 0x00400000
#define R92C_RCR_LSIGEN 0x00800000
#define R92C_RCR_ENMBID 0x01000000
#define R92C_RCR_APP_BA_SSN 0x08000000
#define R92C_RCR_APP_PHYSTS 0x10000000
#define R92C_RCR_APP_ICV 0x20000000
#define R92C_RCR_APP_MIC 0x40000000
#define R92C_RCR_APPFCS 0x80000000
/* Bits for R92C_RX_DRVINFO_SZ. */
/* XXX other values will not work */
#define R92C_RX_DRVINFO_SZ_DEF ((RTWN_PHY_STATUS_SIZE) / 8)
/* Bits for R92C_WMAC_TRXPTCL_CTL. */
#define R92C_WMAC_TRXPTCL_SHPRE 0x00020000
/* Bits for R92C_CAMCMD. */
#define R92C_CAMCMD_ADDR_M 0x0000ffff
#define R92C_CAMCMD_ADDR_S 0
#define R92C_CAMCMD_WRITE 0x00010000
#define R92C_CAMCMD_CLR 0x40000000
#define R92C_CAMCMD_POLLING 0x80000000
/*
* CAM entries.
*/
#define R92C_CAM_CTL0(entry) ((entry) * 8 + 0)
#define R92C_CAM_CTL1(entry) ((entry) * 8 + 1)
#define R92C_CAM_KEY(entry, i) ((entry) * 8 + 2 + (i))
#define R92C_CAM_CTL6(entry) ((entry) * 8 + 6)
#define R92C_CAM_CTL7(entry) ((entry) * 8 + 7)
/* Bits for R92C_CAM_CTL0(i). */
#define R92C_CAM_KEYID_M 0x00000003
#define R92C_CAM_KEYID_S 0
#define R92C_CAM_ALGO_M 0x0000001c
#define R92C_CAM_ALGO_S 2
#define R92C_CAM_ALGO_NONE 0
#define R92C_CAM_ALGO_WEP40 1
#define R92C_CAM_ALGO_TKIP 2
#define R92C_CAM_ALGO_AES 4
#define R92C_CAM_ALGO_WEP104 5
#define R92C_CAM_VALID 0x00008000
#define R92C_CAM_MACLO_M 0xffff0000
#define R92C_CAM_MACLO_S 16
/* Bits for R92C_SECCFG. */
#define R92C_SECCFG_TXUCKEY_DEF 0x0001
#define R92C_SECCFG_RXUCKEY_DEF 0x0002
#define R92C_SECCFG_TXENC_ENA 0x0004
#define R92C_SECCFG_RXDEC_ENA 0x0008
#define R92C_SECCFG_CMP_A2 0x0010
#define R92C_SECCFG_MC_SRCH_DIS 0x0020
#define R92C_SECCFG_TXBCKEY_DEF 0x0040
#define R92C_SECCFG_RXBCKEY_DEF 0x0080
/* Bits for R92C_RXFLTMAP*. */
#define R92C_RXFLTMAP_SUBTYPE(subtype) \
(1 << ((subtype) >> IEEE80211_FC0_SUBTYPE_SHIFT))
/*
* Baseband registers.
*/
#define R92C_FPGA0_RFMOD 0x800
#define R92C_FPGA0_TXINFO 0x804
#define R92C_HSSI_PARAM1(chain) (0x820 + (chain) * 8)
#define R92C_HSSI_PARAM2(chain) (0x824 + (chain) * 8)
#define R92C_TXAGC_RATE18_06(i) (((i) == 0) ? 0xe00 : 0x830)
#define R92C_TXAGC_RATE54_24(i) (((i) == 0) ? 0xe04 : 0x834)
#define R92C_TXAGC_A_CCK1_MCS32 0xe08
#define R92C_TXAGC_B_CCK1_55_MCS32 0x838
#define R92C_TXAGC_B_CCK11_A_CCK2_11 0x86c
#define R92C_TXAGC_MCS03_MCS00(i) (((i) == 0) ? 0xe10 : 0x83c)
#define R92C_TXAGC_MCS07_MCS04(i) (((i) == 0) ? 0xe14 : 0x848)
#define R92C_TXAGC_MCS11_MCS08(i) (((i) == 0) ? 0xe18 : 0x84c)
#define R92C_TXAGC_MCS15_MCS12(i) (((i) == 0) ? 0xe1c : 0x868)
#define R92C_LSSI_PARAM(chain) (0x840 + (chain) * 4)
#define R92C_FPGA0_RFIFACEOE(chain) (0x860 + (chain) * 4)
#define R92C_FPGA0_RFIFACESW(idx) (0x870 + (idx) * 4)
#define R92C_FPGA0_RFPARAM(idx) (0x878 + (idx) * 4)
#define R92C_FPGA0_ANAPARAM2 0x884
#define R92C_LSSI_READBACK(chain) (0x8a0 + (chain) * 4)
#define R92C_HSPI_READBACK(chain) (0x8b8 + (chain) * 4)
#define R92C_FPGA1_RFMOD 0x900
#define R92C_FPGA1_TXINFO 0x90c
#define R92C_CCK0_SYSTEM 0xa00
#define R92C_CCK0_AFESETTING 0xa04
#define R92C_OFDM0_TRXPATHENA 0xc04
#define R92C_OFDM0_TRMUXPAR 0xc08
#define R92C_OFDM0_RXIQIMBALANCE(chain) (0xc14 + (chain) * 8)
#define R92C_OFDM0_ECCATHRESHOLD 0xc4c
#define R92C_OFDM0_AGCCORE1(chain) (0xc50 + (chain) * 8)
#define R92C_OFDM0_AGCPARAM1 0xc70
#define R92C_OFDM0_AGCRSSITABLE 0xc78
#define R92C_OFDM0_TXIQIMBALANCE(chain) (0xc80 + (chain) * 8)
#define R92C_OFDM0_TXAFE(chain) (0xc94 + (chain) * 8)
#define R92C_OFDM0_RXIQEXTANTA 0xca0
#define R92C_OFDM0_TXPSEUDONOISEWGT 0xce4
#define R92C_OFDM1_LSTF 0xd00
/* Bits for R92C_FPGA[01]_RFMOD. */
#define R92C_RFMOD_40MHZ 0x00000001
#define R92C_RFMOD_JAPAN 0x00000002
#define R92C_RFMOD_CCK_TXSC 0x00000030
#define R92C_RFMOD_CCK_EN 0x01000000
#define R92C_RFMOD_OFDM_EN 0x02000000
/* Bits for R92C_HSSI_PARAM1(i). */
#define R92C_HSSI_PARAM1_PI 0x00000100
/* Bits for R92C_HSSI_PARAM2(i). */
#define R92C_HSSI_PARAM2_CCK_HIPWR 0x00000200
#define R92C_HSSI_PARAM2_ADDR_LENGTH 0x00000400
#define R92C_HSSI_PARAM2_DATA_LENGTH 0x00000800
#define R92C_HSSI_PARAM2_READ_ADDR_M 0x7f800000
#define R92C_HSSI_PARAM2_READ_ADDR_S 23
#define R92C_HSSI_PARAM2_READ_EDGE 0x80000000
/* Bits for R92C_TXAGC_A_CCK1_MCS32. */
#define R92C_TXAGC_A_CCK1_M 0x0000ff00
#define R92C_TXAGC_A_CCK1_S 8
/* Bits for R92C_TXAGC_B_CCK11_A_CCK2_11. */
#define R92C_TXAGC_B_CCK11_M 0x000000ff
#define R92C_TXAGC_B_CCK11_S 0
#define R92C_TXAGC_A_CCK2_M 0x0000ff00
#define R92C_TXAGC_A_CCK2_S 8
#define R92C_TXAGC_A_CCK55_M 0x00ff0000
#define R92C_TXAGC_A_CCK55_S 16
#define R92C_TXAGC_A_CCK11_M 0xff000000
#define R92C_TXAGC_A_CCK11_S 24
/* Bits for R92C_TXAGC_B_CCK1_55_MCS32. */
#define R92C_TXAGC_B_CCK1_M 0x0000ff00
#define R92C_TXAGC_B_CCK1_S 8
#define R92C_TXAGC_B_CCK2_M 0x00ff0000
#define R92C_TXAGC_B_CCK2_S 16
#define R92C_TXAGC_B_CCK55_M 0xff000000
#define R92C_TXAGC_B_CCK55_S 24
/* Bits for R92C_TXAGC_RATE18_06(x). */
#define R92C_TXAGC_RATE06_M 0x000000ff
#define R92C_TXAGC_RATE06_S 0
#define R92C_TXAGC_RATE09_M 0x0000ff00
#define R92C_TXAGC_RATE09_S 8
#define R92C_TXAGC_RATE12_M 0x00ff0000
#define R92C_TXAGC_RATE12_S 16
#define R92C_TXAGC_RATE18_M 0xff000000
#define R92C_TXAGC_RATE18_S 24
/* Bits for R92C_TXAGC_RATE54_24(x). */
#define R92C_TXAGC_RATE24_M 0x000000ff
#define R92C_TXAGC_RATE24_S 0
#define R92C_TXAGC_RATE36_M 0x0000ff00
#define R92C_TXAGC_RATE36_S 8
#define R92C_TXAGC_RATE48_M 0x00ff0000
#define R92C_TXAGC_RATE48_S 16
#define R92C_TXAGC_RATE54_M 0xff000000
#define R92C_TXAGC_RATE54_S 24
/* Bits for R92C_TXAGC_MCS03_MCS00(x). */
#define R92C_TXAGC_MCS00_M 0x000000ff
#define R92C_TXAGC_MCS00_S 0
#define R92C_TXAGC_MCS01_M 0x0000ff00
#define R92C_TXAGC_MCS01_S 8
#define R92C_TXAGC_MCS02_M 0x00ff0000
#define R92C_TXAGC_MCS02_S 16
#define R92C_TXAGC_MCS03_M 0xff000000
#define R92C_TXAGC_MCS03_S 24
/* Bits for R92C_TXAGC_MCS07_MCS04(x). */
#define R92C_TXAGC_MCS04_M 0x000000ff
#define R92C_TXAGC_MCS04_S 0
#define R92C_TXAGC_MCS05_M 0x0000ff00
#define R92C_TXAGC_MCS05_S 8
#define R92C_TXAGC_MCS06_M 0x00ff0000
#define R92C_TXAGC_MCS06_S 16
#define R92C_TXAGC_MCS07_M 0xff000000
#define R92C_TXAGC_MCS07_S 24
/* Bits for R92C_TXAGC_MCS11_MCS08(x). */
#define R92C_TXAGC_MCS08_M 0x000000ff
#define R92C_TXAGC_MCS08_S 0
#define R92C_TXAGC_MCS09_M 0x0000ff00
#define R92C_TXAGC_MCS09_S 8
#define R92C_TXAGC_MCS10_M 0x00ff0000
#define R92C_TXAGC_MCS10_S 16
#define R92C_TXAGC_MCS11_M 0xff000000
#define R92C_TXAGC_MCS11_S 24
/* Bits for R92C_TXAGC_MCS15_MCS12(x). */
#define R92C_TXAGC_MCS12_M 0x000000ff
#define R92C_TXAGC_MCS12_S 0
#define R92C_TXAGC_MCS13_M 0x0000ff00
#define R92C_TXAGC_MCS13_S 8
#define R92C_TXAGC_MCS14_M 0x00ff0000
#define R92C_TXAGC_MCS14_S 16
#define R92C_TXAGC_MCS15_M 0xff000000
#define R92C_TXAGC_MCS15_S 24
/* Bits for R92C_LSSI_PARAM(i). */
#define R92C_LSSI_PARAM_DATA_M 0x000fffff
#define R92C_LSSI_PARAM_DATA_S 0
#define R92C_LSSI_PARAM_ADDR_M 0x03f00000
#define R92C_LSSI_PARAM_ADDR_S 20
/* Bits for R92C_FPGA0_RFIFACEOE(0). */
#define R92C_FPGA0_RFIFACEOE0_ANT_M 0x00000300
#define R92C_FPGA0_RFIFACEOE0_ANT_S 8
/* Bits for R92C_FPGA0_ANAPARAM2. */
#define R92C_FPGA0_ANAPARAM2_CBW20 0x00000400
/* Bits for R92C_LSSI_READBACK(i). */
#define R92C_LSSI_READBACK_DATA_M 0x000fffff
#define R92C_LSSI_READBACK_DATA_S 0
/* Bits for R92C_CCK0_SYSTEM. */
#define R92C_CCK0_SYSTEM_CCK_SIDEBAND 0x00000010
/* Bits for R92C_OFDM0_AGCCORE1(i). */
#define R92C_OFDM0_AGCCORE1_GAIN_M 0x0000007f
#define R92C_OFDM0_AGCCORE1_GAIN_S 0
/*
* RF (6052) registers.
*/
#define R92C_RF_AC 0x00
#define R92C_RF_IQADJ_G(i) (0x01 + (i))
#define R92C_RF_POW_TRSW 0x05
#define R92C_RF_GAIN_RX 0x06
#define R92C_RF_GAIN_TX 0x07
#define R92C_RF_TXM_IDAC 0x08
#define R92C_RF_BS_IQGEN 0x0f
#define R92C_RF_MODE1 0x10
#define R92C_RF_MODE2 0x11
#define R92C_RF_RX_AGC_HP 0x12
#define R92C_RF_TX_AGC 0x13
#define R92C_RF_BIAS 0x14
#define R92C_RF_IPA 0x15
#define R92C_RF_POW_ABILITY 0x17
#define R92C_RF_CHNLBW 0x18
#define R92C_RF_RX_G1 0x1a
#define R92C_RF_RX_G2 0x1b
#define R92C_RF_RX_BB2 0x1c
#define R92C_RF_RX_BB1 0x1d
#define R92C_RF_RCK1 0x1e
#define R92C_RF_RCK2 0x1f
#define R92C_RF_TX_G(i) (0x20 + (i))
#define R92C_RF_TX_BB1 0x23
#define R92C_RF_T_METER 0x24
#define R92C_RF_SYN_G(i) (0x25 + (i))
#define R92C_RF_RCK_OS 0x30
#define R92C_RF_TXPA_G(i) (0x31 + (i))
/* Bits for R92C_RF_AC. */
#define R92C_RF_AC_MODE_M 0x70000
#define R92C_RF_AC_MODE_S 16
#define R92C_RF_AC_MODE_STANDBY 1
/* Bits for R92C_RF_CHNLBW. */
#define R92C_RF_CHNLBW_CHNL_M 0x003ff
#define R92C_RF_CHNLBW_CHNL_S 0
#define R92C_RF_CHNLBW_BW20 0x00400
#define R92C_RF_CHNLBW_LCSTART 0x08000
/* Bits for R92C_RF_T_METER. */
#define R92C_RF_T_METER_START 0x60
#define R92C_RF_T_METER_VAL_M 0x1f
#define R92C_RF_T_METER_VAL_S 0
#endif /* R92C_REG_H */
@@ -0,0 +1,93 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* 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: releng/12.0/sys/dev/rtwn/rtl8192c/r92c_rf.c 307529 2016-10-17 20:38:24Z avos $");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/rtl8192c/r92c.h>
#include <dev/rtwn/rtl8192c/r92c_reg.h>
#include <dev/rtwn/rtl8192c/r92c_var.h>
#include <dev/rtwn/rtl8192c/r92c_rom_defs.h>
uint32_t
r92c_rf_read(struct rtwn_softc *sc, int chain, uint8_t addr)
{
struct r92c_softc *rs = sc->sc_priv;
uint32_t reg[R92C_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));
rtwn_bb_write(sc, R92C_HSSI_PARAM2(0),
reg[0] & ~R92C_HSSI_PARAM2_READ_EDGE);
rtwn_delay(sc, rs->rf_read_delay[0]);
rtwn_bb_write(sc, R92C_HSSI_PARAM2(chain),
RW(reg[chain], R92C_HSSI_PARAM2_READ_ADDR, addr) |
R92C_HSSI_PARAM2_READ_EDGE);
rtwn_delay(sc, rs->rf_read_delay[1]);
rtwn_bb_write(sc, R92C_HSSI_PARAM2(0),
reg[0] | 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 (MS(val, R92C_LSSI_READBACK_DATA));
}
void
r92c_rf_write(struct rtwn_softc *sc, int chain, uint8_t addr,
uint32_t val)
{
rtwn_bb_write(sc, R92C_LSSI_PARAM(chain),
SM(R92C_LSSI_PARAM_ADDR, addr) |
SM(R92C_LSSI_PARAM_DATA, val));
}
@@ -0,0 +1,139 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* 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: releng/12.0/sys/dev/rtwn/rtl8192c/r92c_rom.c 307529 2016-10-17 20:38:24Z avos $");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/if_rtwn_debug.h>
#include <dev/rtwn/if_rtwn_efuse.h>
#include <dev/rtwn/rtl8192c/r92c.h>
#include <dev/rtwn/rtl8192c/r92c_priv.h>
#include <dev/rtwn/rtl8192c/r92c_var.h>
#include <dev/rtwn/rtl8192c/r92c_rom_image.h>
static void
r92c_set_chains(struct rtwn_softc *sc)
{
struct r92c_softc *rs = sc->sc_priv;
if (rs->chip & R92C_CHIP_92C) {
sc->ntxchains = (rs->chip & R92C_CHIP_92C_1T2R) ? 1 : 2;
sc->nrxchains = 2;
} else {
sc->ntxchains = 1;
sc->nrxchains = 1;
}
}
void
r92c_efuse_postread(struct rtwn_softc *sc)
{
struct r92c_softc *rs = sc->sc_priv;
/* XXX Weird but this is what the vendor driver does. */
sc->next_rom_addr = 0x1fa;
(void) rtwn_efuse_read_next(sc, &rs->pa_setting);
RTWN_DPRINTF(sc, RTWN_DEBUG_ROM, "%s: PA setting=0x%x\n", __func__,
rs->pa_setting);
}
void
r92c_parse_rom(struct rtwn_softc *sc, uint8_t *buf)
{
struct r92c_softc *rs = sc->sc_priv;
struct rtwn_r92c_txpwr *rt = rs->rs_txpwr;
struct r92c_rom *rom = (struct r92c_rom *)buf;
int i, j;
rs->board_type = MS(rom->rf_opt1, R92C_ROM_RF1_BOARD_TYPE);
rs->regulatory = MS(rom->rf_opt1, R92C_ROM_RF1_REGULATORY);
RTWN_DPRINTF(sc, RTWN_DEBUG_ROM, "%s: regulatory type=%d\n",
__func__, rs->regulatory);
/* Need to be set before postinit() (but after preinit()). */
rtwn_r92c_set_name(sc);
r92c_set_chains(sc);
for (j = 0; j < R92C_GROUP_2G; j++) {
for (i = 0; i < sc->ntxchains; i++) {
rt->cck_tx_pwr[i][j] = rom->cck_tx_pwr[i][j];
rt->ht40_1s_tx_pwr[i][j] = rom->ht40_1s_tx_pwr[i][j];
}
rt->ht40_2s_tx_pwr_diff[0][j] =
MS(rom->ht40_2s_tx_pwr_diff[j], LOW_PART);
rt->ht20_tx_pwr_diff[0][j] =
RTWN_SIGN4TO8(MS(rom->ht20_tx_pwr_diff[j],
LOW_PART));
rt->ofdm_tx_pwr_diff[0][j] =
MS(rom->ofdm_tx_pwr_diff[j], LOW_PART);
rt->ht40_max_pwr[0][j] =
MS(rom->ht40_max_pwr[j], LOW_PART);
rt->ht20_max_pwr[0][j] =
MS(rom->ht20_max_pwr[j], LOW_PART);
if (sc->ntxchains > 1) {
rt->ht40_2s_tx_pwr_diff[1][j] =
MS(rom->ht40_2s_tx_pwr_diff[j], HIGH_PART);
rt->ht20_tx_pwr_diff[1][j] =
RTWN_SIGN4TO8(MS(rom->ht20_tx_pwr_diff[j],
HIGH_PART));
rt->ofdm_tx_pwr_diff[1][j] =
MS(rom->ofdm_tx_pwr_diff[j], HIGH_PART);
rt->ht40_max_pwr[1][j] =
MS(rom->ht40_max_pwr[j], HIGH_PART);
rt->ht20_max_pwr[1][j] =
MS(rom->ht20_max_pwr[j], HIGH_PART);
}
}
sc->thermal_meter = MS(rom->thermal_meter, R92C_ROM_THERMAL_METER);
if (sc->thermal_meter == R92C_ROM_THERMAL_METER_M)
sc->thermal_meter = 0xff;
IEEE80211_ADDR_COPY(sc->sc_ic.ic_macaddr, rom->macaddr);
}
@@ -0,0 +1,57 @@
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $
* $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/r92c_rom_defs.h 307529 2016-10-17 20:38:24Z avos $
*/
#ifndef R92C_ROM_DEFS_H
#define R92C_ROM_DEFS_H
#define R92C_MAX_CHAINS 2
#define R92C_GROUP_2G 3
#define R92C_EFUSE_MAX_LEN 512
#define R92C_EFUSE_MAP_LEN 128
/*
* Some generic rom parsing macros.
*/
#define RTWN_GET_ROM_VAR(var, def) (((var) != 0xff) ? (var) : (def))
#define RTWN_SIGN4TO8(val) (((val) & 0x08) ? (val) | 0xf0 : (val))
#define LOW_PART_M 0x0f
#define LOW_PART_S 0
#define HIGH_PART_M 0xf0
#define HIGH_PART_S 4
/* Bits for rf_board_opt (rf_opt1) field. */
#define R92C_ROM_RF1_REGULATORY_M 0x07
#define R92C_ROM_RF1_REGULATORY_S 0
#define R92C_ROM_RF1_BOARD_TYPE_M 0xe0
#define R92C_ROM_RF1_BOARD_TYPE_S 5
/* Generic board types. */
#define R92C_BOARD_TYPE_DONGLE 0
#define R92C_BOARD_TYPE_HIGHPA 1
#define R92C_BOARD_TYPE_MINICARD 2
#define R92C_BOARD_TYPE_SOLO 3
#define R92C_BOARD_TYPE_COMBO 4
/* Bits for channel_plan field. */
#define R92C_CHANNEL_PLAN_BY_HW 0x80
#endif /* R92C_ROM_DEFS_H */
@@ -0,0 +1,69 @@
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $
* $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/r92c_rom_image.h 320055 2017-06-17 14:39:25Z kevlo $
*/
#ifndef R92C_ROM_IMAGE_H
#define R92C_ROM_IMAGE_H
#include <dev/rtwn/rtl8192c/r92c_rom_defs.h>
/*
* RTL8192CU ROM image.
*/
struct r92c_rom {
uint16_t id; /* 0x8192 */
uint8_t reserved1[5];
uint8_t dbg_sel;
uint16_t reserved2;
uint16_t vid;
uint16_t pid;
uint8_t usb_opt;
uint8_t ep_setting;
uint16_t reserved3;
uint8_t usb_phy;
uint8_t reserved4[3];
uint8_t macaddr[IEEE80211_ADDR_LEN];
uint8_t string[61]; /* "Realtek" */
uint8_t subcustomer_id;
uint8_t cck_tx_pwr[R92C_MAX_CHAINS][R92C_GROUP_2G];
uint8_t ht40_1s_tx_pwr[R92C_MAX_CHAINS][R92C_GROUP_2G];
uint8_t ht40_2s_tx_pwr_diff[R92C_GROUP_2G];
uint8_t ht20_tx_pwr_diff[R92C_GROUP_2G];
uint8_t ofdm_tx_pwr_diff[R92C_GROUP_2G];
uint8_t ht40_max_pwr[R92C_GROUP_2G];
uint8_t ht20_max_pwr[R92C_GROUP_2G];
uint8_t channel_plan;
uint8_t tssi[R92C_MAX_CHAINS];
uint8_t thermal_meter;
#define R92C_ROM_THERMAL_METER_M 0x1f
#define R92C_ROM_THERMAL_METER_S 0
uint8_t rf_opt1;
uint8_t rf_opt2;
uint8_t rf_opt3;
uint8_t rf_opt4;
uint8_t reserved5;
uint8_t version;
uint8_t customer_id;
} __packed;
_Static_assert(sizeof(struct r92c_rom) == R92C_EFUSE_MAP_LEN,
"R92C_EFUSE_MAP_LEN must be equal to sizeof(struct r92c_rom)!");
#endif /* R92C_ROM_IMAGE_H */
@@ -0,0 +1,147 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* 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: releng/12.0/sys/dev/rtwn/rtl8192c/r92c_rx.c 331043 2018-03-16 01:03:10Z avos $");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/if_rtwn_ridx.h>
#include <dev/rtwn/rtl8192c/r92c.h>
#include <dev/rtwn/rtl8192c/r92c_rx_desc.h>
int8_t
r92c_get_rssi_cck(struct rtwn_softc *sc, void *physt)
{
static const int8_t cckoff[] = { 16, -12, -26, -46 };
struct r92c_rx_cck *cck = (struct r92c_rx_cck *)physt;
uint8_t rpt;
int8_t rssi;
if (sc->sc_flags & RTWN_FLAG_CCK_HIPWR) {
rpt = (cck->agc_rpt >> 5) & 0x03;
rssi = (cck->agc_rpt & 0x1f) << 1;
} else {
rpt = (cck->agc_rpt >> 6) & 0x03;
rssi = cck->agc_rpt & 0x3e;
}
rssi = cckoff[rpt] - rssi;
return (rssi);
}
int8_t
r92c_get_rssi_ofdm(struct rtwn_softc *sc, void *physt)
{
struct r92c_rx_phystat *phy = (struct r92c_rx_phystat *)physt;
int rssi;
/* Get average RSSI. */
rssi = ((phy->pwdb_all >> 1) & 0x7f) - 110;
return (rssi);
}
uint8_t
r92c_rx_radiotap_flags(const void *buf)
{
const struct r92c_rx_stat *stat = buf;
uint8_t flags, rate;
if (!(stat->rxdw3 & htole32(R92C_RXDW3_SPLCP)))
return (0);
rate = MS(le32toh(stat->rxdw3), R92C_RXDW3_RATE);
if (RTWN_RATE_IS_CCK(rate))
flags = IEEE80211_RADIOTAP_F_SHORTPRE;
else
flags = IEEE80211_RADIOTAP_F_SHORTGI;
return (flags);
}
void
r92c_get_rx_stats(struct rtwn_softc *sc, struct ieee80211_rx_stats *rxs,
const void *desc, const void *physt_ptr)
{
const struct r92c_rx_stat *stat = desc;
uint32_t rxdw1, rxdw3;
uint8_t rate;
rxdw1 = le32toh(stat->rxdw1);
rxdw3 = le32toh(stat->rxdw3);
rate = MS(rxdw3, R92C_RXDW3_RATE);
if (rxdw1 & R92C_RXDW1_AMPDU)
rxs->c_pktflags |= IEEE80211_RX_F_AMPDU;
else if (rxdw1 & R92C_RXDW1_AMPDU_MORE)
rxs->c_pktflags |= IEEE80211_RX_F_AMPDU_MORE;
if ((rxdw3 & R92C_RXDW3_SPLCP) && rate >= RTWN_RIDX_HT_MCS(0))
rxs->c_pktflags |= IEEE80211_RX_F_SHORTGI;
if (rxdw3 & R92C_RXDW3_HT40)
rxs->c_width = IEEE80211_RX_FW_40MHZ;
else
rxs->c_width = IEEE80211_RX_FW_20MHZ;
if (RTWN_RATE_IS_CCK(rate))
rxs->c_phytype = IEEE80211_RX_FP_11B;
else if (rate < RTWN_RIDX_HT_MCS(0))
rxs->c_phytype = IEEE80211_RX_FP_11G;
else
rxs->c_phytype = IEEE80211_RX_FP_11NG;
/* Map HW rate index to 802.11 rate. */
if (rate < RTWN_RIDX_HT_MCS(0)) {
rxs->c_rate = ridx2rate[rate];
if (RTWN_RATE_IS_CCK(rate))
rxs->c_pktflags |= IEEE80211_RX_F_CCK;
else
rxs->c_pktflags |= IEEE80211_RX_F_OFDM;
} else { /* MCS0~15. */
rxs->c_rate =
IEEE80211_RATE_MCS | (rate - RTWN_RIDX_HT_MCS_SHIFT);
rxs->c_pktflags |= IEEE80211_RX_F_HT;
}
}
@@ -0,0 +1,100 @@
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $
* $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/r92c_rx_desc.h 312315 2017-01-17 00:35:23Z avos $
*/
#ifndef R92C_RX_DESC_H
#define R92C_RX_DESC_H
/* Rx MAC descriptor (common parts / USB). */
struct r92c_rx_stat {
uint32_t rxdw0;
#define R92C_RXDW0_PKTLEN_M 0x00003fff
#define R92C_RXDW0_PKTLEN_S 0
#define R92C_RXDW0_CRCERR 0x00004000
#define R92C_RXDW0_ICVERR 0x00008000
#define R92C_RXDW0_INFOSZ_M 0x000f0000
#define R92C_RXDW0_INFOSZ_S 16
#define R92C_RXDW0_CIPHER_M 0x00700000
#define R92C_RXDW0_CIPHER_S 20
#define R92C_RXDW0_QOS 0x00800000
#define R92C_RXDW0_SHIFT_M 0x03000000
#define R92C_RXDW0_SHIFT_S 24
#define R92C_RXDW0_PHYST 0x04000000
#define R92C_RXDW0_SWDEC 0x08000000
#define R92C_RXDW0_LS 0x10000000
#define R92C_RXDW0_FS 0x20000000
#define R92C_RXDW0_EOR 0x40000000
#define R92C_RXDW0_OWN 0x80000000
uint32_t rxdw1;
#define R92C_RXDW1_MACID_M 0x0000001f
#define R92C_RXDW1_MACID_S 0
#define R92C_RXDW1_AMSDU 0x00002000
#define R92C_RXDW1_AMPDU_MORE 0x00004000
#define R92C_RXDW1_AMPDU 0x00008000
#define R92C_RXDW1_MC 0x40000000
#define R92C_RXDW1_BC 0x80000000
uint32_t rxdw2;
uint32_t rxdw3;
#define R92C_RXDW3_RATE_M 0x0000003f
#define R92C_RXDW3_RATE_S 0
#define R92C_RXDW3_HT 0x00000040
#define R92C_RXDW3_SPLCP 0x00000100
#define R92C_RXDW3_HT40 0x00000200
#define R92C_RXDW3_HTC 0x00000400
#define R92C_RXDW3_BSSID_FIT_M 0x00003000
#define R92C_RXDW3_BSSID_FIT_S 12
uint32_t rxdw4;
uint32_t tsf_low;
} __packed __attribute__((aligned(4)));
/* Rx PHY CCK descriptor. */
struct r92c_rx_cck {
uint8_t adc_pwdb[4];
uint8_t sq_rpt;
uint8_t agc_rpt;
} __packed;
/* Rx PHY descriptor. */
struct r92c_rx_phystat {
uint8_t trsw_gain[4];
uint8_t pwdb_all;
uint8_t cfosho[4];
uint8_t cfotail[4];
uint8_t rxevm[2];
uint8_t rxsnr[4];
uint8_t pdsnr[2];
uint8_t csi_current[2];
uint8_t csi_target[2];
uint8_t sigevm;
uint8_t max_ex_pwr;
uint8_t phy_byte28;
#define R92C_PHY_BYTE28_ANTSEL 0x01
#define R92C_PHY_BYTE28_ANTSEL_B 0x02
#define R92C_PHY_BYTE28_ANT_TRAIN_EN 0x04
#define R92C_PHY_BYTE28_IDLE_LONG 0x08
#define R92C_PHY_BYTE28_RXSC_M 0x30
#define R92C_PHY_BYTE28_RXSC_S 4
#define R92C_PHY_BYTE28_SGI_EN 0x40
#define R92C_PHY_BYTE28_EX_INTF_FLG 0x80
} __packed;
#endif /* R92C_RX_DESC_H */
@@ -0,0 +1,434 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* 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: releng/12.0/sys/dev/rtwn/rtl8192c/r92c_tx.c 322988 2017-08-28 22:14:16Z avos $");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/if_rtwn_ridx.h>
#include <dev/rtwn/if_rtwn_tx.h>
#include <dev/rtwn/rtl8192c/r92c.h>
#include <dev/rtwn/rtl8192c/r92c_var.h>
#include <dev/rtwn/rtl8192c/r92c_tx_desc.h>
static int
r92c_tx_get_sco(struct rtwn_softc *sc, struct ieee80211_channel *c)
{
if (IEEE80211_IS_CHAN_HT40U(c))
return (R92C_TXDW4_SCO_SCA);
else
return (R92C_TXDW4_SCO_SCB);
}
static void
r92c_tx_set_ht40(struct rtwn_softc *sc, void *buf, struct ieee80211_node *ni)
{
struct r92c_tx_desc *txd = (struct r92c_tx_desc *)buf;
if (ni->ni_chan != IEEE80211_CHAN_ANYC &&
IEEE80211_IS_CHAN_HT40(ni->ni_chan)) {
int extc_offset;
extc_offset = r92c_tx_get_sco(sc, ni->ni_chan);
txd->txdw4 |= htole32(R92C_TXDW4_DATA_BW40);
txd->txdw4 |= htole32(SM(R92C_TXDW4_DATA_SCO, extc_offset));
}
}
static void
r92c_tx_protection(struct rtwn_softc *sc, struct r92c_tx_desc *txd,
enum ieee80211_protmode mode, uint8_t ridx)
{
struct ieee80211com *ic = &sc->sc_ic;
uint8_t rate;
switch (mode) {
case IEEE80211_PROT_CTSONLY:
txd->txdw4 |= htole32(R92C_TXDW4_CTS2SELF);
break;
case IEEE80211_PROT_RTSCTS:
txd->txdw4 |= htole32(R92C_TXDW4_RTSEN);
break;
default:
break;
}
if (mode == IEEE80211_PROT_CTSONLY ||
mode == IEEE80211_PROT_RTSCTS) {
if (ridx >= RTWN_RIDX_HT_MCS(0))
rate = rtwn_ctl_mcsrate(ic->ic_rt, ridx);
else
rate = ieee80211_ctl_rate(ic->ic_rt, ridx2rate[ridx]);
ridx = rate2ridx(rate);
txd->txdw4 |= htole32(SM(R92C_TXDW4_RTSRATE, ridx));
/* RTS rate fallback limit (max). */
txd->txdw5 |= htole32(SM(R92C_TXDW5_RTSRATE_FB_LMT, 0xf));
if (RTWN_RATE_IS_CCK(ridx) && ridx != RTWN_RIDX_CCK1 &&
(ic->ic_flags & IEEE80211_F_SHPREAMBLE))
txd->txdw4 |= htole32(R92C_TXDW4_RTS_SHORT);
}
}
static void
r92c_tx_raid(struct rtwn_softc *sc, struct r92c_tx_desc *txd,
struct ieee80211_node *ni, int ismcast)
{
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = ni->ni_vap;
struct ieee80211_channel *chan;
enum ieee80211_phymode mode;
uint8_t raid;
chan = (ni->ni_chan != IEEE80211_CHAN_ANYC) ?
ni->ni_chan : ic->ic_curchan;
mode = ieee80211_chan2mode(chan);
/* NB: group addressed frames are done at 11bg rates for now */
if (ismcast || !(ni->ni_flags & IEEE80211_NODE_HT)) {
switch (mode) {
case IEEE80211_MODE_11B:
case IEEE80211_MODE_11G:
break;
case IEEE80211_MODE_11NG:
mode = IEEE80211_MODE_11G;
break;
default:
device_printf(sc->sc_dev, "unknown mode(1) %d!\n",
ic->ic_curmode);
return;
}
}
switch (mode) {
case IEEE80211_MODE_11B:
raid = R92C_RAID_11B;
break;
case IEEE80211_MODE_11G:
if (vap->iv_flags & IEEE80211_F_PUREG)
raid = R92C_RAID_11G;
else
raid = R92C_RAID_11BG;
break;
case IEEE80211_MODE_11NG:
if (vap->iv_flags_ht & IEEE80211_FHT_PUREN)
raid = R92C_RAID_11N;
else
raid = R92C_RAID_11BGN;
break;
default:
device_printf(sc->sc_dev, "unknown mode(2) %d!\n", mode);
return;
}
txd->txdw1 |= htole32(SM(R92C_TXDW1_RAID, raid));
}
/* XXX move to device-independent layer */
static void
r92c_tx_set_sgi(struct rtwn_softc *sc, void *buf, struct ieee80211_node *ni)
{
struct r92c_tx_desc *txd = (struct r92c_tx_desc *)buf;
struct ieee80211vap *vap = ni->ni_vap;
if ((vap->iv_flags_ht & IEEE80211_FHT_SHORTGI20) && /* HT20 */
(ni->ni_htcap & IEEE80211_HTCAP_SHORTGI20))
txd->txdw5 |= htole32(R92C_TXDW5_SGI);
else if (ni->ni_chan != IEEE80211_CHAN_ANYC && /* HT40 */
IEEE80211_IS_CHAN_HT40(ni->ni_chan) &&
(ni->ni_htcap & IEEE80211_HTCAP_SHORTGI40) &&
(vap->iv_flags_ht & IEEE80211_FHT_SHORTGI40))
txd->txdw5 |= htole32(R92C_TXDW5_SGI);
}
void
r92c_tx_enable_ampdu(void *buf, int enable)
{
struct r92c_tx_desc *txd = (struct r92c_tx_desc *)buf;
if (enable)
txd->txdw1 |= htole32(R92C_TXDW1_AGGEN);
else
txd->txdw1 |= htole32(R92C_TXDW1_AGGBK);
}
void
r92c_tx_setup_hwseq(void *buf)
{
struct r92c_tx_desc *txd = (struct r92c_tx_desc *)buf;
txd->txdw4 |= htole32(R92C_TXDW4_HWSEQ_EN);
}
void
r92c_tx_setup_macid(void *buf, int id)
{
struct r92c_tx_desc *txd = (struct r92c_tx_desc *)buf;
txd->txdw1 |= htole32(SM(R92C_TXDW1_MACID, id));
}
void
r92c_fill_tx_desc(struct rtwn_softc *sc, struct ieee80211_node *ni,
struct mbuf *m, void *buf, uint8_t ridx, int maxretry)
{
#ifndef RTWN_WITHOUT_UCODE
struct r92c_softc *rs = sc->sc_priv;
#endif
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = ni->ni_vap;
struct rtwn_vap *uvp = RTWN_VAP(vap);
struct ieee80211_frame *wh;
struct r92c_tx_desc *txd;
enum ieee80211_protmode prot;
uint8_t type, tid, qos, qsel;
int hasqos, ismcast, macid;
wh = mtod(m, struct ieee80211_frame *);
type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
hasqos = IEEE80211_QOS_HAS_SEQ(wh);
ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
/* Select TX ring for this frame. */
if (hasqos) {
qos = ((const struct ieee80211_qosframe *)wh)->i_qos[0];
tid = qos & IEEE80211_QOS_TID;
} else {
qos = 0;
tid = 0;
}
/* Fill Tx descriptor. */
txd = (struct r92c_tx_desc *)buf;
txd->flags0 |= R92C_FLAGS0_LSG | R92C_FLAGS0_FSG;
if (ismcast)
txd->flags0 |= R92C_FLAGS0_BMCAST;
if (!ismcast) {
struct rtwn_node *un = RTWN_NODE(ni);
/* Unicast frame, check if an ACK is expected. */
if (!qos || (qos & IEEE80211_QOS_ACKPOLICY) !=
IEEE80211_QOS_ACKPOLICY_NOACK) {
txd->txdw5 |= htole32(R92C_TXDW5_RTY_LMT_ENA);
txd->txdw5 |= htole32(SM(R92C_TXDW5_RTY_LMT,
maxretry));
}
macid = un->id;
if (type == IEEE80211_FC0_TYPE_DATA) {
qsel = tid % RTWN_MAX_TID;
rtwn_r92c_tx_enable_ampdu(sc, buf,
(m->m_flags & M_AMPDU_MPDU) != 0);
if (m->m_flags & M_AMPDU_MPDU) {
txd->txdw2 |= htole32(SM(R92C_TXDW2_AMPDU_DEN,
vap->iv_ampdu_density));
txd->txdw6 |= htole32(SM(R92C_TXDW6_MAX_AGG,
0x1f)); /* XXX */
}
if (sc->sc_ratectl == RTWN_RATECTL_NET80211) {
txd->txdw2 |= htole32(R92C_TXDW2_CCX_RPT);
sc->sc_tx_n_active++;
#ifndef RTWN_WITHOUT_UCODE
rs->rs_c2h_pending++;
#endif
}
if (RTWN_RATE_IS_CCK(ridx) && ridx != RTWN_RIDX_CCK1 &&
(ic->ic_flags & IEEE80211_F_SHPREAMBLE))
txd->txdw4 |= htole32(R92C_TXDW4_DATA_SHPRE);
prot = IEEE80211_PROT_NONE;
if (ridx >= RTWN_RIDX_HT_MCS(0)) {
r92c_tx_set_ht40(sc, txd, ni);
r92c_tx_set_sgi(sc, txd, ni);
prot = ic->ic_htprotmode;
} else if (ic->ic_flags & IEEE80211_F_USEPROT)
prot = ic->ic_protmode;
/* XXX fix last comparison for A-MSDU (in net80211) */
/* XXX A-MPDU? */
if (m->m_pkthdr.len + IEEE80211_CRC_LEN >
vap->iv_rtsthreshold &&
vap->iv_rtsthreshold != IEEE80211_RTS_MAX)
prot = IEEE80211_PROT_RTSCTS;
/* NB: checks for ht40 / short bits (set above). */
if (prot != IEEE80211_PROT_NONE)
r92c_tx_protection(sc, txd, prot, ridx);
} else /* IEEE80211_FC0_TYPE_MGT */
qsel = R92C_TXDW1_QSEL_MGNT;
} else {
macid = RTWN_MACID_BC;
qsel = R92C_TXDW1_QSEL_MGNT;
}
txd->txdw1 |= htole32(SM(R92C_TXDW1_QSEL, qsel));
rtwn_r92c_tx_setup_macid(sc, txd, macid);
txd->txdw5 |= htole32(SM(R92C_TXDW5_DATARATE, ridx));
/* Data rate fallback limit (max). */
txd->txdw5 |= htole32(SM(R92C_TXDW5_DATARATE_FB_LMT, 0x1f));
txd->txdw4 |= htole32(SM(R92C_TXDW4_PORT_ID, uvp->id));
r92c_tx_raid(sc, txd, ni, ismcast);
/* Force this rate if needed. */
if (sc->sc_ratectl != RTWN_RATECTL_FW)
txd->txdw4 |= htole32(R92C_TXDW4_DRVRATE);
if (!hasqos) {
/* Use HW sequence numbering for non-QoS frames. */
rtwn_r92c_tx_setup_hwseq(sc, txd);
txd->txdw4 |= htole32(SM(R92C_TXDW4_SEQ_SEL, uvp->id));
} else {
uint16_t seqno;
if (m->m_flags & M_AMPDU_MPDU) {
seqno = ni->ni_txseqs[tid];
ni->ni_txseqs[tid]++;
} else
seqno = M_SEQNO_GET(m) % IEEE80211_SEQ_RANGE;
/* Set sequence number. */
txd->txdseq = htole16(seqno);
}
}
void
r92c_fill_tx_desc_raw(struct rtwn_softc *sc, struct ieee80211_node *ni,
struct mbuf *m, void *buf, const struct ieee80211_bpf_params *params)
{
struct ieee80211vap *vap = ni->ni_vap;
struct rtwn_vap *uvp = RTWN_VAP(vap);
struct ieee80211_frame *wh;
struct r92c_tx_desc *txd;
uint8_t ridx;
int ismcast;
/* XXX TODO: 11n checks, matching r92c_fill_tx_desc() */
wh = mtod(m, struct ieee80211_frame *);
ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
ridx = rate2ridx(params->ibp_rate0);
/* Fill Tx descriptor. */
txd = (struct r92c_tx_desc *)buf;
txd->flags0 |= R92C_FLAGS0_LSG | R92C_FLAGS0_FSG;
if (ismcast)
txd->flags0 |= R92C_FLAGS0_BMCAST;
if ((params->ibp_flags & IEEE80211_BPF_NOACK) == 0) {
txd->txdw5 |= htole32(R92C_TXDW5_RTY_LMT_ENA);
txd->txdw5 |= htole32(SM(R92C_TXDW5_RTY_LMT,
params->ibp_try0));
}
if (params->ibp_flags & IEEE80211_BPF_RTS)
r92c_tx_protection(sc, txd, IEEE80211_PROT_RTSCTS, ridx);
if (params->ibp_flags & IEEE80211_BPF_CTS)
r92c_tx_protection(sc, txd, IEEE80211_PROT_CTSONLY, ridx);
rtwn_r92c_tx_setup_macid(sc, txd, RTWN_MACID_BC);
txd->txdw1 |= htole32(SM(R92C_TXDW1_QSEL, R92C_TXDW1_QSEL_MGNT));
/* Set TX rate index. */
txd->txdw5 |= htole32(SM(R92C_TXDW5_DATARATE, ridx));
txd->txdw5 |= htole32(SM(R92C_TXDW5_DATARATE_FB_LMT, 0x1f));
txd->txdw4 |= htole32(SM(R92C_TXDW4_PORT_ID, uvp->id));
txd->txdw4 |= htole32(R92C_TXDW4_DRVRATE);
r92c_tx_raid(sc, txd, ni, ismcast);
if (!IEEE80211_QOS_HAS_SEQ(wh)) {
/* Use HW sequence numbering for non-QoS frames. */
rtwn_r92c_tx_setup_hwseq(sc, txd);
txd->txdw4 |= htole32(SM(R92C_TXDW4_SEQ_SEL, uvp->id));
} else {
/* Set sequence number. */
txd->txdseq |= htole16(M_SEQNO_GET(m) % IEEE80211_SEQ_RANGE);
}
}
void
r92c_fill_tx_desc_null(struct rtwn_softc *sc, void *buf, int is11b,
int qos, int id)
{
struct r92c_tx_desc *txd = (struct r92c_tx_desc *)buf;
txd->flags0 = R92C_FLAGS0_FSG | R92C_FLAGS0_LSG | R92C_FLAGS0_OWN;
txd->txdw1 = htole32(
SM(R92C_TXDW1_QSEL, R92C_TXDW1_QSEL_MGNT));
txd->txdw4 = htole32(R92C_TXDW4_DRVRATE);
txd->txdw4 |= htole32(SM(R92C_TXDW4_PORT_ID, id));
if (is11b) {
txd->txdw5 = htole32(SM(R92C_TXDW5_DATARATE,
RTWN_RIDX_CCK1));
} else {
txd->txdw5 = htole32(SM(R92C_TXDW5_DATARATE,
RTWN_RIDX_OFDM6));
}
if (!qos) {
rtwn_r92c_tx_setup_hwseq(sc, txd);
txd->txdw4 |= htole32(SM(R92C_TXDW4_SEQ_SEL, id));
}
}
uint8_t
r92c_tx_radiotap_flags(const void *buf)
{
const struct r92c_tx_desc *txd = buf;
uint8_t flags;
flags = 0;
if (txd->txdw4 & htole32(R92C_TXDW4_DATA_SHPRE))
flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
if (txd->txdw5 & htole32(R92C_TXDW5_SGI))
flags |= IEEE80211_RADIOTAP_F_SHORTGI;
return (flags);
}
@@ -0,0 +1,122 @@
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $
* $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/r92c_tx_desc.h 311948 2017-01-11 23:32:40Z avos $
*/
#ifndef R92C_TX_DESC_H
#define R92C_TX_DESC_H
/* Tx MAC descriptor (common part). */
struct r92c_tx_desc {
uint16_t pktlen;
uint8_t offset;
uint8_t flags0;
#define R92C_FLAGS0_BMCAST 0x01
#define R92C_FLAGS0_LSG 0x04
#define R92C_FLAGS0_FSG 0x08
#define R92C_FLAGS0_OWN 0x80
uint32_t txdw1;
#define R92C_TXDW1_MACID_M 0x0000001f
#define R92C_TXDW1_MACID_S 0
#define R92C_TXDW1_AGGEN 0x00000020
#define R92C_TXDW1_AGGBK 0x00000040
#define R92C_TXDW1_QSEL_M 0x00001f00
#define R92C_TXDW1_QSEL_S 8
#define R92C_TXDW1_QSEL_BE 0x00 /* or 0x03 */
#define R92C_TXDW1_QSEL_BK 0x01 /* or 0x02 */
#define R92C_TXDW1_QSEL_VI 0x04 /* or 0x05 */
#define R92C_TXDW1_QSEL_VO 0x06 /* or 0x07 */
#define RTWN_MAX_TID 8
#define R92C_TXDW1_QSEL_BEACON 0x10
#define R92C_TXDW1_QSEL_MGNT 0x12
#define R92C_TXDW1_RAID_M 0x000f0000
#define R92C_TXDW1_RAID_S 16
#define R92C_TXDW1_CIPHER_M 0x00c00000
#define R92C_TXDW1_CIPHER_S 22
#define R92C_TXDW1_CIPHER_NONE 0
#define R92C_TXDW1_CIPHER_RC4 1
#define R92C_TXDW1_CIPHER_AES 3
#define R92C_TXDW1_PKTOFF_M 0x7c000000
#define R92C_TXDW1_PKTOFF_S 26
uint32_t txdw2;
#define R92C_TXDW2_CCX_RPT 0x00080000
#define R92C_TXDW2_AMPDU_DEN_M 0x00700000
#define R92C_TXDW2_AMPDU_DEN_S 20
uint16_t txdw3;
uint16_t txdseq;
uint32_t txdw4;
#define R92C_TXDW4_RTSRATE_M 0x0000001f
#define R92C_TXDW4_RTSRATE_S 0
#define R92C_TXDW4_SEQ_SEL_M 0x00000040
#define R92C_TXDW4_SEQ_SEL_S 6
#define R92C_TXDW4_HWSEQ_EN 0x00000080
#define R92C_TXDW4_DRVRATE 0x00000100
#define R92C_TXDW4_CTS2SELF 0x00000800
#define R92C_TXDW4_RTSEN 0x00001000
#define R92C_TXDW4_HWRTSEN 0x00002000
#define R92C_TXDW4_PORT_ID_M 0x00004000
#define R92C_TXDW4_PORT_ID_S 14
#define R92C_TXDW4_DATA_SCO_M 0x00300000
#define R92C_TXDW4_DATA_SCO_S 20
#define R92C_TXDW4_SCO_SCA 1
#define R92C_TXDW4_SCO_SCB 2
#define R92C_TXDW4_DATA_SHPRE 0x01000000
#define R92C_TXDW4_DATA_BW40 0x02000000
#define R92C_TXDW4_RTS_SHORT 0x04000000
#define R92C_TXDW4_RTS_BW40 0x08000000
#define R92C_TXDW4_RTS_SCO_M 0x30000000
#define R92C_TXDW4_RTS_SCO_S 28
uint32_t txdw5;
#define R92C_TXDW5_DATARATE_M 0x0000003f
#define R92C_TXDW5_DATARATE_S 0
#define R92C_TXDW5_SGI 0x00000040
#define R92C_TXDW5_DATARATE_FB_LMT_M 0x00001f00
#define R92C_TXDW5_DATARATE_FB_LMT_S 8
#define R92C_TXDW5_RTSRATE_FB_LMT_M 0x0001e000
#define R92C_TXDW5_RTSRATE_FB_LMT_S 13
#define R92C_TXDW5_RTY_LMT_ENA 0x00020000
#define R92C_TXDW5_RTY_LMT_M 0x00fc0000
#define R92C_TXDW5_RTY_LMT_S 18
#define R92C_TXDW5_AGGNUM_M 0xff000000
#define R92C_TXDW5_AGGNUM_S 24
uint32_t txdw6;
#define R92C_TXDW6_MAX_AGG_M 0x0000f800
#define R92C_TXDW6_MAX_AGG_S 11
} __packed __attribute__((aligned(4)));
/* Rate adaptation modes. */
#define R92C_RAID_11BGN 0
#define R92C_RAID_11GN 1
#define R92C_RAID_11BN 2
#define R92C_RAID_11N 3
#define R92C_RAID_11BG 4
#define R92C_RAID_11G 5 /* "pure" 11g */
#define R92C_RAID_11B 6
#endif /* R92C_TX_DESC_H */
@@ -0,0 +1,83 @@
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $
* $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/r92c_var.h 322949 2017-08-27 12:44:56Z avos $
*/
#ifndef R92C_VAR_H
#define R92C_VAR_H
#include <dev/rtwn/rtl8192c/r92c_rom_defs.h>
struct r92c_softc {
uint8_t rs_flags;
#define R92C_FLAG_ASSOCIATED 0x01
uint8_t chip;
#define R92C_CHIP_92C 0x01
#define R92C_CHIP_92C_1T2R 0x02
#define R92C_CHIP_UMC_A_CUT 0x04
#ifndef RTWN_WITHOUT_UCODE
struct callout rs_c2h_report;
int rs_c2h_timeout;
int rs_c2h_pending;
int rs_c2h_paused;
#endif
#define R92C_TX_PAUSED_THRESHOLD 20
void *rs_txpwr;
const void *rs_txagc;
uint8_t board_type;
uint8_t regulatory;
uint8_t crystalcap;
uint8_t pa_setting;
void (*rs_scan_start)(struct ieee80211com *);
void (*rs_scan_end)(struct ieee80211com *);
void (*rs_set_bw20)(struct rtwn_softc *, uint8_t);
void (*rs_get_txpower)(struct rtwn_softc *, int,
struct ieee80211_channel *, uint8_t[]);
void (*rs_set_gain)(struct rtwn_softc *, uint8_t);
void (*rs_tx_enable_ampdu)(void *, int);
void (*rs_tx_setup_hwseq)(void *);
void (*rs_tx_setup_macid)(void *, int);
void (*rs_set_name)(struct rtwn_softc *);
int rf_read_delay[3];
uint32_t rf_chnlbw[R92C_MAX_CHAINS];
};
#define R92C_SOFTC(_sc) ((struct r92c_softc *)((_sc)->sc_priv))
#define rtwn_r92c_set_bw20(_sc, _chan) \
((R92C_SOFTC(_sc)->rs_set_bw20)((_sc), (_chan)))
#define rtwn_r92c_get_txpower(_sc, _chain, _c, _power) \
((R92C_SOFTC(_sc)->rs_get_txpower)((_sc), (_chain), (_c), (_power)))
#define rtwn_r92c_set_gain(_sc, _gain) \
((R92C_SOFTC(_sc)->rs_set_gain)((_sc), (_gain)))
#define rtwn_r92c_tx_enable_ampdu(_sc, _buf, _enable) \
((R92C_SOFTC(_sc)->rs_tx_enable_ampdu)((_buf), (_enable)))
#define rtwn_r92c_tx_setup_hwseq(_sc, _buf) \
((R92C_SOFTC(_sc)->rs_tx_setup_hwseq)((_buf)))
#define rtwn_r92c_tx_setup_macid(_sc, _buf, _id) \
((R92C_SOFTC(_sc)->rs_tx_setup_macid)((_buf), (_id)))
#define rtwn_r92c_set_name(_sc) \
((R92C_SOFTC(_sc)->rs_set_name)((_sc)))
#endif /* R92C_VAR_H */
@@ -0,0 +1,56 @@
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $
* $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/usb/r92cu.h 307529 2016-10-17 20:38:24Z avos $
*/
#ifndef RTL8192CU_H
#define RTL8192CU_H
#include <dev/rtwn/rtl8192c/r92c.h>
/*
* Global definitions.
*/
#define R92CU_PUBQ_NPAGES 231
#define R92CU_TX_PAGE_COUNT 248
/*
* Function declarations.
*/
/* r92cu_init.c */
void r92cu_init_bb(struct rtwn_softc *);
int r92cu_power_on(struct rtwn_softc *);
void r92cu_power_off(struct rtwn_softc *);
void r92cu_init_intr(struct rtwn_softc *);
void r92cu_init_tx_agg(struct rtwn_softc *);
void r92cu_init_rx_agg(struct rtwn_softc *);
void r92cu_post_init(struct rtwn_softc *);
/* r92cu_led.c */
void r92cu_set_led(struct rtwn_softc *, int, int);
/* r92cu_rx.c */
int r92cu_classify_intr(struct rtwn_softc *, void *, int);
int r92cu_align_rx(int, int);
/* r92cu_tx.c */
void r92cu_dump_tx_desc(struct rtwn_softc *, const void *);
#endif /* RTL8192CU_H */
@@ -0,0 +1,247 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/usb/r92cu_attach.c 312680 2017-01-24 02:35:38Z kevlo $");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/if_rtwn_nop.h>
#include <dev/rtwn/usb/rtwn_usb_var.h>
#include <dev/rtwn/rtl8192c/r92c_var.h>
#include <dev/rtwn/rtl8192c/usb/r92cu.h>
#include <dev/rtwn/rtl8192c/usb/r92cu_priv.h>
#include <dev/rtwn/rtl8192c/usb/r92cu_reg.h>
#include <dev/rtwn/rtl8192c/usb/r92cu_tx_desc.h>
static struct rtwn_r92c_txpwr r92c_txpwr;
void r92cu_attach(struct rtwn_usb_softc *);
static void
r92cu_postattach(struct rtwn_softc *sc)
{
struct r92c_softc *rs = sc->sc_priv;
struct ieee80211com *ic = &sc->sc_ic;
if (!(rs->chip & R92C_CHIP_92C) &&
rs->board_type == R92C_BOARD_TYPE_HIGHPA) {
sc->agc_prog = &rtl8188ru_agc[0];
sc->agc_size = nitems(rtl8188ru_agc);
rs->rs_txagc = &rtl8188ru_txagc[0];
} else {
sc->agc_prog = &rtl8192ce_agc[0];
sc->agc_size = nitems(rtl8192ce_agc);
rs->rs_txagc = &rtl8192cu_txagc[0];
}
if ((rs->chip & (R92C_CHIP_UMC_A_CUT | R92C_CHIP_92C)) ==
R92C_CHIP_UMC_A_CUT) {
sc->fwname = "rtwn-rtl8192cfwU";
} else {
sc->fwname = "rtwn-rtl8192cfwT";
}
sc->fwsig = 0x88c;
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
r92cu_set_name(struct rtwn_softc *sc)
{
struct r92c_softc *rs = sc->sc_priv;
if (!(rs->chip & R92C_CHIP_92C)) {
if (rs->board_type == R92C_BOARD_TYPE_HIGHPA)
sc->name = "RTL8188RU";
else if (rs->board_type == R92C_BOARD_TYPE_MINICARD)
sc->name = "RTL8188CU-VAU";
else
sc->name = "RTL8188CUS";
} else
sc->name = "RTL8192CU";
}
static void
r92cu_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 = &r92c_txpwr;
rs->rs_set_bw20 = r92c_set_bw20;
rs->rs_get_txpower = r92c_get_txpower;
rs->rs_set_gain = r92c_set_gain;
rs->rs_tx_enable_ampdu = r92c_tx_enable_ampdu;
rs->rs_tx_setup_hwseq = r92c_tx_setup_hwseq;
rs->rs_tx_setup_macid = r92c_tx_setup_macid;
rs->rs_set_name = r92cu_set_name;
#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] = 10;
rs->rf_read_delay[1] = 100;
rs->rf_read_delay[2] = 10;
sc->sc_priv = rs;
}
static void
r92cu_adj_devcaps(struct rtwn_softc *sc)
{
/* XXX Currently broken / incomplete. */
sc->sc_ic.ic_caps &= ~IEEE80211_C_PMGT;
}
void
r92cu_attach(struct rtwn_usb_softc *uc)
{
struct rtwn_softc *sc = &uc->uc_sc;
/* USB part. */
uc->uc_align_rx = r92cu_align_rx;
uc->tx_agg_desc_num = 6;
/* Common part. */
sc->sc_flags = RTWN_FLAG_CAM_FIXED;
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;
sc->sc_dump_tx_desc = r92cu_dump_tx_desc;
sc->sc_tx_radiotap_flags = r92c_tx_radiotap_flags;
sc->sc_rx_radiotap_flags = r92c_rx_radiotap_flags;
sc->sc_get_rx_stats = r92c_get_rx_stats;
sc->sc_get_rssi_cck = r92c_get_rssi_cck;
sc->sc_get_rssi_ofdm = r92c_get_rssi_ofdm;
sc->sc_classify_intr = r92cu_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 = r92c_rf_write;
sc->sc_check_condition = r92c_check_condition;
sc->sc_efuse_postread = r92c_efuse_postread;
sc->sc_parse_rom = r92c_parse_rom;
sc->sc_set_led = r92cu_set_led;
sc->sc_power_on = r92cu_power_on;
sc->sc_power_off = r92cu_power_off;
#ifndef RTWN_WITHOUT_UCODE
sc->sc_fw_reset = r92c_fw_reset;
sc->sc_fw_download_enable = r92c_fw_download_enable;
#endif
sc->sc_llt_init = r92c_llt_init;
sc->sc_set_page_size = r92c_set_page_size;
sc->sc_lc_calib = r92c_lc_calib;
sc->sc_iq_calib = r92c_iq_calib; /* XXX TODO */
sc->sc_read_chipid_vendor = r92c_read_chipid_vendor;
sc->sc_adj_devcaps = r92cu_adj_devcaps;
sc->sc_vap_preattach = rtwn_nop_softc_vap;
sc->sc_postattach = r92cu_postattach;
sc->sc_detach_private = r92c_detach_private;
sc->sc_set_media_status = r92c_joinbss_rpt;
#ifndef RTWN_WITHOUT_UCODE
sc->sc_set_rsvd_page = r92c_set_rsvd_page;
sc->sc_set_pwrmode = r92c_set_pwrmode;
sc->sc_set_rssi = r92c_set_rssi;
#endif
sc->sc_beacon_init = r92c_beacon_init;
sc->sc_beacon_enable = r92c_beacon_enable;
sc->sc_beacon_set_rate = rtwn_nop_void_int;
sc->sc_beacon_select = rtwn_nop_softc_int;
sc->sc_temp_measure = r92c_temp_measure;
sc->sc_temp_read = r92c_temp_read;
sc->sc_init_tx_agg = r92cu_init_tx_agg;
sc->sc_init_rx_agg = r92cu_init_rx_agg;
sc->sc_init_ampdu = r92c_init_ampdu;
sc->sc_init_intr = r92cu_init_intr;
sc->sc_init_edca = r92c_init_edca;
sc->sc_init_bb = r92cu_init_bb;
sc->sc_init_rf = r92c_init_rf;
sc->sc_init_antsel = r92c_init_antsel;
sc->sc_post_init = r92cu_post_init;
sc->sc_init_bcnq1_boundary = rtwn_nop_int_softc;
sc->mac_prog = &rtl8192cu_mac[0];
sc->mac_size = nitems(rtl8192cu_mac);
sc->bb_prog = &rtl8192cu_bb[0];
sc->bb_size = nitems(rtl8192cu_bb);
sc->rf_prog = &rtl8192c_rf[0];
sc->page_count = R92CU_TX_PAGE_COUNT;
sc->pktbuf_count = R92C_TXPKTBUF_COUNT;
sc->ackto = 0x40;
sc->npubqpages = R92CU_PUBQ_NPAGES;
sc->page_size = R92C_TX_PAGE_SIZE;
sc->txdesc_len = sizeof(struct r92cu_tx_desc);
sc->efuse_maxlen = R92C_EFUSE_MAX_LEN;
sc->efuse_maplen = R92C_EFUSE_MAP_LEN;
sc->rx_dma_size = R92C_RX_DMA_BUFFER_SIZE;
sc->macid_limit = R92C_MACID_MAX + 1;
sc->cam_entry_limit = R92C_CAM_ENTRY_COUNT;
sc->fwsize_limit = R92C_MAX_FW_SIZE;
sc->temp_delta = R92C_CALIB_THRESHOLD;
sc->bcn_status_reg[0] = R92C_TDECTRL;
sc->bcn_status_reg[1] = R92C_TDECTRL;
sc->rcr = 0;
r92cu_attach_private(sc);
}
@@ -0,0 +1,391 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* 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: releng/12.0/sys/dev/rtwn/rtl8192c/usb/r92cu_init.c 311347 2017-01-05 02:04:53Z kevlo $");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/if_rtwn_debug.h>
#include <dev/rtwn/usb/rtwn_usb_var.h>
#include <dev/rtwn/rtl8192c/r92c_var.h>
#include <dev/rtwn/rtl8192c/usb/r92cu.h>
#include <dev/rtwn/rtl8192c/usb/r92cu_reg.h>
void
r92cu_init_bb(struct rtwn_softc *sc)
{
/* Enable BB and RF. */
rtwn_setbits_2(sc, R92C_SYS_FUNC_EN, 0,
R92C_SYS_FUNC_EN_BBRSTB | R92C_SYS_FUNC_EN_BB_GLB_RST |
R92C_SYS_FUNC_EN_DIO_RF);
rtwn_write_2(sc, R92C_AFE_PLL_CTRL, 0xdb83);
rtwn_write_1(sc, R92C_RF_CTRL,
R92C_RF_CTRL_EN | R92C_RF_CTRL_RSTB | R92C_RF_CTRL_SDMRSTB);
rtwn_write_1(sc, R92C_SYS_FUNC_EN,
R92C_SYS_FUNC_EN_USBA | R92C_SYS_FUNC_EN_USBD |
R92C_SYS_FUNC_EN_BB_GLB_RST | R92C_SYS_FUNC_EN_BBRSTB);
rtwn_write_1(sc, R92C_LDOHCI12_CTRL, 0x0f);
rtwn_write_1(sc, 0x15, 0xe9);
rtwn_write_1(sc, R92C_AFE_XTAL_CTRL + 1, 0x80);
r92c_init_bb_common(sc);
}
int
r92cu_power_on(struct rtwn_softc *sc)
{
#define RTWN_CHK(res) do { \
if (res != 0) \
return (EIO); \
} while(0)
uint32_t reg;
int ntries;
/* Wait for autoload done bit. */
for (ntries = 0; ntries < 5000; ntries++) {
if (rtwn_read_1(sc, R92C_APS_FSMCO) & R92C_APS_FSMCO_PFM_ALDN)
break;
rtwn_delay(sc, 10);
}
if (ntries == 5000) {
device_printf(sc->sc_dev,
"timeout waiting for chip autoload\n");
return (ETIMEDOUT);
}
/* Unlock ISO/CLK/Power control register. */
RTWN_CHK(rtwn_write_1(sc, R92C_RSV_CTRL, 0));
/* Move SPS into PWM mode. */
RTWN_CHK(rtwn_write_1(sc, R92C_SPS0_CTRL, 0x2b));
/* just in case if power_off() was not properly executed. */
rtwn_delay(sc, 100);
reg = rtwn_read_1(sc, R92C_LDOV12D_CTRL);
if (!(reg & R92C_LDOV12D_CTRL_LDV12_EN)) {
RTWN_CHK(rtwn_write_1(sc, R92C_LDOV12D_CTRL,
reg | R92C_LDOV12D_CTRL_LDV12_EN));
rtwn_delay(sc, 100);
RTWN_CHK(rtwn_setbits_1(sc, R92C_SYS_ISO_CTRL,
R92C_SYS_ISO_CTRL_MD2PP, 0));
}
/* Auto enable WLAN. */
RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, 0,
R92C_APS_FSMCO_APFM_ONMAC, 1));
for (ntries = 0; ntries < 5000; ntries++) {
if (!(rtwn_read_2(sc, R92C_APS_FSMCO) &
R92C_APS_FSMCO_APFM_ONMAC))
break;
rtwn_delay(sc, 10);
}
if (ntries == 5000) {
device_printf(sc->sc_dev,
"timeout waiting for MAC auto ON\n");
return (ETIMEDOUT);
}
/* Enable radio, GPIO and LED functions. */
RTWN_CHK(rtwn_write_2(sc, R92C_APS_FSMCO,
R92C_APS_FSMCO_AFSM_HSUS |
R92C_APS_FSMCO_PDN_EN |
R92C_APS_FSMCO_PFM_ALDN));
/* Release RF digital isolation. */
RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_SYS_ISO_CTRL,
R92C_SYS_ISO_CTRL_DIOR, 0, 1));
/* Initialize MAC. */
RTWN_CHK(rtwn_setbits_1(sc, R92C_APSD_CTRL,
R92C_APSD_CTRL_OFF, 0));
for (ntries = 0; ntries < 1000; ntries++) {
if (!(rtwn_read_1(sc, R92C_APSD_CTRL) &
R92C_APSD_CTRL_OFF_STATUS))
break;
rtwn_delay(sc, 50);
}
if (ntries == 1000) {
device_printf(sc->sc_dev,
"timeout waiting for MAC initialization\n");
return (ETIMEDOUT);
}
/* Enable MAC DMA/WMAC/SCHEDULE/SEC blocks. */
RTWN_CHK(rtwn_setbits_2(sc, R92C_CR, 0,
R92C_CR_HCI_TXDMA_EN | R92C_CR_TXDMA_EN |
R92C_CR_HCI_RXDMA_EN | R92C_CR_RXDMA_EN |
R92C_CR_PROTOCOL_EN | R92C_CR_SCHEDULE_EN |
((sc->sc_hwcrypto != RTWN_CRYPTO_SW) ? R92C_CR_ENSEC : 0) |
R92C_CR_CALTMR_EN));
RTWN_CHK(rtwn_write_1(sc, 0xfe10, 0x19));
return (0);
#undef RTWN_CHK
}
void
r92cu_power_off(struct rtwn_softc *sc)
{
#ifndef RTWN_WITHOUT_UCODE
struct r92c_softc *rs = sc->sc_priv;
#endif
uint32_t reg;
int error;
/* Deinit C2H event handler. */
#ifndef RTWN_WITHOUT_UCODE
callout_stop(&rs->rs_c2h_report);
rs->rs_c2h_paused = 0;
rs->rs_c2h_pending = 0;
rs->rs_c2h_timeout = hz;
#endif
/* Block all Tx queues. */
error = rtwn_write_1(sc, R92C_TXPAUSE, R92C_TX_QUEUE_ALL);
if (error == ENXIO) /* hardware gone */
return;
/* Disable RF */
rtwn_rf_write(sc, 0, 0, 0);
rtwn_write_1(sc, R92C_APSD_CTRL, R92C_APSD_CTRL_OFF);
/* Reset BB state machine */
rtwn_write_1(sc, R92C_SYS_FUNC_EN,
R92C_SYS_FUNC_EN_USBD | R92C_SYS_FUNC_EN_USBA |
R92C_SYS_FUNC_EN_BB_GLB_RST);
rtwn_write_1(sc, R92C_SYS_FUNC_EN,
R92C_SYS_FUNC_EN_USBD | R92C_SYS_FUNC_EN_USBA);
/*
* Reset digital sequence
*/
#ifndef RTWN_WITHOUT_UCODE
if (rtwn_read_1(sc, R92C_MCUFWDL) & R92C_MCUFWDL_RDY) {
/* Reset MCU ready status */
rtwn_write_1(sc, R92C_MCUFWDL, 0);
/* If firmware in ram code, do reset */
r92c_fw_reset(sc, RTWN_FW_RESET_SHUTDOWN);
}
#endif
/* Reset MAC and Enable 8051 */
rtwn_write_1(sc, R92C_SYS_FUNC_EN + 1,
(R92C_SYS_FUNC_EN_CPUEN |
R92C_SYS_FUNC_EN_ELDR |
R92C_SYS_FUNC_EN_HWPDN) >> 8);
/* Reset MCU ready status */
rtwn_write_1(sc, R92C_MCUFWDL, 0);
/* Disable MAC clock */
rtwn_write_2(sc, R92C_SYS_CLKR,
R92C_SYS_CLKR_ANAD16V_EN |
R92C_SYS_CLKR_ANA8M |
R92C_SYS_CLKR_LOADER_EN |
R92C_SYS_CLKR_80M_SSC_DIS |
R92C_SYS_CLKR_SYS_EN |
R92C_SYS_CLKR_RING_EN |
0x4000);
/* Disable AFE PLL */
rtwn_write_1(sc, R92C_AFE_PLL_CTRL, 0x80);
/* Gated AFE DIG_CLOCK */
rtwn_write_2(sc, R92C_AFE_XTAL_CTRL, 0x880F);
/* Isolated digital to PON */
rtwn_write_1(sc, R92C_SYS_ISO_CTRL,
R92C_SYS_ISO_CTRL_MD2PP |
R92C_SYS_ISO_CTRL_PA2PCIE |
R92C_SYS_ISO_CTRL_PD2CORE |
R92C_SYS_ISO_CTRL_IP2MAC |
R92C_SYS_ISO_CTRL_DIOP |
R92C_SYS_ISO_CTRL_DIOE);
/*
* Pull GPIO PIN to balance level and LED control
*/
/* 1. Disable GPIO[7:0] */
rtwn_write_2(sc, R92C_GPIO_IOSEL, 0x0000);
reg = rtwn_read_4(sc, R92C_GPIO_PIN_CTRL) & ~0x0000ff00;
reg |= ((reg << 8) & 0x0000ff00) | 0x00ff0000;
rtwn_write_4(sc, R92C_GPIO_PIN_CTRL, reg);
/* Disable GPIO[10:8] */
rtwn_write_1(sc, R92C_MAC_PINMUX_CFG, 0x00);
reg = rtwn_read_2(sc, R92C_GPIO_IO_SEL) & ~0x00f0;
reg |= (((reg & 0x000f) << 4) | 0x0780);
rtwn_write_2(sc, R92C_GPIO_IO_SEL, reg);
/* Disable LED0 & 1 */
rtwn_write_2(sc, R92C_LEDCFG0, 0x8080);
/*
* Reset digital sequence
*/
/* Disable ELDR clock */
rtwn_write_2(sc, R92C_SYS_CLKR,
R92C_SYS_CLKR_ANAD16V_EN |
R92C_SYS_CLKR_ANA8M |
R92C_SYS_CLKR_LOADER_EN |
R92C_SYS_CLKR_80M_SSC_DIS |
R92C_SYS_CLKR_SYS_EN |
R92C_SYS_CLKR_RING_EN |
0x4000);
/* Isolated ELDR to PON */
rtwn_write_1(sc, R92C_SYS_ISO_CTRL + 1,
(R92C_SYS_ISO_CTRL_DIOR |
R92C_SYS_ISO_CTRL_PWC_EV12V) >> 8);
/*
* Disable analog sequence
*/
/* Disable A15 power */
rtwn_write_1(sc, R92C_LDOA15_CTRL, R92C_LDOA15_CTRL_OBUF);
/* Disable digital core power */
rtwn_setbits_1(sc, R92C_LDOV12D_CTRL,
R92C_LDOV12D_CTRL_LDV12_EN, 0);
/* Enter PFM mode */
rtwn_write_1(sc, R92C_SPS0_CTRL, 0x23);
/* Set USB suspend */
rtwn_write_2(sc, R92C_APS_FSMCO,
R92C_APS_FSMCO_APDM_HOST |
R92C_APS_FSMCO_AFSM_HSUS |
R92C_APS_FSMCO_PFM_ALDN);
/* Lock ISO/CLK/Power control register. */
rtwn_write_1(sc, R92C_RSV_CTRL, 0x0E);
}
void
r92cu_init_intr(struct rtwn_softc *sc)
{
rtwn_write_4(sc, R92C_HISR, 0xffffffff);
rtwn_write_4(sc, R92C_HIMR, 0xffffffff);
}
void
r92cu_init_tx_agg(struct rtwn_softc *sc)
{
struct rtwn_usb_softc *uc = RTWN_USB_SOFTC(sc);
uint32_t reg;
reg = rtwn_read_4(sc, R92C_TDECTRL);
reg = RW(reg, R92C_TDECTRL_BLK_DESC_NUM, uc->tx_agg_desc_num);
rtwn_write_4(sc, R92C_TDECTRL, reg);
}
void
r92cu_init_rx_agg(struct rtwn_softc *sc)
{
/* Rx aggregation (DMA & USB). */
rtwn_setbits_1(sc, R92C_TRXDMA_CTRL, 0,
R92C_TRXDMA_CTRL_RXDMA_AGG_EN);
rtwn_setbits_1(sc, R92C_USB_SPECIAL_OPTION, 0,
R92C_USB_SPECIAL_OPTION_AGG_EN);
/* XXX dehardcode */
rtwn_write_1(sc, R92C_RXDMA_AGG_PG_TH, 48);
rtwn_write_1(sc, R92C_USB_DMA_AGG_TO, 4);
rtwn_write_1(sc, R92C_USB_AGG_TH, 8);
rtwn_write_1(sc, R92C_USB_AGG_TO, 6);
}
void
r92cu_post_init(struct rtwn_softc *sc)
{
/* Perform LO and IQ calibrations. */
r92c_iq_calib(sc);
/* Perform LC calibration. */
r92c_lc_calib(sc);
/* Fix USB interference issue. */
rtwn_write_1(sc, 0xfe40, 0xe0);
rtwn_write_1(sc, 0xfe41, 0x8d);
rtwn_write_1(sc, 0xfe42, 0x80);
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 firmware RA does not work yet */
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;
}
@@ -0,0 +1,66 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/usb/r92cu_led.c 307529 2016-10-17 20:38:24Z avos $");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/rtl8192c/r92c_reg.h>
#include <dev/rtwn/rtl8192c/usb/r92cu.h>
void
r92cu_set_led(struct rtwn_softc *sc, int led, int on)
{
uint8_t reg;
if (led == RTWN_LED_LINK) {
reg = rtwn_read_1(sc, R92C_LEDCFG0) & 0x70;
if (!on)
reg |= R92C_LEDCFG0_DIS;
rtwn_write_1(sc, R92C_LEDCFG0, reg);
sc->ledlink = on; /* Save LED state. */
}
}
@@ -0,0 +1,322 @@
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $
* $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/usb/r92cu_priv.h 307529 2016-10-17 20:38:24Z avos $
*/
#ifndef R92CU_PRIV_H
#define R92CU_PRIV_H
#include <dev/rtwn/rtl8192c/r92c_priv.h>
/*
* MAC initialization values.
*/
static const struct rtwn_mac_prog rtl8192cu_mac[] = {
{ 0x420, 0x80 }, { 0x423, 0x00 }, { 0x430, 0x00 }, { 0x431, 0x00 },
{ 0x432, 0x00 }, { 0x433, 0x01 }, { 0x434, 0x04 }, { 0x435, 0x05 },
{ 0x436, 0x06 }, { 0x437, 0x07 }, { 0x438, 0x00 }, { 0x439, 0x00 },
{ 0x43a, 0x00 }, { 0x43b, 0x01 }, { 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 }, { 0x462, 0x08 },
{ 0x463, 0x03 }, { 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 },
{ 0x515, 0x10 }, { 0x516, 0x0a }, { 0x517, 0x10 }, { 0x51a, 0x16 },
{ 0x524, 0x0f }, { 0x525, 0x4f }, { 0x546, 0x40 }, { 0x547, 0x00 },
{ 0x550, 0x10 }, { 0x551, 0x10 }, { 0x559, 0x02 }, { 0x55a, 0x02 },
{ 0x55d, 0xff }, { 0x605, 0x30 }, { 0x608, 0x0e }, { 0x609, 0x2a },
{ 0x652, 0x20 }, { 0x63c, 0x0a }, { 0x63d, 0x0e }, { 0x63e, 0x0a },
{ 0x63f, 0x0e }, { 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 rtl8192cu_bb_regs0_88ru[] = {
0x024, 0x028, 0x040, 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, 0xa00, 0xa04, 0xa08, 0xa0c, 0xa10, 0xa14, 0xa18,
0xa1c, 0xa20, 0xa24, 0xa28, 0xa2c, 0xa70, 0xa74, 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
}, rtl8192cu_bb_regs0[] = {
0x024, 0x028, 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, 0xa00, 0xa04, 0xa08, 0xa0c, 0xa10, 0xa14, 0xa18, 0xa1c,
0xa20, 0xa24, 0xa28, 0xa2c, 0xa70, 0xa74, 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
}, rtl8192cu_bb_regs1[] = {
0xc74, 0xc78, 0xc7c, 0xc80, 0xc84, 0xc88
}, rtl8192cu_bb_regs2[] = {
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
}, rtl8192cu_bb_regs5_88ru[] = {
0xe60, 0xe68, 0xe6c, 0xe70, 0xe74, 0xe78, 0xe7c, 0xe80, 0xe84,
0xe88, 0xe8c, 0xed0, 0xed4, 0xed8, 0xedc, 0xee0, 0xeec, 0xee8,
0xf14, 0xf4c, 0xf00
};
static const uint32_t rtl8192cu_bb_vals0_88cu[] = {
0x0011800d, 0x00ffdb83, 0x80040000, 0x00000001, 0x0000fc00,
0x0000000a, 0x10005388, 0x020c3d10, 0x02200385, 0x00000000,
0x01000100, 0x00390004, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00010000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x569a569a,
0x001b25a4, 0x66e60230, 0x061f0130, 0x00000000, 0x32323200,
0x07000700, 0x22004000, 0x00000808, 0x00000000, 0xc0083070,
0x000004d5, 0x00000000, 0xccc000c0, 0x00000800, 0xfffffffe,
0x40302010, 0x00706050, 0x00000000, 0x00000023, 0x00000000,
0x81121111, 0x00d047c8, 0x80ff000c, 0x8c838300, 0x2e68120f,
0x9500bb78, 0x11144028, 0x00881117, 0x89140f00, 0x1a1b0000,
0x090e1317, 0x00000204, 0x00d30000, 0x101fbf00, 0x00000007,
0x48071d40, 0x03a05611, 0x000000e4, 0x6c6c6c6c, 0x08800000,
0x40000100, 0x08800000, 0x40000100, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x69e9ac44, 0x469652cf, 0x49795994,
0x0a97971c, 0x1f7c403f, 0x000100b7, 0xec020107, 0x007f037f,
0x6954341e, 0x43bc0094, 0x6954341e, 0x433c0094, 0x00000000,
0x5116848b, 0x47c00bff, 0x00000036, 0x2c7f000d
}, rtl8192cu_bb_vals0_88ru[] = {
0x0011800d, 0x00ffdb83, 0x000c0004, 0x80040000, 0x00000001,
0x0000fc00, 0x0000000a, 0x10005388, 0x020c3d10, 0x02200385,
0x00000000, 0x01000100, 0x00390204, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00010000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x569a569a, 0x001b25a4, 0x66e60230, 0x061f0130, 0x00000000,
0x32323200, 0x03000300, 0x22004000, 0x00000808, 0x00ffc3f1,
0xc0083070, 0x000004d5, 0x00000000, 0xccc000c0, 0x00000800,
0xfffffffe, 0x40302010, 0x00706050, 0x00000000, 0x00000023,
0x00000000, 0x81121111, 0x00d047c8, 0x80ff000c, 0x8c838300,
0x2e68120f, 0x9500bb78, 0x11144028, 0x00881117, 0x89140f00,
0x15160000, 0x070b0f12, 0x00000104, 0x00d30000, 0x101fbf00,
0x00000007, 0x48071d40, 0x03a05611, 0x000000e4, 0x6c6c6c6c,
0x08800000, 0x40000100, 0x08800000, 0x40000100, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x69e9ac44, 0x469652cf,
0x49795994, 0x0a97971c, 0x1f7c403f, 0x000100b7, 0xec020107,
0x007f037f, 0x6954342e, 0x43bc0094, 0x6954342f, 0x433c0094,
0x00000000, 0x5116848b, 0x47c00bff, 0x00000036, 0x2c56000d
}, rtl8192cu_bb_vals0_92ce_92cu[] = {
0x0011800d, 0x00ffdb83, 0x80040002, 0x00000003, 0x0000fc00,
0x0000000a, 0x10005388, 0x020c3d10, 0x02200385, 0x00000000,
0x01000100, 0x00390004, 0x01000100, 0x00390004, 0x27272727,
0x27272727, 0x27272727, 0x27272727, 0x00010000, 0x00010000,
0x27272727, 0x27272727, 0x00000000, 0x00000000, 0x569a569a,
0x0c1b25a4, 0x66e60230, 0x061f0130, 0x27272727, 0x2b2b2b27,
0x07000700, 0x22184000, 0x08080808, 0x00000000, 0xc0083070,
0x000004d5, 0x00000000, 0xcc0000c0, 0x00000800, 0xfffffffe,
0x40302010, 0x00706050, 0x00000000, 0x00000023, 0x00000000,
0x81121313, 0x00d047c8, 0x80ff000c, 0x8c838300, 0x2e68120f,
0x9500bb78, 0x11144028, 0x00881117, 0x89140f00, 0x1a1b0000,
0x090e1317, 0x00000204, 0x00d30000, 0x101fbf00, 0x00000007,
0x48071d40, 0x03a05633, 0x000000e4, 0x6c6c6c6c, 0x08800000,
0x40000100, 0x08800000, 0x40000100, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x69e9ac44, 0x469652cf, 0x49795994,
0x0a97971c, 0x1f7c403f, 0x000100b7, 0xec020107, 0x007f037f,
0x6954341e, 0x43bc0094, 0x6954341e, 0x433c0094, 0x00000000,
0x5116848b, 0x47c00bff, 0x00000036, 0x2c7f000d
}, rtl8192cu_bb_vals1_88ru[] = {
0x018610db, 0x0000001f, 0x00b91612, 0x24000090, 0x20f60000,
0x24000090
}, rtl8192cu_bb_vals1_92cu[] = {
0x0186115b, 0x0000001f, 0x00b99612, 0x40000100, 0x20f60000,
0x40000100
}, rtl8192cu_bb_vals1_88cu_92ce[] = {
0x018610db, 0x0000001f, 0x00b91612, 0x40000100, 0x20f60000,
0x40000100
}, rtl8192cu_bb_vals2[] = {
0x20200000, 0x00121820, 0x00000000, 0x00121820, 0x00007f7f,
0x00000000, 0x00000080, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x28000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x64b22427,
0x00766932, 0x00222222, 0x00000000, 0x37644302, 0x2f97d40c,
0x00080740
}, rtl8192cu_bb_vals5_88cu[] = {
0x00000008, 0x001b25a4, 0x631b25a0, 0x631b25a0, 0x081b25a0,
0x081b25a0, 0x081b25a0, 0x081b25a0, 0x631b25a0, 0x081b25a0,
0x631b25a0, 0x631b25a0, 0x631b25a0, 0x631b25a0, 0x001b25a0,
0x001b25a0, 0x6b1b25a0, 0x00000003, 0x00000000, 0x00000300
}, rtl8192cu_bb_vals5_88ru[] = {
0x00000010, 0x001b25a4, 0x631b25a0, 0x631b25a0, 0x081b25a0,
0x081b25a0, 0x081b25a0, 0x081b25a0, 0x631b25a0, 0x081b25a0,
0x631b25a0, 0x631b25a0, 0x631b25a0, 0x631b25a0, 0x001b25a0,
0x001b25a0, 0x6b1b25a0, 0x31555448, 0x00000003, 0x00000000,
0x00000300
};
static const struct rtwn_bb_prog rtl8192cu_bb[] = {
/* RTL8188CE / RTL8188CU. */
{
nitems(rtl8192cu_bb_regs0),
rtl8192cu_bb_regs0,
rtl8192cu_bb_vals0_88cu,
{ R92C_COND_RTL8188CU | R92C_COND_RTL8188CE },
/* RTL8188RU. */
&(const struct rtwn_bb_prog){
nitems(rtl8192cu_bb_regs0_88ru),
rtl8192cu_bb_regs0_88ru,
rtl8192cu_bb_vals0_88ru,
{ R92C_COND_RTL8188RU },
/* Others. */
&(const struct rtwn_bb_prog){
nitems(rtl8192cu_bb_regs0),
rtl8192cu_bb_regs0,
rtl8192cu_bb_vals0_92ce_92cu,
{ 0 },
NULL
}
}
},
/* RTL8188RU. */
{
nitems(rtl8192cu_bb_regs1),
rtl8192cu_bb_regs1,
rtl8192cu_bb_vals1_88ru,
{ R92C_COND_RTL8188RU },
/* RTL8192CU. */
&(const struct rtwn_bb_prog){
nitems(rtl8192cu_bb_regs1),
rtl8192cu_bb_regs1,
rtl8192cu_bb_vals1_92cu,
{ R92C_COND_RTL8192CU },
/* Others. */
&(const struct rtwn_bb_prog){
nitems(rtl8192cu_bb_regs1),
rtl8192cu_bb_regs1,
rtl8192cu_bb_vals1_88cu_92ce,
{ 0 },
NULL
}
}
},
{
nitems(rtl8192cu_bb_regs2),
rtl8192cu_bb_regs2,
rtl8192cu_bb_vals2,
{ 0 },
NULL
},
/* RTL8192CE / RTL8192CU. */
{
nitems(rtl8192c_bb_regs3),
rtl8192c_bb_regs3,
rtl8192c_bb_vals3_92ce_92cu,
{ R92C_COND_RTL8192C },
/* Others. */
&(const struct rtwn_bb_prog){
nitems(rtl8192c_bb_regs3),
rtl8192c_bb_regs3,
rtl8192c_bb_vals3_88cu_88ru,
{ 0 },
NULL
}
},
{
nitems(rtl8192c_bb_regs4),
rtl8192c_bb_regs4,
rtl8192c_bb_vals4,
{ 0 },
NULL
},
/* RTL8188CE / RTL8188CU. */
{
nitems(rtl8192c_bb_regs5),
rtl8192c_bb_regs5,
rtl8192cu_bb_vals5_88cu,
{ R92C_COND_RTL8188CU | R92C_COND_RTL8188CE },
/* RTL8188RU. */
&(const struct rtwn_bb_prog){
nitems(rtl8192cu_bb_regs5_88ru),
rtl8192cu_bb_regs5_88ru,
rtl8192cu_bb_vals5_88ru,
{ R92C_COND_RTL8188RU },
/* Others. */
&(const struct rtwn_bb_prog){
nitems(rtl8192c_bb_regs5),
rtl8192c_bb_regs5,
rtl8192c_bb_vals5_92ce_92cu,
{ 0 },
NULL
}
}
}
};
static const uint32_t rtl8188ru_agc_vals[] = {
0x7b000001, 0x7b010001, 0x7b020001, 0x7b030001, 0x7b040001,
0x7b050001, 0x7b060001, 0x7b070001, 0x7b080001, 0x7a090001,
0x790a0001, 0x780b0001, 0x770c0001, 0x760d0001, 0x750e0001,
0x740f0001, 0x73100001, 0x72110001, 0x71120001, 0x70130001,
0x6f140001, 0x6e150001, 0x6d160001, 0x6c170001, 0x6b180001,
0x6a190001, 0x691a0001, 0x681b0001, 0x671c0001, 0x661d0001,
0x651e0001, 0x641f0001, 0x63200001, 0x62210001, 0x61220001,
0x60230001, 0x46240001, 0x45250001, 0x44260001, 0x43270001,
0x42280001, 0x41290001, 0x402a0001, 0x262b0001, 0x252c0001,
0x242d0001, 0x232e0001, 0x222f0001, 0x21300001, 0x20310001,
0x06320001, 0x05330001, 0x04340001, 0x03350001, 0x02360001,
0x01370001, 0x00380001, 0x00390001, 0x003a0001, 0x003b0001,
0x003c0001, 0x003d0001, 0x003e0001, 0x003f0001, 0x7b400001,
0x7b410001, 0x7b420001, 0x7b430001, 0x7b440001, 0x7b450001,
0x7b460001, 0x7b470001, 0x7b480001, 0x7a490001, 0x794a0001,
0x784b0001, 0x774c0001, 0x764d0001, 0x754e0001, 0x744f0001,
0x73500001, 0x72510001, 0x71520001, 0x70530001, 0x6f540001,
0x6e550001, 0x6d560001, 0x6c570001, 0x6b580001, 0x6a590001,
0x695a0001, 0x685b0001, 0x675c0001, 0x665d0001, 0x655e0001,
0x645f0001, 0x63600001, 0x62610001, 0x61620001, 0x60630001,
0x46640001, 0x45650001, 0x44660001, 0x43670001, 0x42680001,
0x41690001, 0x406a0001, 0x266b0001, 0x256c0001, 0x246d0001,
0x236e0001, 0x226f0001, 0x21700001, 0x20710001, 0x06720001,
0x05730001, 0x04740001, 0x03750001, 0x02760001, 0x01770001,
0x00780001, 0x00790001, 0x007a0001, 0x007b0001, 0x007c0001,
0x007d0001, 0x007e0001, 0x007f0001, 0x3800001e, 0x3801001e,
0x3802001e, 0x3803001e, 0x3804001e, 0x3805001e, 0x3806001e,
0x3807001e, 0x3808001e, 0x3c09001e, 0x3e0a001e, 0x400b001e,
0x440c001e, 0x480d001e, 0x4c0e001e, 0x500f001e, 0x5210001e,
0x5611001e, 0x5a12001e, 0x5e13001e, 0x6014001e, 0x6015001e,
0x6016001e, 0x6217001e, 0x6218001e, 0x6219001e, 0x621a001e,
0x621b001e, 0x621c001e, 0x621d001e, 0x621e001e, 0x621f001e
};
static const struct rtwn_agc_prog rtl8188ru_agc[] = {
{
nitems(rtl8188ru_agc_vals),
rtl8188ru_agc_vals,
{ 0 },
NULL
}
};
#endif /* R92CU_PRIV_H */
@@ -0,0 +1,65 @@
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $
* $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/usb/r92cu_reg.h 307529 2016-10-17 20:38:24Z avos $
*/
#ifndef R92CU_REG_H
#define R92CU_REG_H
#include <dev/rtwn/rtl8192c/r92c_reg.h>
/*
* MAC registers.
*/
/* System Configuration. */
#define R92C_USB_SIE_INTF 0x0e0
/*
* USB registers.
*/
#define R92C_USB_SUSPEND 0xfe10
#define R92C_USB_INFO 0xfe17
#define R92C_USB_SPECIAL_OPTION 0xfe55
#define R92C_USB_HCPWM 0xfe57
#define R92C_USB_HRPWM 0xfe58
#define R92C_USB_DMA_AGG_TO 0xfe5b
#define R92C_USB_AGG_TO 0xfe5c
#define R92C_USB_AGG_TH 0xfe5d
#define R92C_USB_VID 0xfe60
#define R92C_USB_PID 0xfe62
#define R92C_USB_OPTIONAL 0xfe64
#define R92C_USB_EP 0xfe65
#define R92C_USB_PHY 0xfe68
#define R92C_USB_MAC_ADDR 0xfe70
#define R92C_USB_STRING 0xfe80
/* Bits for R92C_USB_SPECIAL_OPTION. */
#define R92C_USB_SPECIAL_OPTION_AGG_EN 0x08
#define R92C_USB_SPECIAL_OPTION_INT_BULK_SEL 0x10
/* Bits for R92C_USB_EP. */
#define R92C_USB_EP_HQ_M 0x000f
#define R92C_USB_EP_HQ_S 0
#define R92C_USB_EP_NQ_M 0x00f0
#define R92C_USB_EP_NQ_S 4
#define R92C_USB_EP_LQ_M 0x0f00
#define R92C_USB_EP_LQ_S 8
#endif /* R92CU_REG_H */
@@ -0,0 +1,63 @@
/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
* Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* 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: releng/12.0/sys/dev/rtwn/rtl8192c/usb/r92cu_rx.c 307529 2016-10-17 20:38:24Z avos $");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/rtl8192c/usb/r92cu.h>
int
r92cu_classify_intr(struct rtwn_softc *sc, void *buf, int len)
{
/* NB: reports are fetched from C2H_MSG register. */
return (RTWN_RX_DATA);
}
int
r92cu_align_rx(int totlen, int len)
{
return (roundup2(totlen, 128));
}
@@ -0,0 +1,64 @@
/*-
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/usb/r92cu_tx.c 307529 2016-10-17 20:38:24Z avos $");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/if_rtwn_debug.h>
#include <dev/rtwn/rtl8192c/usb/r92cu.h>
#include <dev/rtwn/rtl8192c/usb/r92cu_tx_desc.h>
void
r92cu_dump_tx_desc(struct rtwn_softc *sc, const void *desc)
{
#ifdef RTWN_DEBUG
const struct r92cu_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, sum %04X, pad %04X\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->txdsum), le16toh(txd->pad));
#endif
}
@@ -0,0 +1,45 @@
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
* Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $
* $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/usb/r92cu_tx_desc.h 307529 2016-10-17 20:38:24Z avos $
*/
#ifndef R92CU_TX_DESC_H
#define R92CU_TX_DESC_H
#include <dev/rtwn/rtl8192c/r92c_tx_desc.h>
/* Tx MAC descriptor (USB). */
struct r92cu_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 txdsum;
uint16_t pad;
} __packed __attribute__((aligned(4)));
#endif /* R92CU_TX_DESC_H */
@@ -0,0 +1,82 @@
/*-
* Copyright (c) 2017 Kevin Lo <kevlo@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192e/r92e.h 312680 2017-01-24 02:35:38Z kevlo $
*/
#ifndef RTL8192E_H
#define RTL8192E_H
/*
* Global definitions.
*/
#define R92E_PUBQ_NPAGES 222
#define R92E_TX_PAGE_COUNT 243
#define R92E_TX_PAGE_SIZE 256
#define R92E_RX_DMA_BUFFER_SIZE 0x3d00
#define R92E_MAX_FW_SIZE 0x8000
/*
* Function declarations.
*/
/* r92e_attach.c */
void r92e_detach_private(struct rtwn_softc *);
/* r92e_chan.c */
void r92e_set_chan(struct rtwn_softc *, struct ieee80211_channel *);
/* r92e_fw.c */
#ifndef RTWN_WITHOUT_UCODE
void r92e_fw_reset(struct rtwn_softc *, int);
void r92e_set_media_status(struct rtwn_softc *, int);
int r92e_set_pwrmode(struct rtwn_softc *, struct ieee80211vap *, int);
#endif
/* r92e_init.c */
int r92e_llt_init(struct rtwn_softc *);
void r92e_init_bb(struct rtwn_softc *);
void r92e_init_rf(struct rtwn_softc *);
int r92e_power_on(struct rtwn_softc *);
void r92e_power_off(struct rtwn_softc *);
/* r92e_led.c */
void r92e_set_led(struct rtwn_softc *, int, int);
/* r92e_rf.c */
uint32_t r92e_rf_read(struct rtwn_softc *, int, uint8_t);
void r92e_rf_write(struct rtwn_softc *, int, uint8_t, uint32_t);
/* r92e_rom.c */
void r92e_parse_rom_common(struct rtwn_softc *, uint8_t *);
void r92e_parse_rom(struct rtwn_softc *, uint8_t *);
/* r92e_rx.c */
void r92e_handle_c2h_report(struct rtwn_softc *, uint8_t *, int);
int8_t r92e_get_rssi_cck(struct rtwn_softc *, void *);
#endif /* RTL8192E_H */
@@ -0,0 +1,233 @@
/*-
* Copyright (c) 2017 Kevin Lo <kevlo@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192e/r92e_chan.c 322988 2017-08-28 22:14:16Z avos $");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/if_rtwn_debug.h>
#include <dev/rtwn/if_rtwn_ridx.h>
#include <dev/rtwn/if_rtwn_rx.h>
#include <dev/rtwn/rtl8192c/r92c.h>
#include <dev/rtwn/rtl8192e/r92e.h>
#include <dev/rtwn/rtl8192e/r92e_reg.h>
#include <dev/rtwn/rtl8192e/r92e_var.h>
static int
r92e_get_power_group(struct rtwn_softc *sc, struct ieee80211_channel *c)
{
uint8_t chan;
int group;
chan = rtwn_chan2centieee(c);
if (IEEE80211_IS_CHAN_2GHZ(c)) {
if (chan <= 2) group = 0;
else if (chan <= 5) group = 1;
else if (chan <= 8) group = 2;
else if (chan <= 11) group = 3;
else if (chan <= 14) group = 4;
else {
KASSERT(0, ("wrong 2GHz channel %d!\n", chan));
return (-1);
}
} else {
KASSERT(0, ("wrong channel band (flags %08X)\n", c->ic_flags));
return (-1);
}
return (group);
}
static void
r92e_get_txpower(struct rtwn_softc *sc, int chain, struct ieee80211_channel *c,
uint8_t power[RTWN_RIDX_COUNT])
{
struct r92e_softc *rs = sc->sc_priv;
int i, ridx, group, max_mcs;
/* Determine channel group. */
group = r92e_get_power_group(sc, c);
if (group == -1) { /* shouldn't happen */
device_printf(sc->sc_dev, "%s: incorrect channel\n", __func__);
return;
}
max_mcs = RTWN_RIDX_HT_MCS(sc->ntxchains * 8 - 1);
/* XXX regulatory */
/* XXX net80211 regulatory */
for (ridx = RTWN_RIDX_CCK1; ridx <= RTWN_RIDX_CCK11; ridx++)
power[ridx] = rs->cck_tx_pwr[chain][group];
for (ridx = RTWN_RIDX_OFDM6; ridx <= max_mcs; ridx++)
power[ridx] = rs->ht40_tx_pwr_2g[chain][group];
for (ridx = RTWN_RIDX_OFDM6; ridx <= RTWN_RIDX_OFDM54; ridx++)
power[ridx] += rs->ofdm_tx_pwr_diff_2g[chain][0];
for (i = 0; i < sc->ntxchains; i++) {
uint8_t min_mcs;
uint8_t pwr_diff;
if (IEEE80211_IS_CHAN_HT40(c))
pwr_diff = rs->bw40_tx_pwr_diff_2g[chain][i];
else
pwr_diff = rs->bw20_tx_pwr_diff_2g[chain][i];
min_mcs = RTWN_RIDX_HT_MCS(i * 8);
for (ridx = min_mcs; ridx <= max_mcs; ridx++)
power[ridx] += pwr_diff;
}
/* Apply max limit. */
for (ridx = RTWN_RIDX_CCK1; ridx <= max_mcs; ridx++) {
if (power[ridx] > R92C_MAX_TX_PWR)
power[ridx] = R92C_MAX_TX_PWR;
}
#ifdef RTWN_DEBUG
if (sc->sc_debug & RTWN_DEBUG_TXPWR) {
/* Dump per-rate Tx power values. */
printf("Tx power for chain %d:\n", chain);
for (ridx = RTWN_RIDX_CCK1; ridx < RTWN_RIDX_COUNT; ridx++)
printf("Rate %d = %u\n", ridx, power[ridx]);
}
#endif
}
static void
r92e_set_txpower(struct rtwn_softc *sc, struct ieee80211_channel *c)
{
uint8_t power[RTWN_RIDX_COUNT];
int i;
for (i = 0; i < sc->ntxchains; i++) {
memset(power, 0, sizeof(power));
/* Compute per-rate Tx power values. */
r92e_get_txpower(sc, i, c, power);
/* Write per-rate Tx power values to hardware. */
r92c_write_txpower(sc, i, power);
}
}
static void
r92e_set_bw40(struct rtwn_softc *sc, uint8_t chan, int prichlo)
{
int i;
rtwn_setbits_2(sc, R92C_WMAC_TRXPTCL_CTL, 0x100, 0x80);
rtwn_write_1(sc, R12A_DATA_SEC,
prichlo ? R12A_DATA_SEC_PRIM_DOWN_20 : R12A_DATA_SEC_PRIM_UP_20);
rtwn_bb_setbits(sc, R92C_FPGA0_RFMOD, 0, R92C_RFMOD_40MHZ);
rtwn_bb_setbits(sc, R92C_FPGA1_RFMOD, 0, R92C_RFMOD_40MHZ);
/* Select 40MHz bandwidth. */
for (i = 0; i < sc->nrxchains; i++)
rtwn_rf_setbits(sc, i, R92C_RF_CHNLBW,
R88E_RF_CHNLBW_BW20, 0x400);
/* Set CCK side band. */
rtwn_bb_setbits(sc, R92C_CCK0_SYSTEM,
R92C_CCK0_SYSTEM_CCK_SIDEBAND, (prichlo ? 0 : 1) << 4);
rtwn_bb_setbits(sc, R92C_OFDM1_LSTF, 0x0c00, (prichlo ? 1 : 2) << 10);
rtwn_bb_setbits(sc, R92C_FPGA0_ANAPARAM2,
R92C_FPGA0_ANAPARAM2_CBW20, 0);
rtwn_bb_setbits(sc, 0x818, 0x0c000000, (prichlo ? 2 : 1) << 26);
}
static void
r92e_set_bw20(struct rtwn_softc *sc, uint8_t chan)
{
int i;
rtwn_setbits_2(sc, R92C_WMAC_TRXPTCL_CTL, 0x180, 0);
rtwn_write_1(sc, R12A_DATA_SEC, R12A_DATA_SEC_NO_EXT);
rtwn_bb_setbits(sc, R92C_FPGA0_RFMOD, R92C_RFMOD_40MHZ, 0);
rtwn_bb_setbits(sc, R92C_FPGA1_RFMOD, R92C_RFMOD_40MHZ, 0);
/* Select 20MHz bandwidth. */
for (i = 0; i < sc->nrxchains; i++)
rtwn_rf_setbits(sc, i, R92C_RF_CHNLBW,
R88E_RF_CHNLBW_BW20, 0xc00);
rtwn_bb_setbits(sc, R92C_OFDM0_TXPSEUDONOISEWGT, 0xc0000000, 0);
}
void
r92e_set_chan(struct rtwn_softc *sc, struct ieee80211_channel *c)
{
struct r92e_softc *rs = sc->sc_priv;
u_int chan;
int i;
chan = rtwn_chan2centieee(c);
for (i = 0; i < sc->nrxchains; i++) {
rtwn_rf_write(sc, i, R92C_RF_CHNLBW,
RW(rs->rf_chnlbw[0], R92C_RF_CHNLBW_CHNL, chan));
}
if (IEEE80211_IS_CHAN_HT40(c))
r92e_set_bw40(sc, chan, IEEE80211_IS_CHAN_HT40U(c));
else
r92e_set_bw20(sc, chan);
/* Set Tx power for this new channel. */
r92e_set_txpower(sc, c);
}
@@ -0,0 +1,137 @@
/*-
* Copyright (c) 2017 Kevin Lo <kevlo@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192e/r92e_fw.c 312680 2017-01-24 02:35:38Z kevlo $");
#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/linker.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
#include <dev/rtwn/if_rtwn_debug.h>
#include <dev/rtwn/rtl8188e/r88e.h>
#include <dev/rtwn/rtl8188e/r88e_reg.h>
#include <dev/rtwn/rtl8812a/r12a_fw_cmd.h>
#include <dev/rtwn/rtl8192e/r92e.h>
#ifndef RTWN_WITHOUT_UCODE
void
r92e_fw_reset(struct rtwn_softc *sc, int reason)
{
/* Reset MCU IO wrapper. */
rtwn_setbits_1(sc, R92C_RSV_CTRL + 1, 0x01, 0);
rtwn_setbits_1_shift(sc, R92C_SYS_FUNC_EN,
R92C_SYS_FUNC_EN_CPUEN, 0, 1);
/* Enable MCU IO wrapper. */
rtwn_setbits_1(sc, R92C_RSV_CTRL + 1, 0, 0x01);
rtwn_setbits_1_shift(sc, R92C_SYS_FUNC_EN,
0, R92C_SYS_FUNC_EN_CPUEN, 1);
}
void
r92e_set_media_status(struct rtwn_softc *sc, int macid)
{
struct r88e_fw_cmd_msrrpt status;
if (macid & RTWN_MACID_VALID)
status.msrb0 = R88E_MSRRPT_B0_ASSOC;
else
status.msrb0 = R88E_MSRRPT_B0_DISASSOC;
status.macid = (macid & ~RTWN_MACID_VALID);
if (r88e_fw_cmd(sc, R88E_CMD_MSR_RPT, &status, sizeof(status)) != 0) {
device_printf(sc->sc_dev, "%s: cannot change media status!\n",
__func__);
}
}
int
r92e_set_pwrmode(struct rtwn_softc *sc, struct ieee80211vap *vap, int off)
{
struct r12a_fw_cmd_pwrmode mode;
int error;
if (off && vap->iv_state == IEEE80211_S_RUN &&
(vap->iv_flags & IEEE80211_F_PMGTON)) {
mode.mode = R88E_PWRMODE_LEG;
/*
* TODO: switch to RFOFF state
* (something is missing here - Rx stops with it).
*/
#ifdef RTWN_TODO
mode.pwr_state = R88E_PWRMODE_STATE_RFOFF;
#else
mode.pwr_state = R88E_PWRMODE_STATE_RFON;
#endif
} else {
mode.mode = R88E_PWRMODE_CAM;
mode.pwr_state = R88E_PWRMODE_STATE_ALLON;
}
mode.pwrb1 =
SM(R88E_PWRMODE_B1_SMART_PS, R88E_PWRMODE_B1_LEG_NULLDATA) |
SM(R88E_PWRMODE_B1_RLBM, R88E_PWRMODE_B1_MODE_MIN);
/* XXX ignored */
mode.bcn_pass = 0;
mode.queue_uapsd = 0;
mode.pwrb5 = 0;
error = r88e_fw_cmd(sc, R88E_CMD_SET_PWRMODE, &mode, sizeof(mode));
if (error != 0) {
device_printf(sc->sc_dev,
"%s: CMD_SET_PWRMODE was not sent, error %d\n",
__func__, error);
}
return (error);
}
#endif

Some files were not shown because too many files have changed in this diff Show More