diff --git a/sys/dev/rtwn/rtl8812a/r12a_fw.c b/sys/dev/rtwn/rtl8812a/r12a_fw.c index 6d383fe2f5ad..c2c12c2a2ee2 100644 --- a/sys/dev/rtwn/rtl8812a/r12a_fw.c +++ b/sys/dev/rtwn/rtl8812a/r12a_fw.c @@ -1,191 +1,193 @@ /*- * Copyright (c) 2016 Andriy Voskoboinyk * 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 #include "opt_wlan.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef RTWN_WITHOUT_UCODE void r12a_fw_reset(struct rtwn_softc *sc, int reason) { /* Reset MCU IO wrapper. */ rtwn_setbits_1(sc, R92C_RSV_CTRL, R92C_RSV_CTRL_WLOCK_00, 0); rtwn_setbits_1(sc, R92C_RSV_CTRL + 1, 0x08, 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, R92C_RSV_CTRL_WLOCK_00, 0); rtwn_setbits_1(sc, R92C_RSV_CTRL + 1, 0, 0x08); rtwn_setbits_1_shift(sc, R92C_SYS_FUNC_EN, 0, R92C_SYS_FUNC_EN_CPUEN, 1); } void r12a_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); } } void r12a_set_media_status(struct rtwn_softc *sc, int macid) { struct r12a_fw_cmd_msrrpt status; int error; if (macid & RTWN_MACID_VALID) status.msrb0 = R12A_MSRRPT_B0_ASSOC; else status.msrb0 = R12A_MSRRPT_B0_DISASSOC; status.macid = (macid & ~RTWN_MACID_VALID); status.macid_end = 0; error = r88e_fw_cmd(sc, R12A_CMD_MSR_RPT, &status, sizeof(status)); if (error != 0) device_printf(sc->sc_dev, "cannot change media status!\n"); } int r12a_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 = R12A_PWRMODE_B5_NO_BTCOEX; error = r88e_fw_cmd(sc, R12A_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 r12a_iq_calib_fw(struct rtwn_softc *sc) { struct r12a_softc *rs = sc->sc_priv; struct ieee80211_channel *c = sc->sc_ic.ic_curchan; struct r12a_fw_cmd_iq_calib cmd; if (rs->rs_flags & R12A_IQK_RUNNING) return; RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB, "Starting IQ calibration (FW)\n"); cmd.chan = rtwn_chan2centieee(c); if (IEEE80211_IS_CHAN_5GHZ(c)) cmd.band_bw = RTWN_CMD_IQ_BAND_5GHZ; else cmd.band_bw = RTWN_CMD_IQ_BAND_2GHZ; - /* TODO: 80/160 MHz. */ - if (IEEE80211_IS_CHAN_HT40(c)) + /* TODO: 160MHz */ + if (IEEE80211_IS_CHAN_VHT80(c)) + cmd.band_bw |= RTWN_CMD_IQ_CHAN_WIDTH_80; + else if (IEEE80211_IS_CHAN_HT40(c) || IEEE80211_IS_CHAN_VHT40(c)) cmd.band_bw |= RTWN_CMD_IQ_CHAN_WIDTH_40; else cmd.band_bw |= RTWN_CMD_IQ_CHAN_WIDTH_20; cmd.ext_5g_pa_lna = RTWN_CMD_IQ_EXT_PA_5G(rs->ext_pa_5g); cmd.ext_5g_pa_lna |= RTWN_CMD_IQ_EXT_LNA_5G(rs->ext_lna_5g); if (r88e_fw_cmd(sc, R12A_CMD_IQ_CALIBRATE, &cmd, sizeof(cmd)) != 0) { RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB, "error while sending IQ calibration command to FW!\n"); return; } rs->rs_flags |= R12A_IQK_RUNNING; } #endif diff --git a/sys/dev/rtwn/rtl8812a/r12a_reg.h b/sys/dev/rtwn/rtl8812a/r12a_reg.h index f9acc2047490..4e9892ce2592 100644 --- a/sys/dev/rtwn/rtl8812a/r12a_reg.h +++ b/sys/dev/rtwn/rtl8812a/r12a_reg.h @@ -1,241 +1,241 @@ /*- * Copyright (c) 2016 Andriy Voskoboinyk * 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. */ #ifndef R12A_REG_H #define R12A_REG_H #include /* * MAC registers. */ /* System Configuration. */ #define R12A_SDIO_CTRL 0x070 #define R12A_RF_B_CTRL 0x076 /* Rx DMA Configuration. */ #define R12A_RXDMA_PRO 0x290 #define R12A_EARLY_MODE_CONTROL 0x2bc /* Protocol Configuration. */ #define R12A_TXPKT_EMPTY 0x41a #define R12A_ARFR_5G(i) (0x444 + (i) * 8) #define R12A_CCK_CHECK 0x454 #define R12A_AMPDU_MAX_TIME 0x456 #define R12A_AMPDU_MAX_LENGTH R92C_AGGLEN_LMT #define R12A_DATA_SEC 0x483 #define R12A_ARFR_2G(i) (0x48c + (i) * 8) #define R12A_HT_SINGLE_AMPDU 0x4c7 /* Bits for R92C_MAC_PHY_CTRL. */ #define R12A_MAC_PHY_CRYSTALCAP_M 0x7ff80000 #define R12A_MAC_PHY_CRYSTALCAP_S 19 /* Bits for R92C_LEDCFG2. */ #define R12A_LEDCFG2_ENA 0x20 /* Bits for R12A_RXDMA_PRO. */ #define R12A_DMA_MODE 0x02 #define R12A_BURST_CNT_M 0x0c #define R12A_BURST_CNT_S 2 #define R12A_BURST_SZ_M 0x30 #define R12A_BURST_SZ_S 4 #define R12A_BURST_SZ_USB3 0 #define R12A_BURST_SZ_USB2 1 #define R12A_BURST_SZ_USB1 2 /* Bits for R12A_CCK_CHECK. */ #define R12A_CCK_CHECK_BCN1 0x20 #define R12A_CCK_CHECK_5GHZ 0x80 /* Bits for R12A_DATA_SEC. */ #define R12A_DATA_SEC_NO_EXT 0x00 #define R12A_DATA_SEC_PRIM_UP_20 0x01 #define R12A_DATA_SEC_PRIM_DOWN_20 0x02 #define R12A_DATA_SEC_PRIM_UPPER_20 0x03 #define R12A_DATA_SEC_PRIM_LOWER_20 0x04 -#define R12A_DATA_SEC_PRIM_UP_40 0x90 -#define R12A_DATA_SEC_PRIM_DOWN_40 0xa0 +#define R12A_DATA_SEC_PRIM_UP_40 0x09 +#define R12A_DATA_SEC_PRIM_DOWN_40 0x0a /* Bits for R12A_HT_SINGLE_AMPDU. */ #define R12A_HT_SINGLE_AMPDU_PKT_ENA 0x80 /* Bits for R92C_RCR. */ #define R12A_RCR_DIS_CHK_14 0x00200000 #define R12A_RCR_TCP_OFFLD_EN 0x02000000 #define R12A_RCR_VHT_ACK 0x04000000 /* * Baseband registers. */ #define R12A_CCK_RPT_FORMAT 0x804 #define R12A_OFDMCCK_EN 0x808 #define R12A_RX_PATH R12A_OFDMCCK_EN #define R12A_TX_PATH 0x80c #define R12A_TXAGC_TABLE_SELECT 0x82c #define R12A_PWED_TH 0x830 #define R12A_BW_INDICATION 0x834 #define R12A_CCA_ON_SEC 0x838 #define R12A_L1_PEAK_TH 0x848 #define R12A_FC_AREA 0x860 #define R12A_RFMOD 0x8ac #define R12A_HSSI_PARAM2 0x8b0 #define R12A_ADC_BUF_CLK 0x8c4 #define R12A_ANTSEL_SW 0x900 #define R12A_SINGLETONE_CONT_TX 0x914 #define R12A_CCK_RX_PATH 0xa04 #define R12A_HSSI_PARAM1(chain) (0xc00 + (chain) * 0x200) #define R12A_TX_SCALE(chain) (0xc1c + (chain) * 0x200) #define R12A_TXAGC_CCK11_1(chain) (0xc20 + (chain) * 0x200) #define R12A_TXAGC_OFDM18_6(chain) (0xc24 + (chain) * 0x200) #define R12A_TXAGC_OFDM54_24(chain) (0xc28 + (chain) * 0x200) #define R12A_TXAGC_MCS3_0(chain) (0xc2c + (chain) * 0x200) #define R12A_TXAGC_MCS7_4(chain) (0xc30 + (chain) * 0x200) #define R12A_TXAGC_MCS11_8(chain) (0xc34 + (chain) * 0x200) #define R12A_TXAGC_MCS15_12(chain) (0xc38 + (chain) * 0x200) #define R12A_TXAGC_NSS1IX3_1IX0(chain) (0xc3c + (chain) * 0x200) #define R12A_TXAGC_NSS1IX7_1IX4(chain) (0xc40 + (chain) * 0x200) #define R12A_TXAGC_NSS2IX1_1IX8(chain) (0xc44 + (chain) * 0x200) #define R12A_TXAGC_NSS2IX5_2IX2(chain) (0xc48 + (chain) * 0x200) #define R12A_TXAGC_NSS2IX9_2IX6(chain) (0xc4c + (chain) * 0x200) #define R12A_INITIAL_GAIN(chain) (0xc50 + (chain) * 0x200) #define R12A_AFE_POWER_1(chain) (0xc60 + (chain) * 0x200) #define R12A_AFE_POWER_2(chain) (0xc64 + (chain) * 0x200) #define R12A_SLEEP_NAV(chain) (0xc80 + (chain) * 0x200) #define R12A_PMPD(chain) (0xc84 + (chain) * 0x200) #define R12A_LSSI_PARAM(chain) (0xc90 + (chain) * 0x200) #define R12A_RFE_PINMUX(chain) (0xcb0 + (chain) * 0x200) #define R12A_RFE_INV(chain) (0xcb4 + (chain) * 0x200) #define R12A_RFE(chain) (0xcb8 + (chain) * 0x200) #define R12A_HSPI_READBACK(chain) (0xd04 + (chain) * 0x40) #define R12A_LSSI_READBACK(chain) (0xd08 + (chain) * 0x40) /* Bits for R12A_CCK_RPT_FORMAT. */ #define R12A_CCK_RPT_FORMAT_HIPWR 0x00010000 /* Bits for R12A_OFDMCCK_EN. */ #define R12A_OFDMCCK_EN_CCK 0x10000000 #define R12A_OFDMCCK_EN_OFDM 0x20000000 /* Bits for R12A_CCA_ON_SEC. */ #define R12A_CCA_ON_SEC_EXT_CHAN_M 0xf0000000 #define R12A_CCA_ON_SEC_EXT_CHAN_S 28 /* Bits for R12A_RFE_PINMUX(i). */ #define R12A_RFE_PINMUX_PA_A_MASK 0x000000f0 #define R12A_RFE_PINMUX_LNA_MASK 0x0000f000 /* Bits for R12A_RFMOD. */ #define R12A_RFMOD_EXT_CHAN_M 0x3C #define R12A_RFMOD_EXT_CHAN_S 2 /* Bits for R12A_HSSI_PARAM2. */ #define R12A_HSSI_PARAM2_READ_ADDR_MASK 0xff /* Bits for R12A_HSSI_PARAM1(i). */ #define R12A_HSSI_PARAM1_PI 0x00000004 /* Bits for R12A_TX_SCALE(i). */ #define R12A_TX_SCALE_SWING_M 0xffe00000 #define R12A_TX_SCALE_SWING_S 21 /* Bits for R12A_TXAGC_CCK11_1(i). */ #define R12A_TXAGC_CCK1_M 0x000000ff #define R12A_TXAGC_CCK1_S 0 #define R12A_TXAGC_CCK2_M 0x0000ff00 #define R12A_TXAGC_CCK2_S 8 #define R12A_TXAGC_CCK55_M 0x00ff0000 #define R12A_TXAGC_CCK55_S 16 #define R12A_TXAGC_CCK11_M 0xff000000 #define R12A_TXAGC_CCK11_S 24 /* Bits for R12A_TXAGC_OFDM18_6(i). */ #define R12A_TXAGC_OFDM06_M 0x000000ff #define R12A_TXAGC_OFDM06_S 0 #define R12A_TXAGC_OFDM09_M 0x0000ff00 #define R12A_TXAGC_OFDM09_S 8 #define R12A_TXAGC_OFDM12_M 0x00ff0000 #define R12A_TXAGC_OFDM12_S 16 #define R12A_TXAGC_OFDM18_M 0xff000000 #define R12A_TXAGC_OFDM18_S 24 /* Bits for R12A_TXAGC_OFDM54_24(i). */ #define R12A_TXAGC_OFDM24_M 0x000000ff #define R12A_TXAGC_OFDM24_S 0 #define R12A_TXAGC_OFDM36_M 0x0000ff00 #define R12A_TXAGC_OFDM36_S 8 #define R12A_TXAGC_OFDM48_M 0x00ff0000 #define R12A_TXAGC_OFDM48_S 16 #define R12A_TXAGC_OFDM54_M 0xff000000 #define R12A_TXAGC_OFDM54_S 24 /* Bits for R12A_TXAGC_MCS3_0(i). */ #define R12A_TXAGC_MCS0_M 0x000000ff #define R12A_TXAGC_MCS0_S 0 #define R12A_TXAGC_MCS1_M 0x0000ff00 #define R12A_TXAGC_MCS1_S 8 #define R12A_TXAGC_MCS2_M 0x00ff0000 #define R12A_TXAGC_MCS2_S 16 #define R12A_TXAGC_MCS3_M 0xff000000 #define R12A_TXAGC_MCS3_S 24 /* Bits for R12A_TXAGC_MCS7_4(i). */ #define R12A_TXAGC_MCS4_M 0x000000ff #define R12A_TXAGC_MCS4_S 0 #define R12A_TXAGC_MCS5_M 0x0000ff00 #define R12A_TXAGC_MCS5_S 8 #define R12A_TXAGC_MCS6_M 0x00ff0000 #define R12A_TXAGC_MCS6_S 16 #define R12A_TXAGC_MCS7_M 0xff000000 #define R12A_TXAGC_MCS7_S 24 /* Bits for R12A_TXAGC_MCS11_8(i). */ #define R12A_TXAGC_MCS8_M 0x000000ff #define R12A_TXAGC_MCS8_S 0 #define R12A_TXAGC_MCS9_M 0x0000ff00 #define R12A_TXAGC_MCS9_S 8 #define R12A_TXAGC_MCS10_M 0x00ff0000 #define R12A_TXAGC_MCS10_S 16 #define R12A_TXAGC_MCS11_M 0xff000000 #define R12A_TXAGC_MCS11_S 24 /* Bits for R12A_TXAGC_MCS15_12(i). */ #define R12A_TXAGC_MCS12_M 0x000000ff #define R12A_TXAGC_MCS12_S 0 #define R12A_TXAGC_MCS13_M 0x0000ff00 #define R12A_TXAGC_MCS13_S 8 #define R12A_TXAGC_MCS14_M 0x00ff0000 #define R12A_TXAGC_MCS14_S 16 #define R12A_TXAGC_MCS15_M 0xff000000 #define R12A_TXAGC_MCS15_S 24 /* * RF (6052) registers. */ #define R12A_RF_LCK 0xb4 /* Bits for R12A_RF_LCK. */ #define R12A_RF_LCK_MODE 0x4000 #endif /* R12A_REG_H */ diff --git a/sys/dev/rtwn/rtl8812a/r12a_tx.c b/sys/dev/rtwn/rtl8812a/r12a_tx.c index 6102a0567e74..e6b5111063f7 100644 --- a/sys/dev/rtwn/rtl8812a/r12a_tx.c +++ b/sys/dev/rtwn/rtl8812a/r12a_tx.c @@ -1,471 +1,479 @@ /*- * Copyright (c) 2016 Andriy Voskoboinyk * 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 #include "opt_wlan.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static int r12a_get_primary_channel(struct rtwn_softc *sc, struct ieee80211_channel *c) { /* XXX 80 MHz */ if (IEEE80211_IS_CHAN_HT40U(c)) return (R12A_TXDW5_PRIM_CHAN_20_80_2); else return (R12A_TXDW5_PRIM_CHAN_20_80_3); } static void r12a_tx_set_ht40(struct rtwn_softc *sc, void *buf, struct ieee80211_node *ni) { struct r12a_tx_desc *txd = (struct r12a_tx_desc *)buf; /* XXX 80 Mhz */ if (ni->ni_chan != IEEE80211_CHAN_ANYC && IEEE80211_IS_CHAN_HT40(ni->ni_chan)) { int prim_chan; prim_chan = r12a_get_primary_channel(sc, ni->ni_chan); txd->txdw5 |= htole32(SM(R12A_TXDW5_DATA_BW, R12A_TXDW5_DATA_BW40)); txd->txdw5 |= htole32(SM(R12A_TXDW5_DATA_PRIM_CHAN, prim_chan)); } } static void r12a_tx_protection(struct rtwn_softc *sc, struct r12a_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->txdw3 |= htole32(R12A_TXDW3_CTS2SELF); break; case IEEE80211_PROT_RTSCTS: txd->txdw3 |= htole32(R12A_TXDW3_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(IEEE80211_RV(rate)); txd->txdw4 |= htole32(SM(R12A_TXDW4_RTSRATE, ridx)); /* RTS rate fallback limit (max). */ txd->txdw4 |= htole32(SM(R12A_TXDW4_RTSRATE_FB_LMT, 0xf)); if (RTWN_RATE_IS_CCK(ridx) && ridx != RTWN_RIDX_CCK1 && (ic->ic_flags & IEEE80211_F_SHPREAMBLE)) txd->txdw5 |= htole32(R12A_TXDW5_RTS_SHORT); } } static void r12a_tx_raid(struct rtwn_softc *sc, struct r12a_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_11A: case IEEE80211_MODE_11B: case IEEE80211_MODE_11G: break; case IEEE80211_MODE_11NA: mode = IEEE80211_MODE_11A; break; case IEEE80211_MODE_11NG: mode = IEEE80211_MODE_11G; break; + case IEEE80211_MODE_VHT_5GHZ: + mode = IEEE80211_MODE_VHT_5GHZ; + break; default: device_printf(sc->sc_dev, "unknown mode(1) %d!\n", ic->ic_curmode); return; } } switch (mode) { case IEEE80211_MODE_11A: raid = R12A_RAID_11G; break; case IEEE80211_MODE_11B: raid = R12A_RAID_11B; break; case IEEE80211_MODE_11G: if (vap->iv_flags & IEEE80211_F_PUREG) raid = R12A_RAID_11G; else raid = R12A_RAID_11BG; break; case IEEE80211_MODE_11NA: if (sc->ntxchains == 1) raid = R12A_RAID_11GN_1; else raid = R12A_RAID_11GN_2; break; case IEEE80211_MODE_11NG: if (sc->ntxchains == 1) { if (IEEE80211_IS_CHAN_HT40(chan)) raid = R12A_RAID_11BGN_1_40; else raid = R12A_RAID_11BGN_1; } else { if (IEEE80211_IS_CHAN_HT40(chan)) raid = R12A_RAID_11BGN_2_40; else raid = R12A_RAID_11BGN_2; } break; + case IEEE80211_MODE_VHT_5GHZ: + if (sc->ntxchains == 1) + raid = R12A_RAID_11AC_1; + else + raid = R12A_RAID_11AC_2; + break; default: - /* TODO: 80 MHz / 11ac */ device_printf(sc->sc_dev, "unknown mode(2) %d!\n", mode); return; } txd->txdw1 |= htole32(SM(R12A_TXDW1_RAID, raid)); } static void r12a_tx_set_sgi(struct rtwn_softc *sc, void *buf, struct ieee80211_node *ni) { struct r12a_tx_desc *txd = (struct r12a_tx_desc *)buf; /* TODO: VHT 20/40/80 checks */ /* * Only enable short-GI if we're transmitting in that * width to that node. * * Specifically, do not enable shortgi for 20MHz if * we're attempting to transmit at 40MHz. */ if (ieee80211_ht_check_tx_ht40(ni)) { if (ieee80211_ht_check_tx_shortgi_40(ni)) txd->txdw5 |= htole32(R12A_TXDW5_DATA_SHORT); } else if (ieee80211_ht_check_tx_ht(ni)) { if (ieee80211_ht_check_tx_shortgi_20(ni)) txd->txdw5 |= htole32(R12A_TXDW5_DATA_SHORT); } } static void r12a_tx_set_ldpc(struct rtwn_softc *sc, struct r12a_tx_desc *txd, struct ieee80211_node *ni) { struct ieee80211vap *vap = ni->ni_vap; if ((vap->iv_flags_ht & IEEE80211_FHT_LDPC_TX) && (ni->ni_htcap & IEEE80211_HTCAP_LDPC)) txd->txdw5 |= htole32(R12A_TXDW5_DATA_LDPC); } static int r12a_calculate_tx_agg_window(struct rtwn_softc *sc, const struct ieee80211_node *ni, int tid) { const struct ieee80211_tx_ampdu *tap; int wnd; tap = &ni->ni_tx_ampdu[tid]; /* * BAW is (MAX_AGG * 2) + 1, hence the /2 here. * Ensure we don't send 0 or more than 64. */ wnd = tap->txa_wnd / 2; if (wnd == 0) wnd = 1; else if (wnd > 0x1f) wnd = 0x1f; return (wnd); } void r12a_fill_tx_desc(struct rtwn_softc *sc, struct ieee80211_node *ni, struct mbuf *m, void *buf, uint8_t ridx, int maxretry) { struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = ni->ni_vap; struct rtwn_vap *uvp = RTWN_VAP(vap); struct ieee80211_frame *wh; struct r12a_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 r12a_tx_desc *)buf; txd->flags0 |= R12A_FLAGS0_LSG | R12A_FLAGS0_FSG; if (ismcast) txd->flags0 |= R12A_FLAGS0_BMCAST; if (!ismcast) { /* Unicast frame, check if an ACK is expected. */ if (!qos || (qos & IEEE80211_QOS_ACKPOLICY) != IEEE80211_QOS_ACKPOLICY_NOACK) { txd->txdw4 = htole32(R12A_TXDW4_RETRY_LMT_ENA); txd->txdw4 |= htole32(SM(R12A_TXDW4_RETRY_LMT, maxretry)); } struct rtwn_node *un = RTWN_NODE(ni); macid = un->id; if (type == IEEE80211_FC0_TYPE_DATA) { qsel = tid % RTWN_MAX_TID; if (m->m_flags & M_AMPDU_MPDU) { txd->txdw2 |= htole32(R12A_TXDW2_AGGEN); txd->txdw2 |= htole32(SM(R12A_TXDW2_AMPDU_DEN, ieee80211_ht_get_node_ampdu_density(ni))); txd->txdw3 |= htole32(SM(R12A_TXDW3_MAX_AGG, r12a_calculate_tx_agg_window(sc, ni, tid))); } else txd->txdw2 |= htole32(R12A_TXDW2_AGGBK); if (sc->sc_ratectl == RTWN_RATECTL_NET80211) { txd->txdw2 |= htole32(R12A_TXDW2_SPE_RPT); sc->sc_tx_n_active++; } if (RTWN_RATE_IS_CCK(ridx) && ridx != RTWN_RIDX_CCK1 && (ic->ic_flags & IEEE80211_F_SHPREAMBLE)) txd->txdw5 |= htole32(R12A_TXDW5_DATA_SHORT); prot = IEEE80211_PROT_NONE; if (ridx >= RTWN_RIDX_HT_MCS(0)) { r12a_tx_set_ht40(sc, txd, ni); r12a_tx_set_sgi(sc, txd, ni); r12a_tx_set_ldpc(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; if (prot != IEEE80211_PROT_NONE) r12a_tx_protection(sc, txd, prot, ridx); } else /* IEEE80211_FC0_TYPE_MGT */ qsel = R12A_TXDW1_QSEL_MGNT; } else { macid = RTWN_MACID_BC; qsel = R12A_TXDW1_QSEL_MGNT; } txd->txdw1 |= htole32(SM(R12A_TXDW1_QSEL, qsel)); txd->txdw1 |= htole32(SM(R12A_TXDW1_MACID, macid)); txd->txdw4 |= htole32(SM(R12A_TXDW4_DATARATE, ridx)); /* Data rate fallback limit (max). */ txd->txdw4 |= htole32(SM(R12A_TXDW4_DATARATE_FB_LMT, 0x1f)); /* XXX recheck for non-21au */ txd->txdw6 |= htole32(SM(R21A_TXDW6_MBSSID, uvp->id)); r12a_tx_raid(sc, txd, ni, ismcast); /* Force this rate if needed. */ if (sc->sc_ratectl != RTWN_RATECTL_FW) txd->txdw3 |= htole32(R12A_TXDW3_DRVRATE); if (!hasqos) { /* Use HW sequence numbering for non-QoS frames. */ txd->txdw8 |= htole32(R12A_TXDW8_HWSEQ_EN); txd->txdw3 |= htole32(SM(R12A_TXDW3_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->txdw9 |= htole32(SM(R12A_TXDW9_SEQ, seqno)); } } void r12a_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 r12a_tx_desc *txd; uint8_t ridx; int ismcast; /* XXX TODO: 11n checks, matching rtwn_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 r12a_tx_desc *)buf; txd->flags0 |= R12A_FLAGS0_LSG | R12A_FLAGS0_FSG; if (ismcast) txd->flags0 |= R12A_FLAGS0_BMCAST; if ((params->ibp_flags & IEEE80211_BPF_NOACK) == 0) { txd->txdw4 = htole32(R12A_TXDW4_RETRY_LMT_ENA); txd->txdw4 |= htole32(SM(R12A_TXDW4_RETRY_LMT, params->ibp_try0)); } if (params->ibp_flags & IEEE80211_BPF_RTS) r12a_tx_protection(sc, txd, IEEE80211_PROT_RTSCTS, ridx); if (params->ibp_flags & IEEE80211_BPF_CTS) r12a_tx_protection(sc, txd, IEEE80211_PROT_CTSONLY, ridx); txd->txdw1 |= htole32(SM(R12A_TXDW1_MACID, RTWN_MACID_BC)); txd->txdw1 |= htole32(SM(R12A_TXDW1_QSEL, R12A_TXDW1_QSEL_MGNT)); /* Set TX rate index. */ txd->txdw4 |= htole32(SM(R12A_TXDW4_DATARATE, ridx)); txd->txdw4 |= htole32(SM(R12A_TXDW4_DATARATE_FB_LMT, 0x1f)); txd->txdw6 |= htole32(SM(R21A_TXDW6_MBSSID, uvp->id)); txd->txdw3 |= htole32(R12A_TXDW3_DRVRATE); r12a_tx_raid(sc, txd, ni, ismcast); if (!IEEE80211_QOS_HAS_SEQ(wh)) { /* Use HW sequence numbering for non-QoS frames. */ txd->txdw8 |= htole32(R12A_TXDW8_HWSEQ_EN); txd->txdw3 |= htole32(SM(R12A_TXDW3_SEQ_SEL, uvp->id)); } else { /* Set sequence number. */ txd->txdw9 |= htole32(SM(R12A_TXDW9_SEQ, M_SEQNO_GET(m) % IEEE80211_SEQ_RANGE)); } } void r12a_fill_tx_desc_null(struct rtwn_softc *sc, void *buf, int is11b, int qos, int id) { struct r12a_tx_desc *txd = (struct r12a_tx_desc *)buf; txd->flags0 = R12A_FLAGS0_FSG | R12A_FLAGS0_LSG | R12A_FLAGS0_OWN; txd->txdw1 = htole32( SM(R12A_TXDW1_QSEL, R12A_TXDW1_QSEL_MGNT)); txd->txdw3 = htole32(R12A_TXDW3_DRVRATE); txd->txdw6 = htole32(SM(R21A_TXDW6_MBSSID, id)); if (is11b) { txd->txdw4 = htole32(SM(R12A_TXDW4_DATARATE, RTWN_RIDX_CCK1)); } else { txd->txdw4 = htole32(SM(R12A_TXDW4_DATARATE, RTWN_RIDX_OFDM6)); } if (!qos) { txd->txdw8 = htole32(R12A_TXDW8_HWSEQ_EN); txd->txdw3 |= htole32(SM(R12A_TXDW3_SEQ_SEL, id)); } } uint8_t r12a_tx_radiotap_flags(const void *buf) { const struct r12a_tx_desc *txd = buf; uint8_t flags, rate; if (!(txd->txdw5 & htole32(R12A_TXDW5_DATA_SHORT))) return (0); rate = MS(le32toh(txd->txdw4), R12A_TXDW4_DATARATE); if (RTWN_RATE_IS_CCK(rate)) flags = IEEE80211_RADIOTAP_F_SHORTPRE; else flags = IEEE80211_RADIOTAP_F_SHORTGI; return (flags); } diff --git a/sys/dev/rtwn/rtl8812a/r12a_tx_desc.h b/sys/dev/rtwn/rtl8812a/r12a_tx_desc.h index 93cc9b867401..7d0793a0fe10 100644 --- a/sys/dev/rtwn/rtl8812a/r12a_tx_desc.h +++ b/sys/dev/rtwn/rtl8812a/r12a_tx_desc.h @@ -1,146 +1,144 @@ /*- * Copyright (c) 2016 Andriy Voskoboinyk * 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. */ #ifndef R12A_TX_DESC_H #define R12A_TX_DESC_H /* Tx MAC descriptor (common part). */ struct r12a_tx_desc { uint16_t pktlen; uint8_t offset; uint8_t flags0; #define R12A_FLAGS0_BMCAST 0x01 #define R12A_FLAGS0_LSG 0x04 #define R12A_FLAGS0_FSG 0x08 #define R12A_FLAGS0_OWN 0x80 uint32_t txdw1; #define R12A_TXDW1_MACID_M 0x0000003f #define R12A_TXDW1_MACID_S 0 #define R12A_TXDW1_QSEL_M 0x00001f00 #define R12A_TXDW1_QSEL_S 8 #define R12A_TXDW1_QSEL_BE 0x00 /* or 0x03 */ #define R12A_TXDW1_QSEL_BK 0x01 /* or 0x02 */ #define R12A_TXDW1_QSEL_VI 0x04 /* or 0x05 */ #define R12A_TXDW1_QSEL_VO 0x06 /* or 0x07 */ #define RTWN_MAX_TID 8 #define R12A_TXDW1_QSEL_BEACON 0x10 #define R12A_TXDW1_QSEL_MGNT 0x12 #define R12A_TXDW1_RAID_M 0x001f0000 #define R12A_TXDW1_RAID_S 16 #define R12A_TXDW1_CIPHER_M 0x00c00000 #define R12A_TXDW1_CIPHER_S 22 #define R12A_TXDW1_CIPHER_NONE 0 #define R12A_TXDW1_CIPHER_RC4 1 #define R12A_TXDW1_CIPHER_SM4 2 #define R12A_TXDW1_CIPHER_AES 3 #define R12A_TXDW1_PKTOFF_M 0x1f000000 #define R12A_TXDW1_PKTOFF_S 24 uint32_t txdw2; #define R12A_TXDW2_AGGEN 0x00001000 #define R12A_TXDW2_AGGBK 0x00010000 #define R12A_TXDW2_MOREFRAG 0x00020000 #define R12A_TXDW2_SPE_RPT 0x00080000 #define R12A_TXDW2_AMPDU_DEN_M 0x00700000 #define R12A_TXDW2_AMPDU_DEN_S 20 uint32_t txdw3; #define R12A_TXDW3_SEQ_SEL_M 0x000000c0 #define R12A_TXDW3_SEQ_SEL_S 6 #define R12A_TXDW3_DRVRATE 0x00000100 #define R12A_TXDW3_DISRTSFB 0x00000200 #define R12A_TXDW3_DISDATAFB 0x00000400 #define R12A_TXDW3_CTS2SELF 0x00000800 #define R12A_TXDW3_RTSEN 0x00001000 #define R12A_TXDW3_HWRTSEN 0x00002000 #define R12A_TXDW3_MAX_AGG_M 0x003e0000 #define R12A_TXDW3_MAX_AGG_S 17 uint32_t txdw4; #define R12A_TXDW4_DATARATE_M 0x0000007f #define R12A_TXDW4_DATARATE_S 0 #define R12A_TXDW4_DATARATE_FB_LMT_M 0x00001f00 #define R12A_TXDW4_DATARATE_FB_LMT_S 8 #define R12A_TXDW4_RTSRATE_FB_LMT_M 0x0001e000 #define R12A_TXDW4_RTSRATE_FB_LMT_S 13 #define R12A_TXDW4_RETRY_LMT_ENA 0x00020000 #define R12A_TXDW4_RETRY_LMT_M 0x00fc0000 #define R12A_TXDW4_RETRY_LMT_S 18 #define R12A_TXDW4_RTSRATE_M 0x1f000000 #define R12A_TXDW4_RTSRATE_S 24 uint32_t txdw5; #define R12A_TXDW5_DATA_PRIM_CHAN_M 0x0000000f #define R12A_TXDW5_DATA_PRIM_CHAN_S 0 #define R12A_TXDW5_PRIM_CHAN_20_80_3 1 #define R12A_TXDW5_PRIM_CHAN_20_80_2 2 #define R12A_TXDW5_PRIM_CHAN_20_80_4 3 #define R12A_TXDW5_PRIM_CHAN_20_80_1 4 #define R12A_TXDW5_PRIM_CHAN_40_80_1 9 #define R12A_TXDW5_PRIM_CHAN_40_80_2 10 #define R12A_TXDW5_DATA_SHORT 0x00000010 #define R12A_TXDW5_DATA_BW_M 0x00000060 #define R12A_TXDW5_DATA_BW_S 5 #define R12A_TXDW5_DATA_BW40 1 #define R12A_TXDW5_DATA_BW80 2 #define R12A_TXDW5_DATA_LDPC 0x00000080 #define R12A_TXDW5_RTS_SHORT 0x00001000 #define R12A_TXDW5_RTS_PRIM_CHAN_M 0x0001e000 #define R12A_TXDW5_RTS_PRIM_CHAN_S 13 uint32_t txdw6; #define R21A_TXDW6_MBSSID_M 0x0000f000 #define R21A_TXDW6_MBSSID_S 12 uint32_t reserved; uint32_t txdw8; #define R12A_TXDW8_HWSEQ_EN 0x00008000 uint32_t txdw9; #define R12A_TXDW9_SEQ_M 0x00fff000 #define R12A_TXDW9_SEQ_S 12 } __packed __attribute__((aligned(4))); /* Rate adaptation modes. */ #define R12A_RAID_11BGN_2_40 0 #define R12A_RAID_11BGN_1_40 1 #define R12A_RAID_11BGN_2 2 #define R12A_RAID_11BGN_1 3 #define R12A_RAID_11GN_2 4 #define R12A_RAID_11GN_1 5 #define R12A_RAID_11BG 6 #define R12A_RAID_11G 7 /* "pure" 11g */ #define R12A_RAID_11B 8 -#define R12A_RAID_11AC_2_80 9 -#define R12A_RAID_11AC_1_80 10 -#define R12A_RAID_11AC_1 11 -#define R12A_RAID_11AC_2 12 +#define R12A_RAID_11AC_2 9 +#define R12A_RAID_11AC_1 10 #endif /* R12A_TX_DESC_H */