Changeset View
Changeset View
Standalone View
Standalone View
head/sys/dev/usb/wlan/if_urtwn.c
Show First 20 Lines • Show All 285 Lines • ▼ Show 20 Lines | |||||
static void urtwn_set_txpower(struct urtwn_softc *, | static void urtwn_set_txpower(struct urtwn_softc *, | ||||
struct ieee80211_channel *, | struct ieee80211_channel *, | ||||
struct ieee80211_channel *); | struct ieee80211_channel *); | ||||
static void urtwn_set_rx_bssid_all(struct urtwn_softc *, int); | static void urtwn_set_rx_bssid_all(struct urtwn_softc *, int); | ||||
static void urtwn_set_gain(struct urtwn_softc *, uint8_t); | static void urtwn_set_gain(struct urtwn_softc *, uint8_t); | ||||
static void urtwn_scan_start(struct ieee80211com *); | static void urtwn_scan_start(struct ieee80211com *); | ||||
static void urtwn_scan_end(struct ieee80211com *); | static void urtwn_scan_end(struct ieee80211com *); | ||||
static void urtwn_set_channel(struct ieee80211com *); | static void urtwn_set_channel(struct ieee80211com *); | ||||
static int urtwn_wme_update(struct ieee80211com *); | |||||
static void urtwn_set_promisc(struct urtwn_softc *); | static void urtwn_set_promisc(struct urtwn_softc *); | ||||
static void urtwn_update_promisc(struct ieee80211com *); | static void urtwn_update_promisc(struct ieee80211com *); | ||||
static void urtwn_update_mcast(struct ieee80211com *); | static void urtwn_update_mcast(struct ieee80211com *); | ||||
static void urtwn_set_chan(struct urtwn_softc *, | static void urtwn_set_chan(struct urtwn_softc *, | ||||
struct ieee80211_channel *, | struct ieee80211_channel *, | ||||
struct ieee80211_channel *); | struct ieee80211_channel *); | ||||
static void urtwn_iq_calib(struct urtwn_softc *); | static void urtwn_iq_calib(struct urtwn_softc *); | ||||
static void urtwn_lc_calib(struct urtwn_softc *); | static void urtwn_lc_calib(struct urtwn_softc *); | ||||
▲ Show 20 Lines • Show All 69 Lines • ▼ Show 20 Lines | .flags = { | ||||
.pipe_bof = 1, | .pipe_bof = 1, | ||||
.force_short_xfer = 1 | .force_short_xfer = 1 | ||||
}, | }, | ||||
.callback = urtwn_bulk_tx_callback, | .callback = urtwn_bulk_tx_callback, | ||||
.timeout = URTWN_TX_TIMEOUT, /* ms */ | .timeout = URTWN_TX_TIMEOUT, /* ms */ | ||||
}, | }, | ||||
}; | }; | ||||
static const struct wme_to_queue { | |||||
uint16_t reg; | |||||
uint8_t qid; | |||||
} wme2queue[WME_NUM_AC] = { | |||||
{ R92C_EDCA_BE_PARAM, URTWN_BULK_TX_BE}, | |||||
{ R92C_EDCA_BK_PARAM, URTWN_BULK_TX_BK}, | |||||
{ R92C_EDCA_VI_PARAM, URTWN_BULK_TX_VI}, | |||||
{ R92C_EDCA_VO_PARAM, URTWN_BULK_TX_VO} | |||||
}; | |||||
static int | static int | ||||
urtwn_match(device_t self) | urtwn_match(device_t self) | ||||
{ | { | ||||
struct usb_attach_arg *uaa = device_get_ivars(self); | struct usb_attach_arg *uaa = device_get_ivars(self); | ||||
if (uaa->usb_mode != USB_MODE_HOST) | if (uaa->usb_mode != USB_MODE_HOST) | ||||
return (ENXIO); | return (ENXIO); | ||||
if (uaa->info.bConfigIndex != URTWN_CONFIG_INDEX) | if (uaa->info.bConfigIndex != URTWN_CONFIG_INDEX) | ||||
▲ Show 20 Lines • Show All 81 Lines • ▼ Show 20 Lines | ic->ic_caps = | ||||
IEEE80211_C_STA /* station mode */ | IEEE80211_C_STA /* station mode */ | ||||
| IEEE80211_C_MONITOR /* monitor mode */ | | IEEE80211_C_MONITOR /* monitor mode */ | ||||
| IEEE80211_C_IBSS /* adhoc mode */ | | IEEE80211_C_IBSS /* adhoc mode */ | ||||
| IEEE80211_C_HOSTAP /* hostap mode */ | | IEEE80211_C_HOSTAP /* hostap mode */ | ||||
| IEEE80211_C_SHPREAMBLE /* short preamble supported */ | | IEEE80211_C_SHPREAMBLE /* short preamble supported */ | ||||
| IEEE80211_C_SHSLOT /* short slot time supported */ | | IEEE80211_C_SHSLOT /* short slot time supported */ | ||||
| IEEE80211_C_BGSCAN /* capable of bg scanning */ | | IEEE80211_C_BGSCAN /* capable of bg scanning */ | ||||
| IEEE80211_C_WPA /* 802.11i */ | | IEEE80211_C_WPA /* 802.11i */ | ||||
| IEEE80211_C_WME /* 802.11e */ | |||||
; | ; | ||||
bands = 0; | bands = 0; | ||||
setbit(&bands, IEEE80211_MODE_11B); | setbit(&bands, IEEE80211_MODE_11B); | ||||
setbit(&bands, IEEE80211_MODE_11G); | setbit(&bands, IEEE80211_MODE_11G); | ||||
ieee80211_init_channels(ic, NULL, &bands); | ieee80211_init_channels(ic, NULL, &bands); | ||||
ieee80211_ifattach(ic); | ieee80211_ifattach(ic); | ||||
ic->ic_raw_xmit = urtwn_raw_xmit; | ic->ic_raw_xmit = urtwn_raw_xmit; | ||||
ic->ic_scan_start = urtwn_scan_start; | ic->ic_scan_start = urtwn_scan_start; | ||||
ic->ic_scan_end = urtwn_scan_end; | ic->ic_scan_end = urtwn_scan_end; | ||||
ic->ic_set_channel = urtwn_set_channel; | ic->ic_set_channel = urtwn_set_channel; | ||||
ic->ic_transmit = urtwn_transmit; | ic->ic_transmit = urtwn_transmit; | ||||
ic->ic_parent = urtwn_parent; | ic->ic_parent = urtwn_parent; | ||||
ic->ic_vap_create = urtwn_vap_create; | ic->ic_vap_create = urtwn_vap_create; | ||||
ic->ic_vap_delete = urtwn_vap_delete; | ic->ic_vap_delete = urtwn_vap_delete; | ||||
ic->ic_wme.wme_update = urtwn_wme_update; | |||||
ic->ic_update_promisc = urtwn_update_promisc; | ic->ic_update_promisc = urtwn_update_promisc; | ||||
ic->ic_update_mcast = urtwn_update_mcast; | ic->ic_update_mcast = urtwn_update_mcast; | ||||
ieee80211_radiotap_attach(ic, &sc->sc_txtap.wt_ihdr, | ieee80211_radiotap_attach(ic, &sc->sc_txtap.wt_ihdr, | ||||
sizeof(sc->sc_txtap), URTWN_TX_RADIOTAP_PRESENT, | sizeof(sc->sc_txtap), URTWN_TX_RADIOTAP_PRESENT, | ||||
&sc->sc_rxtap.wr_ihdr, sizeof(sc->sc_rxtap), | &sc->sc_rxtap.wr_ihdr, sizeof(sc->sc_rxtap), | ||||
URTWN_RX_RADIOTAP_PRESENT); | URTWN_RX_RADIOTAP_PRESENT); | ||||
▲ Show 20 Lines • Show All 1,653 Lines • ▼ Show 20 Lines | |||||
urtwn_tx_data(struct urtwn_softc *sc, struct ieee80211_node *ni, | urtwn_tx_data(struct urtwn_softc *sc, struct ieee80211_node *ni, | ||||
struct mbuf *m, struct urtwn_data *data) | struct mbuf *m, struct urtwn_data *data) | ||||
{ | { | ||||
struct ieee80211_frame *wh; | struct ieee80211_frame *wh; | ||||
struct ieee80211_key *k = NULL; | struct ieee80211_key *k = NULL; | ||||
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 r92c_tx_desc *txd; | struct r92c_tx_desc *txd; | ||||
uint8_t macid, raid, ridx, subtype, type, qsel; | uint8_t macid, raid, ridx, subtype, type, tid, qsel; | ||||
int ismcast; | int hasqos, ismcast; | ||||
URTWN_ASSERT_LOCKED(sc); | URTWN_ASSERT_LOCKED(sc); | ||||
/* | /* | ||||
* Software crypto. | * Software crypto. | ||||
*/ | */ | ||||
wh = mtod(m, struct ieee80211_frame *); | wh = mtod(m, struct ieee80211_frame *); | ||||
type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; | type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; | ||||
subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; | subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; | ||||
hasqos = IEEE80211_QOS_HAS_SEQ(wh); | |||||
ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1); | ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1); | ||||
/* Select TX ring for this frame. */ | |||||
if (hasqos) { | |||||
tid = ((const struct ieee80211_qosframe *)wh)->i_qos[0]; | |||||
tid &= IEEE80211_QOS_TID; | |||||
} else | |||||
tid = 0; | |||||
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) { | ||||
device_printf(sc->sc_dev, | device_printf(sc->sc_dev, | ||||
"ieee80211_crypto_encap returns NULL.\n"); | "ieee80211_crypto_encap returns NULL.\n"); | ||||
return (ENOBUFS); | return (ENOBUFS); | ||||
} | } | ||||
Show All 12 Lines | if (ismcast) | ||||
txd->txdw0 |= htole32(R92C_TXDW0_BMCAST); | txd->txdw0 |= htole32(R92C_TXDW0_BMCAST); | ||||
raid = R92C_RAID_11B; /* by default */ | raid = R92C_RAID_11B; /* by default */ | ||||
ridx = URTWN_RIDX_CCK1; | ridx = URTWN_RIDX_CCK1; | ||||
if (!ismcast) { | if (!ismcast) { | ||||
macid = URTWN_MACID_BSS; | macid = URTWN_MACID_BSS; | ||||
if (type == IEEE80211_FC0_TYPE_DATA) { | if (type == IEEE80211_FC0_TYPE_DATA) { | ||||
qsel = R92C_TXDW1_QSEL_BE; | qsel = tid % URTWN_MAX_TID; | ||||
if (!(m->m_flags & M_EAPOL)) { | if (!(m->m_flags & M_EAPOL)) { | ||||
if (ic->ic_curmode != IEEE80211_MODE_11B) { | if (ic->ic_curmode != IEEE80211_MODE_11B) { | ||||
raid = R92C_RAID_11BG; | raid = R92C_RAID_11BG; | ||||
ridx = URTWN_RIDX_OFDM54; | ridx = URTWN_RIDX_OFDM54; | ||||
} else | } else | ||||
ridx = URTWN_RIDX_CCK11; | ridx = URTWN_RIDX_CCK11; | ||||
} | } | ||||
Show All 39 Lines | else | ||||
txd->txdw1 |= htole32(SM(R92C_TXDW1_MACID, macid)); | txd->txdw1 |= htole32(SM(R92C_TXDW1_MACID, macid)); | ||||
txd->txdw5 |= htole32(SM(R92C_TXDW5_DATARATE, ridx)); | txd->txdw5 |= htole32(SM(R92C_TXDW5_DATARATE, ridx)); | ||||
/* Force this rate if needed. */ | /* Force this rate if needed. */ | ||||
if (ismcast || type != IEEE80211_FC0_TYPE_DATA || | if (ismcast || type != IEEE80211_FC0_TYPE_DATA || | ||||
(m->m_flags & M_EAPOL)) | (m->m_flags & M_EAPOL)) | ||||
txd->txdw4 |= htole32(R92C_TXDW4_DRVRATE); | txd->txdw4 |= htole32(R92C_TXDW4_DRVRATE); | ||||
if (!IEEE80211_QOS_HAS_SEQ(wh)) { | if (!hasqos) { | ||||
/* Use HW sequence numbering for non-QoS frames. */ | /* Use HW sequence numbering for non-QoS frames. */ | ||||
if (sc->chip & URTWN_CHIP_88E) | if (sc->chip & URTWN_CHIP_88E) | ||||
txd->txdseq = htole16(R88E_TXDSEQ_HWSEQ_EN); | txd->txdseq = htole16(R88E_TXDSEQ_HWSEQ_EN); | ||||
else | else | ||||
txd->txdw4 |= htole32(R92C_TXDW4_HWSEQ_EN); | txd->txdw4 |= htole32(R92C_TXDW4_HWSEQ_EN); | ||||
} else { | } else { | ||||
/* Set sequence number. */ | /* Set sequence number. */ | ||||
txd->txdseq = htole16(M_SEQNO_GET(m) % IEEE80211_SEQ_RANGE); | txd->txdseq = htole16(M_SEQNO_GET(m) % IEEE80211_SEQ_RANGE); | ||||
Show All 20 Lines | |||||
static void | static void | ||||
urtwn_tx_start(struct urtwn_softc *sc, struct mbuf *m, uint8_t type, | urtwn_tx_start(struct urtwn_softc *sc, struct mbuf *m, uint8_t type, | ||||
struct urtwn_data *data) | struct urtwn_data *data) | ||||
{ | { | ||||
struct usb_xfer *xfer; | struct usb_xfer *xfer; | ||||
struct r92c_tx_desc *txd; | struct r92c_tx_desc *txd; | ||||
uint16_t ac, sum; | uint16_t ac, sum; | ||||
int i, xferlen; | int i, xferlen; | ||||
struct usb_xfer *urtwn_pipes[WME_NUM_AC] = { | |||||
sc->sc_xfer[URTWN_BULK_TX_BE], | |||||
sc->sc_xfer[URTWN_BULK_TX_BK], | |||||
sc->sc_xfer[URTWN_BULK_TX_VI], | |||||
sc->sc_xfer[URTWN_BULK_TX_VO] | |||||
}; | |||||
URTWN_ASSERT_LOCKED(sc); | URTWN_ASSERT_LOCKED(sc); | ||||
ac = M_WME_GETAC(m); | ac = M_WME_GETAC(m); | ||||
switch (type) { | switch (type) { | ||||
case IEEE80211_FC0_TYPE_CTL: | case IEEE80211_FC0_TYPE_CTL: | ||||
case IEEE80211_FC0_TYPE_MGT: | case IEEE80211_FC0_TYPE_MGT: | ||||
xfer = sc->sc_xfer[URTWN_BULK_TX_VO]; | xfer = sc->sc_xfer[URTWN_BULK_TX_VO]; | ||||
break; | break; | ||||
default: | default: | ||||
xfer = urtwn_pipes[ac]; | xfer = sc->sc_xfer[wme2queue[ac].qid]; | ||||
break; | break; | ||||
} | } | ||||
txd = (struct r92c_tx_desc *)data->buf; | txd = (struct r92c_tx_desc *)data->buf; | ||||
txd->txdw0 |= htole32(SM(R92C_TXDW0_PKTLEN, m->m_pkthdr.len)); | txd->txdw0 |= htole32(SM(R92C_TXDW0_PKTLEN, m->m_pkthdr.len)); | ||||
/* Compute Tx descriptor checksum. */ | /* Compute Tx descriptor checksum. */ | ||||
sum = 0; | sum = 0; | ||||
▲ Show 20 Lines • Show All 1,270 Lines • ▼ Show 20 Lines | urtwn_set_channel(struct ieee80211com *ic) | ||||
URTWN_LOCK(sc); | URTWN_LOCK(sc); | ||||
if (vap->iv_state == IEEE80211_S_SCAN) { | if (vap->iv_state == IEEE80211_S_SCAN) { | ||||
/* Make link LED blink during scan. */ | /* Make link LED blink during scan. */ | ||||
urtwn_set_led(sc, URTWN_LED_LINK, !sc->ledlink); | urtwn_set_led(sc, URTWN_LED_LINK, !sc->ledlink); | ||||
} | } | ||||
urtwn_set_chan(sc, ic->ic_curchan, NULL); | urtwn_set_chan(sc, ic->ic_curchan, NULL); | ||||
URTWN_UNLOCK(sc); | URTWN_UNLOCK(sc); | ||||
} | |||||
static int | |||||
urtwn_wme_update(struct ieee80211com *ic) | |||||
{ | |||||
const struct wmeParams *wmep = | |||||
ic->ic_wme.wme_chanParams.cap_wmeParams; | |||||
struct urtwn_softc *sc = ic->ic_softc; | |||||
uint8_t aifs, acm, slottime; | |||||
int ac; | |||||
acm = 0; | |||||
slottime = (ic->ic_flags & IEEE80211_F_SHSLOT) ? | |||||
IEEE80211_DUR_SHSLOT : IEEE80211_DUR_SLOT; | |||||
URTWN_LOCK(sc); | |||||
for (ac = WME_AC_BE; ac < WME_NUM_AC; ac++) { | |||||
/* AIFS[AC] = AIFSN[AC] * aSlotTime + aSIFSTime. */ | |||||
aifs = wmep[ac].wmep_aifsn * slottime + IEEE80211_DUR_SIFS; | |||||
urtwn_write_4(sc, wme2queue[ac].reg, | |||||
SM(R92C_EDCA_PARAM_TXOP, wmep[ac].wmep_txopLimit) | | |||||
SM(R92C_EDCA_PARAM_ECWMIN, wmep[ac].wmep_logcwmin) | | |||||
SM(R92C_EDCA_PARAM_ECWMAX, wmep[ac].wmep_logcwmax) | | |||||
SM(R92C_EDCA_PARAM_AIFS, aifs)); | |||||
if (ac != WME_AC_BE) | |||||
acm |= wmep[ac].wmep_acm << ac; | |||||
} | |||||
if (acm != 0) | |||||
acm |= R92C_ACMHWCTRL_EN; | |||||
urtwn_write_1(sc, R92C_ACMHWCTRL, | |||||
(urtwn_read_1(sc, R92C_ACMHWCTRL) & ~R92C_ACMHWCTRL_ACM_MASK) | | |||||
acm); | |||||
URTWN_UNLOCK(sc); | |||||
return 0; | |||||
} | } | ||||
static void | static void | ||||
urtwn_set_promisc(struct urtwn_softc *sc) | urtwn_set_promisc(struct urtwn_softc *sc) | ||||
{ | { | ||||
struct ieee80211com *ic = &sc->sc_ic; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); | struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); | ||||
uint32_t rcr, mask1, mask2; | uint32_t rcr, mask1, mask2; | ||||
▲ Show 20 Lines • Show All 502 Lines • Show Last 20 Lines |