void ieee80211_create_ibss(struct ieee80211com* ic, struct ieee80211_channel *chan) { struct ieee80211_node *ni; struct ifnet *ifp = &ic->ic_if; ni = ic->ic_bss; if (ifp->if_flags & IFF_DEBUG) printf("%s: creating ibss\n", ifp->if_xname); ic->ic_flags |= IEEE80211_F_SIBSS; ni->ni_chan = chan; ni->ni_rates = ic->ic_sup_rates[ieee80211_chan2mode(ic, ni->ni_chan)]; IEEE80211_ADDR_COPY(ni->ni_macaddr, ic->ic_myaddr); IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_myaddr); if (ic->ic_opmode == IEEE80211_M_IBSS) { if ((ic->ic_flags & IEEE80211_F_DESBSSID) != 0) IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_des_bssid); else ni->ni_bssid[0] |= 0x02; /* local bit for IBSS */ } ni->ni_esslen = ic->ic_des_esslen; memcpy(ni->ni_essid, ic->ic_des_essid, ni->ni_esslen); ni->ni_rssi = 0; ni->ni_rstamp = 0; memset(ni->ni_tstamp, 0, sizeof(ni->ni_tstamp)); ni->ni_intval = ic->ic_lintval; ni->ni_capinfo = IEEE80211_CAPINFO_IBSS; if (ic->ic_flags & IEEE80211_F_WEPON) ni->ni_capinfo |= IEEE80211_CAPINFO_PRIVACY; if (ic->ic_phytype == IEEE80211_T_FH) { ni->ni_fhdwell = 200; /* XXX */ ni->ni_fhindex = 1; } ieee80211_new_state(ic, IEEE80211_S_RUN, -1); }
void mlme_get_linkrate(struct ieee80211_node *ni, u_int32_t* rxlinkspeed, u_int32_t* txlinkspeed) { struct ieee80211vap *vap = ni->ni_vap; struct ieee80211com *ic = ni->ni_ic; int ht_rates_allowed; u_int8_t rate; /* Check if connected to BSS */ if ((ni->ni_htrates.rs_nrates == 0) && (ni->ni_rates.rs_nrates == 0)) { /* Not connected */ if (ic->ic_caps & IEEE80211_C_HT) { *txlinkspeed = get_max_phyrate(ic); *rxlinkspeed = *txlinkspeed; } else { struct ieee80211_rateset *rs; /* Legacy card, report highest rate */ rs = &vap->iv_op_rates[ieee80211_chan2mode(ic->ic_curchan)]; rate = rs->rs_rates[rs->rs_nrates - 1]; *txlinkspeed = mlme_dot11rate_to_bps(rate & IEEE80211_RATE_VAL); *rxlinkspeed = *txlinkspeed; } } else { /* Connected */ /* * With WEP and TKIP encryption algorithms: * Disable 11n if IEEE80211_FEXT_WEP_TKIP_HTRATE is not set. */ ht_rates_allowed = (IEEE80211_IS_CHAN_11N(ic->ic_curchan) && ieee80211vap_htallowed(vap)); if (ni->ni_htrates.rs_nrates && ht_rates_allowed) { mlme_calculate_11n_connection_speed(ni, rxlinkspeed, txlinkspeed); if (ic->ic_reg_parm.indicateRxLinkSpeed) *txlinkspeed = *rxlinkspeed; } else { /* get maximum rate from node rate set */ rate = ni->ni_rates.rs_rates[ni->ni_rates.rs_nrates - 1] & IEEE80211_RATE_VAL; *txlinkspeed = mlme_dot11rate_to_bps(rate); *rxlinkspeed = *txlinkspeed; } } IEEE80211_DPRINTF(vap, IEEE80211_MSG_MLME, "%s: Rx Link speed Data rate: %d, Tx Link speed Data rate: %d\n", __func__, *rxlinkspeed, *txlinkspeed); }
void ath_phyerr_reset(struct ath_softc *sc) { struct ieee80211com *ic = &sc->sc_ic; u_int32_t mode; if (ic->ic_opmode == IEEE80211_M_HOSTAP) { mode = ieee80211_chan2mode(ic, ic->ic_ibss_chan); if (mode == IEEE80211_MODE_TURBO_G) ath_reset_ar(sc); if ((mode == IEEE80211_MODE_11A) || (mode == IEEE80211_MODE_TURBO_A)) ath_reset_radar(sc); } }
void ath_phyerr_diag(struct net_device *dev, u_int phyerr, struct ath_desc *ds, struct sk_buff *skb) { struct ath_softc *sc = dev->priv; struct ieee80211com *ic = &sc->sc_ic; struct ieee80211_channel *chan; u_int32_t mode; chan = ic->ic_bss->ni_chan; if ((phyerr == HAL_PHYERR_RADAR) && (ic->ic_opmode == IEEE80211_M_HOSTAP)) { mode = ieee80211_chan2mode(ic, chan); if (mode == IEEE80211_MODE_TURBO_G) ath_AR_event(dev, ds, skb); else ath_radar_event(dev, ds, skb); } }
static int ieee80211_mgmt_output(struct ieee80211_s *ic, struct ieee80211_node *ni, struct iob_s *iob, int type) { struct ieee80211_frame *wh; int error; DEBUGASSERT(ni != NULL); ni->ni_inact = 0; /* We want to pass the node down to the driver's start routine. We could * stick this in an m_tag and tack that on to the buffer. However that's * rather expensive to do for every frame so instead we stuff it in a special * pkthdr field. */ error = iob_contig(iob, sizeof(struct ieee80211_frame)); if (error < 0) { ndbg("ERROR: Failed to make contiguous: %d\n", error); return error; } #warning REVISIT: We do not want to burden everty IOB with this information //iob->io_priv = ni; wh = (FAR struct ieee80211_frame *)IOB_DATA(iob); wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT | type; wh->i_fc[1] = IEEE80211_FC1_DIR_NODS; *(uint16_t *) & wh->i_dur[0] = 0; *(uint16_t *) & wh->i_seq[0] = htole16(ni->ni_txseq << IEEE80211_SEQ_SEQ_SHIFT); ni->ni_txseq++; IEEE80211_ADDR_COPY(wh->i_addr1, ni->ni_macaddr); IEEE80211_ADDR_COPY(wh->i_addr2, ic->ic_myaddr); IEEE80211_ADDR_COPY(wh->i_addr3, ni->ni_bssid); /* Check if protection is required for this mgmt frame */ if ((ic->ic_caps & IEEE80211_C_MFP) && (type == IEEE80211_FC0_SUBTYPE_DISASSOC || type == IEEE80211_FC0_SUBTYPE_DEAUTH || type == IEEE80211_FC0_SUBTYPE_ACTION)) { /* Hack: we should not set the Protected bit in outgoing group management * frames, however it is used as an indication to the drivers that they * must encrypt the frame. Drivers should clear this bit from group * management frames (software crypto code will do it). */ if (IEEE80211_IS_MULTICAST(wh->i_addr1) || (ni->ni_flags & IEEE80211_NODE_TXMGMTPROT)) { wh->i_fc[1] |= IEEE80211_FC1_PROTECTED; } } #if defined(CONFIG_DEBUG_NET) && defined (CONFIG_DEBUG_VERBOSE) /* avoid to print too many frames */ if ((type & IEEE80211_FC0_SUBTYPE_MASK) != IEEE80211_FC0_SUBTYPE_PROBE_RESP) { nvdbg("%s: sending %s to %s on channel %u mode %s\n", ic->ic_ifname, ieee80211_mgt_subtype_name[(type & IEEE80211_FC0_SUBTYPE_MASK) >> IEEE80211_FC0_SUBTYPE_SHIFT], ieee80211_addr2str(ni->ni_macaddr), ieee80211_chan2ieee(ic, ni-> ni_chan), ieee80211_phymode_name[ieee80211_chan2mode(ic, ni->ni_chan)]); }
int iwl_tx_data(struct iwl_softc *sc, struct mbuf *m, struct ieee80211_node *ni) { struct iwl_ops *ops = &sc->ops; const struct ieee80211_txparam *tp; struct ieee80211vap *vap = ni->ni_vap; struct ieee80211com *ic = ni->ni_ic; struct iwl_node *wn = (void *)ni; struct iwl_tx_ring *ring; struct iwl_tx_desc *desc; struct iwl_tx_data *data; struct iwl_tx_cmd *cmd; struct iwl_cmd_data *tx; struct ieee80211_frame *wh; struct ieee80211_key *k = NULL; struct mbuf *m1; uint32_t flags; uint16_t qos; u_int hdrlen; bus_dma_segment_t *seg, segs[IWL_MAX_SCATTER]; uint8_t tid, ridx, txant, type; int ac, i, totlen, error, pad, nsegs = 0, rate; struct iwl_vap *ivp = IWL_VAP(vap); IWL_LOCK_ASSERT(sc); wh = mtod(m, struct ieee80211_frame *); hdrlen = ieee80211_anyhdrsize(wh); type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; /* Select EDCA Access Category and TX ring for this frame. */ if (IEEE80211_QOS_HAS_SEQ(wh)) { qos = ((const struct ieee80211_qosframe *)wh)->i_qos[0]; tid = qos & IEEE80211_QOS_TID; } else { qos = 0; tid = 0; } if(ivp->ctx == IWL_RXON_PAN_CTX) ac = iwl_pan_ac_to_queue[M_WME_GETAC(m)]; else ac = iwl_bss_ac_to_queue[M_WME_GETAC(m)]; if (IEEE80211_QOS_HAS_SEQ(wh) && IEEE80211_AMPDU_RUNNING(&ni->ni_tx_ampdu[ac])) { struct ieee80211_tx_ampdu *tap = &ni->ni_tx_ampdu[ac]; ring = &sc->txq[*(int *)tap->txa_private]; *(uint16_t *)wh->i_seq = htole16(ni->ni_txseqs[tid] << IEEE80211_SEQ_SEQ_SHIFT); ni->ni_txseqs[tid]++; } else ring = &sc->txq[ac]; desc = &ring->desc[ring->cur]; data = &ring->data[ring->cur]; /* Choose a TX rate index. */ tp = &vap->iv_txparms[ieee80211_chan2mode(ni->ni_chan)]; if (type == IEEE80211_FC0_TYPE_MGT) rate = tp->mgmtrate; else if (IEEE80211_IS_MULTICAST(wh->i_addr1)) rate = tp->mcastrate; else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) rate = tp->ucastrate; else rate = ni->ni_txrate; ridx = ic->ic_rt->rateCodeToIndex[rate]; /* Encrypt the frame if need be. */ if (wh->i_fc[1] & IEEE80211_FC1_WEP) { /* Retrieve key for TX. */ k = ieee80211_crypto_encap(ni, m); if (k == NULL) { m_freem(m); return ENOBUFS; } /* 802.11 header may have moved. */ wh = mtod(m, struct ieee80211_frame *); }
/* * Join an infrastructure network */ int ieee80211_sta_join(struct ieee80211vap *vap, ieee80211_scan_entry_t scan_entry) { struct ieee80211com *ic = vap->iv_ic; struct ieee80211_node_table *nt = &ic->ic_sta; struct ieee80211_node *ni = NULL; const u_int8_t *macaddr = ieee80211_scan_entry_macaddr(scan_entry); int error = 0; ASSERT(vap->iv_opmode == IEEE80211_M_STA); ni = ieee80211_find_node(nt, macaddr); if (ni) { /* * reusing old node has a potential for several bugs . The old node may have some state info from previous association. * get rid of the old bss node and create a new bss node. */ ieee80211_sta_leave(ni); ieee80211_free_node(ni); } /* * Create a BSS node. */ ni = ieee80211_alloc_node(nt, vap, macaddr); if (ni == NULL) return -ENOMEM; /* set the maximum number frmaes to be queued when the vap is in fake sleep */ ieee80211_node_saveq_set_param(ni,IEEE80211_NODE_SAVEQ_DATA_Q_LEN,IEE80211_STA_MAX_NODE_SAVEQ_LEN); /* To become a bss node, a node need an extra reference count, which alloc node already gives */ #ifdef IEEE80211_DEBUG_REFCNT ieee80211_note(ni->ni_vap,"%s ,line %u: increase node %p <%s> refcnt to %d\n", __func__, __LINE__, ni, ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni)); #endif /* setup the bss node for association */ error = ieee80211_setup_node(ni, scan_entry); if (error != 0) { ieee80211_free_node(ni); return error; } /* copy the beacon timestamp */ OS_MEMCPY(ni->ni_tstamp.data, ieee80211_scan_entry_tsf(scan_entry), sizeof(ni->ni_tstamp)); /* * Join the BSS represented by this new node. * This function will free up the old BSS node * and use this one as the new BSS node. */ ieee80211_sta_join_bss(ni); IEEE80211_ADD_NODE_TARGET(ni, ni->ni_vap, 0); /* Save our home channel */ vap->iv_bsschan = ni->ni_chan; vap->iv_cur_mode = ieee80211_chan2mode(ni->ni_chan); /* Update the DotH falg */ ieee80211_update_spectrumrequirement(vap); /* * The OS will control our security keys. * If clear, keys will be cleared. * If static WEP, keys will be plumbed before JoinInfra. * If WPA/WPA2, ciphers will be setup, but no keys will be plumbed until * after they are negotiated. * XXX We should ASSERT that all of the foregoing is true. */ return 0; }
/* * Complete a scan of potential channels. */ void ieee80211_end_scan(struct ifnet *ifp) { struct ieee80211com *ic = (void *)ifp; struct ieee80211_node *ni, *nextbs, *selbs; if (ifp->if_flags & IFF_DEBUG) printf("%s: end %s scan\n", ifp->if_xname, (ic->ic_flags & IEEE80211_F_ASCAN) ? "active" : "passive"); if (ic->ic_scan_count) ic->ic_flags &= ~IEEE80211_F_ASCAN; ni = RB_MIN(ieee80211_tree, &ic->ic_tree); #ifndef IEEE80211_STA_ONLY if (ic->ic_opmode == IEEE80211_M_HOSTAP) { /* XXX off stack? */ u_char occupied[howmany(IEEE80211_CHAN_MAX, NBBY)]; int i, fail; /* * The passive scan to look for existing AP's completed, * select a channel to camp on. Identify the channels * that already have one or more AP's and try to locate * an unnoccupied one. If that fails, pick a random * channel from the active set. */ memset(occupied, 0, sizeof(occupied)); RB_FOREACH(ni, ieee80211_tree, &ic->ic_tree) setbit(occupied, ieee80211_chan2ieee(ic, ni->ni_chan)); for (i = 0; i < IEEE80211_CHAN_MAX; i++) if (isset(ic->ic_chan_active, i) && isclr(occupied, i)) break; if (i == IEEE80211_CHAN_MAX) { fail = arc4random() & 3; /* random 0-3 */ for (i = 0; i < IEEE80211_CHAN_MAX; i++) if (isset(ic->ic_chan_active, i) && fail-- == 0) break; } ieee80211_create_ibss(ic, &ic->ic_channels[i]); goto wakeup; } #endif if (ni == NULL) { DPRINTF(("no scan candidate\n")); notfound: #ifndef IEEE80211_STA_ONLY if (ic->ic_opmode == IEEE80211_M_IBSS && (ic->ic_flags & IEEE80211_F_IBSSON) && ic->ic_des_esslen != 0) { ieee80211_create_ibss(ic, ic->ic_ibss_chan); goto wakeup; } #endif /* * Scan the next mode if nothing has been found. This * is necessary if the device supports different * incompatible modes in the same channel range, like * like 11b and "pure" 11G mode. This will loop * forever except for user-initiated scans. */ if (ieee80211_next_mode(ifp) == IEEE80211_MODE_AUTO) { if (ic->ic_scan_lock & IEEE80211_SCAN_REQUEST && ic->ic_scan_lock & IEEE80211_SCAN_RESUME) { ic->ic_scan_lock = IEEE80211_SCAN_LOCKED; /* Return from an user-initiated scan */ wakeup(&ic->ic_scan_lock); } else if (ic->ic_scan_lock & IEEE80211_SCAN_REQUEST) goto wakeup; ic->ic_scan_count++; } /* * Reset the list of channels to scan and start again. */ ieee80211_next_scan(ifp); return; } selbs = NULL; for (; ni != NULL; ni = nextbs) { nextbs = RB_NEXT(ieee80211_tree, &ic->ic_tree, ni); if (ni->ni_fails) { /* * The configuration of the access points may change * during my scan. So delete the entry for the AP * and retry to associate if there is another beacon. */ if (ni->ni_fails++ > 2) ieee80211_free_node(ic, ni); continue; } if (ieee80211_match_bss(ic, ni) == 0) { if (selbs == NULL) selbs = ni; else if (ni->ni_rssi > selbs->ni_rssi) selbs = ni; } } if (selbs == NULL) goto notfound; (*ic->ic_node_copy)(ic, ic->ic_bss, selbs); ni = ic->ic_bss; /* * Set the erp state (mostly the slot time) to deal with * the auto-select case; this should be redundant if the * mode is locked. */ ic->ic_curmode = ieee80211_chan2mode(ic, ni->ni_chan); ieee80211_reset_erp(ic); if (ic->ic_flags & IEEE80211_F_RSNON) ieee80211_choose_rsnparams(ic); else if (ic->ic_flags & IEEE80211_F_WEPON) ni->ni_rsncipher = IEEE80211_CIPHER_USEGROUP; ieee80211_node_newstate(selbs, IEEE80211_STA_BSS); #ifndef IEEE80211_STA_ONLY if (ic->ic_opmode == IEEE80211_M_IBSS) { ieee80211_fix_rate(ic, ni, IEEE80211_F_DOFRATE | IEEE80211_F_DONEGO | IEEE80211_F_DODEL); if (ni->ni_rates.rs_nrates == 0) goto notfound; ieee80211_new_state(ic, IEEE80211_S_RUN, -1); } else #endif ieee80211_new_state(ic, IEEE80211_S_AUTH, -1); wakeup: if (ic->ic_scan_lock & IEEE80211_SCAN_REQUEST) { /* Return from an user-initiated scan */ wakeup(&ic->ic_scan_lock); } ic->ic_scan_lock = IEEE80211_SCAN_UNLOCKED; }
void ieee80211_create_ibss(struct ieee80211com* ic, struct ieee80211_channel *chan) { struct ieee80211_node *ni; struct ifnet *ifp = &ic->ic_if; ni = ic->ic_bss; if (ifp->if_flags & IFF_DEBUG) printf("%s: creating ibss\n", ifp->if_xname); ic->ic_flags |= IEEE80211_F_SIBSS; ni->ni_chan = chan; ni->ni_rates = ic->ic_sup_rates[ieee80211_chan2mode(ic, ni->ni_chan)]; ni->ni_txrate = 0; IEEE80211_ADDR_COPY(ni->ni_macaddr, ic->ic_myaddr); IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_myaddr); if (ic->ic_opmode == IEEE80211_M_IBSS) { if ((ic->ic_flags & IEEE80211_F_DESBSSID) != 0) IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_des_bssid); else ni->ni_bssid[0] |= 0x02; /* local bit for IBSS */ } ni->ni_esslen = ic->ic_des_esslen; memcpy(ni->ni_essid, ic->ic_des_essid, ni->ni_esslen); ni->ni_rssi = 0; ni->ni_rstamp = 0; memset(ni->ni_tstamp, 0, sizeof(ni->ni_tstamp)); ni->ni_intval = ic->ic_lintval; ni->ni_capinfo = IEEE80211_CAPINFO_IBSS; if (ic->ic_flags & IEEE80211_F_WEPON) ni->ni_capinfo |= IEEE80211_CAPINFO_PRIVACY; if (ic->ic_flags & IEEE80211_F_RSNON) { struct ieee80211_key *k; /* initialize 256-bit global key counter to a random value */ arc4random_buf(ic->ic_globalcnt, EAPOL_KEY_NONCE_LEN); ni->ni_rsnprotos = ic->ic_rsnprotos; ni->ni_rsnakms = ic->ic_rsnakms; ni->ni_rsnciphers = ic->ic_rsnciphers; ni->ni_rsngroupcipher = ic->ic_rsngroupcipher; ni->ni_rsngroupmgmtcipher = ic->ic_rsngroupmgmtcipher; ni->ni_rsncaps = 0; if (ic->ic_caps & IEEE80211_C_MFP) { ni->ni_rsncaps |= IEEE80211_RSNCAP_MFPC; if (ic->ic_flags & IEEE80211_F_MFPR) ni->ni_rsncaps |= IEEE80211_RSNCAP_MFPR; } ic->ic_def_txkey = 1; k = &ic->ic_nw_keys[ic->ic_def_txkey]; memset(k, 0, sizeof(*k)); k->k_id = ic->ic_def_txkey; k->k_cipher = ni->ni_rsngroupcipher; k->k_flags = IEEE80211_KEY_GROUP | IEEE80211_KEY_TX; k->k_len = ieee80211_cipher_keylen(k->k_cipher); arc4random_buf(k->k_key, k->k_len); (*ic->ic_set_key)(ic, ni, k); /* XXX */ if (ic->ic_caps & IEEE80211_C_MFP) { ic->ic_igtk_kid = 4; k = &ic->ic_nw_keys[ic->ic_igtk_kid]; memset(k, 0, sizeof(*k)); k->k_id = ic->ic_igtk_kid; k->k_cipher = ni->ni_rsngroupmgmtcipher; k->k_flags = IEEE80211_KEY_IGTK | IEEE80211_KEY_TX; k->k_len = 16; arc4random_buf(k->k_key, k->k_len); (*ic->ic_set_key)(ic, ni, k); /* XXX */ } /* * In HostAP mode, multicast traffic is sent using ic_bss * as the Tx node, so mark our node as valid so we can send * multicast frames using the group key we've just configured. */ ni->ni_port_valid = 1; ni->ni_flags |= IEEE80211_NODE_TXPROT; /* schedule a GTK/IGTK rekeying after 3600s */ timeout_add_sec(&ic->ic_rsn_timeout, 3600); } timeout_add_sec(&ic->ic_inact_timeout, IEEE80211_INACT_WAIT); timeout_add_sec(&ic->ic_node_cache_timeout, IEEE80211_CACHE_WAIT); ieee80211_new_state(ic, IEEE80211_S_RUN, -1); }
void ath_phyerr_enable(struct ath_softc *sc, struct ieee80211_channel *chan) { u_int32_t rfilt; struct ieee80211com *ic = &sc->sc_ic; u_int32_t index; struct ath_phyerr_state *pe; enum ieee80211_phymode mode; pe = (struct ath_phyerr_state *) sc->sc_phyerr_state; mode = ieee80211_chan2mode(ic, chan); if ((sc->sc_phyerr_cap & (ATH_RADAR_AR_EN | ATH_RADAR_EN)) && (ic->ic_opmode == IEEE80211_M_HOSTAP) && ((mode == IEEE80211_MODE_11A) || (mode == IEEE80211_MODE_TURBO_A) || (mode == IEEE80211_MODE_TURBO_G))) { if (mode == IEEE80211_MODE_TURBO_G) { /* We are in turbo G, so enable AR*/ index = get_radar_chan_index(sc); pe->pe_curRadar = &pe->pe_radarState[index]; ath_reset_ar(sc); pe->pe_curRadar->rad_radarRssi = ATH_AR_RADAR_RSSI_THR; ath_hal_setcapability(sc->sc_ah, HAL_CAP_PHYDIAG, HAL_CAP_RADAR_RRSSI, pe->pe_curRadar->rad_radarRssi, NULL); } else { ath_reset_radar(sc); index = get_radar_chan_index(sc); pe->pe_curRadar = &pe->pe_radarState[index]; pe->pe_curRadar->rad_firpwr = ATH_RADAR_FIRPWR; ath_hal_setcapability(sc->sc_ah, HAL_CAP_PHYDIAG, HAL_CAP_RADAR_FIRPWR, (u_int32_t) pe->pe_curRadar->rad_firpwr, NULL); /* XXX - need to Set firpwr */ pe->pe_curRadar->rad_radarRssi = ATH_RADAR_RRSSI; ath_hal_setcapability(sc->sc_ah, HAL_CAP_PHYDIAG, HAL_CAP_RADAR_RRSSI, pe->pe_curRadar->rad_radarRssi, NULL); pe->pe_curRadar->rad_height = ATH_RADAR_HEIGHT; ath_hal_setcapability(sc->sc_ah, HAL_CAP_PHYDIAG, HAL_CAP_RADAR_HEIGHT, pe->pe_curRadar->rad_height, NULL); pe->pe_curRadar->rad_pulseRssi = ATH_RADAR_PRSSI; ath_hal_setcapability(sc->sc_ah, HAL_CAP_PHYDIAG, HAL_CAP_RADAR_PRSSI, pe->pe_curRadar->rad_pulseRssi, NULL); pe->pe_curRadar->rad_inband = ATH_RADAR_INBAND; ath_hal_setcapability(sc->sc_ah, HAL_CAP_PHYDIAG, HAL_CAP_RADAR_INBAND, pe->pe_curRadar->rad_inband, NULL); } rfilt = ath_hal_getrxfilter(sc->sc_ah); rfilt |= HAL_RX_FILTER_PHYRADAR; ath_hal_setrxfilter(sc->sc_ah,rfilt); ath_hal_enablePhyDiag(sc->sc_ah); } else { rfilt = ath_hal_getrxfilter(sc->sc_ah); rfilt &= ~HAL_RX_FILTER_PHYRADAR; ath_hal_setrxfilter(sc->sc_ah,rfilt); } }
/* * Find the channel information according to the scan entry */ int rtt_find_channel_info (void *arg, wlan_scan_entry_t scan_entry) { wmi_channel *wmi_chan; u_int32_t chan_mode; struct ieee80211com *ic; struct ieee80211_channel *se_chan; static const u_int modeflags[] = { 0, /* IEEE80211_MODE_AUTO */ MODE_11A, /* IEEE80211_MODE_11A */ MODE_11B, /* IEEE80211_MODE_11B */ MODE_11G, /* IEEE80211_MODE_11G */ 0, /* IEEE80211_MODE_FH */ 0, /* IEEE80211_MODE_TURBO_A */ 0, /* IEEE80211_MODE_TURBO_G */ MODE_11NA_HT20, /* IEEE80211_MODE_11NA_HT20 */ MODE_11NG_HT20, /* IEEE80211_MODE_11NG_HT20 */ MODE_11NA_HT40, /* IEEE80211_MODE_11NA_HT40PLUS */ MODE_11NA_HT40, /* IEEE80211_MODE_11NA_HT40MINUS */ MODE_11NG_HT40, /* IEEE80211_MODE_11NG_HT40PLUS */ MODE_11NG_HT40, /* IEEE80211_MODE_11NG_HT40MINUS */ MODE_11NG_HT40, /* IEEE80211_MODE_11NG_HT40 */ MODE_11NA_HT40, /* IEEE80211_MODE_11NA_HT40 */ MODE_11AC_VHT20, /* IEEE80211_MODE_11AC_VHT20 */ MODE_11AC_VHT40, /* IEEE80211_MODE_11AC_VHT40PLUS */ MODE_11AC_VHT40, /* IEEE80211_MODE_11AC_VHT40MINUS*/ MODE_11AC_VHT40, /* IEEE80211_MODE_11AC_VHT40 */ MODE_11AC_VHT80, /* IEEE80211_MODE_11AC_VHT80 */ }; adf_os_print("%s:\n", __func__); if (!(arg && scan_entry)) { return -1; //critical error } wmi_chan = ((channel_search *)arg)->channel; ic = ((channel_search *)arg)->ic; if(!(wmi_chan && ic)) { return -1; //critical error } se_chan = wlan_scan_entry_channel(scan_entry); if(!se_chan) { return -1; //critical error } wmi_chan->mhz = ieee80211_chan2freq(ic,se_chan); chan_mode = ieee80211_chan2mode(se_chan); WMI_SET_CHANNEL_MODE(wmi_chan, modeflags[chan_mode]); if(chan_mode == IEEE80211_MODE_11AC_VHT80) { if (se_chan->ic_ieee < 20) { wmi_chan->band_center_freq1 = ieee80211_ieee2mhz( se_chan->ic_vhtop_ch_freq_seg1, IEEE80211_CHAN_2GHZ); } else { wmi_chan->band_center_freq1 = ieee80211_ieee2mhz( se_chan->ic_vhtop_ch_freq_seg1, IEEE80211_CHAN_5GHZ); } } else if((chan_mode == IEEE80211_MODE_11NA_HT40PLUS) || (chan_mode == IEEE80211_MODE_11NG_HT40PLUS) || (chan_mode == IEEE80211_MODE_11AC_VHT40PLUS)) { wmi_chan->band_center_freq1 = wmi_chan->mhz + 10; } else if((chan_mode == IEEE80211_MODE_11NA_HT40MINUS) || (chan_mode == IEEE80211_MODE_11NG_HT40MINUS) || (chan_mode == IEEE80211_MODE_11AC_VHT40MINUS)) { wmi_chan->band_center_freq1 = wmi_chan->mhz - 10; } else { wmi_chan->band_center_freq1 = wmi_chan->mhz; } /* we do not support HT80PLUS80 yet */ wmi_chan->band_center_freq2=0; WMI_SET_CHANNEL_MIN_POWER(wmi_chan, se_chan->ic_minpower); WMI_SET_CHANNEL_MAX_POWER(wmi_chan, se_chan->ic_maxpower); WMI_SET_CHANNEL_REG_POWER(wmi_chan, se_chan->ic_maxregpower); WMI_SET_CHANNEL_ANTENNA_MAX(wmi_chan, se_chan->ic_antennamax); WMI_SET_CHANNEL_REG_CLASSID(wmi_chan, se_chan->ic_regClassId); if (IEEE80211_IS_CHAN_DFS(se_chan)) WMI_SET_CHANNEL_FLAG(wmi_chan, WMI_CHAN_FLAG_DFS); adf_os_print("WMI channel freq=%d, mode=%x band_center_freq1=%d\n", wmi_chan->mhz, WMI_GET_CHANNEL_MODE(wmi_chan), wmi_chan->band_center_freq1); return 1; //seccessful! }
/* * Complete a scan of potential channels. */ void Voodoo80211Device:: ieee80211_end_scan(struct ieee80211com *ic) { struct ieee80211_node *ni, *nextbs, *selbs; /* TODO if (ifp->if_flags & IFF_DEBUG) printf("%s: end %s scan\n", ifp->if_xname, (ic->ic_flags & IEEE80211_F_ASCAN) ? "active" : "passive"); */ if (ic->ic_scan_count) ic->ic_flags &= ~IEEE80211_F_ASCAN; ni = RB_MIN(ieee80211_tree, &ic->ic_tree); if (ni == NULL) { DPRINTF(("no scan candidate\n")); notfound: /* * Scan the next mode if nothing has been found. This * is necessary if the device supports different * incompatible modes in the same channel range, like * like 11b and "pure" 11G mode. This will loop * forever except for user-initiated scans. */ if (ieee80211_next_mode(ic) == IEEE80211_MODE_AUTO) { if (ic->ic_scan_lock & IEEE80211_SCAN_REQUEST && ic->ic_scan_lock & IEEE80211_SCAN_RESUME) { ic->ic_scan_lock = IEEE80211_SCAN_LOCKED; /* Return from an user-initiated scan */ wakeupOn(&ic->ic_scan_lock); // XXX: pvaibhav: do this here? fInterface->postMessage(APPLE80211_M_SCAN_DONE); } else if (ic->ic_scan_lock & IEEE80211_SCAN_REQUEST) goto wakeup; ic->ic_scan_count++; } /* * Reset the list of channels to scan and start again. */ ieee80211_next_scan(ic); return; } selbs = NULL; for (; ni != NULL; ni = nextbs) { nextbs = RB_NEXT(ieee80211_tree, &ic->ic_tree, ni); if (ni->ni_fails) { /* * The configuration of the access points may change * during my scan. So delete the entry for the AP * and retry to associate if there is another beacon. */ if (ni->ni_fails++ > 2) ieee80211_free_node(ic, ni); continue; } if (ieee80211_match_bss(ic, ni) == 0) { if (selbs == NULL) selbs = ni; else if (ni->ni_rssi > selbs->ni_rssi) selbs = ni; } } if (selbs == NULL) goto notfound; ieee80211_node_copy(ic, ic->ic_bss, selbs); ni = ic->ic_bss; /* * Set the erp state (mostly the slot time) to deal with * the auto-select case; this should be redundant if the * mode is locked. */ ic->ic_curmode = ieee80211_chan2mode(ic, ni->ni_chan); ieee80211_reset_erp(ic); if (ic->ic_flags & IEEE80211_F_RSNON) ieee80211_choose_rsnparams(ic); else if (ic->ic_flags & IEEE80211_F_WEPON) ni->ni_rsncipher = IEEE80211_CIPHER_USEGROUP; ieee80211_node_newstate(selbs, IEEE80211_STA_BSS); ieee80211_newstate(ic, IEEE80211_S_AUTH, -1); wakeup: if (ic->ic_scan_lock & IEEE80211_SCAN_REQUEST) { /* Return from an user-initiated scan */ wakeupOn(&ic->ic_scan_lock); // XXX: pvaibhav: do this here? fInterface->postMessage(APPLE80211_M_SCAN_DONE); } ic->ic_scan_lock = IEEE80211_SCAN_UNLOCKED; }
static int rtwn_tx_data(struct rtwn_softc *sc, struct ieee80211_node *ni, struct mbuf *m) { const struct ieee80211_txparam *tp; struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = ni->ni_vap; struct ieee80211_key *k = NULL; struct ieee80211_channel *chan; 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, maxretry; 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); chan = (ni->ni_chan != IEEE80211_CHAN_ANYC) ? ni->ni_chan : ic->ic_curchan; tp = &vap->iv_txparms[ieee80211_chan2mode(chan)]; maxretry = tp->maxretry; /* Choose a TX rate index. */ if (type == IEEE80211_FC0_TYPE_MGT) rate = tp->mgmtrate; else if (ismcast) rate = tp->mcastrate; else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) rate = tp->ucastrate; else if (m->m_flags & M_EAPOL) rate = tp->mgmtrate; 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 *); }
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; 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; 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)); }