From owner-p4-projects@FreeBSD.ORG Sat Jun 7 21:37:20 2008 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 0F520106567E; Sat, 7 Jun 2008 21:37:20 +0000 (UTC) Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id C47E31065675 for ; Sat, 7 Jun 2008 21:37:19 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id C6AE68FC0C for ; Sat, 7 Jun 2008 21:37:19 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.1/8.14.1) with ESMTP id m57LbJHN074803 for ; Sat, 7 Jun 2008 21:37:19 GMT (envelope-from hselasky@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.1/8.14.1/Submit) id m57LbJAr074801 for perforce@freebsd.org; Sat, 7 Jun 2008 21:37:19 GMT (envelope-from hselasky@FreeBSD.org) Date: Sat, 7 Jun 2008 21:37:19 GMT Message-Id: <200806072137.m57LbJAr074801@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to hselasky@FreeBSD.org using -f From: Hans Petter Selasky To: Perforce Change Reviews Cc: Subject: PERFORCE change 143088 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 07 Jun 2008 21:37:20 -0000 http://perforce.freebsd.org/chv.cgi?CH=143088 Change 143088 by hselasky@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 * - * Copyright (c) 2006 + * Copyright (c) 2006, 2008 * Hans Petter Selasky * * 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 -__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 #include #include +#include #include #include @@ -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) <<<