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