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 }
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); }
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); }
/* * Fill in 802.11 available channel set, mark * all available channels as active, and pick * a default channel if not already specified. */ static void ieee80211_chan_init(struct ieee80211com *ic) { #define DEFAULTRATES(m, def) do { \ if (ic->ic_sup_rates[m].rs_nrates == 0) \ ic->ic_sup_rates[m] = def; \ } while (0) struct ieee80211_channel *c; int i; KASSERT(0 < ic->ic_nchans && ic->ic_nchans <= IEEE80211_CHAN_MAX, ("invalid number of channels specified: %u", ic->ic_nchans)); memset(ic->ic_chan_avail, 0, sizeof(ic->ic_chan_avail)); memset(ic->ic_modecaps, 0, sizeof(ic->ic_modecaps)); setbit(ic->ic_modecaps, IEEE80211_MODE_AUTO); for (i = 0; i < ic->ic_nchans; i++) { c = &ic->ic_channels[i]; KASSERT(c->ic_flags != 0, ("channel with no flags")); /* * Help drivers that work only with frequencies by filling * in IEEE channel #'s if not already calculated. Note this * mimics similar work done in ieee80211_setregdomain when * changing regulatory state. */ if (c->ic_ieee == 0) c->ic_ieee = ieee80211_mhz2ieee(c->ic_freq,c->ic_flags); if (IEEE80211_IS_CHAN_HT40(c) && c->ic_extieee == 0) c->ic_extieee = ieee80211_mhz2ieee(c->ic_freq + (IEEE80211_IS_CHAN_HT40U(c) ? 20 : -20), c->ic_flags); /* default max tx power to max regulatory */ if (c->ic_maxpower == 0) c->ic_maxpower = 2*c->ic_maxregpower; setbit(ic->ic_chan_avail, c->ic_ieee); /* * Identify mode capabilities. */ if (IEEE80211_IS_CHAN_A(c)) setbit(ic->ic_modecaps, IEEE80211_MODE_11A); if (IEEE80211_IS_CHAN_B(c)) setbit(ic->ic_modecaps, IEEE80211_MODE_11B); if (IEEE80211_IS_CHAN_ANYG(c)) setbit(ic->ic_modecaps, IEEE80211_MODE_11G); if (IEEE80211_IS_CHAN_FHSS(c)) setbit(ic->ic_modecaps, IEEE80211_MODE_FH); if (IEEE80211_IS_CHAN_108A(c)) setbit(ic->ic_modecaps, IEEE80211_MODE_TURBO_A); if (IEEE80211_IS_CHAN_108G(c)) setbit(ic->ic_modecaps, IEEE80211_MODE_TURBO_G); if (IEEE80211_IS_CHAN_ST(c)) setbit(ic->ic_modecaps, IEEE80211_MODE_STURBO_A); if (IEEE80211_IS_CHAN_HALF(c)) setbit(ic->ic_modecaps, IEEE80211_MODE_HALF); if (IEEE80211_IS_CHAN_QUARTER(c)) setbit(ic->ic_modecaps, IEEE80211_MODE_QUARTER); if (IEEE80211_IS_CHAN_HTA(c)) setbit(ic->ic_modecaps, IEEE80211_MODE_11NA); if (IEEE80211_IS_CHAN_HTG(c)) setbit(ic->ic_modecaps, IEEE80211_MODE_11NG); } /* initialize candidate channels to all available */ memcpy(ic->ic_chan_active, ic->ic_chan_avail, sizeof(ic->ic_chan_avail)); /* sort channel table to allow lookup optimizations */ ieee80211_sort_channels(ic->ic_channels, ic->ic_nchans); /* invalidate any previous state */ ic->ic_bsschan = IEEE80211_CHAN_ANYC; ic->ic_prevchan = NULL; ic->ic_csa_newchan = NULL; /* arbitrarily pick the first channel */ ic->ic_curchan = &ic->ic_channels[0]; ic->ic_rt = ieee80211_get_ratetable(ic->ic_curchan); /* fillin well-known rate sets if driver has not specified */ DEFAULTRATES(IEEE80211_MODE_11B, ieee80211_rateset_11b); DEFAULTRATES(IEEE80211_MODE_11G, ieee80211_rateset_11g); DEFAULTRATES(IEEE80211_MODE_11A, ieee80211_rateset_11a); DEFAULTRATES(IEEE80211_MODE_TURBO_A, ieee80211_rateset_11a); DEFAULTRATES(IEEE80211_MODE_TURBO_G, ieee80211_rateset_11g); DEFAULTRATES(IEEE80211_MODE_STURBO_A, ieee80211_rateset_11a); DEFAULTRATES(IEEE80211_MODE_HALF, ieee80211_rateset_half); DEFAULTRATES(IEEE80211_MODE_QUARTER, ieee80211_rateset_quarter); DEFAULTRATES(IEEE80211_MODE_11NA, ieee80211_rateset_11a); DEFAULTRATES(IEEE80211_MODE_11NG, ieee80211_rateset_11g); /* * Set auto mode to reset active channel state and any desired channel. */ (void) ieee80211_setmode(ic, IEEE80211_MODE_AUTO); #undef DEFAULTRATES }
/* * 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); }
/* * 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); } } }
/* * 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); }