static void ath_rx_tap(struct ifnet *ifp, struct mbuf *m, const struct ath_rx_status *rs, u_int64_t tsf, int16_t nf) { #define CHAN_HT20 htole32(IEEE80211_CHAN_HT20) #define CHAN_HT40U htole32(IEEE80211_CHAN_HT40U) #define CHAN_HT40D htole32(IEEE80211_CHAN_HT40D) #define CHAN_HT (CHAN_HT20|CHAN_HT40U|CHAN_HT40D) struct ath_softc *sc = ifp->if_softc; const HAL_RATE_TABLE *rt; uint8_t rix; rt = sc->sc_currates; KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode)); rix = rt->rateCodeToIndex[rs->rs_rate]; sc->sc_rx_th.wr_rate = sc->sc_hwmap[rix].ieeerate; sc->sc_rx_th.wr_flags = sc->sc_hwmap[rix].rxflags; #ifdef AH_SUPPORT_AR5416 sc->sc_rx_th.wr_chan_flags &= ~CHAN_HT; if (rs->rs_status & HAL_RXERR_PHY) { /* * PHY error - make sure the channel flags * reflect the actual channel configuration, * not the received frame. */ if (IEEE80211_IS_CHAN_HT40U(sc->sc_curchan)) sc->sc_rx_th.wr_chan_flags |= CHAN_HT40U; else if (IEEE80211_IS_CHAN_HT40D(sc->sc_curchan)) sc->sc_rx_th.wr_chan_flags |= CHAN_HT40D; else if (IEEE80211_IS_CHAN_HT20(sc->sc_curchan)) sc->sc_rx_th.wr_chan_flags |= CHAN_HT20; } else if (sc->sc_rx_th.wr_rate & IEEE80211_RATE_MCS) { /* HT rate */ struct ieee80211com *ic = ifp->if_l2com; if ((rs->rs_flags & HAL_RX_2040) == 0) sc->sc_rx_th.wr_chan_flags |= CHAN_HT20; else if (IEEE80211_IS_CHAN_HT40U(ic->ic_curchan)) sc->sc_rx_th.wr_chan_flags |= CHAN_HT40U; else sc->sc_rx_th.wr_chan_flags |= CHAN_HT40D; if ((rs->rs_flags & HAL_RX_GI) == 0) sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_SHORTGI; } #endif sc->sc_rx_th.wr_tsf = htole64(ath_extend_tsf(sc, rs->rs_tstamp, tsf)); if (rs->rs_status & HAL_RXERR_CRC) sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_BADFCS; /* XXX propagate other error flags from descriptor */ sc->sc_rx_th.wr_antnoise = nf; sc->sc_rx_th.wr_antsignal = nf + rs->rs_rssi; sc->sc_rx_th.wr_antenna = rs->rs_antenna; #undef CHAN_HT #undef CHAN_HT20 #undef CHAN_HT40U #undef CHAN_HT40D }
/* * rt2860_rf_select_chan_group */ void rt2860_rf_select_chan_group(struct rt2860_softc *sc, struct ieee80211_channel *c) { struct ifnet *ifp; struct ieee80211com *ic; int chan, group; uint32_t tmp; ifp = sc->ifp; ic = ifp->if_l2com; chan = ieee80211_chan2ieee(ic, c); if (chan == 0 || chan == IEEE80211_CHAN_ANY) return; if (chan <= 14) group = 0; else if (chan <= 64) group = 1; else if (chan <= 128) group = 2; else group = 3; rt2860_io_bbp_write(sc, 62, 0x37 - sc->lna_gain[group]); rt2860_io_bbp_write(sc, 63, 0x37 - sc->lna_gain[group]); rt2860_io_bbp_write(sc, 64, 0x37 - sc->lna_gain[group]); rt2860_io_bbp_write(sc, 86, 0x00); if (group == 0) { if (sc->ext_lna_2ghz) { rt2860_io_bbp_write(sc, 82, 0x62); rt2860_io_bbp_write(sc, 75, 0x46); } else { rt2860_io_bbp_write(sc, 82, 0x84); rt2860_io_bbp_write(sc, 75, 0x50); } } else { rt2860_io_bbp_write(sc, 82, 0xf2); if (sc->ext_lna_5ghz) rt2860_io_bbp_write(sc, 75, 0x46); else rt2860_io_bbp_write(sc, 75, 0x50); } if (group == 0) { tmp = 0x2e + sc->lna_gain[group]; } else { if ((ic->ic_flags & IEEE80211_F_SCAN) || !IEEE80211_IS_CHAN_HT40(c)) tmp = 0x32 + sc->lna_gain[group] * 5 / 3; else tmp = 0x3a + sc->lna_gain[group] * 5 / 3; } rt2860_io_bbp_write(sc, 66, tmp); tmp = RT2860_REG_RFTR_ENABLE | RT2860_REG_TRSW_ENABLE | RT2860_REG_LNA_PE_G1_ENABLE | RT2860_REG_LNA_PE_A1_ENABLE | RT2860_REG_LNA_PE_G0_ENABLE | RT2860_REG_LNA_PE_A0_ENABLE; if (group == 0) tmp |= RT2860_REG_PA_PE_G1_ENABLE | RT2860_REG_PA_PE_G0_ENABLE; else tmp |= RT2860_REG_PA_PE_A1_ENABLE | RT2860_REG_PA_PE_A0_ENABLE; if (sc->ntxpath == 1) tmp &= ~(RT2860_REG_PA_PE_G1_ENABLE | RT2860_REG_PA_PE_A1_ENABLE); if (sc->nrxpath == 1) tmp &= ~(RT2860_REG_LNA_PE_G1_ENABLE | RT2860_REG_LNA_PE_A1_ENABLE); rt2860_io_mac_write(sc, RT2860_REG_TX_PIN_CFG, tmp); tmp = rt2860_io_mac_read(sc, RT2860_REG_TX_BAND_CFG); tmp &= ~(RT2860_REG_TX_BAND_BG | RT2860_REG_TX_BAND_A | RT2860_REG_TX_BAND_HT40_ABOVE); if (group == 0) tmp |= RT2860_REG_TX_BAND_BG; else tmp |= RT2860_REG_TX_BAND_A; /* set central channel position */ if (IEEE80211_IS_CHAN_HT40U(c)) tmp |= RT2860_REG_TX_BAND_HT40_BELOW; else if (IEEE80211_IS_CHAN_HT40D(c)) tmp |= RT2860_REG_TX_BAND_HT40_ABOVE; else tmp |= RT2860_REG_TX_BAND_HT40_BELOW; rt2860_io_mac_write(sc, RT2860_REG_TX_BAND_CFG, tmp); /* set bandwidth (20MHz or 40MHz) */ tmp = rt2860_io_bbp_read(sc, 4); tmp &= ~0x18; if (IEEE80211_IS_CHAN_HT40(c)) tmp |= 0x10; rt2860_io_bbp_write(sc, 4, tmp); /* set central channel position */ tmp = rt2860_io_bbp_read(sc, 3); tmp &= ~0x20; if (IEEE80211_IS_CHAN_HT40D(c)) tmp |= 0x20; rt2860_io_bbp_write(sc, 3, tmp); if (sc->mac_rev == 0x28600100) { if (!IEEE80211_IS_CHAN_HT40(c)) { rt2860_io_bbp_write(sc, 69, 0x16); rt2860_io_bbp_write(sc, 70, 0x08); rt2860_io_bbp_write(sc, 73, 0x12); } else { rt2860_io_bbp_write(sc, 69, 0x1a); rt2860_io_bbp_write(sc, 70, 0x0a); rt2860_io_bbp_write(sc, 73, 0x16); } } }
/* * rt2860_rf_set_chan */ void rt2860_rf_set_chan(struct rt2860_softc *sc, struct ieee80211_channel *c) { struct ifnet *ifp; struct ieee80211com *ic; const struct rt2860_rf_prog *prog; uint32_t r1, r2, r3, r4; int8_t txpow1, txpow2; int i, chan; if (sc->mac_rev == 0x28720200) { rt2872_rf_set_chan(sc, c); return; } ifp = sc->ifp; ic = ifp->if_l2com; prog = rt2860_rf_2850; /* get central channel position */ chan = ieee80211_chan2ieee(ic, c); if ((sc->mac_rev & 0xffff0000) >= 0x30710000) { rt3090_set_chan(sc, chan); return; } if (IEEE80211_IS_CHAN_HT40U(c)) chan += 2; else if (IEEE80211_IS_CHAN_HT40D(c)) chan -= 2; RT2860_DPRINTF(sc, RT2860_DEBUG_CHAN, "%s: RF set channel: channel=%u, HT%s%s\n", device_get_nameunit(sc->dev), ieee80211_chan2ieee(ic, c), !IEEE80211_IS_CHAN_HT(c) ? " disabled" : IEEE80211_IS_CHAN_HT20(c) ? "20": IEEE80211_IS_CHAN_HT40U(c) ? "40U" : "40D", (ic->ic_flags & IEEE80211_F_SCAN) ? ", scanning" : ""); if (chan == 0 || chan == IEEE80211_CHAN_ANY) return; for (i = 0; prog[i].chan != chan; i++); r1 = prog[i].r1; r2 = prog[i].r2; r3 = prog[i].r3; r4 = prog[i].r4; txpow1 = sc->txpow1[i]; txpow2 = sc->txpow2[i]; if (sc->ntxpath == 1) r2 |= (1 << 14); if (sc->nrxpath == 2) r2 |= (1 << 6); else if (sc->nrxpath == 1) r2 |= (1 << 17) | (1 << 6); if (IEEE80211_IS_CHAN_2GHZ(c)) { r3 = (r3 & 0xffffc1ff) | (txpow1 << 9); r4 = (r4 & ~0x001f87c0) | (sc->rf_freq_off << 15) | (txpow2 << 6); } else { r3 = r3 & 0xffffc1ff; r4 = (r4 & ~0x001f87c0) | (sc->rf_freq_off << 15); if (txpow1 >= RT2860_EEPROM_TXPOW_5GHZ_MIN && txpow1 < 0) { txpow1 = (-RT2860_EEPROM_TXPOW_5GHZ_MIN + txpow1); if (txpow1 > RT2860_EEPROM_TXPOW_5GHZ_MAX) txpow1 = RT2860_EEPROM_TXPOW_5GHZ_MAX; r3 |= (txpow1 << 10); } else { if (txpow1 > RT2860_EEPROM_TXPOW_5GHZ_MAX) txpow1 = RT2860_EEPROM_TXPOW_5GHZ_MAX; r3 |= (txpow1 << 10) | (1 << 9); } if (txpow2 >= RT2860_EEPROM_TXPOW_5GHZ_MIN && txpow2 < 0) { txpow2 = (-RT2860_EEPROM_TXPOW_5GHZ_MIN + txpow2); if (txpow2 > RT2860_EEPROM_TXPOW_5GHZ_MAX) txpow2 = RT2860_EEPROM_TXPOW_5GHZ_MAX; r4 |= (txpow2 << 7); } else { if (txpow2 > RT2860_EEPROM_TXPOW_5GHZ_MAX) txpow2 = RT2860_EEPROM_TXPOW_5GHZ_MAX; r4 |= (txpow2 << 7) | (1 << 6); } } if (!(ic->ic_flags & IEEE80211_F_SCAN) && IEEE80211_IS_CHAN_HT40(c)) r4 |= (1 << 21); rt2860_io_rf_write(sc, RT2860_REG_RF_R1, r1); rt2860_io_rf_write(sc, RT2860_REG_RF_R2, r2); rt2860_io_rf_write(sc, RT2860_REG_RF_R3, r3 & ~(1 << 2)); rt2860_io_rf_write(sc, RT2860_REG_RF_R4, r4); DELAY(200); rt2860_io_rf_write(sc, RT2860_REG_RF_R1, r1); rt2860_io_rf_write(sc, RT2860_REG_RF_R2, r2); rt2860_io_rf_write(sc, RT2860_REG_RF_R3, r3 | (1 << 2)); rt2860_io_rf_write(sc, RT2860_REG_RF_R4, r4); DELAY(200); rt2860_io_rf_write(sc, RT2860_REG_RF_R1, r1); rt2860_io_rf_write(sc, RT2860_REG_RF_R2, r2); rt2860_io_rf_write(sc, RT2860_REG_RF_R3, r3 & ~(1 << 2)); rt2860_io_rf_write(sc, RT2860_REG_RF_R4, r4); rt2860_rf_select_chan_group(sc, c); DELAY(1000); }
/* * rt2872_rf_set_chan */ static void rt2872_rf_set_chan(struct rt2860_softc *sc, struct ieee80211_channel *c) { struct ifnet *ifp; struct ieee80211com *ic; const struct rt2860_rf_prog *prog; uint32_t r1, r2, r3, r4; uint32_t r6, r7, r12, r13, r23, r24; int8_t txpow1, txpow2; int i, chan; ifp = sc->ifp; ic = ifp->if_l2com; prog = rt2860_rf_2850; /* get central channel position */ chan = ieee80211_chan2ieee(ic, c); if (IEEE80211_IS_CHAN_HT40U(c)) chan += 2; else if (IEEE80211_IS_CHAN_HT40D(c)) chan -= 2; RT2860_DPRINTF(sc, RT2860_DEBUG_CHAN, "%s: RF set channel: channel=%u, HT%s%s\n", device_get_nameunit(sc->dev), ieee80211_chan2ieee(ic, c), !IEEE80211_IS_CHAN_HT(c) ? " disabled" : IEEE80211_IS_CHAN_HT20(c) ? "20": IEEE80211_IS_CHAN_HT40U(c) ? "40U" : "40D", (ic->ic_flags & IEEE80211_F_SCAN) ? ", scanning" : ""); if (chan == 0 || chan == IEEE80211_CHAN_ANY) return; for (i = 0; prog[i].chan != chan; i++); r1 = prog[i].r1; r2 = prog[i].r2; r3 = prog[i].r3; r4 = prog[i].r4; txpow1 = sc->txpow1[i]; txpow2 = sc->txpow2[i]; for (i = 0; rt2860_rf_fi3020[i].channel != chan; i++); /* Programm channel parameters */ r2 = rt2860_rf_fi3020[i].n; rt2860_io_rf_write(sc, 2 , r2 ); r3 = rt2860_rf_fi3020[i].k; rt2860_io_rf_write(sc, 3 , r3 ); r6 = (rt3052_rf_default[6] & 0xFC) | (rt2860_rf_fi3020[i].r & 0x03); rt2860_io_rf_write(sc, 6 , r6 ); /* Set Tx Power */ r12 = (rt3052_rf_default[12] & 0xE0) | (txpow1 & 0x1f); rt2860_io_rf_write(sc, 12, r12); /* Set Tx1 Power */ r13 = (rt3052_rf_default[13] & 0xE0) | (txpow2 & 0x1f); rt2860_io_rf_write(sc, 13, r13); /* Set RF offset */ r23 = (rt3052_rf_default[23] & 0x80) | (sc->rf_freq_off); rt2860_io_rf_write(sc, 23, r23); /* Set BW */ r24 = (rt3052_rf_default[24] & 0xDF); if (!(ic->ic_flags & IEEE80211_F_SCAN) && IEEE80211_IS_CHAN_HT40(c)) r24 |= 0x20; rt2860_io_rf_write(sc, 24, r24); /* Enable RF tuning */ r7 = (rt3052_rf_default[7]) | 1; rt2860_io_rf_write(sc, 7 , r7 ); /* Antenna */ r1 = (rt3052_rf_default[1] & 0xab) | ((sc->nrxpath == 1)?0x10:0) | ((sc->ntxpath == 1)?0x20:0); rt2860_io_rf_write(sc, 1 , r1 ); DELAY(200); rt2860_rf_select_chan_group(sc, c); DELAY(1000); }