Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/ral/rt2860.c
Show First 20 Lines • Show All 1,446 Lines • ▼ Show 20 Lines | if (r & RT2860_MAC_INT_4) /* GP timer */ | ||||
rt2860_gp_intr(sc); | rt2860_gp_intr(sc); | ||||
RAL_UNLOCK(sc); | RAL_UNLOCK(sc); | ||||
} | } | ||||
static int | static int | ||||
rt2860_tx(struct rt2860_softc *sc, struct mbuf *m, struct ieee80211_node *ni) | rt2860_tx(struct rt2860_softc *sc, struct mbuf *m, struct ieee80211_node *ni) | ||||
{ | { | ||||
const struct ieee80211_rate_t *rate; | |||||
struct ieee80211com *ic = &sc->sc_ic; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ieee80211vap *vap = ni->ni_vap; | struct ieee80211vap *vap = ni->ni_vap; | ||||
struct rt2860_tx_ring *ring; | struct rt2860_tx_ring *ring; | ||||
struct rt2860_tx_data *data; | struct rt2860_tx_data *data; | ||||
struct rt2860_txd *txd; | struct rt2860_txd *txd; | ||||
struct rt2860_txwi *txwi; | struct rt2860_txwi *txwi; | ||||
struct ieee80211_frame *wh; | struct ieee80211_frame *wh; | ||||
const struct ieee80211_txparam *tp = ni->ni_txparms; | const struct ieee80211_txparam_vht *tp = ni->ni_txparms; | ||||
struct ieee80211_key *k; | struct ieee80211_key *k; | ||||
struct mbuf *m1; | struct mbuf *m1; | ||||
bus_dma_segment_t segs[RT2860_MAX_SCATTER]; | bus_dma_segment_t segs[RT2860_MAX_SCATTER]; | ||||
bus_dma_segment_t *seg; | bus_dma_segment_t *seg; | ||||
u_int hdrlen; | u_int hdrlen; | ||||
uint16_t qos, dur; | uint16_t qos, dur, rate_idx; | ||||
uint8_t type, qsel, mcs, pid, tid, qid; | uint8_t type, qsel, mcs, pid, tid, qid; | ||||
int i, nsegs, ntxds, pad, rate, ridx, error; | int i, nsegs, ntxds, pad, ridx, error; | ||||
/* the data pool contains at least one element, pick the first */ | /* the data pool contains at least one element, pick the first */ | ||||
data = SLIST_FIRST(&sc->data_pool); | data = SLIST_FIRST(&sc->data_pool); | ||||
wh = mtod(m, struct ieee80211_frame *); | wh = mtod(m, struct ieee80211_frame *); | ||||
if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { | if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { | ||||
k = ieee80211_crypto_encap(ni, m); | k = ieee80211_crypto_encap(ni, m); | ||||
if (k == NULL) { | if (k == NULL) { | ||||
m_freem(m); | m_freem(m); | ||||
return ENOBUFS; | return ENOBUFS; | ||||
} | } | ||||
/* packet header may have moved, reset our local pointer */ | /* packet header may have moved, reset our local pointer */ | ||||
wh = mtod(m, struct ieee80211_frame *); | wh = mtod(m, struct ieee80211_frame *); | ||||
} | } | ||||
hdrlen = ieee80211_anyhdrsize(wh); | hdrlen = ieee80211_anyhdrsize(wh); | ||||
type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; | type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; | ||||
if (m->m_flags & M_EAPOL) { | if (m->m_flags & M_EAPOL) { | ||||
rate = tp->mgmtrate; | rate_idx = tp->mgmtrate; | ||||
} else if (IEEE80211_IS_MULTICAST(wh->i_addr1)) { | } else if (IEEE80211_IS_MULTICAST(wh->i_addr1)) { | ||||
rate = tp->mcastrate; | rate_idx = tp->mcastrate; | ||||
} else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) { | } else if (tp->ucastrate != IEEE80211_RATE_NONEXISTENT) { | ||||
rate = tp->ucastrate; | rate_idx = tp->ucastrate; | ||||
} else { | } else { | ||||
(void) ieee80211_ratectl_rate(ni, NULL, 0); | (void) ieee80211_ratectl_rate(ni, NULL, 0); | ||||
rate = ni->ni_txrate; | rate_idx = ni->ni_txrate; | ||||
} | } | ||||
rate &= IEEE80211_RATE_VAL; | rate = ieee80211_get_rate(rate_idx); | ||||
qid = M_WME_GETAC(m); | qid = M_WME_GETAC(m); | ||||
if (IEEE80211_QOS_HAS_SEQ(wh)) { | if (IEEE80211_QOS_HAS_SEQ(wh)) { | ||||
qos = ((const struct ieee80211_qosframe *)wh)->i_qos[0]; | qos = ((const struct ieee80211_qosframe *)wh)->i_qos[0]; | ||||
tid = qos & IEEE80211_QOS_TID; | tid = qos & IEEE80211_QOS_TID; | ||||
} else { | } else { | ||||
qos = 0; | qos = 0; | ||||
tid = 0; | tid = 0; | ||||
} | } | ||||
ring = &sc->txq[qid]; | ring = &sc->txq[qid]; | ||||
ridx = ieee80211_legacy_rate_lookup(ic->ic_rt, rate); | ridx = ieee80211_legacy_rate_lookup(ic->ic_rt->ctl_rates, rate_idx); | ||||
/* get MCS code from rate index */ | /* get MCS code from rate index */ | ||||
mcs = rt2860_rates[ridx].mcs; | mcs = rt2860_rates[ridx].mcs; | ||||
/* setup TX Wireless Information */ | /* setup TX Wireless Information */ | ||||
txwi = data->txwi; | txwi = data->txwi; | ||||
txwi->flags = 0; | txwi->flags = 0; | ||||
/* let HW generate seq numbers for non-QoS frames */ | /* let HW generate seq numbers for non-QoS frames */ | ||||
txwi->xflags = qos ? 0 : RT2860_TX_NSEQ; | txwi->xflags = qos ? 0 : RT2860_TX_NSEQ; | ||||
if (type == IEEE80211_FC0_TYPE_DATA) | if (type == IEEE80211_FC0_TYPE_DATA) | ||||
txwi->wcid = IEEE80211_AID(ni->ni_associd); | txwi->wcid = IEEE80211_AID(ni->ni_associd); | ||||
else | else | ||||
txwi->wcid = 0xff; | txwi->wcid = 0xff; | ||||
txwi->len = htole16(m->m_pkthdr.len); | txwi->len = htole16(m->m_pkthdr.len); | ||||
if (rt2860_rates[ridx].phy == IEEE80211_T_DS) { | if (rate->type == IEEE80211_T_DS) { | ||||
txwi->phy = htole16(RT2860_PHY_CCK); | txwi->phy = htole16(RT2860_PHY_CCK); | ||||
if (ridx != RT2860_RIDX_CCK1 && | if (rate->props.cck.short_preamble && | ||||
(ic->ic_flags & IEEE80211_F_SHPREAMBLE)) | (ic->ic_flags & IEEE80211_F_SHPREAMBLE)) | ||||
mcs |= RT2860_PHY_SHPRE; | mcs |= RT2860_PHY_SHPRE; | ||||
} else | } else | ||||
txwi->phy = htole16(RT2860_PHY_OFDM); | txwi->phy = htole16(RT2860_PHY_OFDM); | ||||
txwi->phy |= htole16(mcs); | txwi->phy |= htole16(mcs); | ||||
/* | /* | ||||
* We store the MCS code into the driver-private PacketID field. | * We store the MCS code into the driver-private PacketID field. | ||||
* The PacketID is latched into TX_STAT_FIFO when Tx completes so | * The PacketID is latched into TX_STAT_FIFO when Tx completes so | ||||
* that we know at which initial rate the frame was transmitted. | * that we know at which initial rate the frame was transmitted. | ||||
* We add 1 to the MCS code because setting the PacketID field to | * We add 1 to the MCS code because setting the PacketID field to | ||||
* 0 means that we don't want feedback in TX_STAT_FIFO. | * 0 means that we don't want feedback in TX_STAT_FIFO. | ||||
*/ | */ | ||||
pid = (mcs + 1) & 0xf; | pid = (mcs + 1) & 0xf; | ||||
txwi->len |= htole16(pid << RT2860_TX_PID_SHIFT); | txwi->len |= htole16(pid << RT2860_TX_PID_SHIFT); | ||||
/* check if RTS/CTS or CTS-to-self protection is required */ | /* check if RTS/CTS or CTS-to-self protection is required */ | ||||
if (!IEEE80211_IS_MULTICAST(wh->i_addr1) && | if (!IEEE80211_IS_MULTICAST(wh->i_addr1) && | ||||
(m->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold || | (m->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold || | ||||
((ic->ic_flags & IEEE80211_F_USEPROT) && | ((ic->ic_flags & IEEE80211_F_USEPROT) && | ||||
rt2860_rates[ridx].phy == IEEE80211_T_OFDM))) | rate->type == IEEE80211_T_OFDM))) | ||||
txwi->txop = RT2860_TX_TXOP_HT; | txwi->txop = RT2860_TX_TXOP_HT; | ||||
else | else | ||||
txwi->txop = RT2860_TX_TXOP_BACKOFF; | txwi->txop = RT2860_TX_TXOP_BACKOFF; | ||||
if (!IEEE80211_IS_MULTICAST(wh->i_addr1) && | if (!IEEE80211_IS_MULTICAST(wh->i_addr1) && | ||||
(!qos || (qos & IEEE80211_QOS_ACKPOLICY) != | (!qos || (qos & IEEE80211_QOS_ACKPOLICY) != | ||||
IEEE80211_QOS_ACKPOLICY_NOACK)) { | IEEE80211_QOS_ACKPOLICY_NOACK)) { | ||||
txwi->xflags |= RT2860_TX_ACK; | txwi->xflags |= RT2860_TX_ACK; | ||||
Show All 10 Lines | if ((wh->i_fc[0] & | ||||
(IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_PROBE_RESP)) | (IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_PROBE_RESP)) | ||||
/* NOTE: beacons do not pass through tx_data() */ | /* NOTE: beacons do not pass through tx_data() */ | ||||
txwi->flags |= RT2860_TX_TS; | txwi->flags |= RT2860_TX_TS; | ||||
if (ieee80211_radiotap_active_vap(vap)) { | if (ieee80211_radiotap_active_vap(vap)) { | ||||
struct rt2860_tx_radiotap_header *tap = &sc->sc_txtap; | struct rt2860_tx_radiotap_header *tap = &sc->sc_txtap; | ||||
tap->wt_flags = 0; | tap->wt_flags = 0; | ||||
tap->wt_rate = rate; | tap->wt_rate = ieee80211_convert_to_legacy_rate(rate_idx); | ||||
if (mcs & RT2860_PHY_SHPRE) | if (mcs & RT2860_PHY_SHPRE) | ||||
tap->wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE; | tap->wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE; | ||||
ieee80211_radiotap_tx(vap, m); | ieee80211_radiotap_tx(vap, m); | ||||
} | } | ||||
pad = (hdrlen + 3) & ~3; | pad = (hdrlen + 3) & ~3; | ||||
▲ Show 20 Lines • Show All 137 Lines • ▼ Show 20 Lines | rt2860_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, | ||||
RAL_UNLOCK(sc); | RAL_UNLOCK(sc); | ||||
return error; | return error; | ||||
} | } | ||||
static int | static int | ||||
rt2860_tx_raw(struct rt2860_softc *sc, struct mbuf *m, | rt2860_tx_raw(struct rt2860_softc *sc, struct mbuf *m, | ||||
struct ieee80211_node *ni, const struct ieee80211_bpf_params *params) | struct ieee80211_node *ni, const struct ieee80211_bpf_params *params) | ||||
{ | { | ||||
const struct ieee80211_rate_t *rate; | |||||
struct ieee80211com *ic = &sc->sc_ic; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ieee80211vap *vap = ni->ni_vap; | struct ieee80211vap *vap = ni->ni_vap; | ||||
struct rt2860_tx_ring *ring; | struct rt2860_tx_ring *ring; | ||||
struct rt2860_tx_data *data; | struct rt2860_tx_data *data; | ||||
struct rt2860_txd *txd; | struct rt2860_txd *txd; | ||||
struct rt2860_txwi *txwi; | struct rt2860_txwi *txwi; | ||||
struct ieee80211_frame *wh; | struct ieee80211_frame *wh; | ||||
struct mbuf *m1; | struct mbuf *m1; | ||||
bus_dma_segment_t segs[RT2860_MAX_SCATTER]; | bus_dma_segment_t segs[RT2860_MAX_SCATTER]; | ||||
bus_dma_segment_t *seg; | bus_dma_segment_t *seg; | ||||
u_int hdrlen; | u_int hdrlen; | ||||
uint16_t dur; | uint16_t dur; | ||||
uint8_t type, qsel, mcs, pid, tid, qid; | uint8_t type, qsel, mcs, pid, tid, qid; | ||||
int i, nsegs, ntxds, pad, rate, ridx, error; | int i, nsegs, ntxds, pad, ridx, error; | ||||
/* the data pool contains at least one element, pick the first */ | /* the data pool contains at least one element, pick the first */ | ||||
data = SLIST_FIRST(&sc->data_pool); | data = SLIST_FIRST(&sc->data_pool); | ||||
wh = mtod(m, struct ieee80211_frame *); | wh = mtod(m, struct ieee80211_frame *); | ||||
hdrlen = ieee80211_hdrsize(wh); | hdrlen = ieee80211_hdrsize(wh); | ||||
type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; | type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; | ||||
/* Choose a TX rate index. */ | /* Choose a TX rate index. */ | ||||
rate = params->ibp_rate0; | rate = ieee80211_get_rate(params->ibp_rate0); | ||||
ridx = ieee80211_legacy_rate_lookup(ic->ic_rt, | ridx = ieee80211_legacy_rate_lookup(ic->ic_rt->ctl_rates, | ||||
rate & IEEE80211_RATE_VAL); | params->ibp_rate0); | ||||
if (ridx == (uint8_t)-1) { | if (ridx == (uint8_t)-1) { | ||||
/* XXX fall back to mcast/mgmt rate? */ | /* XXX fall back to mcast/mgmt rate? */ | ||||
m_freem(m); | m_freem(m); | ||||
return EINVAL; | return EINVAL; | ||||
} | } | ||||
qid = params->ibp_pri & 3; | qid = params->ibp_pri & 3; | ||||
tid = 0; | tid = 0; | ||||
ring = &sc->txq[qid]; | ring = &sc->txq[qid]; | ||||
/* get MCS code from rate index */ | /* get MCS code from rate index */ | ||||
mcs = rt2860_rates[ridx].mcs; | mcs = rt2860_rates[ridx].mcs; | ||||
/* setup TX Wireless Information */ | /* setup TX Wireless Information */ | ||||
txwi = data->txwi; | txwi = data->txwi; | ||||
txwi->flags = 0; | txwi->flags = 0; | ||||
/* let HW generate seq numbers for non-QoS frames */ | /* let HW generate seq numbers for non-QoS frames */ | ||||
txwi->xflags = params->ibp_pri & 3 ? 0 : RT2860_TX_NSEQ; | txwi->xflags = params->ibp_pri & 3 ? 0 : RT2860_TX_NSEQ; | ||||
txwi->wcid = 0xff; | txwi->wcid = 0xff; | ||||
txwi->len = htole16(m->m_pkthdr.len); | txwi->len = htole16(m->m_pkthdr.len); | ||||
if (rt2860_rates[ridx].phy == IEEE80211_T_DS) { | if (rate->type == IEEE80211_T_DS) { | ||||
txwi->phy = htole16(RT2860_PHY_CCK); | txwi->phy = htole16(RT2860_PHY_CCK); | ||||
if (ridx != RT2860_RIDX_CCK1 && | if (rate->props.cck.short_preamble && | ||||
(ic->ic_flags & IEEE80211_F_SHPREAMBLE)) | (ic->ic_flags & IEEE80211_F_SHPREAMBLE)) | ||||
mcs |= RT2860_PHY_SHPRE; | mcs |= RT2860_PHY_SHPRE; | ||||
} else | } else | ||||
txwi->phy = htole16(RT2860_PHY_OFDM); | txwi->phy = htole16(RT2860_PHY_OFDM); | ||||
txwi->phy |= htole16(mcs); | txwi->phy |= htole16(mcs); | ||||
/* | /* | ||||
* We store the MCS code into the driver-private PacketID field. | * We store the MCS code into the driver-private PacketID field. | ||||
Show All 26 Lines | if ((wh->i_fc[0] & | ||||
(IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_PROBE_RESP)) | (IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_PROBE_RESP)) | ||||
/* NOTE: beacons do not pass through tx_data() */ | /* NOTE: beacons do not pass through tx_data() */ | ||||
txwi->flags |= RT2860_TX_TS; | txwi->flags |= RT2860_TX_TS; | ||||
if (ieee80211_radiotap_active_vap(vap)) { | if (ieee80211_radiotap_active_vap(vap)) { | ||||
struct rt2860_tx_radiotap_header *tap = &sc->sc_txtap; | struct rt2860_tx_radiotap_header *tap = &sc->sc_txtap; | ||||
tap->wt_flags = 0; | tap->wt_flags = 0; | ||||
tap->wt_rate = rate; | tap->wt_rate = | ||||
ieee80211_convert_to_legacy_rate(params->ibp_rate0); | |||||
if (mcs & RT2860_PHY_SHPRE) | if (mcs & RT2860_PHY_SHPRE) | ||||
tap->wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE; | tap->wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE; | ||||
ieee80211_radiotap_tx(vap, m); | ieee80211_radiotap_tx(vap, m); | ||||
} | } | ||||
pad = (hdrlen + 3) & ~3; | pad = (hdrlen + 3) & ~3; | ||||
▲ Show 20 Lines • Show All 423 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
void | void | ||||
rt2860_set_basicrates(struct rt2860_softc *sc, | rt2860_set_basicrates(struct rt2860_softc *sc, | ||||
const struct ieee80211_rateset *rs) | const struct ieee80211_rateset *rs) | ||||
{ | { | ||||
struct ieee80211com *ic = &sc->sc_ic; | struct ieee80211com *ic = &sc->sc_ic; | ||||
uint32_t mask = 0; | uint32_t mask = 0; | ||||
uint8_t rate; | |||||
int i; | int i; | ||||
for (i = 0; i < rs->rs_nrates; i++) { | for (i = 0; i < rs->rs_nrates; i++) { | ||||
rate = rs->rs_rates[i]; | if (!rs->rates[i].rs_basic) | ||||
if (!(rate & IEEE80211_RATE_BASIC)) | |||||
continue; | continue; | ||||
mask |= 1 << ieee80211_legacy_rate_lookup(ic->ic_rt, | mask |= 1 << ieee80211_legacy_rate_lookup(ic->ic_rt->ctl_rates, | ||||
IEEE80211_RV(rate)); | rs->rates[i].rs_index); | ||||
} | } | ||||
RAL_WRITE(sc, RT2860_LEGACY_BASIC_RATE, mask); | RAL_WRITE(sc, RT2860_LEGACY_BASIC_RATE, mask); | ||||
} | } | ||||
static void | static void | ||||
rt2860_scan_start(struct ieee80211com *ic) | rt2860_scan_start(struct ieee80211com *ic) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 2,064 Lines • Show Last 20 Lines |