PERFORCE change 143107 for review
Hans Petter Selasky
hselasky at FreeBSD.org
Sun Jun 8 10:52:54 UTC 2008
http://perforce.freebsd.org/chv.cgi?CH=143107
Change 143107 by hselasky at hselasky_laptop001 on 2008/06/08 10:52:49
Integrate RUM USB WLAN driver @143078 separately, hence
there was a ton of changes to integrate after Sam & Co :-)
Some small bugs were found and corrected.
Affected files ...
.. //depot/projects/usb/src/sys/dev/usb/if_rum.c#29 edit
.. //depot/projects/usb/src/sys/dev/usb/if_rumreg.h#5 edit
.. //depot/projects/usb/src/sys/dev/usb/if_rumvar.h#6 edit
Differences ...
==== //depot/projects/usb/src/sys/dev/usb/if_rum.c#29 (text+ko) ====
@@ -1,7 +1,7 @@
/*-
* Copyright (c) 2005-2007 Damien Bergamini <damien.bergamini at free.fr>
* Copyright (c) 2006 Niall O'Higgins <niallo at openbsd.org>
- * Copyright (c) 2007 Hans Petter Selasky <hselasky at freebsd.org>
+ * Copyright (c) 2007-2008 Hans Petter Selasky <hselasky at freebsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -22,7 +22,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: src/sys/dev/usb/if_rum.c,v 1.23 2008/06/07 18:38:02 sam Exp $");
/*-
* Ralink Technology RT2501USB/RT2601USB chipset driver
@@ -50,6 +50,7 @@
#include <net80211/ieee80211_radiotap.h>
#include <net80211/ieee80211_amrr.h>
#include <net80211/ieee80211_regdomain.h>
+#include <net80211/ieee80211_phy.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
@@ -102,15 +103,11 @@
static usbd_config_td_command_t rum_cfg_scan_end;
static usbd_config_td_command_t rum_cfg_select_band;
static usbd_config_td_command_t rum_cfg_set_chan;
-static usbd_config_td_command_t rum_cfg_pre_set_run;
-static usbd_config_td_command_t rum_cfg_set_run;
static usbd_config_td_command_t rum_cfg_enable_tsf_sync;
-static usbd_config_td_command_t rum_cfg_disable_tsf_sync;
static usbd_config_td_command_t rum_cfg_enable_mrr;
static usbd_config_td_command_t rum_cfg_update_slot;
static usbd_config_td_command_t rum_cfg_select_antenna;
static usbd_config_td_command_t rum_cfg_set_txpreamble;
-static usbd_config_td_command_t rum_cfg_set_basicrates;
static usbd_config_td_command_t rum_cfg_update_promisc;
static usbd_config_td_command_t rum_cfg_pre_init;
static usbd_config_td_command_t rum_cfg_init;
@@ -118,26 +115,19 @@
static usbd_config_td_command_t rum_cfg_stop;
static usbd_config_td_command_t rum_cfg_amrr_timeout;
static usbd_config_td_command_t rum_cfg_prepare_beacon;
+static usbd_config_td_command_t rum_cfg_newstate;
static const char *rum_get_rf(uint32_t rev);
static int rum_ioctl_cb(struct ifnet *ifp, u_long cmd, caddr_t data);
-static int rum_media_change_cb(struct ifnet *ifp);
-static int rum_newstate_cb(struct ieee80211com *ic, enum ieee80211_state nstate, int arg);
-static int rum_reset_cb(struct ifnet *ifp);
static void rum_std_command(struct ieee80211com *ic, usbd_config_td_command_t *func);
static void rum_scan_start_cb(struct ieee80211com *);
static void rum_scan_end_cb(struct ieee80211com *);
static void rum_set_channel_cb(struct ieee80211com *);
-static uint16_t rum_ack_rate(const struct ieee80211com *ic, uint16_t rate);
static uint16_t rum_cfg_eeprom_read_2(struct rum_softc *sc, uint16_t addr);
-static uint16_t rum_rxrate(const struct rum_rx_desc *desc);
-static uint16_t rum_txtime(struct rum_softc *sc, uint16_t len, uint16_t rate, uint32_t flags);
static uint32_t rum_cfg_bbp_disbusy(struct rum_softc *sc);
static uint32_t rum_cfg_read(struct rum_softc *sc, uint16_t reg);
static uint8_t rum_cfg_bbp_init(struct rum_softc *sc);
static uint8_t rum_cfg_bbp_read(struct rum_softc *sc, uint8_t reg);
-static uint8_t rum_plcp_signal(uint16_t rate);
-static uint8_t rum_bulk_write_callback_sub(struct usbd_xfer *xfer, struct mbuf *m, struct ieee80211_node *ni, uint32_t flags, uint16_t rate);
static void rum_cfg_amrr_start(struct rum_softc *sc);
static void rum_cfg_bbp_write(struct rum_softc *sc, uint8_t reg, uint8_t val);
static void rum_cfg_do_request(struct rum_softc *sc, usb_device_request_t *req, void *data);
@@ -152,11 +142,27 @@
static void rum_cfg_write_multi(struct rum_softc *sc, uint16_t reg, void *buf, uint16_t len);
static void rum_end_of_commands(struct rum_softc *sc);
static void rum_init_cb(void *arg);
-static void rum_setup_tx_desc(struct rum_softc *sc, uint32_t flags, uint16_t xflags, uint16_t len, uint16_t rate);
static void rum_start_cb(struct ifnet *ifp);
static void rum_watchdog(void *arg);
+static uint8_t rum_get_rssi(struct rum_softc *sc, uint8_t raw);
-static uint8_t rum_get_rssi(struct rum_softc *sc, uint8_t raw);
+
+static struct ieee80211vap *rum_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit, int opmode, int flags, const uint8_t bssid[IEEE80211_ADDR_LEN], const uint8_t mac[IEEE80211_ADDR_LEN]);
+static void rum_vap_delete(struct ieee80211vap *);
+static struct ieee80211_node *rum_node_alloc(struct ieee80211_node_table *);
+static void rum_newassoc(struct ieee80211_node *, int);
+static void rum_cfg_disable_tsf_sync(struct rum_softc *sc);
+static void rum_cfg_set_run(struct rum_softc *sc, struct rum_config_copy *cc);
+static void rum_fill_write_queue(struct rum_softc *sc);
+static void rum_tx_clean_queue(struct rum_softc *sc);
+static void rum_tx_freem(struct mbuf *m);
+static void rum_tx_mgt(struct rum_softc *sc, struct mbuf *m, struct ieee80211_node *ni);
+static struct ieee80211vap *rum_get_vap(struct rum_softc *sc);
+static void rum_tx_data(struct rum_softc *sc, struct mbuf *m, struct ieee80211_node *ni);
+static void rum_tx_prot(struct rum_softc *sc, const struct mbuf *m, struct ieee80211_node *ni, uint8_t prot, uint16_t rate);
+static void rum_tx_raw(struct rum_softc *sc, struct mbuf *m, struct ieee80211_node *ni, const struct ieee80211_bpf_params *params);
+static int rum_raw_xmit_cb(struct ieee80211_node *ni, struct mbuf *m, const struct ieee80211_bpf_params *params);
+static void rum_setup_desc_and_tx(struct rum_softc *sc, struct mbuf *m, uint32_t flags, uint16_t xflags, uint16_t rate);
/* various supported device vendors/products */
static const struct usb_devno rum_devs[] = {
@@ -528,8 +534,8 @@
rum_cfg_pre_stop(sc, NULL, 0);
- ic = &(sc->sc_ic);
- ifp = ic->ic_ifp;
+ ifp = sc->sc_ifp;
+ ic = ifp->if_l2com;
mtx_unlock(&(sc->sc_mtx));
@@ -749,27 +755,22 @@
rum_cfg_first_time_setup(struct rum_softc *sc,
struct rum_config_copy *cc, uint16_t refcount)
{
- struct ieee80211com *ic = &(sc->sc_ic);
+ struct ieee80211com *ic;
struct ifnet *ifp;
uint32_t tmp;
- uint32_t bands;
uint16_t i;
+ uint8_t bands;
/* setup RX tap header */
- sc->sc_rxtap_len = sizeof(sc->sc_rxtap.h);
- sc->sc_rxtap.h.wr_ihdr.it_len = htole16(sc->sc_rxtap_len);
- sc->sc_rxtap.h.wr_ihdr.it_present = htole32(RT2573_RX_RADIOTAP_PRESENT);
+ sc->sc_rxtap_len = sizeof(sc->sc_rxtap);
+ sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len);
+ sc->sc_rxtap.wr_ihdr.it_present = htole32(RT2573_RX_RADIOTAP_PRESENT);
/* setup TX tap header */
- sc->sc_txtap_len = sizeof(sc->sc_txtap.h);
- sc->sc_txtap.h.wt_ihdr.it_len = htole16(sc->sc_txtap_len);
- sc->sc_txtap.h.wt_ihdr.it_present = htole32(RT2573_TX_RADIOTAP_PRESENT);
+ sc->sc_txtap_len = sizeof(sc->sc_txtap);
+ sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len);
+ sc->sc_txtap.wt_ihdr.it_present = htole32(RT2573_TX_RADIOTAP_PRESENT);
- /* setup AMRR */
- ieee80211_amrr_init(&sc->sc_amrr, ic,
- IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD,
- IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD);
-
/* retrieve RT2573 rev. no */
for (i = 0; i < 100; i++) {
@@ -797,7 +798,7 @@
mtx_unlock(&(sc->sc_mtx));
- ifp = if_alloc(IFT_ETHER);
+ ifp = if_alloc(IFT_IEEE80211);
mtx_lock(&(sc->sc_mtx));
@@ -807,6 +808,7 @@
}
sc->sc_evilhack = ifp;
sc->sc_ifp = ifp;
+ ic = ifp->if_l2com;
ifp->if_softc = sc;
if_initname(ifp, "rum", sc->sc_unit);
@@ -821,12 +823,11 @@
ic->ic_ifp = ifp;
ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
- ic->ic_opmode = IEEE80211_M_STA;/* default to BSS mode */
- ic->ic_state = IEEE80211_S_INIT;
/* set device capabilities */
ic->ic_caps =
- IEEE80211_C_IBSS /* IBSS mode supported */
+ IEEE80211_C_STA /* station mode supported */
+ | IEEE80211_C_IBSS /* IBSS mode supported */
| IEEE80211_C_MONITOR /* monitor mode supported */
| IEEE80211_C_HOSTAP /* HostAp mode supported */
| IEEE80211_C_TXPMGT /* tx power management */
@@ -839,7 +840,7 @@
bands = 0;
setbit(&bands, IEEE80211_MODE_11B);
setbit(&bands, IEEE80211_MODE_11G);
- ieee80211_init_channels(ic, 0, CTRY_DEFAULT, bands, 0, 1);
+ ieee80211_init_channels(ic, NULL, &bands);
if ((sc->sc_rf_rev == RT2573_RF_5225) ||
(sc->sc_rf_rev == RT2573_RF_5226)) {
@@ -878,27 +879,23 @@
mtx_lock(&(sc->sc_mtx));
- /* enable SW bmiss handling in sta mode */
- ic->ic_flags_ext |= IEEE80211_FEXT_SWBMISS;
+ ic->ic_newassoc = &rum_newassoc;
+ ic->ic_raw_xmit = &rum_raw_xmit_cb;
+ ic->ic_node_alloc = &rum_node_alloc;
- /* overrides */
- sc->sc_newstate = ic->ic_newstate;
- ic->ic_newstate = &rum_newstate_cb;
-#if 0
- ic->ic_raw_xmit = &rum_raw_xmit_cb;
-#endif
- ic->ic_reset = &rum_reset_cb;
ic->ic_scan_start = &rum_scan_start_cb;
ic->ic_scan_end = &rum_scan_end_cb;
ic->ic_set_channel = &rum_set_channel_cb;
+ ic->ic_vap_create = &rum_vap_create;
+ ic->ic_vap_delete = &rum_vap_delete;
+
+ sc->sc_rates = ieee80211_get_ratetable(ic->ic_curchan);
mtx_unlock(&(sc->sc_mtx));
- ieee80211_media_init(ic, rum_media_change_cb, ieee80211_media_status);
+ bpfattach(ifp, DLT_IEEE802_11_RADIO,
+ sizeof(struct ieee80211_frame) + sizeof(sc->sc_txtap));
- bpfattach2(ifp, DLT_IEEE802_11_RADIO,
- sizeof(struct ieee80211_frame) + 64, &sc->sc_drvbpf);
-
if (bootverbose) {
ieee80211_announce(ic);
}
@@ -912,10 +909,32 @@
{
sc->sc_flags &= ~RUM_FLAG_WAIT_COMMAND;
- if ((sc->sc_flags & RUM_FLAG_LL_READY) &&
- (sc->sc_flags & RUM_FLAG_HL_READY)) {
- /* start write transfer, if not started */
- usbd_transfer_start(sc->sc_xfer[0]);
+ /* start write transfer, if not started */
+ usbd_transfer_start(sc->sc_xfer[0]);
+ return;
+}
+
+static void
+rum_config_copy_chan(struct rum_config_copy_chan *cc,
+ struct ieee80211com *ic, struct ieee80211_channel *c)
+{
+ if (!c)
+ return;
+ cc->chan_to_ieee =
+ ieee80211_chan2ieee(ic, c);
+ if (c != IEEE80211_CHAN_ANYC) {
+ cc->chan_to_mode =
+ ieee80211_chan2mode(c);
+ if (IEEE80211_IS_CHAN_B(c))
+ cc->chan_is_b = 1;
+ if (IEEE80211_IS_CHAN_A(c))
+ cc->chan_is_a = 1;
+ if (IEEE80211_IS_CHAN_2GHZ(c))
+ cc->chan_is_2ghz = 1;
+ if (IEEE80211_IS_CHAN_5GHZ(c))
+ cc->chan_is_5ghz = 1;
+ if (IEEE80211_IS_CHAN_ANYG(c))
+ cc->chan_is_g = 1;
}
return;
}
@@ -924,46 +943,46 @@
rum_config_copy(struct rum_softc *sc,
struct rum_config_copy *cc, uint16_t refcount)
{
- struct ieee80211com *ic = &(sc->sc_ic);
- struct ieee80211_channel *c = ic->ic_curchan;
- struct ifnet *ifp = ic->ic_ifp;
+ struct ifnet *ifp;
+ struct ieee80211com *ic;
+ struct ieee80211_node *ni;
+ struct ieee80211vap *vap;
+ const struct ieee80211_txparam *tp;
bzero(cc, sizeof(*cc));
- if (c) {
- cc->ic_curchan.chan_to_ieee = ieee80211_chan2ieee(ic, c);
- cc->ic_curchan.chan_is_b = IEEE80211_IS_CHAN_B(c) ? 1 : 0;
- cc->ic_curchan.chan_is_a = IEEE80211_IS_CHAN_A(c) ? 1 : 0;
- if (c != IEEE80211_CHAN_ANYC) {
- cc->ic_curchan.chan_is_2ghz = IEEE80211_IS_CHAN_2GHZ(c) ? 1 : 0;
- cc->ic_curchan.chan_is_5ghz = IEEE80211_IS_CHAN_5GHZ(c) ? 1 : 0;
- }
- }
- if (ic->ic_bss) {
- if ((ic->ic_bss->ni_chan) &&
- (ic->ic_bss->ni_chan != IEEE80211_CHAN_ANYC)) {
- cc->ic_bss.ni_chan.chan_is_5ghz =
- IEEE80211_IS_CHAN_5GHZ(ic->ic_bss->ni_chan) ? 1 : 0;
- }
- cc->ic_bss.ni_intval = ic->ic_bss->ni_intval;
- bcopy(ic->ic_bss->ni_bssid, cc->ic_bss.ni_bssid,
- sizeof(cc->ic_bss.ni_bssid));
- }
- cc->ic_opmode = ic->ic_opmode;
- cc->ic_state = ic->ic_state;
- cc->ic_flags = ic->ic_flags;
-
+ ifp = sc->sc_ifp;
if (ifp) {
cc->if_flags = ifp->if_flags;
bcopy(ifp->if_broadcastaddr, cc->if_broadcastaddr,
sizeof(cc->if_broadcastaddr));
- }
- cc->ic_txpowlimit = ic->ic_txpowlimit;
- cc->ic_curmode = ic->ic_curmode;
- bcopy(ic->ic_myaddr, cc->ic_myaddr,
- sizeof(cc->ic_myaddr));
+ ic = ifp->if_l2com;
+ if (ic) {
+ rum_config_copy_chan(&cc->ic_curchan, ic, ic->ic_curchan);
+ rum_config_copy_chan(&cc->ic_bsschan, ic, ic->ic_bsschan);
+ vap = TAILQ_FIRST(&ic->ic_vaps);
+ if (vap) {
+ ni = vap->iv_bss;
+ if (ni) {
+ cc->iv_bss.ni_intval = ni->ni_intval;
+ bcopy(ni->ni_bssid, cc->iv_bss.ni_bssid,
+ sizeof(cc->iv_bss.ni_bssid));
+ }
+ tp = vap->iv_txparms + cc->ic_bsschan.chan_to_mode;
+ if (tp->ucastrate == IEEE80211_FIXED_RATE_NONE) {
+ cc->iv_bss.fixed_rate_none = 1;
+ }
+ }
+ cc->ic_opmode = ic->ic_opmode;
+ cc->ic_flags = ic->ic_flags;
+ cc->ic_txpowlimit = ic->ic_txpowlimit;
+ cc->ic_curmode = ic->ic_curmode;
+ bcopy(ic->ic_myaddr, cc->ic_myaddr,
+ sizeof(cc->ic_myaddr));
+ }
+ }
sc->sc_flags |= RUM_FLAG_WAIT_COMMAND;
return;
}
@@ -984,54 +1003,14 @@
}
}
-/* quickly determine if a given rate is CCK or OFDM */
-#define RUM_RATE_IS_OFDM(rate) (((rate) >= 12) && ((rate) != 22))
-
-#define RUM_ACK_SIZE 14 /* 10 + 4(FCS) */
-#define RUM_CTS_SIZE 14 /* 10 + 4(FCS) */
-
-static uint16_t
-rum_rxrate(const struct rum_rx_desc *desc)
-{
- if (le32toh(desc->flags) & RT2573_RX_OFDM) {
- /* reverse function of "rum_plcp_signal()" */
- switch (desc->rate) {
- case 0xb:return (12);
- case 0xf:
- return (18);
- case 0xa:
- return (24);
- case 0xe:
- return (36);
- case 0x9:
- return (48);
- case 0xd:
- return (72);
- case 0x8:
- return (96);
- case 0xc:
- return (108);
- }
- } else {
- if (desc->rate == 10)
- return (2);
- if (desc->rate == 20)
- return (4);
- if (desc->rate == 55)
- return (11);
- if (desc->rate == 110)
- return (22);
- }
- return (2); /* should not get here */
-}
-
static void
rum_bulk_read_callback(struct usbd_xfer *xfer)
{
struct rum_softc *sc = xfer->priv_sc;
- struct ieee80211com *ic = &(sc->sc_ic);
- struct ifnet *ifp = ic->ic_ifp;
- struct ieee80211_node *ni = NULL;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211_node *ni;
+
struct mbuf *m = NULL;
uint32_t flags;
uint32_t max_len;
@@ -1092,20 +1071,20 @@
DPRINTF(sc, 0, "real length=%d bytes, rssi=%d\n", m->m_len, rssi);
- if (bpf_peers_present(sc->sc_drvbpf)) {
- struct rum_rx_radiotap_header *tap = &(sc->sc_rxtap.h);
+ if (bpf_peers_present(ifp->if_bpf)) {
+ struct rum_rx_radiotap_header *tap = &(sc->sc_rxtap);
tap->wr_flags = IEEE80211_RADIOTAP_F_FCS;
- tap->wr_rate = rum_rxrate(&sc->sc_rx_desc);
+ tap->wr_rate = ieee80211_plcp2rate(sc->sc_rx_desc.rate,
+ (sc->sc_rx_desc.flags & htole32(RT2573_RX_OFDM)) ?
+ IEEE80211_T_OFDM : IEEE80211_T_CCK);
tap->wr_chan_freq = htole16(ic->ic_curchan->ic_freq);
tap->wr_chan_flags = htole16(ic->ic_curchan->ic_flags);
tap->wr_antenna = sc->sc_rx_ant;
tap->wr_antsignal = rssi;
- bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_rxtap_len, m);
+ bpf_mtap2(ifp->if_bpf, tap, sc->sc_rxtap_len, m);
}
- ni = ieee80211_find_rxnode(ic, (void *)(m->m_data));
-
case USBD_ST_SETUP:
tr_setup:
@@ -1124,11 +1103,17 @@
if (m) {
mtx_unlock(&(sc->sc_mtx));
- /* send the frame to the 802.11 layer */
- ieee80211_input(ic, m, ni, rssi, RT2573_NOISE_FLOOR, 0);
-
- mtx_lock(&(sc->sc_mtx));
-
+ ni = ieee80211_find_rxnode(ic, mtod(m, struct ieee80211_frame_min *));
+ if (ni != NULL) {
+ if (ieee80211_input(ni, m, rssi, RT2573_NOISE_FLOOR, 0)) {
+ /* ignore */
+ }
+ ieee80211_free_node(ni);
+ } else {
+ if (ieee80211_input_all(ic, m, rssi, RT2573_NOISE_FLOOR, 0)) {
+ /* ignore */
+ }
+ }
/* node is no longer needed */
ieee80211_free_node(ni);
}
@@ -1159,76 +1144,14 @@
return;
}
-/*
- * Return the expected ack rate for a frame transmitted at rate "rate".
- */
-static uint16_t
-rum_ack_rate(const struct ieee80211com *ic, uint16_t rate)
-{
- switch (rate) {
- /* CCK rates */
- case 2:
- return (2);
- case 4:
- case 11:
- case 22:
- return (ic->ic_curmode == IEEE80211_MODE_11B) ? 4 : rate;
-
- /* OFDM rates */
- case 12:
- case 18:
- return (12);
- case 24:
- case 36:
- return (24);
- case 48:
- case 72:
- case 96:
- case 108:
- return (48);
- }
-
- /* default to 1Mbps */
- return (2);
-}
-
-/*
- * Compute the duration (in us) needed to transmit "len" bytes at rate "rate".
- * The function automatically determines the operating mode depending on the
- * given rate. "flags" indicates whether short preamble is in use or not.
- */
-static uint16_t
-rum_txtime(struct rum_softc *sc, uint16_t len, uint16_t rate, uint32_t flags)
-{
- uint16_t txtime;
-
- if (rate < 2) {
- DPRINTF(sc, 0, "rate < 2!\n");
-
- /* avoid division by zero */
- rate = 2;
- }
- if (RUM_RATE_IS_OFDM(rate)) {
- /* IEEE Std 802.11a-1999, pp. 37 */
- txtime = (8 + (4 * len) + 3 + rate - 1) / rate;
- txtime = 16 + 4 + (4 * txtime) + 6;
- } else {
- /* IEEE Std 802.11b-1999, pp. 28 */
- txtime = ((16 * len) + rate - 1) / rate;
- if ((rate != 2) && (flags & IEEE80211_F_SHPREAMBLE))
- txtime += 72 + 24;
- else
- txtime += 144 + 48;
- }
- return (txtime);
-}
-
static uint8_t
rum_plcp_signal(uint16_t rate)
{
+ ; /* indent fix */
switch (rate) {
- /* CCK rates (returned values are device-dependent) */
- case 2:return (0x0);
+ /* CCK rates (NB: not IEEE std, device-specific) */
+ case 2:
+ return (0x0);
case 4:
return (0x1);
case 11:
@@ -1254,26 +1177,70 @@
case 108:
return (0xc);
- /* unsupported rates (should not get there) */
+ /* XXX unsupported/unknown rate */
default:
return (0xff);
}
}
+/*
+ * We assume that "m->m_pkthdr.rcvif" is pointing to the "ni" that
+ * should be freed, when "rum_setup_desc_and_tx" is called.
+ */
+
static void
-rum_setup_tx_desc(struct rum_softc *sc, uint32_t flags, uint16_t xflags,
- uint16_t len, uint16_t rate)
+rum_setup_desc_and_tx(struct rum_softc *sc, struct mbuf *m, uint32_t flags,
+ uint16_t xflags, uint16_t rate)
{
- struct ieee80211com *ic = &(sc->sc_ic);
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
+ struct mbuf *mm;
+ enum ieee80211_phytype phytype;
uint16_t plcp_length;
+ uint16_t len;
uint8_t remainder;
+ uint8_t is_beacon;
+
+ if (xflags & RT2573_TX_BEACON) {
+ xflags &= ~RT2573_TX_BEACON;
+ is_beacon = 1;
+ } else {
+ is_beacon = 0;
+ }
+ if (sc->sc_tx_queue.ifq_len >= IFQ_MAXLEN) {
+ /* free packet */
+ rum_tx_freem(m);
+ ifp->if_oerrors++;
+ return;
+ }
+ if (!((sc->sc_flags & RUM_FLAG_LL_READY) &&
+ (sc->sc_flags & RUM_FLAG_HL_READY))) {
+ /* free packet */
+ rum_tx_freem(m);
+ ifp->if_oerrors++;
+ return;
+ }
if (rate < 2) {
DPRINTF(sc, 0, "rate < 2!\n");
/* avoid division by zero */
rate = 2;
}
+ ic->ic_lastdata = ticks;
+ if (bpf_peers_present(ifp->if_bpf)) {
+ struct rum_tx_radiotap_header *tap = &(sc->sc_txtap);
+
+ tap->wt_flags = 0;
+ tap->wt_rate = rate;
+ tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq);
+ tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags);
+ tap->wt_antenna = sc->sc_tx_ant;
+
+ bpf_mtap2(ifp->if_bpf, tap, sc->sc_txtap_len, m);
+ }
+ len = m->m_pkthdr.len;
+
flags |= RT2573_TX_VALID;
flags |= (len << 16);
@@ -1289,7 +1256,9 @@
len += IEEE80211_CRC_LEN;
- if (RUM_RATE_IS_OFDM(rate)) {
+ phytype = ieee80211_rate2phytype(sc->sc_rates, rate);
+
+ if (phytype == IEEE80211_T_OFDM) {
sc->sc_tx_desc.flags |= htole32(RT2573_TX_OFDM);
plcp_length = (len & 0xfff);
@@ -1311,150 +1280,54 @@
sc->sc_tx_desc.plcp_signal |= 0x08;
}
}
- return;
-}
-/*------------------------------------------------------------------------*
- * rum_bulk_write_callback_sub
- *
- * Returns:
- * 0: Success
- * Else: Failure
- *------------------------------------------------------------------------*/
-static uint8_t
-rum_bulk_write_callback_sub(struct usbd_xfer *xfer, struct mbuf *m,
- struct ieee80211_node *ni, uint32_t flags, uint16_t rate)
-{
- struct rum_softc *sc = xfer->priv_sc;
- struct ieee80211com *ic = &(sc->sc_ic);
- struct ieee80211_frame *wh;
- struct ieee80211_key *k;
- uint32_t temp_len;
- uint16_t dur;
- uint8_t align;
- uint8_t type;
- uint8_t sub_type;
-
- wh = mtod(m, struct ieee80211_frame *);
-
- if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
- k = ieee80211_crypto_encap(ic, ni, m);
- if (k == NULL) {
- return (1);
- }
- /*
- * packet header may have moved, reset our
- * local pointer
- */
- wh = mtod(m, struct ieee80211_frame *);
+ if (sizeof(sc->sc_tx_desc) > MHLEN) {
+ DPRINTF(sc, 0, "No room for header structure!\n");
+ rum_tx_freem(m);
+ return;
+ }
+ mm = m_gethdr(M_NOWAIT, MT_DATA);
+ if (mm == NULL) {
+ DPRINTF(sc, 0, "Could not allocate header mbuf!\n");
+ rum_tx_freem(m);
+ return;
}
- if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
+ bcopy(&(sc->sc_tx_desc), mm->m_data, sizeof(sc->sc_tx_desc));
+ mm->m_len = sizeof(sc->sc_tx_desc);
+ mm->m_next = m;
+ mm->m_pkthdr.len = mm->m_len + m->m_pkthdr.len;
+ mm->m_pkthdr.rcvif = NULL;
- type = (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK);
- sub_type = (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
+ if (is_beacon) {
- if (type == IEEE80211_FC0_TYPE_DATA) {
-
- flags |= (RT2573_TX_NEED_ACK |
- RT2573_TX_MORE_FRAG);
-
- dur = rum_txtime(sc, RUM_ACK_SIZE, rum_ack_rate(ic, rate),
- ic->ic_flags) + sc->sc_sifs;
-
- USETW(wh->i_dur, dur);
-
- } else if ((type == IEEE80211_FC0_TYPE_MGT) &&
- (sub_type == IEEE80211_FC0_SUBTYPE_BEACON)) {
-
- /* do nothing */
-
- } else {
-
- flags |= RT2573_TX_NEED_ACK;
-
- dur = rum_txtime(sc, RUM_ACK_SIZE, rum_ack_rate(ic, rate),
- ic->ic_flags) + sc->sc_sifs;
-
- USETW(wh->i_dur, dur);
-
- /*
- * tell hardware to add timestamp for probe
- * responses
- */
- if ((type == IEEE80211_FC0_TYPE_MGT) &&
- (sub_type == IEEE80211_FC0_SUBTYPE_PROBE_RESP)) {
- flags |= RT2573_TX_TIMESTAMP;
- }
+ if (mm->m_pkthdr.len > sizeof(sc->sc_beacon_buf)) {
+ DPRINTF(sc, -1, "Truncating beacon"
+ ", %u bytes!\n", mm->m_pkthdr.len);
+ mm->m_pkthdr.len = sizeof(sc->sc_beacon_buf);
}
- }
- ic->ic_lastdata = ticks;
+ m_copydata(mm, 0, mm->m_pkthdr.len, sc->sc_beacon_buf);
- if (m->m_pkthdr.len > MCLBYTES) {
- DPRINTF(sc, 0, "data overflow, %u bytes\n",
- m->m_pkthdr.len);
- m->m_pkthdr.len = MCLBYTES;
+ /* copy the first 24 bytes of Tx descriptor into NIC memory */
+ rum_cfg_write_multi(sc, RT2573_HW_BEACON_BASE0,
+ sc->sc_beacon_buf, mm->m_pkthdr.len);
+ rum_tx_freem(mm);
+ return;
}
- if (bpf_peers_present(sc->sc_drvbpf)) {
- struct rum_tx_radiotap_header *tap = &(sc->sc_txtap.h);
+ /* start write transfer, if not started */
+ _IF_ENQUEUE(&(sc->sc_tx_queue), mm);
- tap->wt_flags = 0;
- tap->wt_rate = rate;
- tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq);
- tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags);
- tap->wt_antenna = sc->sc_tx_ant;
-
- bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_txtap_len, m);
- }
- rum_setup_tx_desc(sc, flags, 0, m->m_pkthdr.len, rate);
-
- usbd_copy_in(xfer->frbuffers, 0, &(sc->sc_tx_desc),
- RT2573_TX_DESC_SIZE);
-
- usbd_m_copy_in(xfer->frbuffers, RT2573_TX_DESC_SIZE,
- m, 0, m->m_pkthdr.len);
-
- /* compute transfer length */
- temp_len = (RT2573_TX_DESC_SIZE + m->m_pkthdr.len);
-
- /* make transfer length 32-bit aligned */
- if (temp_len & 3) {
- align = (-(temp_len)) & 3;
- /* zero the extra byte(s) */
- usbd_bzero(xfer->frbuffers, temp_len, align);
- temp_len += align;
- }
- /* check if we need to add four extra bytes */
- if ((temp_len % 64) == 0) {
- /* zero the extra bytes */
- usbd_bzero(xfer->frbuffers, temp_len, 4);
- temp_len += 4;
- }
- DPRINTF(sc, 10, "sending frame len=%u rate=%u xferlen=%u\n",
- m->m_pkthdr.len, rate, temp_len);
-
- if (m->m_flags & M_TXCB) {
- ieee80211_process_callback(ni, m, 0);
- }
- m_freem(m);
-
- if (ni) {
- ieee80211_free_node(ni);
- }
- xfer->frlengths[0] = temp_len;
- usbd_start_hardware(xfer);
- return (0);
+ usbd_transfer_start(sc->sc_xfer[0]);
+ return;
}
static void
rum_bulk_write_callback(struct usbd_xfer *xfer)
{
struct rum_softc *sc = xfer->priv_sc;
- struct ieee80211com *ic = &(sc->sc_ic);
- struct ifnet *ifp = sc->sc_ic.ic_ifp;
- struct ieee80211_node *ni = NULL;
- struct ether_header *eh;
- struct mbuf *m = NULL;
- uint16_t rate;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct mbuf *m;
+ uint16_t temp_len;
+ uint8_t align;
switch (USBD_GET_STATE(xfer)) {
case USBD_ST_TRANSFERRED:
@@ -1463,101 +1336,58 @@
ifp->if_opackets++;
case USBD_ST_SETUP:
-tr_setup:
if (sc->sc_flags & RUM_FLAG_WRITE_STALL) {
usbd_transfer_start(sc->sc_xfer[2]);
- goto done;
+ break;
}
if (sc->sc_flags & RUM_FLAG_WAIT_COMMAND) {
/*
* don't send anything while a command is pending !
*/
- goto done;
+ break;
}
- IF_DEQUEUE(&(ic->ic_mgtq), m);
+ rum_fill_write_queue(sc);
- if (m) {
-
- ni = (void *)(m->m_pkthdr.rcvif);
- m->m_pkthdr.rcvif = NULL;
-
- if (bpf_peers_present(ic->ic_rawbpf)) {
- bpf_mtap(ic->ic_rawbpf, m);
- }
- rate = (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ? 12 : 2);
-
- if (rum_bulk_write_callback_sub(xfer, m, ni, 0, rate)) {
- goto error;
- }
- goto done;
- }
- if (ic->ic_state != IEEE80211_S_RUN) {
- goto done;
- }
- IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
+ _IF_DEQUEUE(&(sc->sc_tx_queue), m);
if (m) {
- /*
- * Cancel any background scan.
- */
- if (ic->ic_flags & IEEE80211_F_SCAN) {
- ieee80211_cancel_scan(ic);
+ if (m->m_pkthdr.len > (MCLBYTES + RT2573_TX_DESC_SIZE)) {
+ DPRINTF(sc, -1, "data overflow, %u bytes\n",
+ m->m_pkthdr.len);
+ m->m_pkthdr.len = (MCLBYTES + RT2573_TX_DESC_SIZE);
}
- if (m->m_len < sizeof(struct ether_header)) {
- m = m_pullup(m, sizeof(struct ether_header));
+ usbd_m_copy_in(xfer->frbuffers, 0,
+ m, 0, m->m_pkthdr.len);
- if (m == NULL) {
- goto error;
- }
- }
- eh = mtod(m, struct ether_header *);
- ni = ieee80211_find_txnode(ic, eh->ether_dhost);
- if (ni == NULL) {
- goto error;
- }
- BPF_MTAP(ifp, m);
+ /* compute transfer length */
+ temp_len = m->m_pkthdr.len;
- m = ieee80211_encap(ic, m, ni);
+ /* make transfer length 32-bit aligned */
+ align = (-(temp_len)) & 3;
- if (m == NULL) {
- goto error;
+ /* check if we need to add four extra bytes */
+ if (((temp_len + align) % 64) == 0) {
+ align += 4;
}
- if (bpf_peers_present(ic->ic_rawbpf)) {
- bpf_mtap(ic->ic_rawbpf, m);
+ /* check if we need to align length */
+ if (align != 0) {
+ /* zero the extra bytes */
+ usbd_bzero(xfer->frbuffers, temp_len, align);
+ temp_len += align;
}
- if (ic->ic_fixed_rate != IEEE80211_FIXED_RATE_NONE)
- rate = ic->ic_fixed_rate;
- else
- rate = ni->ni_rates.rs_rates[ni->ni_txrate];
+ DPRINTF(sc, 10, "sending frame len=%u ferlen=%u\n",
+ m->m_pkthdr.len, temp_len);
- rate &= IEEE80211_RATE_VAL;
+ xfer->frlengths[0] = temp_len;
+ usbd_start_hardware(xfer);
- if (rum_bulk_write_callback_sub(xfer, m, ni, 0, rate)) {
- goto error;
- }
- goto done;
- }
-done:
- return;
+ /* free mbuf and node */
+ rum_tx_freem(m);
-error:
- if (m) {
-
- if (m->m_flags & M_TXCB) {
- ieee80211_process_callback(ni, m, 0);
- }
- m_freem(m);
- m = NULL;
}
- if (ni) {
- ieee80211_free_node(ni);
- ni = NULL;
- }
- ifp->if_oerrors++;
+ break;
- goto tr_setup;
-
default: /* Error */
DPRINTF(sc, 10, "transfer error, %s\n",
usbd_errstr(xfer->error));
@@ -1568,10 +1398,9 @@
usbd_transfer_start(sc->sc_xfer[2]);
}
ifp->if_oerrors++;
- return;
-
-
+ break;
}
+ return;
}
static void
@@ -1595,12 +1424,7 @@
mtx_assert(&(sc->sc_mtx), MA_OWNED);
- if ((sc->sc_amrr_timer) &&
- (--sc->sc_amrr_timer == 0)) {
-
- /* restart timeout */
- sc->sc_amrr_timer = 1;
-
+ if (sc->sc_amrr_timer) {
usbd_config_td_queue_command
(&(sc->sc_config_td), NULL,
&rum_cfg_amrr_timeout, 0, 0);
@@ -1631,14 +1455,13 @@
rum_ioctl_cb(struct ifnet *ifp, u_long cmd, caddr_t data)
{
struct rum_softc *sc = ifp->if_softc;
- struct ieee80211com *ic = &(sc->sc_ic);
+ struct ieee80211com *ic = ifp->if_l2com;
int error = 0;
- mtx_lock(&(sc->sc_mtx));
-
switch (cmd) {
case SIOCSIFFLAGS:
+ mtx_lock(&(sc->sc_mtx));
if (ifp->if_flags & IFF_UP) {
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
usbd_config_td_queue_command
@@ -1656,30 +1479,20 @@
&rum_cfg_stop, 0, 0);
}
}
+ mtx_unlock(&(sc->sc_mtx));
+ break;
+
>>> TRUNCATED FOR MAIL (1000 lines) <<<
More information about the p4-projects
mailing list