PERFORCE change 143088 for review
Hans Petter Selasky
hselasky at FreeBSD.org
Sat Jun 7 21:37:20 UTC 2008
http://perforce.freebsd.org/chv.cgi?CH=143088
Change 143088 by hselasky at hselasky_laptop001 on 2008/06/07 21:36:25
Integrate URAL 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_ural.c#54 edit
.. //depot/projects/usb/src/sys/dev/usb/if_uralvar.h#21 edit
Differences ...
==== //depot/projects/usb/src/sys/dev/usb/if_ural.c#54 (text+ko) ====
@@ -2,7 +2,7 @@
* Copyright (c) 2005, 2006
* Damien Bergamini <damien.bergamini at free.fr>
*
- * Copyright (c) 2006
+ * Copyright (c) 2006, 2008
* Hans Petter Selasky <hselasky at freebsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
@@ -17,16 +17,16 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
+ */
+
+/*
*
* NOTE: all function names beginning like "ural_cfg_" can only
* be called from within the config thread function !
- *
- * TODO: add support for raw transmit trough BPF. See:
- * http://www.freebsd.org/cgi/cvsweb.cgi/src/sys/dev/usb/if_ural.c.diff?r1=1.41&r2=1.42
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/dev/usb/if_ural.c,v 1.70 2007/11/06 07:30:12 kevlo Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/usb/if_ural.c,v 1.73 2008/05/12 00:32:52 sam Exp $");
/*-
* Ralink Technology RT2500USB chipset driver
@@ -54,6 +54,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>
@@ -108,19 +109,16 @@
static usbd_config_td_command_t ural_cfg_scan_start;
static usbd_config_td_command_t ural_cfg_scan_end;
static usbd_config_td_command_t ural_cfg_set_chan;
-static usbd_config_td_command_t ural_cfg_pre_set_run;
-static usbd_config_td_command_t ural_cfg_set_run;
static usbd_config_td_command_t ural_cfg_enable_tsf_sync;
-static usbd_config_td_command_t ural_cfg_disable_tsf_sync;
static usbd_config_td_command_t ural_cfg_update_slot;
static usbd_config_td_command_t ural_cfg_set_txpreamble;
-static usbd_config_td_command_t ural_cfg_set_basicrates;
static usbd_config_td_command_t ural_cfg_update_promisc;
static usbd_config_td_command_t ural_cfg_pre_init;
static usbd_config_td_command_t ural_cfg_init;
static usbd_config_td_command_t ural_cfg_pre_stop;
static usbd_config_td_command_t ural_cfg_stop;
static usbd_config_td_command_t ural_cfg_amrr_timeout;
+static usbd_config_td_command_t ural_cfg_newstate;
static void ural_cfg_do_request(struct ural_softc *sc, usb_device_request_t *req, void *data);
static void ural_cfg_set_testmode(struct ural_softc *sc);
@@ -134,23 +132,15 @@
static void ural_cfg_rf_write(struct ural_softc *sc, uint8_t reg, uint32_t val);
static void ural_end_of_commands(struct ural_softc *sc);
static const char *ural_get_rf(int rev);
-static int ural_rxrate(struct ural_rx_desc *desc);
-static uint16_t ural_ack_rate(struct ieee80211com *ic, uint16_t rate);
-static uint16_t ural_txtime(struct ural_softc *sc, uint16_t len, uint16_t rate, uint32_t flags);
-static uint8_t ural_plcp_signal(uint16_t rate);
-static void ural_setup_tx_desc(struct ural_softc *sc, uint32_t flags, uint16_t len, uint16_t rate);
static void ural_watchdog(void *arg);
static void ural_init_cb(void *arg);
static int ural_ioctl_cb(struct ifnet *ifp, u_long cmd, caddr_t data);
static void ural_start_cb(struct ifnet *ifp);
-static int ural_media_change_cb(struct ifnet *ifp);
-static int ural_reset_cb(struct ifnet *ifp);
-static int ural_newstate_cb(struct ieee80211com *ic, enum ieee80211_state nstate, int arg);
+static int ural_newstate_cb(struct ieee80211vap *ic, enum ieee80211_state nstate, int arg);
static void ural_std_command(struct ieee80211com *ic, usbd_config_td_command_t *func);
static void ural_scan_start_cb(struct ieee80211com *);
static void ural_scan_end_cb(struct ieee80211com *);
static void ural_set_channel_cb(struct ieee80211com *);
-static void ural_cfg_tx_bcn(struct ural_softc *sc);
static void ural_cfg_disable_rf_tune(struct ural_softc *sc);
static void ural_cfg_set_bssid(struct ural_softc *sc, uint8_t *bssid);
static void ural_cfg_set_macaddr(struct ural_softc *sc, uint8_t *addr);
@@ -159,6 +149,23 @@
static void ural_cfg_read_eeprom(struct ural_softc *sc);
static uint8_t ural_cfg_bbp_init(struct ural_softc *sc);
static void ural_cfg_amrr_start(struct ural_softc *sc);
+static struct ieee80211vap *ural_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 ural_vap_delete(struct ieee80211vap *);
+static struct ieee80211_node *ural_node_alloc(struct ieee80211_node_table *);
+static void ural_newassoc(struct ieee80211_node *, int);
+static void ural_cfg_disable_tsf_sync(struct ural_softc *sc);
+static void ural_cfg_set_run(struct ural_softc *sc, struct ural_config_copy *cc);
+static void ural_fill_write_queue(struct ural_softc *sc);
+static void ural_tx_clean_queue(struct ural_softc *sc);
+static void ural_tx_freem(struct mbuf *m);
+static void ural_tx_mgt(struct ural_softc *sc, struct mbuf *m, struct ieee80211_node *ni);
+static struct ieee80211vap *ural_get_vap(struct ural_softc *sc);
+static void ural_tx_bcn(struct ural_softc *sc);
+static void ural_tx_data(struct ural_softc *sc, struct mbuf *m, struct ieee80211_node *ni);
+static void ural_tx_prot(struct ural_softc *sc, const struct mbuf *m, struct ieee80211_node *ni, uint8_t prot, uint16_t rate);
+static void ural_tx_raw(struct ural_softc *sc, struct mbuf *m, struct ieee80211_node *ni, const struct ieee80211_bpf_params *params);
+static int ural_raw_xmit_cb(struct ieee80211_node *ni, struct mbuf *m, const struct ieee80211_bpf_params *params);
+static void ural_setup_desc_and_tx(struct ural_softc *sc, struct mbuf *m, uint32_t flags, uint16_t rate);
/* various supported device vendors/products */
static const struct usb_devno ural_devs[] = {
@@ -522,8 +529,8 @@
ural_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));
@@ -778,25 +785,20 @@
ural_cfg_first_time_setup(struct ural_softc *sc,
struct ural_config_copy *cc, uint16_t refcount)
{
- struct ieee80211com *ic = &(sc->sc_ic);
+ struct ieee80211com *ic;
struct ifnet *ifp;
- uint32_t bands;
+ 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(RAL_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(RAL_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(RAL_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(RAL_TX_RADIOTAP_PRESENT);
- /* setup AMRR */
- ieee80211_amrr_init(&(sc->sc_amrr), ic,
- IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD,
- IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD);
-
/* retrieve RT2570 rev. no */
sc->sc_asic_rev = ural_cfg_read(sc, RAL_MAC_CSR0);
@@ -808,7 +810,7 @@
mtx_unlock(&(sc->sc_mtx));
- ifp = if_alloc(IFT_ETHER);
+ ifp = if_alloc(IFT_IEEE80211);
mtx_lock(&(sc->sc_mtx));
@@ -818,6 +820,7 @@
}
sc->sc_evilhack = ifp;
sc->sc_ifp = ifp;
+ ic = ifp->if_l2com;
ifp->if_softc = sc;
if_initname(ifp, "ural", sc->sc_unit);
@@ -832,12 +835,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 */
@@ -854,7 +856,7 @@
if (sc->sc_rf_rev == RAL_RF_5222) {
setbit(&bands, IEEE80211_MODE_11A);
}
- ieee80211_init_channels(ic, 0, CTRY_DEFAULT, bands, 0, 1);
+ ieee80211_init_channels(ic, NULL, &bands);
mtx_unlock(&(sc->sc_mtx));
@@ -862,28 +864,22 @@
mtx_lock(&(sc->sc_mtx));
- /* enable SW bmiss handling in sta mode */
-#if (defined(IEEE80211_FEXT_SWBMISS) || (__FreeBSD_version >= 700022))
- ic->ic_flags_ext |= IEEE80211_FEXT_SWBMISS;
-#endif
+ ic->ic_newassoc = &ural_newassoc;
+ ic->ic_raw_xmit = &ural_raw_xmit_cb;
+ ic->ic_node_alloc = &ural_node_alloc;
- /* override state transition machine */
- sc->sc_newstate = ic->ic_newstate;
- ic->ic_newstate = &ural_newstate_cb;
-#if 0
- ic->ic_raw_xmit = &ural_raw_xmit_cb;
-#endif
- ic->ic_reset = &ural_reset_cb;
ic->ic_scan_start = &ural_scan_start_cb;
ic->ic_scan_end = &ural_scan_end_cb;
ic->ic_set_channel = &ural_set_channel_cb;
+ ic->ic_vap_create = &ural_vap_create;
+ ic->ic_vap_delete = &ural_vap_delete;
+ sc->sc_rates = ieee80211_get_ratetable(ic->ic_curchan);
+
mtx_unlock(&(sc->sc_mtx));
- ieee80211_media_init(ic, ural_media_change_cb, ieee80211_media_status);
-
- bpfattach2(ifp, DLT_IEEE802_11_RADIO,
- sizeof(struct ieee80211_frame) + 64, &sc->sc_drvbpf);
+ bpfattach(ifp, DLT_IEEE802_11_RADIO,
+ sizeof(struct ieee80211_frame) + sizeof(sc->sc_txtap));
if (bootverbose) {
ieee80211_announce(ic);
@@ -898,10 +894,31 @@
{
sc->sc_flags &= ~URAL_FLAG_WAIT_COMMAND;
- if ((sc->sc_flags & URAL_FLAG_LL_READY) &&
- (sc->sc_flags & URAL_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
+ural_config_copy_chan(struct ural_config_copy_chan *cc, 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;
}
@@ -910,45 +927,46 @@
ural_config_copy(struct ural_softc *sc,
struct ural_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;
- }
- }
- 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) {
+ ural_config_copy_chan(&cc->ic_curchan, ic->ic_curchan);
+ ural_config_copy_chan(&cc->ic_bsschan, 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 |= URAL_FLAG_WAIT_COMMAND;
return;
}
@@ -975,54 +993,6 @@
}
}
-/* quickly determine if a given rate is CCK or OFDM */
-#define RAL_RATE_IS_OFDM(rate) (((rate) >= 12) && ((rate) != 22))
-
-#define RAL_ACK_SIZE 14 /* 10 + 4(FCS) */
-#define RAL_CTS_SIZE 14 /* 10 + 4(FCS) */
-
-#define RAL_SIFS 10 /* us */
-
-#define RAL_RXTX_TURNAROUND 5 /* us */
-
-/*------------------------------------------------------------------------*
- * ural_rxrate - this function is only used by the Rx radiotap code
- *------------------------------------------------------------------------*/
-static int
-ural_rxrate(struct ural_rx_desc *desc)
-{
- if (le32toh(desc->flags) & RAL_RX_OFDM) {
- /* reverse function of ural_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 there */
-}
-
/*------------------------------------------------------------------------*
* ural_bulk_read_callback - data read "thread"
*------------------------------------------------------------------------*/
@@ -1030,9 +1000,9 @@
ural_bulk_read_callback(struct usbd_xfer *xfer)
{
struct ural_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;
@@ -1098,23 +1068,24 @@
rssi = URAL_RSSI(sc->sc_rx_desc.rssi);
- if (bpf_peers_present(sc->sc_drvbpf)) {
- struct ural_rx_radiotap_header *tap = &(sc->sc_rxtap.h);
+ if (bpf_peers_present(ifp->if_bpf)) {
+ struct ural_rx_radiotap_header *tap = &(sc->sc_rxtap);
tap->wr_flags = IEEE80211_RADIOTAP_F_FCS;
- tap->wr_rate = ural_rxrate(&sc->sc_rx_desc);
+ tap->wr_rate = ieee80211_plcp2rate(sc->sc_rx_desc.rate,
+ (sc->sc_rx_desc.flags & htole32(RAL_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);
}
/* Strip trailing 802.11 MAC FCS. */
m_adj(m, -IEEE80211_CRC_LEN);
- ni = ieee80211_find_rxnode(ic, (void *)(m->m_data));
-
case USBD_ST_SETUP:
tr_setup:
@@ -1133,13 +1104,20 @@
if (m) {
mtx_unlock(&(sc->sc_mtx));
- /* send the frame to the 802.11 layer */
- ieee80211_input(ic, m, ni, rssi, RAL_NOISE_FLOOR, 0);
+ ni = ieee80211_find_rxnode(ic, (void *)(m->m_data));
+
+ if (ni) {
+ /* send the frame to the 802.11 layer */
+ ieee80211_input(ni, m, rssi, RAL_NOISE_FLOOR, 0);
+
+ /* node is no longer needed */
+ ieee80211_free_node(ni);
+ } else {
+ /* broadcast */
+ ieee80211_input_all(ic, m, rssi, RAL_NOISE_FLOOR, 0);
+ }
mtx_lock(&(sc->sc_mtx));
-
- /* node is no longer needed */
- ieee80211_free_node(ni);
}
return;
@@ -1168,80 +1146,14 @@
return;
}
-/*------------------------------------------------------------------------*
- * ural_ack_rate - return the expected ack rate for a frame
- * transmitted at rate "rate".
- *
- * XXX: this should depend on the destination node basic rate set.
- *------------------------------------------------------------------------*/
-static uint16_t
-ural_ack_rate(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);
-}
-
-/*------------------------------------------------------------------------*
- * ural_txtime - 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
-ural_txtime(struct ural_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 (RAL_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
ural_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:
@@ -1267,26 +1179,62 @@
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 "ural_setup_desc_and_tx" is called.
+ */
static void
-ural_setup_tx_desc(struct ural_softc *sc, uint32_t flags, uint16_t len,
- uint16_t rate)
+ural_setup_desc_and_tx(struct ural_softc *sc, struct mbuf *m,
+ uint32_t flags, 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;
+ if (sc->sc_tx_queue.ifq_len >= IFQ_MAXLEN) {
+ /* free packet */
+ ural_tx_freem(m);
+ ifp->if_oerrors++;
+ return;
+ }
+ if (!((sc->sc_flags & URAL_FLAG_LL_READY) &&
+ (sc->sc_flags & URAL_FLAG_HL_READY))) {
+ /* free packet */
+ ural_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 ural_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;
+
sc->sc_tx_desc.flags = htole32(flags);
sc->sc_tx_desc.flags |= htole32(RAL_TX_NEWSEQ);
sc->sc_tx_desc.flags |= htole32(len << 16);
@@ -1302,7 +1250,9 @@
len += IEEE80211_CRC_LEN;
- if (RAL_RATE_IS_OFDM(rate)) {
+ phytype = ieee80211_rate2phytype(sc->sc_rates, rate);
+
+ if (phytype == IEEE80211_T_OFDM) {
sc->sc_tx_desc.flags |= htole32(RAL_TX_OFDM);
plcp_length = len & 0xfff;
@@ -1328,148 +1278,39 @@
sc->sc_tx_desc.iv = 0;
sc->sc_tx_desc.eiv = 0;
- return;
-}
-/*------------------------------------------------------------------------*
- * ural_bulk_write_callback - data write "thread"
- *
- * Returns:
- * 0: Success
- * Else: Error
- *------------------------------------------------------------------------*/
-static uint8_t
-ural_bulk_write_callback_sub(struct usbd_xfer *xfer, struct mbuf *m,
- struct ieee80211_node *ni, uint32_t flags, uint16_t rate)
-{
- struct ural_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 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");
+ ural_tx_freem(m);
+ return;
}
- if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
-
- type = (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK);
- sub_type = (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
-
- if (type == IEEE80211_FC0_TYPE_DATA) {
-
- flags |= RAL_TX_ACK;
- flags |= RAL_TX_RETRY(7);
-
- dur = ural_txtime(sc, RAL_ACK_SIZE, ural_ack_rate(ic, rate),
- ic->ic_flags) + RAL_SIFS;
- USETW(wh->i_dur, dur);
-
- } else if ((type == IEEE80211_FC0_TYPE_MGT) &&
- (sub_type == IEEE80211_FC0_SUBTYPE_BEACON)) {
-
- /* do nothing */
-
- } else {
-
- flags |= RAL_TX_ACK;
-
- dur = ural_txtime
- (sc, RAL_ACK_SIZE, rate, ic->ic_flags) + RAL_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 |= RAL_TX_TIMESTAMP;
- }
- }
+ mm = m_gethdr(M_NOWAIT, MT_DATA);
+ if (mm == NULL) {
+ DPRINTF(sc, 0, "Could not allocate header mbuf!\n");
+ ural_tx_freem(m);
+ return;
}
- ic->ic_lastdata = ticks;
+ bcopy(&(sc->sc_tx_desc), mm->m_data, sizeof(sc->sc_tx_desc));
+ mm->m_len = sizeof(sc->sc_tx_desc);
- if (m->m_pkthdr.len > RAL_FRAME_SIZE) {
- DPRINTF(sc, 0, "data overflow, %u bytes\n",
- m->m_pkthdr.len);
- m->m_pkthdr.len = RAL_FRAME_SIZE;
- }
- if (bpf_peers_present(sc->sc_drvbpf)) {
- struct ural_tx_radiotap_header *tap = &(sc->sc_txtap.h);
+ mm->m_next = m;
+ mm->m_pkthdr.len = mm->m_len + m->m_pkthdr.len;
+ mm->m_pkthdr.rcvif = NULL;
- 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;
+ /* start write transfer, if not started */
+ _IF_ENQUEUE(&(sc->sc_tx_queue), mm);
- bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_txtap_len, m);
- }
- ural_setup_tx_desc(sc, flags, m->m_pkthdr.len, rate);
-
- usbd_copy_in(xfer->frbuffers, 0, &(sc->sc_tx_desc),
- RAL_TX_DESC_SIZE);
-
- usbd_m_copy_in(xfer->frbuffers, RAL_TX_DESC_SIZE,
- m, 0, m->m_pkthdr.len);
-
- /* compute transfer length */
- temp_len = (RAL_TX_DESC_SIZE + m->m_pkthdr.len);
-
- /* make transfer length 16-bit aligned */
- if (temp_len & 1) {
- /* zero the extra byte */
- usbd_bzero(xfer->frbuffers, temp_len, 1);
- temp_len++;
- }
- /* check if we need to add two extra bytes */
- if ((temp_len % 64) == 0) {
- /* zero the extra bytes */
- usbd_bzero(xfer->frbuffers, temp_len, 2);
- temp_len += 2;
- }
- 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);
- }
- xfer->frlengths[0] = temp_len;
-
- m_freem(m);
-
- if (ni) {
- ieee80211_free_node(ni);
- }
- usbd_start_hardware(xfer);
- return (0);
+ usbd_transfer_start(sc->sc_xfer[0]);
+ return;
}
static void
ural_bulk_write_callback(struct usbd_xfer *xfer)
{
struct ural_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;
switch (USBD_GET_STATE(xfer)) {
case USBD_ST_TRANSFERRED:
@@ -1478,123 +1319,57 @@
ifp->if_opackets++;
case USBD_ST_SETUP:
-tr_setup:
if (sc->sc_flags & URAL_FLAG_WRITE_STALL) {
usbd_transfer_start(sc->sc_xfer[2]);
- goto done;
+ break;
}
if (sc->sc_flags & URAL_FLAG_WAIT_COMMAND) {
/*
* don't send anything while a command is pending !
*/
- goto done;
+ break;
}
- if (sc->sc_flags & URAL_FLAG_SEND_BYTE_FRAME) {
- sc->sc_flags &= ~URAL_FLAG_SEND_BYTE_FRAME;
+ ural_fill_write_queue(sc);
- usbd_bzero(xfer->frbuffers, 0, 1);
+ _IF_DEQUEUE(&(sc->sc_tx_queue), m);
- xfer->frlengths[0] = 1; /* bytes */
-
- usbd_start_hardware(xfer);
- goto done;
- }
- if (sc->sc_flags & URAL_FLAG_SEND_BCN_FRAME) {
- sc->sc_flags &= ~URAL_FLAG_SEND_BCN_FRAME;
-
- m = sc->sc_bcn_mbuf;
- sc->sc_bcn_mbuf = NULL;
-
- if (ural_bulk_write_callback_sub
- (xfer, m, NULL, sc->sc_bcn_flags, sc->sc_bcn_rate)) {
- goto error;
- }
- goto done;
- }
- IF_DEQUEUE(&(ic->ic_mgtq), m);
-
if (m) {
- ni = (struct ieee80211_node *)(m->m_pkthdr.rcvif);
- m->m_pkthdr.rcvif = NULL;
-
- if (bpf_peers_present(ic->ic_rawbpf)) {
- bpf_mtap(ic->ic_rawbpf, m);
+ if (m->m_pkthdr.len > (RAL_FRAME_SIZE + RAL_TX_DESC_SIZE)) {
+ DPRINTF(sc, -1, "data overflow, %u bytes\n",
+ m->m_pkthdr.len);
+ m->m_pkthdr.len = (RAL_FRAME_SIZE + RAL_TX_DESC_SIZE);
}
- rate = (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ? 12 : 2);
+ usbd_m_copy_in(xfer->frbuffers, 0,
+ m, 0, m->m_pkthdr.len);
- if (ural_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);
+ /* compute transfer length */
+ temp_len = m->m_pkthdr.len;
- if (m) {
-
- /*
- * Cancel any background scan.
- */
- if (ic->ic_flags & IEEE80211_F_SCAN) {
- ieee80211_cancel_scan(ic);
+ /* make transfer length 16-bit aligned */
+ if (temp_len & 1) {
+ /* zero the extra byte */
+ usbd_bzero(xfer->frbuffers, temp_len, 1);
+ temp_len++;
}
- if (m->m_len < sizeof(struct ether_header)) {
- m = m_pullup(m, sizeof(struct ether_header));
-
- if (m == NULL) {
- goto error;
- }
+ /* check if we need to add two extra bytes */
+ if ((temp_len % 64) == 0) {
+ /* zero the extra bytes */
+ usbd_bzero(xfer->frbuffers, temp_len, 2);
+ temp_len += 2;
}
- eh = mtod(m, struct ether_header *);
- ni = ieee80211_find_txnode(ic, eh->ether_dhost);
- if (ni == NULL) {
- goto error;
- }
- BPF_MTAP(ifp, m);
+ DPRINTF(sc, 10, "sending frame len=%u xferlen=%u\n",
+ m->m_pkthdr.len, temp_len);
- m = ieee80211_encap(ic, m, ni);
+ xfer->frlengths[0] = temp_len;
- if (m == NULL) {
- goto error;
- }
- if (bpf_peers_present(ic->ic_rawbpf)) {
- bpf_mtap(ic->ic_rawbpf, m);
- }
- if (ic->ic_fixed_rate != IEEE80211_FIXED_RATE_NONE)
- rate = ic->ic_fixed_rate;
- else
- rate = ni->ni_rates.rs_rates[ni->ni_txrate];
+ usbd_start_hardware(xfer);
- rate &= IEEE80211_RATE_VAL;
-
- if (ural_bulk_write_callback_sub(xfer, m, ni, 0, rate)) {
- goto error;
- }
- goto done;
+ /* free mbuf and node */
+ ural_tx_freem(m);
}
-done:
- return;
-
-error:
- if (m) {
-
- if (m->m_flags & M_TXCB) {
- ieee80211_process_callback(ni, m, EINVAL);
- }
- 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));
@@ -1605,10 +1380,9 @@
usbd_transfer_start(sc->sc_xfer[2]);
}
ifp->if_oerrors++;
- return;
-
-
+ break;
}
+ return;
}
static void
@@ -1632,12 +1406,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,
&ural_cfg_amrr_timeout, 0, 0);
@@ -1672,14 +1441,12 @@
>>> TRUNCATED FOR MAIL (1000 lines) <<<
More information about the p4-projects
mailing list