/* * Return whether 11n rates are possible. * * Some 11n devices may return HT information but no HT rates. * Thus, we shouldn't treat them as an 11n node. */ static int amrr_node_is_11n(struct ieee80211_node *ni) { if (ni->ni_chan == NULL) return (0); if (ni->ni_chan == IEEE80211_CHAN_ANYC) return (0); if (IEEE80211_IS_CHAN_HT(ni->ni_chan) && ni->ni_htrates.rs_nrates == 0) return (0); return (IEEE80211_IS_CHAN_HT(ni->ni_chan)); }
static void dumpchannels(struct ath_hal *ah, int nc, const struct ieee80211_channel *chans, int16_t *txpow) { int i; for (i = 0; i < nc; i++) { const struct ieee80211_channel *c = &chans[i]; int type; if (showchannels) printf("%s%3d", sep, ath_hal_mhz2ieee(ah, c->ic_freq, c->ic_flags)); else printf("%s%u", sep, c->ic_freq); if (IEEE80211_IS_CHAN_HALF(c)) type = 'H'; else if (IEEE80211_IS_CHAN_QUARTER(c)) type = 'Q'; else if (IEEE80211_IS_CHAN_TURBO(c)) type = 'T'; else if (IEEE80211_IS_CHAN_HT(c)) type = 'N'; else if (IEEE80211_IS_CHAN_A(c)) type = 'A'; else if (IEEE80211_IS_CHAN_108G(c)) type = 'T'; else if (IEEE80211_IS_CHAN_G(c)) type = 'G'; else type = 'B'; if (dopassive && IEEE80211_IS_CHAN_PASSIVE(c)) type = tolower(type); if (isdfs && is4ms) printf("%c%c%c %d.%d", type, IEEE80211_IS_CHAN_DFS(c) ? '*' : ' ', IEEE80211_IS_CHAN_4MS(c) ? '4' : ' ', txpow[i]/2, (txpow[i]%2)*5); else if (isdfs) printf("%c%c %d.%d", type, IEEE80211_IS_CHAN_DFS(c) ? '*' : ' ', txpow[i]/2, (txpow[i]%2)*5); else if (is4ms) printf("%c%c %d.%d", type, IEEE80211_IS_CHAN_4MS(c) ? '4' : ' ', txpow[i]/2, (txpow[i]%2)*5); else printf("%c %d.%d", type, txpow[i]/2, (txpow[i]%2)*5); if ((n++ % (showchannels ? 7 : 6)) == 0) sep = "\n"; else sep = " "; } }
static char channel_type(const struct ieee80211_channel *c) { if (IEEE80211_IS_CHAN_ST(c)) return 'S'; if (IEEE80211_IS_CHAN_108A(c)) return 'T'; if (IEEE80211_IS_CHAN_108G(c)) return 'G'; if (IEEE80211_IS_CHAN_HT(c)) return 'n'; if (IEEE80211_IS_CHAN_A(c)) return 'a'; if (IEEE80211_IS_CHAN_ANYG(c)) return 'g'; if (IEEE80211_IS_CHAN_B(c)) return 'b'; return 'f'; }
/* * Calculate the receive filter according to the * operating mode and state: * * o always accept unicast, broadcast, and multicast traffic * o accept PHY error frames when hardware doesn't have MIB support * to count and we need them for ANI (sta mode only until recently) * and we are not scanning (ANI is disabled) * NB: older hal's add rx filter bits out of sight and we need to * blindly preserve them * o probe request frames are accepted only when operating in * hostap, adhoc, mesh, or monitor modes * o enable promiscuous mode * - when in monitor mode * - if interface marked PROMISC (assumes bridge setting is filtered) * o accept beacons: * - when operating in station mode for collecting rssi data when * the station is otherwise quiet, or * - when operating in adhoc mode so the 802.11 layer creates * node table entries for peers, * - when scanning * - when doing s/w beacon miss (e.g. for ap+sta) * - when operating in ap mode in 11g to detect overlapping bss that * require protection * - when operating in mesh mode to detect neighbors * o accept control frames: * - when in monitor mode * XXX HT protection for 11n */ u_int32_t ath_calcrxfilter(struct ath_softc *sc) { struct ieee80211com *ic = &sc->sc_ic; u_int32_t rfilt; rfilt = HAL_RX_FILTER_UCAST | HAL_RX_FILTER_BCAST | HAL_RX_FILTER_MCAST; if (!sc->sc_needmib && !sc->sc_scanning) rfilt |= HAL_RX_FILTER_PHYERR; if (ic->ic_opmode != IEEE80211_M_STA) rfilt |= HAL_RX_FILTER_PROBEREQ; /* XXX ic->ic_monvaps != 0? */ if (ic->ic_opmode == IEEE80211_M_MONITOR || ic->ic_promisc > 0) rfilt |= HAL_RX_FILTER_PROM; /* * Only listen to all beacons if we're scanning. * * Otherwise we only really need to hear beacons from * our own BSSID. * * IBSS? software beacon miss? Just receive all beacons. * We need to hear beacons/probe requests from everyone so * we can merge ibss. */ if (ic->ic_opmode == IEEE80211_M_IBSS || sc->sc_swbmiss) { rfilt |= HAL_RX_FILTER_BEACON; } else if (ic->ic_opmode == IEEE80211_M_STA) { if (sc->sc_do_mybeacon && ! sc->sc_scanning) { rfilt |= HAL_RX_FILTER_MYBEACON; } else { /* scanning, non-mybeacon chips */ rfilt |= HAL_RX_FILTER_BEACON; } } /* * NB: We don't recalculate the rx filter when * ic_protmode changes; otherwise we could do * this only when ic_protmode != NONE. */ if (ic->ic_opmode == IEEE80211_M_HOSTAP && IEEE80211_IS_CHAN_ANYG(ic->ic_curchan)) rfilt |= HAL_RX_FILTER_BEACON; /* * Enable hardware PS-POLL RX only for hostap mode; * STA mode sends PS-POLL frames but never * receives them. */ if (ath_hal_getcapability(sc->sc_ah, HAL_CAP_PSPOLL, 0, NULL) == HAL_OK && ic->ic_opmode == IEEE80211_M_HOSTAP) rfilt |= HAL_RX_FILTER_PSPOLL; if (sc->sc_nmeshvaps) { rfilt |= HAL_RX_FILTER_BEACON; if (sc->sc_hasbmatch) rfilt |= HAL_RX_FILTER_BSSID; else rfilt |= HAL_RX_FILTER_PROM; } if (ic->ic_opmode == IEEE80211_M_MONITOR) rfilt |= HAL_RX_FILTER_CONTROL; /* * Enable RX of compressed BAR frames only when doing * 802.11n. Required for A-MPDU. */ if (IEEE80211_IS_CHAN_HT(ic->ic_curchan)) rfilt |= HAL_RX_FILTER_COMPBAR; /* * Enable radar PHY errors if requested by the * DFS module. */ if (sc->sc_dodfs) rfilt |= HAL_RX_FILTER_PHYRADAR; /* * Enable spectral PHY errors if requested by the * spectral module. */ if (sc->sc_dospectral) rfilt |= HAL_RX_FILTER_PHYRADAR; DPRINTF(sc, ATH_DEBUG_MODE, "%s: RX filter 0x%x, %s\n", __func__, rfilt, ieee80211_opmode_name[ic->ic_opmode]); return rfilt; }
/* * Calculate the receive filter according to the * operating mode and state: * * o always accept unicast, broadcast, and multicast traffic * o accept PHY error frames when hardware doesn't have MIB support * to count and we need them for ANI (sta mode only until recently) * and we are not scanning (ANI is disabled) * NB: older hal's add rx filter bits out of sight and we need to * blindly preserve them * o probe request frames are accepted only when operating in * hostap, adhoc, mesh, or monitor modes * o enable promiscuous mode * - when in monitor mode * - if interface marked PROMISC (assumes bridge setting is filtered) * o accept beacons: * - when operating in station mode for collecting rssi data when * the station is otherwise quiet, or * - when operating in adhoc mode so the 802.11 layer creates * node table entries for peers, * - when scanning * - when doing s/w beacon miss (e.g. for ap+sta) * - when operating in ap mode in 11g to detect overlapping bss that * require protection * - when operating in mesh mode to detect neighbors * o accept control frames: * - when in monitor mode * XXX HT protection for 11n */ u_int32_t ath_calcrxfilter(struct ath_softc *sc) { struct ifnet *ifp = sc->sc_ifp; struct ieee80211com *ic = ifp->if_l2com; u_int32_t rfilt; rfilt = HAL_RX_FILTER_UCAST | HAL_RX_FILTER_BCAST | HAL_RX_FILTER_MCAST; if (!sc->sc_needmib && !sc->sc_scanning) rfilt |= HAL_RX_FILTER_PHYERR; if (ic->ic_opmode != IEEE80211_M_STA) rfilt |= HAL_RX_FILTER_PROBEREQ; /* XXX ic->ic_monvaps != 0? */ if (ic->ic_opmode == IEEE80211_M_MONITOR || (ifp->if_flags & IFF_PROMISC)) rfilt |= HAL_RX_FILTER_PROM; if (ic->ic_opmode == IEEE80211_M_STA || ic->ic_opmode == IEEE80211_M_IBSS || sc->sc_swbmiss || sc->sc_scanning) rfilt |= HAL_RX_FILTER_BEACON; /* * NB: We don't recalculate the rx filter when * ic_protmode changes; otherwise we could do * this only when ic_protmode != NONE. */ if (ic->ic_opmode == IEEE80211_M_HOSTAP && IEEE80211_IS_CHAN_ANYG(ic->ic_curchan)) rfilt |= HAL_RX_FILTER_BEACON; /* * Enable hardware PS-POLL RX only for hostap mode; * STA mode sends PS-POLL frames but never * receives them. */ if (ath_hal_getcapability(sc->sc_ah, HAL_CAP_PSPOLL, 0, NULL) == HAL_OK && ic->ic_opmode == IEEE80211_M_HOSTAP) rfilt |= HAL_RX_FILTER_PSPOLL; if (sc->sc_nmeshvaps) { rfilt |= HAL_RX_FILTER_BEACON; if (sc->sc_hasbmatch) rfilt |= HAL_RX_FILTER_BSSID; else rfilt |= HAL_RX_FILTER_PROM; } if (ic->ic_opmode == IEEE80211_M_MONITOR) rfilt |= HAL_RX_FILTER_CONTROL; /* * Enable RX of compressed BAR frames only when doing * 802.11n. Required for A-MPDU. */ if (IEEE80211_IS_CHAN_HT(ic->ic_curchan)) rfilt |= HAL_RX_FILTER_COMPBAR; /* * Enable radar PHY errors if requested by the * DFS module. */ if (sc->sc_dodfs) rfilt |= HAL_RX_FILTER_PHYRADAR; /* * Enable spectral PHY errors if requested by the * spectral module. */ if (sc->sc_dospectral) rfilt |= HAL_RX_FILTER_PHYRADAR; DPRINTF(sc, ATH_DEBUG_MODE, "%s: RX filter 0x%x, %s if_flags 0x%x\n", __func__, rfilt, ieee80211_opmode_name[ic->ic_opmode], ifp->if_flags); return rfilt; }
/* * 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); }