Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/usb/wlan/if_zyd.c
Show First 20 Lines • Show All 2,430 Lines • ▼ Show 20 Lines | default: /* Error */ | ||||
} | } | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
static int | static int | ||||
zyd_tx_start(struct zyd_softc *sc, struct mbuf *m0, struct ieee80211_node *ni) | zyd_tx_start(struct zyd_softc *sc, struct mbuf *m0, struct ieee80211_node *ni) | ||||
{ | { | ||||
const struct ieee80211_rate_t *rate; | |||||
const struct ieee80211_txparam_vht *tp = ni->ni_txparms; | |||||
struct ieee80211vap *vap = ni->ni_vap; | struct ieee80211vap *vap = ni->ni_vap; | ||||
struct ieee80211com *ic = ni->ni_ic; | struct ieee80211com *ic = ni->ni_ic; | ||||
struct zyd_tx_desc *desc; | struct zyd_tx_desc *desc; | ||||
struct zyd_tx_data *data; | struct zyd_tx_data *data; | ||||
struct ieee80211_frame *wh; | struct ieee80211_frame *wh; | ||||
const struct ieee80211_txparam *tp = ni->ni_txparms; | |||||
struct ieee80211_key *k; | struct ieee80211_key *k; | ||||
int rate, totlen, type, ismcast; | int totlen, type, ismcast; | ||||
static const uint8_t ratediv[] = ZYD_TX_RATEDIV; | static const uint8_t ratediv[] = ZYD_TX_RATEDIV; | ||||
uint8_t phy; | |||||
uint16_t pktlen; | |||||
uint32_t bits; | uint32_t bits; | ||||
uint16_t pktlen, rate_idx; | |||||
uint8_t phy; | |||||
wh = mtod(m0, struct ieee80211_frame *); | wh = mtod(m0, struct ieee80211_frame *); | ||||
data = STAILQ_FIRST(&sc->tx_free); | data = STAILQ_FIRST(&sc->tx_free); | ||||
STAILQ_REMOVE_HEAD(&sc->tx_free, next); | STAILQ_REMOVE_HEAD(&sc->tx_free, next); | ||||
sc->tx_nfree--; | sc->tx_nfree--; | ||||
ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1); | ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1); | ||||
type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; | type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; | ||||
if (type == IEEE80211_FC0_TYPE_MGT || | if (type == IEEE80211_FC0_TYPE_MGT || | ||||
type == IEEE80211_FC0_TYPE_CTL || | type == IEEE80211_FC0_TYPE_CTL || | ||||
(m0->m_flags & M_EAPOL) != 0) { | (m0->m_flags & M_EAPOL) != 0) { | ||||
rate = tp->mgmtrate; | rate_idx = tp->mgmtrate; | ||||
} else { | } else { | ||||
/* for data frames */ | /* for data frames */ | ||||
if (ismcast) | if (ismcast) | ||||
rate = tp->mcastrate; | rate_idx = tp->mcastrate; | ||||
else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) | else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) | ||||
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_get_rate(rate_idx); | |||||
if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { | if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { | ||||
k = ieee80211_crypto_encap(ni, m0); | k = ieee80211_crypto_encap(ni, m0); | ||||
if (k == NULL) { | if (k == NULL) { | ||||
return (ENOBUFS); | return (ENOBUFS); | ||||
} | } | ||||
/* packet header may have moved, reset our local pointer */ | /* packet header may have moved, reset our local pointer */ | ||||
wh = mtod(m0, struct ieee80211_frame *); | wh = mtod(m0, struct ieee80211_frame *); | ||||
} | } | ||||
data->ni = ni; | data->ni = ni; | ||||
data->m = m0; | data->m = m0; | ||||
data->rate = rate; | data->rate = rate->value; | ||||
/* fill Tx descriptor */ | /* fill Tx descriptor */ | ||||
desc = &data->desc; | desc = &data->desc; | ||||
phy = zyd_plcp_signal(sc, rate); | phy = zyd_plcp_signal(sc, rate->value); | ||||
desc->phy = phy; | desc->phy = phy; | ||||
if (ZYD_RATE_IS_OFDM(rate)) { | if (rate->type == IEEE80211_T_OFDM) { | ||||
desc->phy |= ZYD_TX_PHY_OFDM; | desc->phy |= ZYD_TX_PHY_OFDM; | ||||
if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) | if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) | ||||
desc->phy |= ZYD_TX_PHY_5GHZ; | desc->phy |= ZYD_TX_PHY_5GHZ; | ||||
} else if (rate != 2 && (ic->ic_flags & IEEE80211_F_SHPREAMBLE)) | } else if (rate->props.cck.short_preamble && | ||||
(ic->ic_flags & IEEE80211_F_SHPREAMBLE)) | |||||
desc->phy |= ZYD_TX_PHY_SHPREAMBLE; | desc->phy |= ZYD_TX_PHY_SHPREAMBLE; | ||||
totlen = m0->m_pkthdr.len + IEEE80211_CRC_LEN; | totlen = m0->m_pkthdr.len + IEEE80211_CRC_LEN; | ||||
desc->len = htole16(totlen); | desc->len = htole16(totlen); | ||||
desc->flags = ZYD_TX_FLAG_BACKOFF; | desc->flags = ZYD_TX_FLAG_BACKOFF; | ||||
if (!ismcast) { | if (!ismcast) { | ||||
/* multicast frames are not sent at OFDM rates in 802.11b/g */ | /* multicast frames are not sent at OFDM rates in 802.11b/g */ | ||||
if (totlen > vap->iv_rtsthreshold) { | if (totlen > vap->iv_rtsthreshold) { | ||||
desc->flags |= ZYD_TX_FLAG_RTS; | desc->flags |= ZYD_TX_FLAG_RTS; | ||||
} else if (ZYD_RATE_IS_OFDM(rate) && | } else if (rate->type == IEEE80211_T_OFDM && | ||||
(ic->ic_flags & IEEE80211_F_USEPROT)) { | (ic->ic_flags & IEEE80211_F_USEPROT)) { | ||||
if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) | if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) | ||||
desc->flags |= ZYD_TX_FLAG_CTS_TO_SELF; | desc->flags |= ZYD_TX_FLAG_CTS_TO_SELF; | ||||
else if (ic->ic_protmode == IEEE80211_PROT_RTSCTS) | else if (ic->ic_protmode == IEEE80211_PROT_RTSCTS) | ||||
desc->flags |= ZYD_TX_FLAG_RTS; | desc->flags |= ZYD_TX_FLAG_RTS; | ||||
} | } | ||||
} else | } else | ||||
desc->flags |= ZYD_TX_FLAG_MULTICAST; | desc->flags |= ZYD_TX_FLAG_MULTICAST; | ||||
if ((wh->i_fc[0] & | if ((wh->i_fc[0] & | ||||
(IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) == | (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) == | ||||
(IEEE80211_FC0_TYPE_CTL | IEEE80211_FC0_SUBTYPE_PS_POLL)) | (IEEE80211_FC0_TYPE_CTL | IEEE80211_FC0_SUBTYPE_PS_POLL)) | ||||
desc->flags |= ZYD_TX_FLAG_TYPE(ZYD_TX_TYPE_PS_POLL); | desc->flags |= ZYD_TX_FLAG_TYPE(ZYD_TX_TYPE_PS_POLL); | ||||
/* actual transmit length (XXX why +10?) */ | /* actual transmit length (XXX why +10?) */ | ||||
pktlen = ZYD_TX_DESC_SIZE + 10; | pktlen = ZYD_TX_DESC_SIZE + 10; | ||||
if (sc->sc_macrev == ZYD_ZD1211) | if (sc->sc_macrev == ZYD_ZD1211) | ||||
pktlen += totlen; | pktlen += totlen; | ||||
desc->pktlen = htole16(pktlen); | desc->pktlen = htole16(pktlen); | ||||
bits = (rate == 11) ? (totlen * 16) + 10 : | bits = (rate->value == 11) ? (totlen * 16) + 10 : | ||||
((rate == 22) ? (totlen * 8) + 10 : (totlen * 8)); | ((rate->value == 22) ? (totlen * 8) + 10 : (totlen * 8)); | ||||
desc->plcp_length = htole16(bits / ratediv[phy]); | desc->plcp_length = htole16(bits / ratediv[phy]); | ||||
desc->plcp_service = 0; | desc->plcp_service = 0; | ||||
if (rate == 22 && (bits % 11) > 0 && (bits % 11) <= 3) | if (rate->value == 22 && (bits % 11) > 0 && (bits % 11) <= 3) | ||||
desc->plcp_service |= ZYD_PLCP_LENGEXT; | desc->plcp_service |= ZYD_PLCP_LENGEXT; | ||||
desc->nextlen = 0; | desc->nextlen = 0; | ||||
if (ieee80211_radiotap_active_vap(vap)) { | if (ieee80211_radiotap_active_vap(vap)) { | ||||
struct zyd_tx_radiotap_header *tap = &sc->sc_txtap; | struct zyd_tx_radiotap_header *tap = &sc->sc_txtap; | ||||
tap->wt_flags = 0; | tap->wt_flags = 0; | ||||
tap->wt_rate = rate; | tap->wt_rate = rate->value; | ||||
ieee80211_radiotap_tx(vap, m0); | ieee80211_radiotap_tx(vap, m0); | ||||
} | } | ||||
DPRINTF(sc, ZYD_DEBUG_XMIT, | DPRINTF(sc, ZYD_DEBUG_XMIT, | ||||
"%s: sending data frame len=%zu rate=%u\n", | "%s: sending data frame len=%zu rate=%u/%u\n", | ||||
device_get_nameunit(sc->sc_dev), (size_t)m0->m_pkthdr.len, | device_get_nameunit(sc->sc_dev), (size_t)m0->m_pkthdr.len, | ||||
rate); | rate->type, rate->value); | ||||
STAILQ_INSERT_TAIL(&sc->tx_q, data, next); | STAILQ_INSERT_TAIL(&sc->tx_q, data, next); | ||||
usbd_transfer_start(sc->sc_xfer[ZYD_BULK_WR]); | usbd_transfer_start(sc->sc_xfer[ZYD_BULK_WR]); | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
▲ Show 20 Lines • Show All 370 Lines • Show Last 20 Lines |