2011-08-15 22:24:34 +04:00
|
|
|
/* $NetBSD: wi.c,v 1.235 2011/08/15 18:24:34 dyoung Exp $ */
|
2004-07-23 01:31:56 +04:00
|
|
|
|
|
|
|
/*-
|
|
|
|
* Copyright (c) 2004 The NetBSD Foundation, Inc.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* This code is derived from software contributed to The NetBSD Foundation
|
|
|
|
* by Charles M. Hannum.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
|
|
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
|
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
|
|
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
1999-07-15 02:24:07 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Copyright (c) 1997, 1998, 1999
|
|
|
|
* Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
* 3. All advertising materials mentioning features or use of this software
|
|
|
|
* must display the following acknowledgement:
|
|
|
|
* This product includes software developed by Bill Paul.
|
|
|
|
* 4. Neither the name of the author nor the names of any co-contributors
|
|
|
|
* may be used to endorse or promote products derived from this software
|
|
|
|
* without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
|
|
|
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
|
|
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Lucent WaveLAN/IEEE 802.11 PCMCIA driver for NetBSD.
|
|
|
|
*
|
|
|
|
* Original FreeBSD driver written by Bill Paul <wpaul@ctr.columbia.edu>
|
|
|
|
* Electrical Engineering Department
|
|
|
|
* Columbia University, New York City
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The WaveLAN/IEEE adapter is the second generation of the WaveLAN
|
|
|
|
* from Lucent. Unlike the older cards, the new ones are programmed
|
|
|
|
* entirely via a firmware-driven controller called the Hermes.
|
|
|
|
* Unfortunately, Lucent will not release the Hermes programming manual
|
|
|
|
* without an NDA (if at all). What they do release is an API library
|
|
|
|
* called the HCF (Hardware Control Functions) which is supposed to
|
|
|
|
* do the device-specific operations of a device driver for you. The
|
2005-02-27 03:26:58 +03:00
|
|
|
* publically available version of the HCF library (the 'HCF Light') is
|
1999-07-15 02:24:07 +04:00
|
|
|
* a) extremely gross, b) lacks certain features, particularly support
|
|
|
|
* for 802.11 frames, and c) is contaminated by the GNU Public License.
|
|
|
|
*
|
|
|
|
* This driver does not use the HCF or HCF Light at all. Instead, it
|
|
|
|
* programs the Hermes controller directly, using information gleaned
|
|
|
|
* from the HCF Light code and corresponding documentation.
|
|
|
|
*
|
|
|
|
* This driver supports both the PCMCIA and ISA versions of the
|
|
|
|
* WaveLAN/IEEE cards. Note however that the ISA card isn't really
|
|
|
|
* anything of the sort: it's actually a PCMCIA bridge adapter
|
|
|
|
* that fits into an ISA slot, into which a PCMCIA WaveLAN card is
|
|
|
|
* inserted. Consequently, you need to use the pccard support for
|
|
|
|
* both the ISA and PCMCIA adapters.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* FreeBSD driver ported to NetBSD by Bill Sommerfeld in the back of the
|
|
|
|
* Oslo IETF plenary meeting.
|
|
|
|
*/
|
|
|
|
|
2001-11-13 16:14:31 +03:00
|
|
|
#include <sys/cdefs.h>
|
2011-08-15 22:24:34 +04:00
|
|
|
__KERNEL_RCSID(0, "$NetBSD: wi.c,v 1.235 2011/08/15 18:24:34 dyoung Exp $");
|
2001-11-13 16:14:31 +03:00
|
|
|
|
1999-07-15 02:24:07 +04:00
|
|
|
#define WI_HERMES_AUTOINC_WAR /* Work around data write autoinc bug. */
|
|
|
|
#define WI_HERMES_STATS_WAR /* Work around stats counter bug. */
|
2004-07-23 00:34:52 +04:00
|
|
|
#undef WI_HISTOGRAM
|
2004-07-23 01:56:58 +04:00
|
|
|
#undef WI_RING_DEBUG
|
2004-07-22 23:47:24 +04:00
|
|
|
#define STATIC static
|
1999-07-15 02:24:07 +04:00
|
|
|
|
|
|
|
|
|
|
|
#include <sys/param.h>
|
2005-07-16 02:33:29 +04:00
|
|
|
#include <sys/sysctl.h>
|
1999-07-15 02:24:07 +04:00
|
|
|
#include <sys/systm.h>
|
2000-03-23 10:01:25 +03:00
|
|
|
#include <sys/callout.h>
|
1999-07-15 02:24:07 +04:00
|
|
|
#include <sys/device.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <sys/mbuf.h>
|
|
|
|
#include <sys/ioctl.h>
|
|
|
|
#include <sys/kernel.h> /* for hz */
|
2000-02-04 10:48:29 +03:00
|
|
|
#include <sys/proc.h>
|
2006-05-15 01:42:26 +04:00
|
|
|
#include <sys/kauth.h>
|
1999-07-15 02:24:07 +04:00
|
|
|
|
|
|
|
#include <net/if.h>
|
|
|
|
#include <net/if_dl.h>
|
2003-04-08 08:31:23 +04:00
|
|
|
#include <net/if_llc.h>
|
1999-07-15 02:24:07 +04:00
|
|
|
#include <net/if_media.h>
|
|
|
|
#include <net/if_ether.h>
|
2004-07-03 03:41:34 +04:00
|
|
|
#include <net/route.h>
|
2003-10-13 12:07:21 +04:00
|
|
|
|
2005-06-22 10:14:51 +04:00
|
|
|
#include <net80211/ieee80211_netbsd.h>
|
2003-10-13 12:07:21 +04:00
|
|
|
#include <net80211/ieee80211_var.h>
|
|
|
|
#include <net80211/ieee80211_ioctl.h>
|
2003-11-16 12:02:42 +03:00
|
|
|
#include <net80211/ieee80211_radiotap.h>
|
2003-12-07 08:44:49 +03:00
|
|
|
#include <net80211/ieee80211_rssadapt.h>
|
1999-07-15 02:24:07 +04:00
|
|
|
|
|
|
|
#include <net/bpf.h>
|
|
|
|
#include <net/bpfdesc.h>
|
|
|
|
|
2007-10-19 15:59:34 +04:00
|
|
|
#include <sys/bus.h>
|
1999-07-15 02:24:07 +04:00
|
|
|
|
2001-05-06 07:26:38 +04:00
|
|
|
#include <dev/ic/wi_ieee.h>
|
|
|
|
#include <dev/ic/wireg.h>
|
|
|
|
#include <dev/ic/wivar.h>
|
1999-07-15 02:24:07 +04:00
|
|
|
|
2004-07-22 23:47:24 +04:00
|
|
|
STATIC int wi_init(struct ifnet *);
|
|
|
|
STATIC void wi_stop(struct ifnet *, int);
|
|
|
|
STATIC void wi_start(struct ifnet *);
|
|
|
|
STATIC int wi_reset(struct wi_softc *);
|
|
|
|
STATIC void wi_watchdog(struct ifnet *);
|
2007-03-04 08:59:00 +03:00
|
|
|
STATIC int wi_ioctl(struct ifnet *, u_long, void *);
|
2004-07-22 23:47:24 +04:00
|
|
|
STATIC int wi_media_change(struct ifnet *);
|
|
|
|
STATIC void wi_media_status(struct ifnet *, struct ifmediareq *);
|
|
|
|
|
2011-08-15 22:24:34 +04:00
|
|
|
static void wi_ioctl_init(struct wi_softc *);
|
|
|
|
static int wi_ioctl_enter(struct wi_softc *);
|
|
|
|
static void wi_ioctl_exit(struct wi_softc *);
|
|
|
|
static void wi_ioctl_drain(struct wi_softc *);
|
|
|
|
|
2005-06-22 10:14:51 +04:00
|
|
|
STATIC struct ieee80211_node *wi_node_alloc(struct ieee80211_node_table *);
|
|
|
|
STATIC void wi_node_free(struct ieee80211_node *);
|
2003-12-07 08:44:49 +03:00
|
|
|
|
2004-07-22 23:47:24 +04:00
|
|
|
STATIC void wi_raise_rate(struct ieee80211com *, struct ieee80211_rssdesc *);
|
|
|
|
STATIC void wi_lower_rate(struct ieee80211com *, struct ieee80211_rssdesc *);
|
2004-07-23 00:06:05 +04:00
|
|
|
STATIC int wi_choose_rate(struct ieee80211com *, struct ieee80211_node *,
|
2003-12-07 08:44:49 +03:00
|
|
|
struct ieee80211_frame *, u_int);
|
2004-07-22 23:47:24 +04:00
|
|
|
STATIC void wi_rssadapt_updatestats_cb(void *, struct ieee80211_node *);
|
|
|
|
STATIC void wi_rssadapt_updatestats(void *);
|
|
|
|
STATIC void wi_rssdescs_init(struct wi_rssdesc (*)[], wi_rssdescq_t *);
|
|
|
|
STATIC void wi_rssdescs_reset(struct ieee80211com *, struct wi_rssdesc (*)[],
|
|
|
|
wi_rssdescq_t *, u_int8_t (*)[]);
|
|
|
|
STATIC void wi_sync_bssid(struct wi_softc *, u_int8_t new_bssid[]);
|
|
|
|
|
|
|
|
STATIC void wi_rx_intr(struct wi_softc *);
|
|
|
|
STATIC void wi_txalloc_intr(struct wi_softc *);
|
2004-07-23 12:31:39 +04:00
|
|
|
STATIC void wi_cmd_intr(struct wi_softc *);
|
2004-07-22 23:47:24 +04:00
|
|
|
STATIC void wi_tx_intr(struct wi_softc *);
|
|
|
|
STATIC void wi_tx_ex_intr(struct wi_softc *);
|
|
|
|
STATIC void wi_info_intr(struct wi_softc *);
|
|
|
|
|
2005-06-25 07:56:53 +04:00
|
|
|
STATIC int wi_key_delete(struct ieee80211com *, const struct ieee80211_key *);
|
|
|
|
STATIC int wi_key_set(struct ieee80211com *, const struct ieee80211_key *,
|
|
|
|
const u_int8_t[IEEE80211_ADDR_LEN]);
|
|
|
|
STATIC void wi_key_update_begin(struct ieee80211com *);
|
|
|
|
STATIC void wi_key_update_end(struct ieee80211com *);
|
|
|
|
|
2004-07-23 01:56:58 +04:00
|
|
|
STATIC void wi_push_packet(struct wi_softc *);
|
2007-03-04 08:59:00 +03:00
|
|
|
STATIC int wi_get_cfg(struct ifnet *, u_long, void *);
|
|
|
|
STATIC int wi_set_cfg(struct ifnet *, u_long, void *);
|
2004-07-22 23:47:24 +04:00
|
|
|
STATIC int wi_cfg_txrate(struct wi_softc *);
|
|
|
|
STATIC int wi_write_txrate(struct wi_softc *, int);
|
|
|
|
STATIC int wi_write_wep(struct wi_softc *);
|
|
|
|
STATIC int wi_write_multi(struct wi_softc *);
|
|
|
|
STATIC int wi_alloc_fid(struct wi_softc *, int, int *);
|
|
|
|
STATIC void wi_read_nicid(struct wi_softc *);
|
|
|
|
STATIC int wi_write_ssid(struct wi_softc *, int, u_int8_t *, int);
|
|
|
|
|
|
|
|
STATIC int wi_cmd(struct wi_softc *, int, int, int, int);
|
2004-12-13 20:55:28 +03:00
|
|
|
STATIC int wi_cmd_start(struct wi_softc *, int, int, int, int);
|
|
|
|
STATIC int wi_cmd_wait(struct wi_softc *, int, int);
|
2004-07-22 23:47:24 +04:00
|
|
|
STATIC int wi_seek_bap(struct wi_softc *, int, int);
|
|
|
|
STATIC int wi_read_bap(struct wi_softc *, int, int, void *, int);
|
|
|
|
STATIC int wi_write_bap(struct wi_softc *, int, int, void *, int);
|
|
|
|
STATIC int wi_mwrite_bap(struct wi_softc *, int, int, struct mbuf *, int);
|
|
|
|
STATIC int wi_read_rid(struct wi_softc *, int, void *, int *);
|
|
|
|
STATIC int wi_write_rid(struct wi_softc *, int, void *, int);
|
|
|
|
|
|
|
|
STATIC int wi_newstate(struct ieee80211com *, enum ieee80211_state, int);
|
2005-11-18 19:53:56 +03:00
|
|
|
STATIC void wi_set_tim(struct ieee80211_node *, int);
|
2004-07-22 23:47:24 +04:00
|
|
|
|
|
|
|
STATIC int wi_scan_ap(struct wi_softc *, u_int16_t, u_int16_t);
|
|
|
|
STATIC void wi_scan_result(struct wi_softc *, int, int);
|
|
|
|
|
|
|
|
STATIC void wi_dump_pkt(struct wi_frame *, struct ieee80211_node *, int rssi);
|
2005-07-14 04:28:51 +04:00
|
|
|
STATIC void wi_mend_flags(struct wi_softc *, enum ieee80211_state);
|
2004-07-22 23:47:24 +04:00
|
|
|
|
2004-07-22 23:48:28 +04:00
|
|
|
static inline int
|
2002-09-30 10:50:35 +04:00
|
|
|
wi_write_val(struct wi_softc *sc, int rid, u_int16_t val)
|
|
|
|
{
|
|
|
|
|
|
|
|
val = htole16(val);
|
|
|
|
return wi_write_rid(sc, rid, &val, sizeof(val));
|
|
|
|
}
|
|
|
|
|
2003-05-13 11:13:49 +04:00
|
|
|
static struct timeval lasttxerror; /* time of last tx error msg */
|
2003-05-17 20:46:03 +04:00
|
|
|
static int curtxeps = 0; /* current tx error msgs/sec */
|
2003-05-13 11:13:49 +04:00
|
|
|
static int wi_txerate = 0; /* tx error rate: max msgs/sec */
|
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
#ifdef WI_DEBUG
|
2005-07-16 02:33:29 +04:00
|
|
|
#define WI_DEBUG_MAX 2
|
2003-01-09 11:52:19 +03:00
|
|
|
int wi_debug = 0;
|
2002-09-30 10:50:35 +04:00
|
|
|
|
|
|
|
#define DPRINTF(X) if (wi_debug) printf X
|
|
|
|
#define DPRINTF2(X) if (wi_debug > 1) printf X
|
2003-05-13 10:48:56 +04:00
|
|
|
#define IFF_DUMPPKTS(_ifp) \
|
|
|
|
(((_ifp)->if_flags & (IFF_DEBUG|IFF_LINK2)) == (IFF_DEBUG|IFF_LINK2))
|
2005-07-16 02:33:29 +04:00
|
|
|
static int wi_sysctl_verify_debug(SYSCTLFN_PROTO);
|
2002-09-30 10:50:35 +04:00
|
|
|
#else
|
|
|
|
#define DPRINTF(X)
|
|
|
|
#define DPRINTF2(X)
|
2003-05-13 10:48:56 +04:00
|
|
|
#define IFF_DUMPPKTS(_ifp) 0
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
#endif
|
2002-09-30 10:50:35 +04:00
|
|
|
|
2004-03-25 09:17:51 +03:00
|
|
|
#define WI_INTRS (WI_EV_RX | WI_EV_ALLOC | WI_EV_INFO | \
|
2004-07-23 12:31:39 +04:00
|
|
|
WI_EV_TX | WI_EV_TX_EXC | WI_EV_CMD)
|
2002-09-30 10:50:35 +04:00
|
|
|
|
|
|
|
struct wi_card_ident
|
|
|
|
wi_card_ident[] = {
|
2002-08-11 03:16:14 +04:00
|
|
|
/* CARD_ID CARD_NAME FIRM_TYPE */
|
2002-04-05 04:54:51 +04:00
|
|
|
{ WI_NIC_LUCENT_ID, WI_NIC_LUCENT_STR, WI_LUCENT },
|
|
|
|
{ WI_NIC_SONY_ID, WI_NIC_SONY_STR, WI_LUCENT },
|
|
|
|
{ WI_NIC_LUCENT_EMB_ID, WI_NIC_LUCENT_EMB_STR, WI_LUCENT },
|
|
|
|
{ WI_NIC_EVB2_ID, WI_NIC_EVB2_STR, WI_INTERSIL },
|
|
|
|
{ WI_NIC_HWB3763_ID, WI_NIC_HWB3763_STR, WI_INTERSIL },
|
|
|
|
{ WI_NIC_HWB3163_ID, WI_NIC_HWB3163_STR, WI_INTERSIL },
|
|
|
|
{ WI_NIC_HWB3163B_ID, WI_NIC_HWB3163B_STR, WI_INTERSIL },
|
|
|
|
{ WI_NIC_EVB3_ID, WI_NIC_EVB3_STR, WI_INTERSIL },
|
|
|
|
{ WI_NIC_HWB1153_ID, WI_NIC_HWB1153_STR, WI_INTERSIL },
|
|
|
|
{ WI_NIC_P2_SST_ID, WI_NIC_P2_SST_STR, WI_INTERSIL },
|
|
|
|
{ WI_NIC_EVB2_SST_ID, WI_NIC_EVB2_SST_STR, WI_INTERSIL },
|
|
|
|
{ WI_NIC_3842_EVA_ID, WI_NIC_3842_EVA_STR, WI_INTERSIL },
|
2002-04-04 11:06:16 +04:00
|
|
|
{ WI_NIC_3842_PCMCIA_AMD_ID, WI_NIC_3842_PCMCIA_STR, WI_INTERSIL },
|
|
|
|
{ WI_NIC_3842_PCMCIA_SST_ID, WI_NIC_3842_PCMCIA_STR, WI_INTERSIL },
|
|
|
|
{ WI_NIC_3842_PCMCIA_ATM_ID, WI_NIC_3842_PCMCIA_STR, WI_INTERSIL },
|
|
|
|
{ WI_NIC_3842_MINI_AMD_ID, WI_NIC_3842_MINI_STR, WI_INTERSIL },
|
|
|
|
{ WI_NIC_3842_MINI_SST_ID, WI_NIC_3842_MINI_STR, WI_INTERSIL },
|
|
|
|
{ WI_NIC_3842_MINI_ATM_ID, WI_NIC_3842_MINI_STR, WI_INTERSIL },
|
|
|
|
{ WI_NIC_3842_PCI_AMD_ID, WI_NIC_3842_PCI_STR, WI_INTERSIL },
|
|
|
|
{ WI_NIC_3842_PCI_SST_ID, WI_NIC_3842_PCI_STR, WI_INTERSIL },
|
|
|
|
{ WI_NIC_3842_PCI_ATM_ID, WI_NIC_3842_PCI_STR, WI_INTERSIL },
|
|
|
|
{ WI_NIC_P3_PCMCIA_AMD_ID, WI_NIC_P3_PCMCIA_STR, WI_INTERSIL },
|
|
|
|
{ WI_NIC_P3_PCMCIA_SST_ID, WI_NIC_P3_PCMCIA_STR, WI_INTERSIL },
|
|
|
|
{ WI_NIC_P3_MINI_AMD_ID, WI_NIC_P3_MINI_STR, WI_INTERSIL },
|
|
|
|
{ WI_NIC_P3_MINI_SST_ID, WI_NIC_P3_MINI_STR, WI_INTERSIL },
|
|
|
|
{ 0, NULL, 0 },
|
|
|
|
};
|
|
|
|
|
2008-11-12 15:35:50 +03:00
|
|
|
#ifndef _MODULE
|
2005-07-16 02:33:29 +04:00
|
|
|
/*
|
|
|
|
* Setup sysctl(3) MIB, hw.wi.*
|
|
|
|
*
|
2008-11-12 15:35:50 +03:00
|
|
|
* TBD condition CTLFLAG_PERMANENT on being a module or not
|
2005-07-16 02:33:29 +04:00
|
|
|
*/
|
|
|
|
SYSCTL_SETUP(sysctl_wi, "sysctl wi(4) subtree setup")
|
|
|
|
{
|
|
|
|
int rc;
|
2005-07-16 08:06:39 +04:00
|
|
|
const struct sysctlnode *rnode;
|
|
|
|
#ifdef WI_DEBUG
|
|
|
|
const struct sysctlnode *cnode;
|
|
|
|
#endif /* WI_DEBUG */
|
2005-07-16 02:33:29 +04:00
|
|
|
|
|
|
|
if ((rc = sysctl_createv(clog, 0, NULL, &rnode,
|
|
|
|
CTLFLAG_PERMANENT, CTLTYPE_NODE, "hw", NULL,
|
|
|
|
NULL, 0, NULL, 0, CTL_HW, CTL_EOL)) != 0)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
if ((rc = sysctl_createv(clog, 0, &rnode, &rnode,
|
|
|
|
CTLFLAG_PERMANENT, CTLTYPE_NODE, "wi",
|
|
|
|
"Lucent/Prism/Symbol 802.11 controls",
|
|
|
|
NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL)) != 0)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
#ifdef WI_DEBUG
|
|
|
|
/* control debugging printfs */
|
|
|
|
if ((rc = sysctl_createv(clog, 0, &rnode, &cnode,
|
|
|
|
CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT,
|
|
|
|
"debug", SYSCTL_DESCR("Enable debugging output"),
|
|
|
|
wi_sysctl_verify_debug, 0, &wi_debug, 0, CTL_CREATE, CTL_EOL)) != 0)
|
|
|
|
goto err;
|
|
|
|
#endif /* WI_DEBUG */
|
|
|
|
return;
|
|
|
|
err:
|
|
|
|
printf("%s: sysctl_createv failed (rc = %d)\n", __func__, rc);
|
|
|
|
}
|
2005-07-23 20:09:39 +04:00
|
|
|
#endif
|
2005-07-16 02:33:29 +04:00
|
|
|
|
|
|
|
#ifdef WI_DEBUG
|
|
|
|
static int
|
|
|
|
wi_sysctl_verify(SYSCTLFN_ARGS, int lower, int upper)
|
|
|
|
{
|
|
|
|
int error, t;
|
|
|
|
struct sysctlnode node;
|
|
|
|
|
|
|
|
node = *rnode;
|
|
|
|
t = *(int*)rnode->sysctl_data;
|
|
|
|
node.sysctl_data = &t;
|
|
|
|
error = sysctl_lookup(SYSCTLFN_CALL(&node));
|
|
|
|
if (error || newp == NULL)
|
|
|
|
return (error);
|
|
|
|
|
|
|
|
if (t < lower || t > upper)
|
|
|
|
return (EINVAL);
|
|
|
|
|
|
|
|
*(int*)rnode->sysctl_data = t;
|
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
wi_sysctl_verify_debug(SYSCTLFN_ARGS)
|
|
|
|
{
|
|
|
|
return wi_sysctl_verify(SYSCTLFN_CALL(__UNCONST(rnode)),
|
|
|
|
0, WI_DEBUG_MAX);
|
|
|
|
}
|
|
|
|
#endif /* WI_DEBUG */
|
|
|
|
|
2004-12-13 20:21:35 +03:00
|
|
|
STATIC int
|
|
|
|
wi_read_xrid(struct wi_softc *sc, int rid, void *buf, int ebuflen)
|
|
|
|
{
|
|
|
|
int buflen, rc;
|
|
|
|
|
|
|
|
buflen = ebuflen;
|
|
|
|
if ((rc = wi_read_rid(sc, rid, buf, &buflen)) != 0)
|
|
|
|
return rc;
|
|
|
|
|
|
|
|
if (buflen < ebuflen) {
|
|
|
|
#ifdef WI_DEBUG
|
|
|
|
printf("%s: rid=%#04x read %d, expected %d\n", __func__,
|
|
|
|
rid, buflen, ebuflen);
|
|
|
|
#endif
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
1999-07-15 02:24:07 +04:00
|
|
|
int
|
2004-08-07 21:12:44 +04:00
|
|
|
wi_attach(struct wi_softc *sc, const u_int8_t *macaddr)
|
1999-07-15 02:24:07 +04:00
|
|
|
{
|
2002-09-30 10:50:35 +04:00
|
|
|
struct ieee80211com *ic = &sc->sc_ic;
|
2005-06-22 10:14:51 +04:00
|
|
|
struct ifnet *ifp = &sc->sc_if;
|
2003-11-02 04:39:22 +03:00
|
|
|
int chan, nrate, buflen;
|
|
|
|
u_int16_t val, chanavail;
|
2003-11-16 12:41:01 +03:00
|
|
|
struct {
|
|
|
|
u_int16_t nrates;
|
|
|
|
char rates[IEEE80211_RATE_SIZE];
|
|
|
|
} ratebuf;
|
2002-09-30 10:50:35 +04:00
|
|
|
static const u_int8_t empty_macaddr[IEEE80211_ADDR_LEN] = {
|
2000-03-06 13:31:27 +03:00
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
|
|
|
};
|
2003-05-16 05:26:17 +04:00
|
|
|
int s;
|
1999-07-15 02:24:07 +04:00
|
|
|
|
2011-08-15 22:24:34 +04:00
|
|
|
wi_ioctl_init(sc);
|
|
|
|
|
2003-05-16 05:26:17 +04:00
|
|
|
s = splnet();
|
2000-07-18 18:53:26 +04:00
|
|
|
|
1999-07-15 02:24:07 +04:00
|
|
|
/* Make sure interrupts are disabled. */
|
|
|
|
CSR_WRITE_2(sc, WI_INT_EN, 0);
|
2002-09-30 10:50:35 +04:00
|
|
|
CSR_WRITE_2(sc, WI_EVENT_ACK, ~0);
|
1999-07-15 02:24:07 +04:00
|
|
|
|
2003-05-20 05:29:35 +04:00
|
|
|
sc->sc_invalid = 0;
|
|
|
|
|
1999-07-15 02:24:07 +04:00
|
|
|
/* Reset the NIC. */
|
2002-09-30 10:50:35 +04:00
|
|
|
if (wi_reset(sc) != 0) {
|
2003-05-20 05:29:35 +04:00
|
|
|
sc->sc_invalid = 1;
|
2003-05-16 05:26:17 +04:00
|
|
|
splx(s);
|
2002-09-30 10:50:35 +04:00
|
|
|
return 1;
|
|
|
|
}
|
1999-07-15 02:24:07 +04:00
|
|
|
|
2005-02-13 10:33:06 +03:00
|
|
|
if (wi_read_xrid(sc, WI_RID_MAC_NODE, ic->ic_myaddr,
|
|
|
|
IEEE80211_ADDR_LEN) != 0 ||
|
|
|
|
IEEE80211_ADDR_EQ(ic->ic_myaddr, empty_macaddr)) {
|
|
|
|
if (macaddr != NULL)
|
|
|
|
memcpy(ic->ic_myaddr, macaddr, IEEE80211_ADDR_LEN);
|
|
|
|
else {
|
2004-08-07 21:12:44 +04:00
|
|
|
printf(" could not get mac address, attach failed\n");
|
|
|
|
splx(s);
|
|
|
|
return 1;
|
|
|
|
}
|
2005-02-13 10:33:06 +03:00
|
|
|
}
|
2000-02-13 09:17:58 +03:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
printf(" 802.11 address %s\n", ether_sprintf(ic->ic_myaddr));
|
1999-07-15 02:24:07 +04:00
|
|
|
|
2001-05-15 08:14:06 +04:00
|
|
|
/* Read NIC identification */
|
2002-09-30 10:50:35 +04:00
|
|
|
wi_read_nicid(sc);
|
2001-05-15 08:14:06 +04:00
|
|
|
|
2010-11-23 07:33:09 +03:00
|
|
|
memcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ);
|
1999-07-15 02:24:07 +04:00
|
|
|
ifp->if_softc = sc;
|
|
|
|
ifp->if_start = wi_start;
|
|
|
|
ifp->if_ioctl = wi_ioctl;
|
|
|
|
ifp->if_watchdog = wi_watchdog;
|
2000-10-12 06:24:08 +04:00
|
|
|
ifp->if_init = wi_init;
|
|
|
|
ifp->if_stop = wi_stop;
|
2002-09-30 10:50:35 +04:00
|
|
|
ifp->if_flags =
|
|
|
|
IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST | IFF_NOTRAILERS;
|
2000-12-14 09:27:23 +03:00
|
|
|
IFQ_SET_READY(&ifp->if_snd);
|
1999-07-15 02:24:07 +04:00
|
|
|
|
2005-06-22 10:14:51 +04:00
|
|
|
ic->ic_ifp = ifp;
|
2002-09-30 10:50:35 +04:00
|
|
|
ic->ic_phytype = IEEE80211_T_DS;
|
|
|
|
ic->ic_opmode = IEEE80211_M_STA;
|
2004-07-22 23:50:43 +04:00
|
|
|
ic->ic_caps = IEEE80211_C_AHDEMO;
|
2002-09-30 10:50:35 +04:00
|
|
|
ic->ic_state = IEEE80211_S_INIT;
|
2003-04-08 08:31:23 +04:00
|
|
|
ic->ic_max_aid = WI_MAX_AID;
|
2002-09-30 10:50:35 +04:00
|
|
|
|
|
|
|
/* Find available channel */
|
2004-12-13 20:21:35 +03:00
|
|
|
if (wi_read_xrid(sc, WI_RID_CHANNEL_LIST, &chanavail,
|
|
|
|
sizeof(chanavail)) != 0) {
|
2010-11-23 07:33:09 +03:00
|
|
|
aprint_normal_dev(sc->sc_dev, "using default channel list\n");
|
2004-08-07 21:12:44 +04:00
|
|
|
chanavail = htole16(0x1fff); /* assume 1-13 */
|
|
|
|
}
|
2003-11-02 04:39:22 +03:00
|
|
|
for (chan = 16; chan > 0; chan--) {
|
|
|
|
if (!isset((u_int8_t*)&chanavail, chan - 1))
|
|
|
|
continue;
|
|
|
|
ic->ic_ibss_chan = &ic->ic_channels[chan];
|
2003-10-13 12:07:21 +04:00
|
|
|
ic->ic_channels[chan].ic_freq =
|
|
|
|
ieee80211_ieee2mhz(chan, IEEE80211_CHAN_2GHZ);
|
|
|
|
ic->ic_channels[chan].ic_flags = IEEE80211_CHAN_B;
|
2002-09-30 10:50:35 +04:00
|
|
|
}
|
|
|
|
|
2003-11-02 04:39:22 +03:00
|
|
|
/* Find default IBSS channel */
|
2004-12-13 20:21:35 +03:00
|
|
|
if (wi_read_xrid(sc, WI_RID_OWN_CHNL, &val, sizeof(val)) == 0) {
|
2003-11-02 04:39:22 +03:00
|
|
|
chan = le16toh(val);
|
|
|
|
if (isset((u_int8_t*)&chanavail, chan - 1))
|
|
|
|
ic->ic_ibss_chan = &ic->ic_channels[chan];
|
|
|
|
}
|
2004-08-07 21:12:44 +04:00
|
|
|
if (ic->ic_ibss_chan == NULL) {
|
2010-11-23 07:33:09 +03:00
|
|
|
aprint_error_dev(sc->sc_dev, "no available channel\n");
|
2004-08-07 21:12:44 +04:00
|
|
|
return 1;
|
|
|
|
}
|
2003-11-02 04:39:22 +03:00
|
|
|
|
2003-07-06 11:15:55 +04:00
|
|
|
if (sc->sc_firmware_type == WI_LUCENT) {
|
|
|
|
sc->sc_dbm_offset = WI_LUCENT_DBM_OFFSET;
|
|
|
|
} else {
|
|
|
|
if ((sc->sc_flags & WI_FLAGS_HAS_DBMADJUST) &&
|
2004-12-13 20:21:35 +03:00
|
|
|
wi_read_xrid(sc, WI_RID_DBM_ADJUST, &val, sizeof(val)) == 0)
|
2003-07-06 11:15:55 +04:00
|
|
|
sc->sc_dbm_offset = le16toh(val);
|
|
|
|
else
|
|
|
|
sc->sc_dbm_offset = WI_PRISM_DBM_OFFSET;
|
2002-11-16 09:02:53 +03:00
|
|
|
}
|
|
|
|
|
2004-03-26 09:43:25 +03:00
|
|
|
sc->sc_flags |= WI_FLAGS_RSSADAPTSTA;
|
|
|
|
|
2002-08-11 05:30:28 +04:00
|
|
|
/*
|
|
|
|
* Set flags based on firmware version.
|
|
|
|
*/
|
|
|
|
switch (sc->sc_firmware_type) {
|
|
|
|
case WI_LUCENT:
|
2002-09-30 10:50:35 +04:00
|
|
|
sc->sc_flags |= WI_FLAGS_HAS_SYSSCALE;
|
|
|
|
#ifdef WI_HERMES_AUTOINC_WAR
|
|
|
|
/* XXX: not confirmed, but never seen for recent firmware */
|
|
|
|
if (sc->sc_sta_firmware_ver < 40000) {
|
|
|
|
sc->sc_flags |= WI_FLAGS_BUG_AUTOINC;
|
2002-08-11 05:30:28 +04:00
|
|
|
}
|
2002-09-30 10:50:35 +04:00
|
|
|
#endif
|
|
|
|
if (sc->sc_sta_firmware_ver >= 60000)
|
|
|
|
sc->sc_flags |= WI_FLAGS_HAS_MOR;
|
2003-06-19 10:16:36 +04:00
|
|
|
if (sc->sc_sta_firmware_ver >= 60006) {
|
2003-10-13 12:07:21 +04:00
|
|
|
ic->ic_caps |= IEEE80211_C_IBSS;
|
|
|
|
ic->ic_caps |= IEEE80211_C_MONITOR;
|
2003-06-19 10:16:36 +04:00
|
|
|
}
|
2004-07-22 23:50:43 +04:00
|
|
|
ic->ic_caps |= IEEE80211_C_PMGT;
|
2002-09-30 10:50:35 +04:00
|
|
|
sc->sc_ibss_port = 1;
|
2002-08-11 05:30:28 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case WI_INTERSIL:
|
2002-11-18 18:10:22 +03:00
|
|
|
sc->sc_flags |= WI_FLAGS_HAS_FRAGTHR;
|
2002-09-30 10:50:35 +04:00
|
|
|
sc->sc_flags |= WI_FLAGS_HAS_ROAMING;
|
|
|
|
sc->sc_flags |= WI_FLAGS_HAS_SYSSCALE;
|
2002-12-27 10:54:35 +03:00
|
|
|
if (sc->sc_sta_firmware_ver > 10101)
|
|
|
|
sc->sc_flags |= WI_FLAGS_HAS_DBMADJUST;
|
2002-08-11 05:30:28 +04:00
|
|
|
if (sc->sc_sta_firmware_ver >= 800) {
|
2003-03-27 08:00:21 +03:00
|
|
|
if (sc->sc_sta_firmware_ver != 10402)
|
2003-10-13 12:07:21 +04:00
|
|
|
ic->ic_caps |= IEEE80211_C_HOSTAP;
|
|
|
|
ic->ic_caps |= IEEE80211_C_IBSS;
|
|
|
|
ic->ic_caps |= IEEE80211_C_MONITOR;
|
2002-08-11 05:30:28 +04:00
|
|
|
}
|
2004-07-22 23:50:43 +04:00
|
|
|
ic->ic_caps |= IEEE80211_C_PMGT;
|
2002-09-30 10:50:35 +04:00
|
|
|
sc->sc_ibss_port = 0;
|
2003-12-07 08:44:49 +03:00
|
|
|
sc->sc_alt_retry = 2;
|
2002-08-11 05:30:28 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case WI_SYMBOL:
|
2002-09-30 10:50:35 +04:00
|
|
|
sc->sc_flags |= WI_FLAGS_HAS_DIVERSITY;
|
2002-10-25 05:35:12 +04:00
|
|
|
if (sc->sc_sta_firmware_ver >= 20000)
|
2003-10-13 12:07:21 +04:00
|
|
|
ic->ic_caps |= IEEE80211_C_IBSS;
|
2002-09-30 10:50:35 +04:00
|
|
|
sc->sc_ibss_port = 4;
|
2002-08-11 05:30:28 +04:00
|
|
|
break;
|
|
|
|
}
|
2002-01-21 14:28:18 +03:00
|
|
|
|
2000-02-04 10:48:29 +03:00
|
|
|
/*
|
|
|
|
* Find out if we support WEP on this card.
|
|
|
|
*/
|
2004-12-13 20:21:35 +03:00
|
|
|
if (wi_read_xrid(sc, WI_RID_WEP_AVAIL, &val, sizeof(val)) == 0 &&
|
|
|
|
val != htole16(0))
|
2003-10-13 12:07:21 +04:00
|
|
|
ic->ic_caps |= IEEE80211_C_WEP;
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
|
2002-08-11 05:35:10 +04:00
|
|
|
/* Find supported rates. */
|
2002-09-30 10:50:35 +04:00
|
|
|
buflen = sizeof(ratebuf);
|
2004-08-07 21:12:44 +04:00
|
|
|
if (wi_read_rid(sc, WI_RID_DATA_RATES, &ratebuf, &buflen) == 0 &&
|
|
|
|
buflen > 2) {
|
2003-11-16 12:41:01 +03:00
|
|
|
nrate = le16toh(ratebuf.nrates);
|
2002-09-30 10:50:35 +04:00
|
|
|
if (nrate > IEEE80211_RATE_SIZE)
|
|
|
|
nrate = IEEE80211_RATE_SIZE;
|
2003-10-13 12:07:21 +04:00
|
|
|
memcpy(ic->ic_sup_rates[IEEE80211_MODE_11B].rs_rates,
|
2003-11-16 12:41:01 +03:00
|
|
|
&ratebuf.rates[0], nrate);
|
2003-10-13 12:07:21 +04:00
|
|
|
ic->ic_sup_rates[IEEE80211_MODE_11B].rs_nrates = nrate;
|
2004-08-07 21:12:44 +04:00
|
|
|
} else {
|
2010-11-23 07:33:09 +03:00
|
|
|
aprint_error_dev(sc->sc_dev, "no supported rate list\n");
|
2004-08-07 21:12:44 +04:00
|
|
|
return 1;
|
2002-08-21 07:26:29 +04:00
|
|
|
}
|
2002-09-30 10:50:35 +04:00
|
|
|
|
|
|
|
sc->sc_max_datalen = 2304;
|
|
|
|
sc->sc_rts_thresh = 2347;
|
2002-11-16 09:02:53 +03:00
|
|
|
sc->sc_frag_thresh = 2346;
|
2002-09-30 10:50:35 +04:00
|
|
|
sc->sc_system_scale = 1;
|
2002-10-15 12:53:46 +04:00
|
|
|
sc->sc_cnfauthmode = IEEE80211_AUTH_OPEN;
|
2002-09-30 10:50:35 +04:00
|
|
|
sc->sc_roaming_mode = 1;
|
2002-08-11 04:00:41 +04:00
|
|
|
|
2007-07-10 00:51:58 +04:00
|
|
|
callout_init(&sc->sc_rssadapt_ch, 0);
|
2003-12-07 08:44:49 +03:00
|
|
|
|
1999-07-15 02:24:07 +04:00
|
|
|
/*
|
|
|
|
* Call MI attach routines.
|
|
|
|
*/
|
2002-09-30 10:50:35 +04:00
|
|
|
if_attach(ifp);
|
2005-06-22 10:14:51 +04:00
|
|
|
ieee80211_ifattach(ic);
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
|
2003-10-13 12:07:21 +04:00
|
|
|
sc->sc_newstate = ic->ic_newstate;
|
2005-06-22 10:14:51 +04:00
|
|
|
sc->sc_set_tim = ic->ic_set_tim;
|
2003-10-13 12:07:21 +04:00
|
|
|
ic->ic_newstate = wi_newstate;
|
2003-12-07 08:44:49 +03:00
|
|
|
ic->ic_node_alloc = wi_node_alloc;
|
|
|
|
ic->ic_node_free = wi_node_free;
|
2003-10-13 12:07:21 +04:00
|
|
|
ic->ic_set_tim = wi_set_tim;
|
|
|
|
|
2005-06-25 07:56:53 +04:00
|
|
|
ic->ic_crypto.cs_key_delete = wi_key_delete;
|
|
|
|
ic->ic_crypto.cs_key_set = wi_key_set;
|
|
|
|
ic->ic_crypto.cs_key_update_begin = wi_key_update_begin;
|
|
|
|
ic->ic_crypto.cs_key_update_end = wi_key_update_end;
|
|
|
|
|
2005-06-22 10:14:51 +04:00
|
|
|
ieee80211_media_init(ic, wi_media_change, wi_media_status);
|
2003-07-07 00:01:17 +04:00
|
|
|
|
2010-04-05 11:19:28 +04:00
|
|
|
bpf_attach2(ifp, DLT_IEEE802_11_RADIO,
|
2003-11-16 12:02:42 +03:00
|
|
|
sizeof(struct ieee80211_frame) + 64, &sc->sc_drvbpf);
|
|
|
|
|
|
|
|
memset(&sc->sc_rxtapu, 0, sizeof(sc->sc_rxtapu));
|
2006-03-12 06:22:02 +03:00
|
|
|
sc->sc_rxtap.wr_ihdr.it_len = htole16(sizeof(sc->sc_rxtapu));
|
|
|
|
sc->sc_rxtap.wr_ihdr.it_present = htole32(WI_RX_RADIOTAP_PRESENT);
|
2003-11-16 12:02:42 +03:00
|
|
|
|
|
|
|
memset(&sc->sc_txtapu, 0, sizeof(sc->sc_txtapu));
|
2006-03-12 06:22:02 +03:00
|
|
|
sc->sc_txtap.wt_ihdr.it_len = htole16(sizeof(sc->sc_txtapu));
|
|
|
|
sc->sc_txtap.wt_ihdr.it_present = htole32(WI_TX_RADIOTAP_PRESENT);
|
2003-11-16 12:02:42 +03:00
|
|
|
|
2001-05-06 07:26:38 +04:00
|
|
|
/* Attach is successful. */
|
|
|
|
sc->sc_attached = 1;
|
2000-02-12 19:08:04 +03:00
|
|
|
|
2003-05-16 05:26:17 +04:00
|
|
|
splx(s);
|
2005-07-07 03:58:14 +04:00
|
|
|
ieee80211_announce(ic);
|
2001-05-06 07:26:38 +04:00
|
|
|
return 0;
|
1999-07-15 02:24:07 +04:00
|
|
|
}
|
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
int
|
|
|
|
wi_detach(struct wi_softc *sc)
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
{
|
2005-06-22 10:14:51 +04:00
|
|
|
struct ifnet *ifp = &sc->sc_if;
|
2003-05-16 05:26:17 +04:00
|
|
|
int s;
|
2002-09-30 10:50:35 +04:00
|
|
|
|
|
|
|
if (!sc->sc_attached)
|
|
|
|
return 0;
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
|
2005-06-22 10:14:51 +04:00
|
|
|
sc->sc_invalid = 1;
|
2003-05-16 05:26:17 +04:00
|
|
|
s = splnet();
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
|
2003-05-20 05:29:35 +04:00
|
|
|
wi_stop(ifp, 1);
|
|
|
|
|
2005-06-22 10:14:51 +04:00
|
|
|
ieee80211_ifdetach(&sc->sc_ic);
|
2002-09-30 10:50:35 +04:00
|
|
|
if_detach(ifp);
|
2003-05-16 05:26:17 +04:00
|
|
|
splx(s);
|
2011-08-15 22:24:34 +04:00
|
|
|
wi_ioctl_drain(sc);
|
2002-09-30 10:50:35 +04:00
|
|
|
return 0;
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
}
|
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
int
|
2009-05-12 18:16:35 +04:00
|
|
|
wi_activate(device_t self, enum devact act)
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
{
|
2009-09-16 00:51:12 +04:00
|
|
|
struct wi_softc *sc = device_private(self);
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
switch (act) {
|
|
|
|
case DVACT_DEACTIVATE:
|
2005-06-22 10:14:51 +04:00
|
|
|
if_deactivate(&sc->sc_if);
|
2009-09-16 00:51:12 +04:00
|
|
|
return 0;
|
|
|
|
default:
|
|
|
|
return EOPNOTSUPP;
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
}
|
2002-09-30 10:50:35 +04:00
|
|
|
}
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
int
|
|
|
|
wi_intr(void *arg)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
struct wi_softc *sc = arg;
|
2005-06-22 10:14:51 +04:00
|
|
|
struct ifnet *ifp = &sc->sc_if;
|
2003-05-22 10:34:45 +04:00
|
|
|
u_int16_t status;
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
if (sc->sc_enabled == 0 ||
|
2010-11-23 07:33:09 +03:00
|
|
|
!device_is_active(sc->sc_dev) ||
|
2002-09-30 10:50:35 +04:00
|
|
|
(ifp->if_flags & IFF_RUNNING) == 0)
|
|
|
|
return 0;
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
if ((ifp->if_flags & IFF_UP) == 0) {
|
|
|
|
CSR_WRITE_2(sc, WI_INT_EN, 0);
|
2003-02-25 03:51:14 +03:00
|
|
|
CSR_WRITE_2(sc, WI_EVENT_ACK, ~0);
|
2002-09-30 10:50:35 +04:00
|
|
|
return 1;
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
}
|
|
|
|
|
2003-05-22 10:34:45 +04:00
|
|
|
/* This is superfluous on Prism, but Lucent breaks if we
|
|
|
|
* do not disable interrupts.
|
|
|
|
*/
|
|
|
|
CSR_WRITE_2(sc, WI_INT_EN, 0);
|
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
/* maximum 10 loops per interrupt */
|
|
|
|
for (i = 0; i < 10; i++) {
|
2003-05-22 10:34:45 +04:00
|
|
|
status = CSR_READ_2(sc, WI_EVENT_STAT);
|
2004-12-13 20:55:28 +03:00
|
|
|
#ifdef WI_DEBUG
|
|
|
|
if (wi_debug > 1) {
|
|
|
|
printf("%s: iter %d status %#04x\n", __func__, i,
|
|
|
|
status);
|
|
|
|
}
|
|
|
|
#endif /* WI_DEBUG */
|
2002-09-30 10:50:35 +04:00
|
|
|
if ((status & WI_INTRS) == 0)
|
|
|
|
break;
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
|
2004-12-13 20:55:28 +03:00
|
|
|
sc->sc_status = status;
|
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
if (status & WI_EV_RX)
|
|
|
|
wi_rx_intr(sc);
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
if (status & WI_EV_ALLOC)
|
2003-12-07 08:44:49 +03:00
|
|
|
wi_txalloc_intr(sc);
|
|
|
|
|
|
|
|
if (status & WI_EV_TX)
|
2002-09-30 10:50:35 +04:00
|
|
|
wi_tx_intr(sc);
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
|
2003-05-13 11:13:49 +04:00
|
|
|
if (status & WI_EV_TX_EXC)
|
|
|
|
wi_tx_ex_intr(sc);
|
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
if (status & WI_EV_INFO)
|
|
|
|
wi_info_intr(sc);
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
|
2004-12-13 20:55:28 +03:00
|
|
|
CSR_WRITE_2(sc, WI_EVENT_ACK, sc->sc_status);
|
2004-07-23 00:12:20 +04:00
|
|
|
|
2004-12-13 20:55:28 +03:00
|
|
|
if (sc->sc_status & WI_EV_CMD)
|
2004-07-23 12:31:39 +04:00
|
|
|
wi_cmd_intr(sc);
|
|
|
|
|
2002-10-04 08:23:20 +04:00
|
|
|
if ((ifp->if_flags & IFF_OACTIVE) == 0 &&
|
|
|
|
(sc->sc_flags & WI_FLAGS_OUTRANGE) == 0 &&
|
2002-09-30 10:50:35 +04:00
|
|
|
!IFQ_IS_EMPTY(&ifp->if_snd))
|
|
|
|
wi_start(ifp);
|
2004-12-13 20:55:28 +03:00
|
|
|
|
|
|
|
sc->sc_status = 0;
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
}
|
|
|
|
|
2003-05-22 10:34:45 +04:00
|
|
|
/* re-enable interrupts */
|
|
|
|
CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
|
|
|
|
|
2004-12-13 20:55:28 +03:00
|
|
|
sc->sc_status = 0;
|
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
return 1;
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
}
|
|
|
|
|
2004-02-10 03:47:41 +03:00
|
|
|
#define arraylen(a) (sizeof(a) / sizeof((a)[0]))
|
|
|
|
|
2004-07-22 23:47:24 +04:00
|
|
|
STATIC void
|
2004-02-10 03:47:41 +03:00
|
|
|
wi_rssdescs_init(struct wi_rssdesc (*rssd)[WI_NTXRSS], wi_rssdescq_t *rssdfree)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
SLIST_INIT(rssdfree);
|
|
|
|
for (i = 0; i < arraylen(*rssd); i++) {
|
|
|
|
SLIST_INSERT_HEAD(rssdfree, &(*rssd)[i], rd_next);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-07-22 23:47:24 +04:00
|
|
|
STATIC void
|
2004-02-10 03:47:41 +03:00
|
|
|
wi_rssdescs_reset(struct ieee80211com *ic, struct wi_rssdesc (*rssd)[WI_NTXRSS],
|
|
|
|
wi_rssdescq_t *rssdfree, u_int8_t (*txpending)[IEEE80211_RATE_MAXSIZE])
|
|
|
|
{
|
|
|
|
struct ieee80211_node *ni;
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < arraylen(*rssd); i++) {
|
|
|
|
ni = (*rssd)[i].rd_desc.id_node;
|
|
|
|
(*rssd)[i].rd_desc.id_node = NULL;
|
2005-06-22 10:14:51 +04:00
|
|
|
if (ni != NULL && (ic->ic_ifp->if_flags & IFF_DEBUG) != 0)
|
2004-02-10 03:47:41 +03:00
|
|
|
printf("%s: cleaning outstanding rssadapt "
|
|
|
|
"descriptor for %s\n",
|
2005-06-22 10:14:51 +04:00
|
|
|
ic->ic_ifp->if_xname, ether_sprintf(ni->ni_macaddr));
|
2004-08-10 04:57:20 +04:00
|
|
|
if (ni != NULL)
|
2005-06-22 10:14:51 +04:00
|
|
|
ieee80211_free_node(ni);
|
2004-02-10 03:47:41 +03:00
|
|
|
}
|
|
|
|
memset(*txpending, 0, sizeof(*txpending));
|
|
|
|
wi_rssdescs_init(rssd, rssdfree);
|
|
|
|
}
|
|
|
|
|
2004-07-22 23:47:24 +04:00
|
|
|
STATIC int
|
2002-09-30 10:50:35 +04:00
|
|
|
wi_init(struct ifnet *ifp)
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
{
|
2002-09-30 10:50:35 +04:00
|
|
|
struct wi_softc *sc = ifp->if_softc;
|
|
|
|
struct ieee80211com *ic = &sc->sc_ic;
|
|
|
|
struct wi_joinreq join;
|
|
|
|
int i;
|
|
|
|
int error = 0, wasenabled;
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
DPRINTF(("wi_init: enabled %d\n", sc->sc_enabled));
|
|
|
|
wasenabled = sc->sc_enabled;
|
|
|
|
if (!sc->sc_enabled) {
|
2010-11-23 07:33:09 +03:00
|
|
|
if ((error = (*sc->sc_enable)(sc->sc_dev, 1)) != 0)
|
2002-09-30 10:50:35 +04:00
|
|
|
goto out;
|
|
|
|
sc->sc_enabled = 1;
|
|
|
|
} else
|
|
|
|
wi_stop(ifp, 0);
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
/* Symbol firmware cannot be initialized more than once */
|
2003-05-13 12:35:58 +04:00
|
|
|
if (sc->sc_firmware_type != WI_SYMBOL || !wasenabled)
|
2002-09-30 10:50:35 +04:00
|
|
|
if ((error = wi_reset(sc)) != 0)
|
|
|
|
goto out;
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
/* common 802.11 configuration */
|
2002-10-04 02:32:37 +04:00
|
|
|
ic->ic_flags &= ~IEEE80211_F_IBSSON;
|
2002-10-04 08:23:20 +04:00
|
|
|
sc->sc_flags &= ~WI_FLAGS_OUTRANGE;
|
2002-09-30 10:50:35 +04:00
|
|
|
switch (ic->ic_opmode) {
|
|
|
|
case IEEE80211_M_STA:
|
|
|
|
wi_write_val(sc, WI_RID_PORTTYPE, WI_PORTTYPE_BSS);
|
|
|
|
break;
|
2002-09-30 19:48:41 +04:00
|
|
|
case IEEE80211_M_IBSS:
|
2002-09-30 10:50:35 +04:00
|
|
|
wi_write_val(sc, WI_RID_PORTTYPE, sc->sc_ibss_port);
|
2002-10-04 02:32:37 +04:00
|
|
|
ic->ic_flags |= IEEE80211_F_IBSSON;
|
2002-09-30 10:50:35 +04:00
|
|
|
break;
|
2002-09-30 19:48:41 +04:00
|
|
|
case IEEE80211_M_AHDEMO:
|
|
|
|
wi_write_val(sc, WI_RID_PORTTYPE, WI_PORTTYPE_ADHOC);
|
|
|
|
break;
|
2002-09-30 10:50:35 +04:00
|
|
|
case IEEE80211_M_HOSTAP:
|
|
|
|
wi_write_val(sc, WI_RID_PORTTYPE, WI_PORTTYPE_HOSTAP);
|
|
|
|
break;
|
2003-02-25 04:57:35 +03:00
|
|
|
case IEEE80211_M_MONITOR:
|
2003-06-19 10:16:36 +04:00
|
|
|
if (sc->sc_firmware_type == WI_LUCENT)
|
|
|
|
wi_write_val(sc, WI_RID_PORTTYPE, WI_PORTTYPE_ADHOC);
|
2003-02-25 04:57:35 +03:00
|
|
|
wi_cmd(sc, WI_CMD_TEST | (WI_TEST_MONITOR << 8), 0, 0, 0);
|
|
|
|
break;
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
}
|
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
/* Intersil interprets this RID as joining ESS even in IBSS mode */
|
|
|
|
if (sc->sc_firmware_type == WI_LUCENT &&
|
|
|
|
(ic->ic_flags & IEEE80211_F_IBSSON) && ic->ic_des_esslen > 0)
|
|
|
|
wi_write_val(sc, WI_RID_CREATE_IBSS, 1);
|
|
|
|
else
|
|
|
|
wi_write_val(sc, WI_RID_CREATE_IBSS, 0);
|
|
|
|
wi_write_val(sc, WI_RID_MAX_SLEEP, ic->ic_lintval);
|
|
|
|
wi_write_ssid(sc, WI_RID_DESIRED_SSID, ic->ic_des_essid,
|
|
|
|
ic->ic_des_esslen);
|
2003-10-13 12:07:21 +04:00
|
|
|
wi_write_val(sc, WI_RID_OWN_CHNL,
|
|
|
|
ieee80211_chan2ieee(ic, ic->ic_ibss_chan));
|
2002-09-30 10:50:35 +04:00
|
|
|
wi_write_ssid(sc, WI_RID_OWN_SSID, ic->ic_des_essid, ic->ic_des_esslen);
|
2007-12-21 00:08:17 +03:00
|
|
|
IEEE80211_ADDR_COPY(ic->ic_myaddr, CLLADDR(ifp->if_sadl));
|
2002-09-30 10:50:35 +04:00
|
|
|
wi_write_rid(sc, WI_RID_MAC_NODE, ic->ic_myaddr, IEEE80211_ADDR_LEN);
|
2004-07-22 23:51:37 +04:00
|
|
|
if (ic->ic_caps & IEEE80211_C_PMGT)
|
|
|
|
wi_write_val(sc, WI_RID_PM_ENABLED,
|
|
|
|
(ic->ic_flags & IEEE80211_F_PMGTON) ? 1 : 0);
|
2002-09-30 10:50:35 +04:00
|
|
|
|
|
|
|
/* not yet common 802.11 configuration */
|
|
|
|
wi_write_val(sc, WI_RID_MAX_DATALEN, sc->sc_max_datalen);
|
|
|
|
wi_write_val(sc, WI_RID_RTS_THRESH, sc->sc_rts_thresh);
|
2002-11-18 18:10:22 +03:00
|
|
|
if (sc->sc_flags & WI_FLAGS_HAS_FRAGTHR)
|
|
|
|
wi_write_val(sc, WI_RID_FRAG_THRESH, sc->sc_frag_thresh);
|
2002-09-30 10:50:35 +04:00
|
|
|
|
|
|
|
/* driver specific 802.11 configuration */
|
|
|
|
if (sc->sc_flags & WI_FLAGS_HAS_SYSSCALE)
|
|
|
|
wi_write_val(sc, WI_RID_SYSTEM_SCALE, sc->sc_system_scale);
|
|
|
|
if (sc->sc_flags & WI_FLAGS_HAS_ROAMING)
|
|
|
|
wi_write_val(sc, WI_RID_ROAMING_MODE, sc->sc_roaming_mode);
|
|
|
|
if (sc->sc_flags & WI_FLAGS_HAS_MOR)
|
|
|
|
wi_write_val(sc, WI_RID_MICROWAVE_OVEN, sc->sc_microwave_oven);
|
2003-10-16 14:57:35 +04:00
|
|
|
wi_cfg_txrate(sc);
|
2002-09-30 10:50:35 +04:00
|
|
|
wi_write_ssid(sc, WI_RID_NODENAME, sc->sc_nodename, sc->sc_nodelen);
|
|
|
|
|
2005-06-26 08:37:25 +04:00
|
|
|
#ifndef IEEE80211_NO_HOSTAP
|
2002-10-01 20:11:19 +04:00
|
|
|
if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
|
|
|
|
sc->sc_firmware_type == WI_INTERSIL) {
|
2002-09-30 10:50:35 +04:00
|
|
|
wi_write_val(sc, WI_RID_OWN_BEACON_INT, ic->ic_lintval);
|
|
|
|
wi_write_val(sc, WI_RID_DTIM_PERIOD, 1);
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
}
|
2005-06-26 08:37:25 +04:00
|
|
|
#endif /* !IEEE80211_NO_HOSTAP */
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
|
2004-07-22 23:55:08 +04:00
|
|
|
if (sc->sc_firmware_type == WI_INTERSIL) {
|
|
|
|
struct ieee80211_rateset *rs =
|
|
|
|
&ic->ic_sup_rates[IEEE80211_MODE_11B];
|
|
|
|
u_int16_t basic = 0, supported = 0, rate;
|
|
|
|
|
|
|
|
for (i = 0; i < rs->rs_nrates; i++) {
|
|
|
|
switch (rs->rs_rates[i] & IEEE80211_RATE_VAL) {
|
|
|
|
case 2:
|
|
|
|
rate = 1;
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
rate = 2;
|
|
|
|
break;
|
|
|
|
case 11:
|
|
|
|
rate = 4;
|
|
|
|
break;
|
|
|
|
case 22:
|
|
|
|
rate = 8;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
rate = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (rs->rs_rates[i] & IEEE80211_RATE_BASIC)
|
|
|
|
basic |= rate;
|
|
|
|
supported |= rate;
|
|
|
|
}
|
|
|
|
wi_write_val(sc, WI_RID_BASIC_RATE, basic);
|
|
|
|
wi_write_val(sc, WI_RID_SUPPORT_RATE, supported);
|
2003-12-07 08:44:49 +03:00
|
|
|
wi_write_val(sc, WI_RID_ALT_RETRY_COUNT, sc->sc_alt_retry);
|
2004-07-22 23:55:08 +04:00
|
|
|
}
|
2003-12-07 08:44:49 +03:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
/*
|
|
|
|
* Initialize promisc mode.
|
2003-11-16 12:05:53 +03:00
|
|
|
* Being in Host-AP mode causes a great
|
|
|
|
* deal of pain if promiscuous mode is set.
|
2002-09-30 10:50:35 +04:00
|
|
|
* Therefore we avoid confusing the firmware
|
|
|
|
* and always reset promisc mode in Host-AP
|
|
|
|
* mode. Host-AP sees all the packets anyway.
|
|
|
|
*/
|
|
|
|
if (ic->ic_opmode != IEEE80211_M_HOSTAP &&
|
|
|
|
(ifp->if_flags & IFF_PROMISC) != 0) {
|
|
|
|
wi_write_val(sc, WI_RID_PROMISC, 1);
|
|
|
|
} else {
|
|
|
|
wi_write_val(sc, WI_RID_PROMISC, 0);
|
|
|
|
}
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
/* Configure WEP. */
|
2005-06-25 07:56:53 +04:00
|
|
|
if (ic->ic_caps & IEEE80211_C_WEP) {
|
|
|
|
sc->sc_cnfauthmode = ic->ic_bss->ni_authmode;
|
2002-09-30 10:50:35 +04:00
|
|
|
wi_write_wep(sc);
|
2005-06-25 07:56:53 +04:00
|
|
|
}
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
/* Set multicast filter. */
|
|
|
|
wi_write_multi(sc);
|
|
|
|
|
2004-07-23 00:25:23 +04:00
|
|
|
sc->sc_txalloc = 0;
|
2004-07-23 00:23:31 +04:00
|
|
|
sc->sc_txalloced = 0;
|
2004-07-23 00:25:23 +04:00
|
|
|
sc->sc_txqueue = 0;
|
2004-07-23 00:30:43 +04:00
|
|
|
sc->sc_txqueued = 0;
|
2004-07-23 01:56:58 +04:00
|
|
|
sc->sc_txstart = 0;
|
|
|
|
sc->sc_txstarted = 0;
|
2004-07-23 00:23:31 +04:00
|
|
|
|
2002-10-02 21:11:34 +04:00
|
|
|
if (sc->sc_firmware_type != WI_SYMBOL || !wasenabled) {
|
|
|
|
sc->sc_buflen = IEEE80211_MAX_LEN + sizeof(struct wi_frame);
|
|
|
|
if (sc->sc_firmware_type == WI_SYMBOL)
|
|
|
|
sc->sc_buflen = 1585; /* XXX */
|
|
|
|
for (i = 0; i < WI_NTXBUF; i++) {
|
|
|
|
error = wi_alloc_fid(sc, sc->sc_buflen,
|
|
|
|
&sc->sc_txd[i].d_fid);
|
|
|
|
if (error) {
|
2010-11-23 07:33:09 +03:00
|
|
|
aprint_error_dev(sc->sc_dev,
|
|
|
|
"tx buffer allocation failed\n");
|
2002-10-02 21:11:34 +04:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
DPRINTF2(("wi_init: txbuf %d allocated %x\n", i,
|
|
|
|
sc->sc_txd[i].d_fid));
|
2004-07-23 00:23:31 +04:00
|
|
|
++sc->sc_txalloced;
|
2002-09-30 10:50:35 +04:00
|
|
|
}
|
|
|
|
}
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
|
2004-02-10 03:47:41 +03:00
|
|
|
wi_rssdescs_init(&sc->sc_rssd, &sc->sc_rssdfree);
|
2003-12-07 08:44:49 +03:00
|
|
|
|
2003-05-13 10:33:40 +04:00
|
|
|
/* Enable desired port */
|
|
|
|
wi_cmd(sc, WI_CMD_ENABLE | sc->sc_portnum, 0, 0, 0);
|
2002-09-30 10:50:35 +04:00
|
|
|
ifp->if_flags |= IFF_RUNNING;
|
|
|
|
ifp->if_flags &= ~IFF_OACTIVE;
|
2003-10-13 12:07:21 +04:00
|
|
|
ic->ic_state = IEEE80211_S_INIT;
|
|
|
|
|
2002-09-30 19:48:41 +04:00
|
|
|
if (ic->ic_opmode == IEEE80211_M_AHDEMO ||
|
2005-06-25 07:56:53 +04:00
|
|
|
ic->ic_opmode == IEEE80211_M_IBSS ||
|
2003-02-25 04:57:35 +03:00
|
|
|
ic->ic_opmode == IEEE80211_M_MONITOR ||
|
2002-09-30 19:48:41 +04:00
|
|
|
ic->ic_opmode == IEEE80211_M_HOSTAP)
|
2005-06-25 07:56:53 +04:00
|
|
|
ieee80211_create_ibss(ic, ic->ic_ibss_chan);
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
/* Enable interrupts */
|
|
|
|
CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
|
2005-06-26 08:37:25 +04:00
|
|
|
#ifndef IEEE80211_NO_HOSTAP
|
2002-10-02 21:11:34 +04:00
|
|
|
if (!wasenabled &&
|
|
|
|
ic->ic_opmode == IEEE80211_M_HOSTAP &&
|
|
|
|
sc->sc_firmware_type == WI_INTERSIL) {
|
2002-09-30 10:50:35 +04:00
|
|
|
/* XXX: some card need to be re-enabled for hostap */
|
|
|
|
wi_cmd(sc, WI_CMD_DISABLE | WI_PORT0, 0, 0, 0);
|
|
|
|
wi_cmd(sc, WI_CMD_ENABLE | WI_PORT0, 0, 0, 0);
|
|
|
|
}
|
2005-06-26 08:37:25 +04:00
|
|
|
#endif /* !IEEE80211_NO_HOSTAP */
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
if (ic->ic_opmode == IEEE80211_M_STA &&
|
|
|
|
((ic->ic_flags & IEEE80211_F_DESBSSID) ||
|
2003-10-13 12:07:21 +04:00
|
|
|
ic->ic_des_chan != IEEE80211_CHAN_ANYC)) {
|
2002-09-30 10:50:35 +04:00
|
|
|
memset(&join, 0, sizeof(join));
|
|
|
|
if (ic->ic_flags & IEEE80211_F_DESBSSID)
|
|
|
|
IEEE80211_ADDR_COPY(&join.wi_bssid, ic->ic_des_bssid);
|
2003-10-13 12:07:21 +04:00
|
|
|
if (ic->ic_des_chan != IEEE80211_CHAN_ANYC)
|
|
|
|
join.wi_chan =
|
|
|
|
htole16(ieee80211_chan2ieee(ic, ic->ic_des_chan));
|
2002-12-27 11:29:46 +03:00
|
|
|
/* Lucent firmware does not support the JOIN RID. */
|
|
|
|
if (sc->sc_firmware_type != WI_LUCENT)
|
|
|
|
wi_write_rid(sc, WI_RID_JOIN_REQ, &join, sizeof(join));
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
}
|
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
out:
|
|
|
|
if (error) {
|
2010-11-23 07:33:09 +03:00
|
|
|
printf("%s: interface not running\n", device_xname(sc->sc_dev));
|
2002-10-01 20:11:19 +04:00
|
|
|
wi_stop(ifp, 0);
|
2002-09-30 10:50:35 +04:00
|
|
|
}
|
|
|
|
DPRINTF(("wi_init: return %d\n", error));
|
|
|
|
return error;
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
}
|
|
|
|
|
2004-12-14 22:53:46 +03:00
|
|
|
STATIC void
|
|
|
|
wi_txcmd_wait(struct wi_softc *sc)
|
|
|
|
{
|
|
|
|
KASSERT(sc->sc_txcmds == 1);
|
|
|
|
if (sc->sc_status & WI_EV_CMD) {
|
|
|
|
sc->sc_status &= ~WI_EV_CMD;
|
|
|
|
CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_CMD);
|
|
|
|
} else
|
|
|
|
(void)wi_cmd_wait(sc, WI_CMD_TX | WI_RECLAIM, 0);
|
|
|
|
}
|
|
|
|
|
2004-07-22 23:47:24 +04:00
|
|
|
STATIC void
|
2002-09-30 10:50:35 +04:00
|
|
|
wi_stop(struct ifnet *ifp, int disable)
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
{
|
2002-09-30 10:50:35 +04:00
|
|
|
struct wi_softc *sc = ifp->if_softc;
|
2003-10-13 12:07:21 +04:00
|
|
|
struct ieee80211com *ic = &sc->sc_ic;
|
2004-02-10 03:47:41 +03:00
|
|
|
int s;
|
2003-05-13 10:33:40 +04:00
|
|
|
|
2003-05-20 05:29:35 +04:00
|
|
|
if (!sc->sc_enabled)
|
|
|
|
return;
|
|
|
|
|
2003-05-16 05:26:17 +04:00
|
|
|
s = splnet();
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
DPRINTF(("wi_stop: disable %d\n", disable));
|
2003-05-20 05:29:35 +04:00
|
|
|
|
2003-10-13 12:07:21 +04:00
|
|
|
ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
|
2004-12-14 22:53:46 +03:00
|
|
|
|
|
|
|
/* wait for tx command completion (deassoc, deauth) */
|
|
|
|
while (sc->sc_txcmds > 0) {
|
|
|
|
wi_txcmd_wait(sc);
|
|
|
|
wi_cmd_intr(sc);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* TBD wait for deassoc, deauth tx completion? */
|
|
|
|
|
2003-05-20 05:29:35 +04:00
|
|
|
if (!sc->sc_invalid) {
|
2002-09-30 10:50:35 +04:00
|
|
|
CSR_WRITE_2(sc, WI_INT_EN, 0);
|
2003-05-13 10:33:40 +04:00
|
|
|
wi_cmd(sc, WI_CMD_DISABLE | sc->sc_portnum, 0, 0, 0);
|
2002-09-30 10:50:35 +04:00
|
|
|
}
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
|
2004-02-10 03:47:41 +03:00
|
|
|
wi_rssdescs_reset(ic, &sc->sc_rssd, &sc->sc_rssdfree,
|
|
|
|
&sc->sc_txpending);
|
2003-12-07 08:44:49 +03:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
sc->sc_tx_timer = 0;
|
|
|
|
sc->sc_scan_timer = 0;
|
2003-01-01 05:06:47 +03:00
|
|
|
sc->sc_false_syns = 0;
|
2002-09-30 10:50:35 +04:00
|
|
|
sc->sc_naps = 0;
|
|
|
|
ifp->if_flags &= ~(IFF_OACTIVE | IFF_RUNNING);
|
|
|
|
ifp->if_timer = 0;
|
2003-05-13 10:33:40 +04:00
|
|
|
|
2003-05-20 05:29:35 +04:00
|
|
|
if (disable) {
|
2010-11-23 07:33:09 +03:00
|
|
|
(*sc->sc_enable)(sc->sc_dev, 0);
|
2003-05-20 05:29:35 +04:00
|
|
|
sc->sc_enabled = 0;
|
|
|
|
}
|
2003-05-16 05:26:17 +04:00
|
|
|
splx(s);
|
2002-09-30 10:50:35 +04:00
|
|
|
}
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
|
2003-12-07 08:44:49 +03:00
|
|
|
/*
|
|
|
|
* Choose a data rate for a packet len bytes long that suits the packet
|
2004-02-10 03:59:38 +03:00
|
|
|
* type and the wireless conditions.
|
2003-12-07 08:44:49 +03:00
|
|
|
*
|
|
|
|
* TBD Adapt fragmentation threshold.
|
|
|
|
*/
|
2004-07-23 00:06:05 +04:00
|
|
|
STATIC int
|
2003-12-07 08:44:49 +03:00
|
|
|
wi_choose_rate(struct ieee80211com *ic, struct ieee80211_node *ni,
|
|
|
|
struct ieee80211_frame *wh, u_int len)
|
|
|
|
{
|
2005-06-22 10:14:51 +04:00
|
|
|
struct wi_softc *sc = ic->ic_ifp->if_softc;
|
2004-03-17 20:00:34 +03:00
|
|
|
struct wi_node *wn = (void*)ni;
|
|
|
|
struct ieee80211_rssadapt *ra = &wn->wn_rssadapt;
|
|
|
|
int do_not_adapt, i, rateidx, s;
|
2003-12-07 08:44:49 +03:00
|
|
|
|
2004-03-17 20:00:34 +03:00
|
|
|
do_not_adapt = (ic->ic_opmode != IEEE80211_M_HOSTAP) &&
|
|
|
|
(sc->sc_flags & WI_FLAGS_RSSADAPTSTA) == 0;
|
2003-12-07 08:44:49 +03:00
|
|
|
|
2004-03-17 20:00:34 +03:00
|
|
|
s = splnet();
|
2003-12-07 08:44:49 +03:00
|
|
|
|
2004-03-17 20:00:34 +03:00
|
|
|
rateidx = ieee80211_rssadapt_choose(ra, &ni->ni_rates, wh, len,
|
|
|
|
ic->ic_fixed_rate,
|
2005-06-22 10:14:51 +04:00
|
|
|
((ic->ic_ifp->if_flags & IFF_DEBUG) == 0) ? NULL : ic->ic_ifp->if_xname,
|
2004-03-17 20:00:34 +03:00
|
|
|
do_not_adapt);
|
2003-12-07 08:44:49 +03:00
|
|
|
|
2004-07-23 00:06:05 +04:00
|
|
|
ni->ni_txrate = rateidx;
|
|
|
|
|
2003-12-07 08:44:49 +03:00
|
|
|
if (ic->ic_opmode != IEEE80211_M_HOSTAP) {
|
|
|
|
/* choose the slowest pending rate so that we don't
|
|
|
|
* accidentally send a packet on the MAC's queue
|
|
|
|
* too fast. TBD find out if the MAC labels Tx
|
|
|
|
* packets w/ rate when enqueued or dequeued.
|
2005-02-27 03:26:58 +03:00
|
|
|
*/
|
2003-12-07 08:44:49 +03:00
|
|
|
for (i = 0; i < rateidx && sc->sc_txpending[i] == 0; i++);
|
2004-07-23 00:06:05 +04:00
|
|
|
rateidx = i;
|
|
|
|
}
|
|
|
|
|
2003-12-07 08:44:49 +03:00
|
|
|
splx(s);
|
2004-07-23 00:06:05 +04:00
|
|
|
return (rateidx);
|
2003-12-07 08:44:49 +03:00
|
|
|
}
|
|
|
|
|
2004-07-22 23:47:24 +04:00
|
|
|
STATIC void
|
2003-12-07 08:44:49 +03:00
|
|
|
wi_raise_rate(struct ieee80211com *ic, struct ieee80211_rssdesc *id)
|
|
|
|
{
|
|
|
|
struct wi_node *wn;
|
|
|
|
if (id->id_node == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
wn = (void*)id->id_node;
|
|
|
|
ieee80211_rssadapt_raise_rate(ic, &wn->wn_rssadapt, id);
|
|
|
|
}
|
|
|
|
|
2004-07-22 23:47:24 +04:00
|
|
|
STATIC void
|
2003-12-07 08:44:49 +03:00
|
|
|
wi_lower_rate(struct ieee80211com *ic, struct ieee80211_rssdesc *id)
|
|
|
|
{
|
|
|
|
struct ieee80211_node *ni;
|
|
|
|
struct wi_node *wn;
|
|
|
|
int s;
|
|
|
|
|
|
|
|
s = splnet();
|
|
|
|
|
|
|
|
if ((ni = id->id_node) == NULL) {
|
|
|
|
DPRINTF(("wi_lower_rate: missing node\n"));
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
wn = (void *)ni;
|
|
|
|
|
|
|
|
ieee80211_rssadapt_lower_rate(ic, ni, &wn->wn_rssadapt, id);
|
|
|
|
out:
|
|
|
|
splx(s);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2004-07-22 23:47:24 +04:00
|
|
|
STATIC void
|
2002-09-30 10:50:35 +04:00
|
|
|
wi_start(struct ifnet *ifp)
|
|
|
|
{
|
|
|
|
struct wi_softc *sc = ifp->if_softc;
|
|
|
|
struct ieee80211com *ic = &sc->sc_ic;
|
2005-06-22 10:14:51 +04:00
|
|
|
struct ether_header *eh;
|
2003-05-16 05:26:17 +04:00
|
|
|
struct ieee80211_node *ni;
|
2002-09-30 10:50:35 +04:00
|
|
|
struct ieee80211_frame *wh;
|
2003-12-07 08:44:49 +03:00
|
|
|
struct ieee80211_rateset *rs;
|
|
|
|
struct wi_rssdesc *rd;
|
|
|
|
struct ieee80211_rssdesc *id;
|
2003-01-09 11:49:39 +03:00
|
|
|
struct mbuf *m0;
|
2002-09-30 10:50:35 +04:00
|
|
|
struct wi_frame frmhdr;
|
2004-07-23 00:06:05 +04:00
|
|
|
int cur, fid, off, rateidx;
|
2003-05-13 12:35:58 +04:00
|
|
|
|
2003-05-20 05:29:35 +04:00
|
|
|
if (!sc->sc_enabled || sc->sc_invalid)
|
2003-05-13 12:35:58 +04:00
|
|
|
return;
|
2003-05-16 05:26:17 +04:00
|
|
|
if (sc->sc_flags & WI_FLAGS_OUTRANGE)
|
2002-10-04 08:23:20 +04:00
|
|
|
return;
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
memset(&frmhdr, 0, sizeof(frmhdr));
|
2004-07-23 00:25:23 +04:00
|
|
|
cur = sc->sc_txqueue;
|
2002-09-30 10:50:35 +04:00
|
|
|
for (;;) {
|
2003-10-13 12:07:21 +04:00
|
|
|
ni = ic->ic_bss;
|
2004-07-23 00:23:31 +04:00
|
|
|
if (sc->sc_txalloced == 0 || SLIST_EMPTY(&sc->sc_rssdfree)) {
|
2004-07-03 01:20:10 +04:00
|
|
|
ifp->if_flags |= IFF_OACTIVE;
|
|
|
|
break;
|
|
|
|
}
|
2003-04-08 08:31:23 +04:00
|
|
|
if (!IF_IS_EMPTY(&ic->ic_mgtq)) {
|
2002-09-30 10:50:35 +04:00
|
|
|
IF_DEQUEUE(&ic->ic_mgtq, m0);
|
|
|
|
m_copydata(m0, 4, ETHER_ADDR_LEN * 2,
|
2007-03-04 08:59:00 +03:00
|
|
|
(void *)&frmhdr.wi_ehdr);
|
2002-09-30 10:50:35 +04:00
|
|
|
frmhdr.wi_ehdr.ether_type = 0;
|
|
|
|
wh = mtod(m0, struct ieee80211_frame *);
|
2003-11-02 03:55:46 +03:00
|
|
|
ni = (struct ieee80211_node *)m0->m_pkthdr.rcvif;
|
|
|
|
m0->m_pkthdr.rcvif = NULL;
|
2005-06-22 10:14:51 +04:00
|
|
|
} else if (ic->ic_state == IEEE80211_S_RUN) {
|
2002-09-30 10:50:35 +04:00
|
|
|
IFQ_POLL(&ifp->if_snd, m0);
|
2005-06-22 10:14:51 +04:00
|
|
|
if (m0 == NULL)
|
2002-09-30 10:50:35 +04:00
|
|
|
break;
|
|
|
|
IFQ_DEQUEUE(&ifp->if_snd, m0);
|
|
|
|
ifp->if_opackets++;
|
2005-02-27 03:26:58 +03:00
|
|
|
m_copydata(m0, 0, ETHER_HDR_LEN,
|
2007-03-04 08:59:00 +03:00
|
|
|
(void *)&frmhdr.wi_ehdr);
|
2010-04-05 11:19:28 +04:00
|
|
|
bpf_mtap(ifp, m0);
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
|
2005-06-22 10:14:51 +04:00
|
|
|
eh = mtod(m0, struct ether_header *);
|
|
|
|
ni = ieee80211_find_txnode(ic, eh->ether_dhost);
|
|
|
|
if (ni == NULL) {
|
2002-09-30 10:50:35 +04:00
|
|
|
ifp->if_oerrors++;
|
|
|
|
continue;
|
|
|
|
}
|
2005-06-22 10:14:51 +04:00
|
|
|
if ((ni->ni_flags & IEEE80211_NODE_PWR_MGT) &&
|
|
|
|
(m0->m_flags & M_PWR_SAV) == 0) {
|
|
|
|
ieee80211_pwrsave(ic, ni, m0);
|
|
|
|
goto next;
|
2002-09-30 10:50:35 +04:00
|
|
|
}
|
2005-06-22 10:14:51 +04:00
|
|
|
if ((m0 = ieee80211_encap(ic, m0, ni)) == NULL) {
|
|
|
|
ieee80211_free_node(ni);
|
|
|
|
ifp->if_oerrors++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
wh = mtod(m0, struct ieee80211_frame *);
|
|
|
|
} else
|
|
|
|
break;
|
2010-04-05 11:19:28 +04:00
|
|
|
bpf_mtap3(ic->ic_rawbpf, m0);
|
2003-12-07 08:44:49 +03:00
|
|
|
frmhdr.wi_tx_ctl =
|
|
|
|
htole16(WI_ENC_TX_802_11|WI_TXCNTL_TX_EX|WI_TXCNTL_TX_OK);
|
2005-06-26 08:37:25 +04:00
|
|
|
#ifndef IEEE80211_NO_HOSTAP
|
2004-02-10 03:52:12 +03:00
|
|
|
if (ic->ic_opmode == IEEE80211_M_HOSTAP)
|
|
|
|
frmhdr.wi_tx_ctl |= htole16(WI_TXCNTL_ALTRTRY);
|
2002-09-30 10:50:35 +04:00
|
|
|
if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
|
|
|
|
(wh->i_fc[1] & IEEE80211_FC1_WEP)) {
|
2005-06-22 10:14:51 +04:00
|
|
|
if (ieee80211_crypto_encap(ic, ni, m0) == NULL) {
|
2005-07-07 03:44:15 +04:00
|
|
|
m_freem(m0);
|
2002-09-30 10:50:35 +04:00
|
|
|
ifp->if_oerrors++;
|
2003-10-13 12:07:21 +04:00
|
|
|
goto next;
|
2002-09-30 10:50:35 +04:00
|
|
|
}
|
|
|
|
frmhdr.wi_tx_ctl |= htole16(WI_TXCNTL_NOCRYPT);
|
|
|
|
}
|
2005-06-26 08:37:25 +04:00
|
|
|
#endif /* !IEEE80211_NO_HOSTAP */
|
2003-12-07 08:44:49 +03:00
|
|
|
|
2004-07-23 00:06:05 +04:00
|
|
|
rateidx = wi_choose_rate(ic, ni, wh, m0->m_pkthdr.len);
|
|
|
|
rs = &ni->ni_rates;
|
2003-12-07 08:44:49 +03:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
if (sc->sc_drvbpf) {
|
2003-11-16 12:02:42 +03:00
|
|
|
struct wi_tx_radiotap_header *tap = &sc->sc_txtap;
|
|
|
|
|
2004-07-23 00:13:20 +04:00
|
|
|
tap->wt_rate = rs->rs_rates[rateidx];
|
2004-02-10 03:32:40 +03:00
|
|
|
tap->wt_chan_freq =
|
|
|
|
htole16(ic->ic_bss->ni_chan->ic_freq);
|
|
|
|
tap->wt_chan_flags =
|
|
|
|
htole16(ic->ic_bss->ni_chan->ic_flags);
|
|
|
|
/* TBD tap->wt_flags */
|
2003-11-16 12:02:42 +03:00
|
|
|
|
2010-04-05 11:19:28 +04:00
|
|
|
bpf_mtap2(sc->sc_drvbpf, tap, tap->wt_ihdr.it_len, m0);
|
2002-09-30 10:50:35 +04:00
|
|
|
}
|
2004-07-23 00:06:05 +04:00
|
|
|
|
2003-12-07 08:44:49 +03:00
|
|
|
rd = SLIST_FIRST(&sc->sc_rssdfree);
|
|
|
|
id = &rd->rd_desc;
|
|
|
|
id->id_len = m0->m_pkthdr.len;
|
2004-07-23 00:06:05 +04:00
|
|
|
id->id_rateidx = ni->ni_txrate;
|
2003-12-07 08:44:49 +03:00
|
|
|
id->id_rssi = ni->ni_rssi;
|
|
|
|
|
|
|
|
frmhdr.wi_tx_idx = rd - sc->sc_rssd;
|
|
|
|
|
|
|
|
if (ic->ic_opmode == IEEE80211_M_HOSTAP)
|
2004-07-23 00:06:05 +04:00
|
|
|
frmhdr.wi_tx_rate = 5 * (rs->rs_rates[rateidx] &
|
2003-12-07 08:44:49 +03:00
|
|
|
IEEE80211_RATE_VAL);
|
2004-02-10 03:59:38 +03:00
|
|
|
else if (sc->sc_flags & WI_FLAGS_RSSADAPTSTA)
|
2004-07-23 00:06:05 +04:00
|
|
|
(void)wi_write_txrate(sc, rs->rs_rates[rateidx]);
|
2003-12-07 08:44:49 +03:00
|
|
|
|
2003-10-20 02:00:54 +04:00
|
|
|
m_copydata(m0, 0, sizeof(struct ieee80211_frame),
|
2007-03-04 08:59:00 +03:00
|
|
|
(void *)&frmhdr.wi_whdr);
|
2003-10-20 02:00:54 +04:00
|
|
|
m_adj(m0, sizeof(struct ieee80211_frame));
|
|
|
|
frmhdr.wi_dat_len = htole16(m0->m_pkthdr.len);
|
2003-05-13 10:48:56 +04:00
|
|
|
if (IFF_DUMPPKTS(ifp))
|
|
|
|
wi_dump_pkt(&frmhdr, ni, -1);
|
2002-09-30 10:50:35 +04:00
|
|
|
fid = sc->sc_txd[cur].d_fid;
|
|
|
|
off = sizeof(frmhdr);
|
2003-01-09 11:49:39 +03:00
|
|
|
if (wi_write_bap(sc, fid, 0, &frmhdr, sizeof(frmhdr)) != 0 ||
|
|
|
|
wi_mwrite_bap(sc, fid, off, m0, m0->m_pkthdr.len) != 0) {
|
2010-11-23 07:33:09 +03:00
|
|
|
aprint_error_dev(sc->sc_dev, "%s write fid %x failed\n",
|
2008-04-08 16:07:25 +04:00
|
|
|
__func__, fid);
|
2003-01-09 11:49:39 +03:00
|
|
|
ifp->if_oerrors++;
|
|
|
|
m_freem(m0);
|
2003-10-13 12:07:21 +04:00
|
|
|
goto next;
|
2002-09-30 10:50:35 +04:00
|
|
|
}
|
|
|
|
m_freem(m0);
|
2004-07-23 00:06:05 +04:00
|
|
|
sc->sc_txpending[ni->ni_txrate]++;
|
2004-07-23 00:23:31 +04:00
|
|
|
--sc->sc_txalloced;
|
2004-07-23 00:30:43 +04:00
|
|
|
if (sc->sc_txqueued++ == 0) {
|
2004-07-23 01:56:58 +04:00
|
|
|
#ifdef DIAGNOSTIC
|
|
|
|
if (cur != sc->sc_txstart)
|
|
|
|
printf("%s: ring is desynchronized\n",
|
2010-11-23 07:33:09 +03:00
|
|
|
device_xname(sc->sc_dev));
|
2004-07-23 01:56:58 +04:00
|
|
|
#endif
|
|
|
|
wi_push_packet(sc);
|
|
|
|
} else {
|
|
|
|
#ifdef WI_RING_DEBUG
|
|
|
|
printf("%s: queue %04x, alloc %d queue %d start %d alloced %d queued %d started %d\n",
|
2010-11-23 07:33:09 +03:00
|
|
|
device_xname(sc->sc_dev), fid,
|
2004-07-23 01:56:58 +04:00
|
|
|
sc->sc_txalloc, sc->sc_txqueue, sc->sc_txstart,
|
|
|
|
sc->sc_txalloced, sc->sc_txqueued, sc->sc_txstarted);
|
|
|
|
#endif
|
2002-09-30 10:50:35 +04:00
|
|
|
}
|
2004-07-23 00:25:23 +04:00
|
|
|
sc->sc_txqueue = cur = (cur + 1) % WI_NTXBUF;
|
2003-12-07 08:44:49 +03:00
|
|
|
SLIST_REMOVE_HEAD(&sc->sc_rssdfree, rd_next);
|
2004-02-10 03:59:38 +03:00
|
|
|
id->id_node = ni;
|
|
|
|
continue;
|
2003-10-13 12:07:21 +04:00
|
|
|
next:
|
2004-08-10 04:57:20 +04:00
|
|
|
if (ni != NULL)
|
2005-06-22 10:14:51 +04:00
|
|
|
ieee80211_free_node(ni);
|
2002-09-30 10:50:35 +04:00
|
|
|
}
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-07-22 23:47:24 +04:00
|
|
|
STATIC int
|
2002-09-30 10:50:35 +04:00
|
|
|
wi_reset(struct wi_softc *sc)
|
1999-07-15 02:24:07 +04:00
|
|
|
{
|
2002-09-30 10:50:35 +04:00
|
|
|
int i, error;
|
1999-07-15 02:24:07 +04:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
DPRINTF(("wi_reset\n"));
|
2003-03-27 07:34:16 +03:00
|
|
|
|
|
|
|
if (sc->sc_reset)
|
|
|
|
(*sc->sc_reset)(sc);
|
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
error = 0;
|
|
|
|
for (i = 0; i < 5; i++) {
|
2005-06-22 10:14:51 +04:00
|
|
|
if (sc->sc_invalid)
|
|
|
|
return ENXIO;
|
2002-09-30 10:50:35 +04:00
|
|
|
DELAY(20*1000); /* XXX: way too long! */
|
|
|
|
if ((error = wi_cmd(sc, WI_CMD_INI, 0, 0, 0)) == 0)
|
|
|
|
break;
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
}
|
2002-09-30 10:50:35 +04:00
|
|
|
if (error) {
|
2010-11-23 07:33:09 +03:00
|
|
|
aprint_error_dev(sc->sc_dev, "init failed\n");
|
2002-09-30 10:50:35 +04:00
|
|
|
return error;
|
1999-07-15 02:24:07 +04:00
|
|
|
}
|
2002-09-30 10:50:35 +04:00
|
|
|
CSR_WRITE_2(sc, WI_INT_EN, 0);
|
|
|
|
CSR_WRITE_2(sc, WI_EVENT_ACK, ~0);
|
1999-07-15 02:24:07 +04:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
/* Calibrate timer. */
|
|
|
|
wi_write_val(sc, WI_RID_TICK_TIME, 0);
|
|
|
|
return 0;
|
|
|
|
}
|
1999-07-15 02:24:07 +04:00
|
|
|
|
2004-07-22 23:47:24 +04:00
|
|
|
STATIC void
|
2002-09-30 10:50:35 +04:00
|
|
|
wi_watchdog(struct ifnet *ifp)
|
|
|
|
{
|
|
|
|
struct wi_softc *sc = ifp->if_softc;
|
|
|
|
|
|
|
|
ifp->if_timer = 0;
|
|
|
|
if (!sc->sc_enabled)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (sc->sc_tx_timer) {
|
|
|
|
if (--sc->sc_tx_timer == 0) {
|
|
|
|
printf("%s: device timeout\n", ifp->if_xname);
|
|
|
|
ifp->if_oerrors++;
|
|
|
|
wi_init(ifp);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
ifp->if_timer = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sc->sc_scan_timer) {
|
|
|
|
if (--sc->sc_scan_timer <= WI_SCAN_WAIT - WI_SCAN_INQWAIT &&
|
|
|
|
sc->sc_firmware_type == WI_INTERSIL) {
|
|
|
|
DPRINTF(("wi_watchdog: inquire scan\n"));
|
|
|
|
wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_SCAN_RESULTS, 0, 0);
|
|
|
|
}
|
|
|
|
if (sc->sc_scan_timer)
|
|
|
|
ifp->if_timer = 1;
|
2000-02-28 02:10:51 +03:00
|
|
|
}
|
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
/* TODO: rate control */
|
2005-06-22 10:14:51 +04:00
|
|
|
ieee80211_watchdog(&sc->sc_ic);
|
1999-07-15 02:24:07 +04:00
|
|
|
}
|
|
|
|
|
2011-08-15 22:24:34 +04:00
|
|
|
static int
|
|
|
|
wi_ioctl_enter(struct wi_softc *sc)
|
|
|
|
{
|
|
|
|
int rc = 0;
|
|
|
|
|
|
|
|
mutex_enter(&sc->sc_ioctl_mtx);
|
|
|
|
sc->sc_ioctl_nwait++;
|
|
|
|
while (sc->sc_ioctl_lwp != NULL && sc->sc_ioctl_lwp != curlwp) {
|
|
|
|
rc = sc->sc_ioctl_gone
|
|
|
|
? ENXIO
|
|
|
|
: cv_wait_sig(&sc->sc_ioctl_cv, &sc->sc_ioctl_mtx);
|
|
|
|
if (rc != 0)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (rc == 0) {
|
|
|
|
sc->sc_ioctl_lwp = curlwp;
|
|
|
|
sc->sc_ioctl_depth++;
|
|
|
|
}
|
|
|
|
if (--sc->sc_ioctl_nwait == 0)
|
|
|
|
cv_signal(&sc->sc_ioctl_cv);
|
|
|
|
mutex_exit(&sc->sc_ioctl_mtx);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
wi_ioctl_exit(struct wi_softc *sc)
|
|
|
|
{
|
|
|
|
KASSERT(sc->sc_ioctl_lwp == curlwp);
|
|
|
|
mutex_enter(&sc->sc_ioctl_mtx);
|
|
|
|
if (--sc->sc_ioctl_depth == 0) {
|
|
|
|
sc->sc_ioctl_lwp = NULL;
|
|
|
|
cv_signal(&sc->sc_ioctl_cv);
|
|
|
|
}
|
|
|
|
mutex_exit(&sc->sc_ioctl_mtx);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
wi_ioctl_init(struct wi_softc *sc)
|
|
|
|
{
|
|
|
|
mutex_init(&sc->sc_ioctl_mtx, MUTEX_DEFAULT, IPL_NONE);
|
|
|
|
cv_init(&sc->sc_ioctl_cv, device_xname(sc->sc_dev));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
wi_ioctl_drain(struct wi_softc *sc)
|
|
|
|
{
|
|
|
|
wi_ioctl_enter(sc);
|
|
|
|
|
|
|
|
mutex_enter(&sc->sc_ioctl_mtx);
|
|
|
|
sc->sc_ioctl_gone = true;
|
|
|
|
cv_broadcast(&sc->sc_ioctl_cv);
|
|
|
|
while (sc->sc_ioctl_nwait != 0)
|
|
|
|
cv_wait(&sc->sc_ioctl_cv, &sc->sc_ioctl_mtx);
|
|
|
|
mutex_exit(&sc->sc_ioctl_mtx);
|
|
|
|
|
|
|
|
wi_ioctl_exit(sc);
|
|
|
|
|
|
|
|
mutex_destroy(&sc->sc_ioctl_mtx);
|
|
|
|
cv_destroy(&sc->sc_ioctl_cv);
|
|
|
|
}
|
|
|
|
|
2004-07-22 23:47:24 +04:00
|
|
|
STATIC int
|
2007-03-04 08:59:00 +03:00
|
|
|
wi_ioctl(struct ifnet *ifp, u_long cmd, void *data)
|
1999-07-15 02:24:07 +04:00
|
|
|
{
|
2002-09-30 10:50:35 +04:00
|
|
|
struct wi_softc *sc = ifp->if_softc;
|
|
|
|
struct ieee80211com *ic = &sc->sc_ic;
|
|
|
|
struct ifreq *ifr = (struct ifreq *)data;
|
2003-05-16 05:26:17 +04:00
|
|
|
int s, error = 0;
|
1999-07-15 02:24:07 +04:00
|
|
|
|
2010-11-23 07:33:09 +03:00
|
|
|
if (!device_is_active(sc->sc_dev))
|
2002-09-30 10:50:35 +04:00
|
|
|
return ENXIO;
|
2000-02-28 02:10:51 +03:00
|
|
|
|
2003-05-16 05:26:17 +04:00
|
|
|
s = splnet();
|
1999-07-15 02:24:07 +04:00
|
|
|
|
2011-08-15 22:24:34 +04:00
|
|
|
if ((error = wi_ioctl_enter(sc)) != 0)
|
|
|
|
return error;
|
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
switch (cmd) {
|
2001-05-06 07:26:38 +04:00
|
|
|
case SIOCSIFFLAGS:
|
*** Summary ***
When a link-layer address changes (e.g., ifconfig ex0 link
02:de:ad:be:ef:02 active), send a gratuitous ARP and/or a Neighbor
Advertisement to update the network-/link-layer address bindings
on our LAN peers.
Refuse a change of ethernet address to the address 00:00:00:00:00:00
or to any multicast/broadcast address. (Thanks matt@.)
Reorder ifnet ioctl operations so that driver ioctls may inherit
the functions of their "class"---ether_ioctl(), fddi_ioctl(), et
cetera---and the class ioctls may inherit from the generic ioctl,
ifioctl_common(), but both driver- and class-ioctls may override
the generic behavior. Make network drivers share more code.
Distinguish a "factory" link-layer address from others for the
purposes of both protecting that address from deletion and computing
EUI64.
Return consistent, appropriate error codes from network drivers.
Improve readability. KNF.
*** Details ***
In if_attach(), always initialize the interface ioctl routine,
ifnet->if_ioctl, if the driver has not already initialized it.
Delete if_ioctl == NULL tests everywhere else, because it cannot
happen.
In the ioctl routines of network interfaces, inherit common ioctl
behaviors by calling either ifioctl_common() or whichever ioctl
routine is appropriate for the class of interface---e.g., ether_ioctl()
for ethernets.
Stop (ab)using SIOCSIFADDR and start to use SIOCINITIFADDR. In
the user->kernel interface, SIOCSIFADDR's argument was an ifreq,
but on the protocol->ifnet interface, SIOCSIFADDR's argument was
an ifaddr. That was confusing, and it would work against me as I
make it possible for a network interface to overload most ioctls.
On the protocol->ifnet interface, replace SIOCSIFADDR with
SIOCINITIFADDR. In ifioctl(), return EPERM if userland tries to
invoke SIOCINITIFADDR.
In ifioctl(), give the interface the first shot at handling most
interface ioctls, and give the protocol the second shot, instead
of the other way around. Finally, let compatibility code (COMPAT_OSOCK)
take a shot.
Pull device initialization out of switch statements under
SIOCINITIFADDR. For example, pull ..._init() out of any switch
statement that looks like this:
switch (...->sa_family) {
case ...:
..._init();
...
break;
...
default:
..._init();
...
break;
}
Rewrite many if-else clauses that handle all permutations of IFF_UP
and IFF_RUNNING to use a switch statement,
switch (x & (IFF_UP|IFF_RUNNING)) {
case 0:
...
break;
case IFF_RUNNING:
...
break;
case IFF_UP:
...
break;
case IFF_UP|IFF_RUNNING:
...
break;
}
unifdef lots of code containing #ifdef FreeBSD, #ifdef NetBSD, and
#ifdef SIOCSIFMTU, especially in fwip(4) and in ndis(4).
In ipw(4), remove an if_set_sadl() call that is out of place.
In nfe(4), reuse the jumbo MTU logic in ether_ioctl().
Let ethernets register a callback for setting h/w state such as
promiscuous mode and the multicast filter in accord with a change
in the if_flags: ether_set_ifflags_cb() registers a callback that
returns ENETRESET if the caller should reset the ethernet by calling
if_init(), 0 on success, != 0 on failure. Pull common code from
ex(4), gem(4), nfe(4), sip(4), tlp(4), vge(4) into ether_ioctl(),
and register if_flags callbacks for those drivers.
Return ENOTTY instead of EINVAL for inappropriate ioctls. In
zyd(4), use ENXIO instead of ENOTTY to indicate that the device is
not any longer attached.
Add to if_set_sadl() a boolean 'factory' argument that indicates
whether a link-layer address was assigned by the factory or some
other source. In a comment, recommend using the factory address
for generating an EUI64, and update in6_get_hw_ifid() to prefer a
factory address to any other link-layer address.
Add a routing message, RTM_LLINFO_UPD, that tells protocols to
update the binding of network-layer addresses to link-layer addresses.
Implement this message in IPv4 and IPv6 by sending a gratuitous
ARP or a neighbor advertisement, respectively. Generate RTM_LLINFO_UPD
messages on a change of an interface's link-layer address.
In ether_ioctl(), do not let SIOCALIFADDR set a link-layer address
that is broadcast/multicast or equal to 00:00:00:00:00:00.
Make ether_ioctl() call ifioctl_common() to handle ioctls that it
does not understand.
In gif(4), initialize if_softc and use it, instead of assuming that
the gif_softc and ifp overlap.
Let ifioctl_common() handle SIOCGIFADDR.
Sprinkle rtcache_invariants(), which checks on DIAGNOSTIC kernels
that certain invariants on a struct route are satisfied.
In agr(4), rewrite agr_ioctl_filter() to be a bit more explicit
about the ioctls that we do not allow on an agr(4) member interface.
bzero -> memset. Delete unnecessary casts to void *. Use
sockaddr_in_init() and sockaddr_in6_init(). Compare pointers with
NULL instead of "testing truth". Replace some instances of (type
*)0 with NULL. Change some K&R prototypes to ANSI C, and join
lines.
2008-11-07 03:20:01 +03:00
|
|
|
if ((error = ifioctl_common(ifp, cmd, data)) != 0)
|
|
|
|
break;
|
2003-05-13 12:35:58 +04:00
|
|
|
/*
|
|
|
|
* Can't do promisc and hostap at the same time. If all that's
|
|
|
|
* changing is the promisc flag, try to short-circuit a call to
|
|
|
|
* wi_init() by just setting PROMISC in the hardware.
|
|
|
|
*/
|
2001-05-08 20:42:49 +04:00
|
|
|
if (ifp->if_flags & IFF_UP) {
|
|
|
|
if (sc->sc_enabled) {
|
2002-09-30 10:50:35 +04:00
|
|
|
if (ic->ic_opmode != IEEE80211_M_HOSTAP &&
|
|
|
|
(ifp->if_flags & IFF_PROMISC) != 0)
|
|
|
|
wi_write_val(sc, WI_RID_PROMISC, 1);
|
|
|
|
else
|
|
|
|
wi_write_val(sc, WI_RID_PROMISC, 0);
|
|
|
|
} else
|
|
|
|
error = wi_init(ifp);
|
|
|
|
} else if (sc->sc_enabled)
|
|
|
|
wi_stop(ifp, 1);
|
2001-05-06 07:26:38 +04:00
|
|
|
break;
|
2000-03-02 08:00:47 +03:00
|
|
|
case SIOCSIFMEDIA:
|
|
|
|
case SIOCGIFMEDIA:
|
2003-07-07 00:01:17 +04:00
|
|
|
error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
|
2000-03-02 08:00:47 +03:00
|
|
|
break;
|
2002-09-30 10:50:35 +04:00
|
|
|
case SIOCADDMULTI:
|
|
|
|
case SIOCDELMULTI:
|
2007-09-01 11:32:22 +04:00
|
|
|
if ((error = ether_ioctl(ifp, cmd, data)) == ENETRESET) {
|
2004-10-30 22:08:34 +04:00
|
|
|
if (ifp->if_flags & IFF_RUNNING) {
|
2002-09-30 10:50:35 +04:00
|
|
|
/* do not rescan */
|
|
|
|
error = wi_write_multi(sc);
|
|
|
|
} else
|
|
|
|
error = 0;
|
1999-07-15 02:24:07 +04:00
|
|
|
}
|
|
|
|
break;
|
2002-09-30 10:50:35 +04:00
|
|
|
case SIOCGIFGENERIC:
|
|
|
|
error = wi_get_cfg(ifp, cmd, data);
|
|
|
|
break;
|
|
|
|
case SIOCSIFGENERIC:
|
2009-04-16 00:44:24 +04:00
|
|
|
error = kauth_authorize_network(curlwp->l_cred,
|
|
|
|
KAUTH_NETWORK_INTERFACE,
|
|
|
|
KAUTH_REQ_NETWORK_INTERFACE_SETPRIV, ifp, KAUTH_ARG(cmd),
|
|
|
|
NULL);
|
1999-07-15 02:24:07 +04:00
|
|
|
if (error)
|
|
|
|
break;
|
2002-09-30 10:50:35 +04:00
|
|
|
error = wi_set_cfg(ifp, cmd, data);
|
|
|
|
if (error == ENETRESET) {
|
2004-10-30 22:08:34 +04:00
|
|
|
if (ifp->if_flags & IFF_RUNNING)
|
2002-09-30 10:50:35 +04:00
|
|
|
error = wi_init(ifp);
|
|
|
|
else
|
|
|
|
error = 0;
|
2000-07-05 06:35:53 +04:00
|
|
|
}
|
2000-12-12 07:04:29 +03:00
|
|
|
break;
|
2002-12-27 11:29:46 +03:00
|
|
|
case SIOCS80211BSSID:
|
|
|
|
if (sc->sc_firmware_type == WI_LUCENT) {
|
|
|
|
error = ENODEV;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* fall through */
|
1999-07-15 02:24:07 +04:00
|
|
|
default:
|
2005-07-14 04:28:51 +04:00
|
|
|
ic->ic_flags |= sc->sc_ic_flags;
|
2005-06-22 10:14:51 +04:00
|
|
|
error = ieee80211_ioctl(&sc->sc_ic, cmd, data);
|
2005-07-14 04:28:51 +04:00
|
|
|
sc->sc_ic_flags = ic->ic_flags & IEEE80211_F_DROPUNENC;
|
2002-09-30 10:50:35 +04:00
|
|
|
if (error == ENETRESET) {
|
|
|
|
if (sc->sc_enabled)
|
|
|
|
error = wi_init(ifp);
|
|
|
|
else
|
|
|
|
error = 0;
|
|
|
|
}
|
1999-07-15 02:24:07 +04:00
|
|
|
break;
|
|
|
|
}
|
2005-07-14 04:28:51 +04:00
|
|
|
wi_mend_flags(sc, ic->ic_state);
|
2011-08-15 22:24:34 +04:00
|
|
|
wi_ioctl_exit(sc);
|
2003-05-16 05:26:17 +04:00
|
|
|
splx(s);
|
2002-09-30 10:50:35 +04:00
|
|
|
return error;
|
1999-07-15 02:24:07 +04:00
|
|
|
}
|
|
|
|
|
2004-07-22 23:47:24 +04:00
|
|
|
STATIC int
|
2002-09-30 10:50:35 +04:00
|
|
|
wi_media_change(struct ifnet *ifp)
|
1999-07-15 02:24:07 +04:00
|
|
|
{
|
2000-10-12 06:24:08 +04:00
|
|
|
struct wi_softc *sc = ifp->if_softc;
|
2002-09-30 10:50:35 +04:00
|
|
|
struct ieee80211com *ic = &sc->sc_ic;
|
2004-06-06 09:32:17 +04:00
|
|
|
int error;
|
1999-07-15 02:24:07 +04:00
|
|
|
|
2004-06-06 09:32:17 +04:00
|
|
|
error = ieee80211_media_change(ifp);
|
2002-09-30 10:50:35 +04:00
|
|
|
if (error == ENETRESET) {
|
|
|
|
if (sc->sc_enabled)
|
|
|
|
error = wi_init(ifp);
|
|
|
|
else
|
|
|
|
error = 0;
|
|
|
|
}
|
2003-07-07 00:01:17 +04:00
|
|
|
ifp->if_baudrate = ifmedia_baudrate(ic->ic_media.ifm_cur->ifm_media);
|
1999-07-15 02:24:07 +04:00
|
|
|
|
2002-09-30 19:48:41 +04:00
|
|
|
return error;
|
1999-07-15 02:24:07 +04:00
|
|
|
}
|
|
|
|
|
2004-07-22 23:47:24 +04:00
|
|
|
STATIC void
|
2002-09-30 10:50:35 +04:00
|
|
|
wi_media_status(struct ifnet *ifp, struct ifmediareq *imr)
|
1999-07-15 02:24:07 +04:00
|
|
|
{
|
2002-09-30 10:50:35 +04:00
|
|
|
struct wi_softc *sc = ifp->if_softc;
|
|
|
|
struct ieee80211com *ic = &sc->sc_ic;
|
|
|
|
u_int16_t val;
|
2004-12-13 20:21:35 +03:00
|
|
|
int rate;
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
if (sc->sc_enabled == 0) {
|
|
|
|
imr->ifm_active = IFM_IEEE80211 | IFM_NONE;
|
|
|
|
imr->ifm_status = 0;
|
|
|
|
return;
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
}
|
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
imr->ifm_status = IFM_AVALID;
|
|
|
|
imr->ifm_active = IFM_IEEE80211;
|
2002-10-04 08:23:20 +04:00
|
|
|
if (ic->ic_state == IEEE80211_S_RUN &&
|
|
|
|
(sc->sc_flags & WI_FLAGS_OUTRANGE) == 0)
|
2002-09-30 10:50:35 +04:00
|
|
|
imr->ifm_status |= IFM_ACTIVE;
|
2004-12-13 20:21:35 +03:00
|
|
|
if (wi_read_xrid(sc, WI_RID_CUR_TX_RATE, &val, sizeof(val)) == 0) {
|
2002-10-04 08:23:20 +04:00
|
|
|
/* convert to 802.11 rate */
|
2003-11-16 12:41:01 +03:00
|
|
|
val = le16toh(val);
|
2002-10-04 08:23:20 +04:00
|
|
|
rate = val * 2;
|
|
|
|
if (sc->sc_firmware_type == WI_LUCENT) {
|
|
|
|
if (rate == 10)
|
|
|
|
rate = 11; /* 5.5Mbps */
|
|
|
|
} else {
|
|
|
|
if (rate == 4*2)
|
|
|
|
rate = 11; /* 5.5Mbps */
|
|
|
|
else if (rate == 8*2)
|
|
|
|
rate = 22; /* 11Mbps */
|
2002-09-30 10:50:35 +04:00
|
|
|
}
|
2004-08-07 21:12:44 +04:00
|
|
|
} else
|
|
|
|
rate = 0;
|
2003-10-13 12:07:21 +04:00
|
|
|
imr->ifm_active |= ieee80211_rate2media(ic, rate, IEEE80211_MODE_11B);
|
2002-09-30 10:50:35 +04:00
|
|
|
switch (ic->ic_opmode) {
|
|
|
|
case IEEE80211_M_STA:
|
|
|
|
break;
|
2002-09-30 19:48:41 +04:00
|
|
|
case IEEE80211_M_IBSS:
|
2002-09-30 10:50:35 +04:00
|
|
|
imr->ifm_active |= IFM_IEEE80211_ADHOC;
|
2002-09-30 19:48:41 +04:00
|
|
|
break;
|
|
|
|
case IEEE80211_M_AHDEMO:
|
|
|
|
imr->ifm_active |= IFM_IEEE80211_ADHOC | IFM_FLAG0;
|
2002-09-30 10:50:35 +04:00
|
|
|
break;
|
|
|
|
case IEEE80211_M_HOSTAP:
|
|
|
|
imr->ifm_active |= IFM_IEEE80211_HOSTAP;
|
|
|
|
break;
|
2003-02-25 04:57:35 +03:00
|
|
|
case IEEE80211_M_MONITOR:
|
|
|
|
imr->ifm_active |= IFM_IEEE80211_MONITOR;
|
|
|
|
break;
|
2002-09-30 10:50:35 +04:00
|
|
|
}
|
|
|
|
}
|
1999-07-15 02:24:07 +04:00
|
|
|
|
2004-07-22 23:47:24 +04:00
|
|
|
STATIC struct ieee80211_node *
|
2006-11-16 04:32:37 +03:00
|
|
|
wi_node_alloc(struct ieee80211_node_table *nt)
|
2003-12-07 08:44:49 +03:00
|
|
|
{
|
|
|
|
struct wi_node *wn =
|
|
|
|
malloc(sizeof(struct wi_node), M_DEVBUF, M_NOWAIT | M_ZERO);
|
|
|
|
return wn ? &wn->wn_node : NULL;
|
|
|
|
}
|
|
|
|
|
2004-07-22 23:47:24 +04:00
|
|
|
STATIC void
|
2005-06-22 10:14:51 +04:00
|
|
|
wi_node_free(struct ieee80211_node *ni)
|
2003-12-07 08:44:49 +03:00
|
|
|
{
|
2005-06-22 10:14:51 +04:00
|
|
|
struct wi_softc *sc = ni->ni_ic->ic_ifp->if_softc;
|
2003-12-07 08:44:49 +03:00
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < WI_NTXRSS; i++) {
|
|
|
|
if (sc->sc_rssd[i].rd_desc.id_node == ni)
|
|
|
|
sc->sc_rssd[i].rd_desc.id_node = NULL;
|
|
|
|
}
|
|
|
|
free(ni, M_DEVBUF);
|
|
|
|
}
|
|
|
|
|
2004-07-22 23:47:24 +04:00
|
|
|
STATIC void
|
2003-01-01 05:06:47 +03:00
|
|
|
wi_sync_bssid(struct wi_softc *sc, u_int8_t new_bssid[IEEE80211_ADDR_LEN])
|
|
|
|
{
|
|
|
|
struct ieee80211com *ic = &sc->sc_ic;
|
2003-10-13 12:07:21 +04:00
|
|
|
struct ieee80211_node *ni = ic->ic_bss;
|
2005-06-22 10:14:51 +04:00
|
|
|
struct ifnet *ifp = &sc->sc_if;
|
2003-01-01 05:06:47 +03:00
|
|
|
|
|
|
|
if (IEEE80211_ADDR_EQ(new_bssid, ni->ni_bssid))
|
|
|
|
return;
|
|
|
|
|
2003-05-13 12:35:58 +04:00
|
|
|
DPRINTF(("wi_sync_bssid: bssid %s -> ", ether_sprintf(ni->ni_bssid)));
|
2003-01-01 05:06:47 +03:00
|
|
|
DPRINTF(("%s ?\n", ether_sprintf(new_bssid)));
|
|
|
|
|
|
|
|
/* In promiscuous mode, the BSSID field is not a reliable
|
|
|
|
* indicator of the firmware's BSSID. Damp spurious
|
|
|
|
* change-of-BSSID indications.
|
|
|
|
*/
|
|
|
|
if ((ifp->if_flags & IFF_PROMISC) != 0 &&
|
2004-09-28 04:42:11 +04:00
|
|
|
!ppsratecheck(&sc->sc_last_syn, &sc->sc_false_syns,
|
|
|
|
WI_MAX_FALSE_SYNS))
|
2003-01-01 05:06:47 +03:00
|
|
|
return;
|
|
|
|
|
2005-06-25 07:56:53 +04:00
|
|
|
sc->sc_false_syns = MAX(0, sc->sc_false_syns - 1);
|
|
|
|
/*
|
|
|
|
* XXX hack; we should create a new node with the new bssid
|
|
|
|
* and replace the existing ic_bss with it but since we don't
|
|
|
|
* process management frames to collect state we cheat by
|
|
|
|
* reusing the existing node as we know wi_newstate will be
|
|
|
|
* called and it will overwrite the node state.
|
|
|
|
*/
|
|
|
|
ieee80211_sta_join(ic, ieee80211_ref_node(ni));
|
2003-01-01 05:06:47 +03:00
|
|
|
}
|
|
|
|
|
2005-12-24 23:27:29 +03:00
|
|
|
static inline void
|
2003-12-07 08:44:49 +03:00
|
|
|
wi_rssadapt_input(struct ieee80211com *ic, struct ieee80211_node *ni,
|
2006-11-16 04:32:37 +03:00
|
|
|
struct ieee80211_frame *wh, int rssi)
|
2003-12-07 08:44:49 +03:00
|
|
|
{
|
|
|
|
struct wi_node *wn;
|
|
|
|
|
|
|
|
if (ni == NULL) {
|
|
|
|
printf("%s: null node", __func__);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
wn = (void*)ni;
|
|
|
|
ieee80211_rssadapt_input(ic, ni, &wn->wn_rssadapt, rssi);
|
|
|
|
}
|
|
|
|
|
2004-07-22 23:47:24 +04:00
|
|
|
STATIC void
|
2002-09-30 10:50:35 +04:00
|
|
|
wi_rx_intr(struct wi_softc *sc)
|
|
|
|
{
|
|
|
|
struct ieee80211com *ic = &sc->sc_ic;
|
2005-06-22 10:14:51 +04:00
|
|
|
struct ifnet *ifp = &sc->sc_if;
|
2003-10-13 12:07:21 +04:00
|
|
|
struct ieee80211_node *ni;
|
2002-09-30 10:50:35 +04:00
|
|
|
struct wi_frame frmhdr;
|
|
|
|
struct mbuf *m;
|
|
|
|
struct ieee80211_frame *wh;
|
2002-10-02 21:11:34 +04:00
|
|
|
int fid, len, off, rssi;
|
2003-01-01 05:06:47 +03:00
|
|
|
u_int8_t dir;
|
2002-09-30 10:50:35 +04:00
|
|
|
u_int16_t status;
|
2002-10-02 21:11:34 +04:00
|
|
|
u_int32_t rstamp;
|
1999-07-15 02:24:07 +04:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
fid = CSR_READ_2(sc, WI_RX_FID);
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
/* First read in the frame header */
|
|
|
|
if (wi_read_bap(sc, fid, 0, &frmhdr, sizeof(frmhdr))) {
|
2010-11-23 07:33:09 +03:00
|
|
|
aprint_error_dev(sc->sc_dev, "%s read fid %x failed\n",
|
2004-07-23 00:30:43 +04:00
|
|
|
__func__, fid);
|
2002-09-30 10:50:35 +04:00
|
|
|
ifp->if_ierrors++;
|
|
|
|
return;
|
|
|
|
}
|
1999-07-15 02:24:07 +04:00
|
|
|
|
2003-05-13 10:51:10 +04:00
|
|
|
if (IFF_DUMPPKTS(ifp))
|
|
|
|
wi_dump_pkt(&frmhdr, NULL, frmhdr.wi_rx_signal);
|
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
/*
|
|
|
|
* Drop undecryptable or packets with receive errors here
|
|
|
|
*/
|
|
|
|
status = le16toh(frmhdr.wi_status);
|
2003-12-07 08:44:49 +03:00
|
|
|
if ((status & WI_STAT_ERRSTAT) != 0 &&
|
|
|
|
ic->ic_opmode != IEEE80211_M_MONITOR) {
|
2002-09-30 10:50:35 +04:00
|
|
|
ifp->if_ierrors++;
|
|
|
|
DPRINTF(("wi_rx_intr: fid %x error status %x\n", fid, status));
|
|
|
|
return;
|
|
|
|
}
|
2002-10-02 21:11:34 +04:00
|
|
|
rssi = frmhdr.wi_rx_signal;
|
|
|
|
rstamp = (le16toh(frmhdr.wi_rx_tstamp0) << 16) |
|
|
|
|
le16toh(frmhdr.wi_rx_tstamp1);
|
2002-08-11 10:13:53 +04:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
len = le16toh(frmhdr.wi_dat_len);
|
|
|
|
off = ALIGN(sizeof(struct ieee80211_frame));
|
1999-07-15 02:24:07 +04:00
|
|
|
|
2003-02-25 04:57:35 +03:00
|
|
|
/* Sometimes the PRISM2.x returns bogusly large frames. Except
|
|
|
|
* in monitor mode, just throw them away.
|
|
|
|
*/
|
2003-01-09 11:49:39 +03:00
|
|
|
if (off + len > MCLBYTES) {
|
2003-02-25 04:57:35 +03:00
|
|
|
if (ic->ic_opmode != IEEE80211_M_MONITOR) {
|
|
|
|
ifp->if_ierrors++;
|
|
|
|
DPRINTF(("wi_rx_intr: oversized packet\n"));
|
|
|
|
return;
|
|
|
|
} else
|
|
|
|
len = 0;
|
2003-01-09 11:49:39 +03:00
|
|
|
}
|
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
MGETHDR(m, M_DONTWAIT, MT_DATA);
|
|
|
|
if (m == NULL) {
|
|
|
|
ifp->if_ierrors++;
|
|
|
|
DPRINTF(("wi_rx_intr: MGET failed\n"));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (off + len > MHLEN) {
|
|
|
|
MCLGET(m, M_DONTWAIT);
|
|
|
|
if ((m->m_flags & M_EXT) == 0) {
|
|
|
|
m_freem(m);
|
|
|
|
ifp->if_ierrors++;
|
|
|
|
DPRINTF(("wi_rx_intr: MCLGET failed\n"));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
m->m_data += off - sizeof(struct ieee80211_frame);
|
|
|
|
memcpy(m->m_data, &frmhdr.wi_whdr, sizeof(struct ieee80211_frame));
|
|
|
|
wi_read_bap(sc, fid, sizeof(frmhdr),
|
|
|
|
m->m_data + sizeof(struct ieee80211_frame), len);
|
|
|
|
m->m_pkthdr.len = m->m_len = sizeof(struct ieee80211_frame) + len;
|
|
|
|
m->m_pkthdr.rcvif = ifp;
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
|
2005-07-14 04:28:51 +04:00
|
|
|
wh = mtod(m, struct ieee80211_frame *);
|
|
|
|
if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
|
|
|
|
/*
|
|
|
|
* WEP is decrypted by hardware. Clear WEP bit
|
|
|
|
* header for ieee80211_input().
|
|
|
|
*/
|
|
|
|
wh->i_fc[1] &= ~IEEE80211_FC1_WEP;
|
|
|
|
}
|
2002-09-30 10:50:35 +04:00
|
|
|
if (sc->sc_drvbpf) {
|
2003-11-16 12:02:42 +03:00
|
|
|
struct wi_rx_radiotap_header *tap = &sc->sc_rxtap;
|
|
|
|
|
|
|
|
tap->wr_rate = frmhdr.wi_rx_rate / 5;
|
2004-08-06 02:57:32 +04:00
|
|
|
tap->wr_antsignal = frmhdr.wi_rx_signal;
|
|
|
|
tap->wr_antnoise = frmhdr.wi_rx_silence;
|
2004-02-10 03:32:40 +03:00
|
|
|
tap->wr_chan_freq = htole16(ic->ic_bss->ni_chan->ic_freq);
|
|
|
|
tap->wr_chan_flags = htole16(ic->ic_bss->ni_chan->ic_flags);
|
2003-11-16 12:02:42 +03:00
|
|
|
if (frmhdr.wi_status & WI_STAT_PCF)
|
|
|
|
tap->wr_flags |= IEEE80211_RADIOTAP_F_CFP;
|
1999-07-15 02:24:07 +04:00
|
|
|
|
2005-07-14 04:28:51 +04:00
|
|
|
/* XXX IEEE80211_RADIOTAP_F_WEP */
|
2010-04-05 11:19:28 +04:00
|
|
|
bpf_mtap2(sc->sc_drvbpf, tap, tap->wr_ihdr.it_len, m);
|
1999-07-15 02:24:07 +04:00
|
|
|
}
|
2003-01-01 05:06:47 +03:00
|
|
|
|
|
|
|
/* synchronize driver's BSSID with firmware's BSSID */
|
|
|
|
dir = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK;
|
|
|
|
if (ic->ic_opmode == IEEE80211_M_IBSS && dir == IEEE80211_FC1_DIR_NODS)
|
|
|
|
wi_sync_bssid(sc, wh->i_addr3);
|
|
|
|
|
2005-06-22 10:14:51 +04:00
|
|
|
ni = ieee80211_find_rxnode(ic, mtod(m, struct ieee80211_frame_min *));
|
2003-10-13 12:07:21 +04:00
|
|
|
|
2005-06-22 10:14:51 +04:00
|
|
|
ieee80211_input(ic, m, ni, rssi, rstamp);
|
2003-10-13 12:07:21 +04:00
|
|
|
|
2003-12-07 08:44:49 +03:00
|
|
|
wi_rssadapt_input(ic, ni, wh, rssi);
|
|
|
|
|
2003-10-13 12:07:21 +04:00
|
|
|
/*
|
|
|
|
* The frame may have caused the node to be marked for
|
|
|
|
* reclamation (e.g. in response to a DEAUTH message)
|
2004-08-10 04:57:20 +04:00
|
|
|
* so use release_node here instead of unref_node.
|
2003-10-13 12:07:21 +04:00
|
|
|
*/
|
2005-06-22 10:14:51 +04:00
|
|
|
ieee80211_free_node(ni);
|
1999-07-15 02:24:07 +04:00
|
|
|
}
|
|
|
|
|
2004-07-22 23:47:24 +04:00
|
|
|
STATIC void
|
2003-05-13 11:13:49 +04:00
|
|
|
wi_tx_ex_intr(struct wi_softc *sc)
|
|
|
|
{
|
|
|
|
struct ieee80211com *ic = &sc->sc_ic;
|
2005-06-22 10:14:51 +04:00
|
|
|
struct ifnet *ifp = &sc->sc_if;
|
2003-12-07 08:44:49 +03:00
|
|
|
struct ieee80211_node *ni;
|
|
|
|
struct ieee80211_rssdesc *id;
|
|
|
|
struct wi_rssdesc *rssd;
|
2003-05-13 11:13:49 +04:00
|
|
|
struct wi_frame frmhdr;
|
|
|
|
int fid;
|
2003-12-07 08:44:49 +03:00
|
|
|
u_int16_t status;
|
2003-05-13 11:13:49 +04:00
|
|
|
|
|
|
|
fid = CSR_READ_2(sc, WI_TX_CMP_FID);
|
|
|
|
/* Read in the frame header */
|
2003-12-07 08:44:49 +03:00
|
|
|
if (wi_read_bap(sc, fid, 0, &frmhdr, sizeof(frmhdr)) != 0) {
|
2010-11-23 07:33:09 +03:00
|
|
|
aprint_error_dev(sc->sc_dev, "%s read fid %x failed\n",
|
2004-02-10 04:08:05 +03:00
|
|
|
__func__, fid);
|
|
|
|
wi_rssdescs_reset(ic, &sc->sc_rssd, &sc->sc_rssdfree,
|
|
|
|
&sc->sc_txpending);
|
|
|
|
goto out;
|
2003-12-07 08:44:49 +03:00
|
|
|
}
|
2003-05-13 11:13:49 +04:00
|
|
|
|
2003-12-07 08:44:49 +03:00
|
|
|
if (frmhdr.wi_tx_idx >= WI_NTXRSS) {
|
2010-11-23 07:33:09 +03:00
|
|
|
aprint_error_dev(sc->sc_dev, "%s bad idx %02x\n",
|
|
|
|
__func__, frmhdr.wi_tx_idx);
|
2004-02-10 04:08:05 +03:00
|
|
|
wi_rssdescs_reset(ic, &sc->sc_rssd, &sc->sc_rssdfree,
|
|
|
|
&sc->sc_txpending);
|
|
|
|
goto out;
|
2003-12-07 08:44:49 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
status = le16toh(frmhdr.wi_status);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Spontaneous station disconnects appear as xmit
|
|
|
|
* errors. Don't announce them and/or count them
|
|
|
|
* as an output error.
|
|
|
|
*/
|
|
|
|
if (ppsratecheck(&lasttxerror, &curtxeps, wi_txerate)) {
|
2010-11-23 07:33:09 +03:00
|
|
|
aprint_error_dev(sc->sc_dev, "tx failed");
|
2003-12-07 08:44:49 +03:00
|
|
|
if (status & WI_TXSTAT_RET_ERR)
|
|
|
|
printf(", retry limit exceeded");
|
|
|
|
if (status & WI_TXSTAT_AGED_ERR)
|
|
|
|
printf(", max transmit lifetime exceeded");
|
|
|
|
if (status & WI_TXSTAT_DISCONNECT)
|
|
|
|
printf(", port disconnected");
|
|
|
|
if (status & WI_TXSTAT_FORM_ERR)
|
|
|
|
printf(", invalid format (data len %u src %s)",
|
|
|
|
le16toh(frmhdr.wi_dat_len),
|
|
|
|
ether_sprintf(frmhdr.wi_ehdr.ether_shost));
|
|
|
|
if (status & ~0xf)
|
|
|
|
printf(", status=0x%x", status);
|
|
|
|
printf("\n");
|
|
|
|
}
|
|
|
|
ifp->if_oerrors++;
|
|
|
|
rssd = &sc->sc_rssd[frmhdr.wi_tx_idx];
|
|
|
|
id = &rssd->rd_desc;
|
|
|
|
if ((status & WI_TXSTAT_RET_ERR) != 0)
|
|
|
|
wi_lower_rate(ic, id);
|
|
|
|
|
|
|
|
ni = id->id_node;
|
|
|
|
id->id_node = NULL;
|
|
|
|
|
2004-02-10 04:08:05 +03:00
|
|
|
if (ni == NULL) {
|
2010-11-23 07:33:09 +03:00
|
|
|
aprint_error_dev(sc->sc_dev, "%s null node, rssdesc %02x\n",
|
2008-04-08 16:07:25 +04:00
|
|
|
__func__, frmhdr.wi_tx_idx);
|
2004-02-10 04:08:05 +03:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
2003-12-07 08:44:49 +03:00
|
|
|
if (sc->sc_txpending[id->id_rateidx]-- == 0) {
|
2010-11-23 07:33:09 +03:00
|
|
|
aprint_error_dev(sc->sc_dev, "%s txpending[%i] wraparound",
|
2004-02-10 04:08:05 +03:00
|
|
|
__func__, id->id_rateidx);
|
2003-12-07 08:44:49 +03:00
|
|
|
sc->sc_txpending[id->id_rateidx] = 0;
|
|
|
|
}
|
2004-08-10 04:57:20 +04:00
|
|
|
if (ni != NULL)
|
2005-06-22 10:14:51 +04:00
|
|
|
ieee80211_free_node(ni);
|
2003-12-07 08:44:49 +03:00
|
|
|
SLIST_INSERT_HEAD(&sc->sc_rssdfree, rssd, rd_next);
|
2004-02-10 04:08:05 +03:00
|
|
|
out:
|
2003-12-07 08:44:49 +03:00
|
|
|
ifp->if_flags &= ~IFF_OACTIVE;
|
2003-05-13 11:13:49 +04:00
|
|
|
}
|
|
|
|
|
2004-07-22 23:47:24 +04:00
|
|
|
STATIC void
|
2003-12-07 08:44:49 +03:00
|
|
|
wi_txalloc_intr(struct wi_softc *sc)
|
1999-07-15 02:24:07 +04:00
|
|
|
{
|
2002-09-30 10:50:35 +04:00
|
|
|
int fid, cur;
|
1999-07-15 02:24:07 +04:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
fid = CSR_READ_2(sc, WI_ALLOC_FID);
|
2002-08-11 10:13:53 +04:00
|
|
|
|
2004-07-23 00:25:23 +04:00
|
|
|
cur = sc->sc_txalloc;
|
2004-07-23 01:56:58 +04:00
|
|
|
#ifdef DIAGNOSTIC
|
|
|
|
if (sc->sc_txstarted == 0) {
|
|
|
|
printf("%s: spurious alloc %x != %x, alloc %d queue %d start %d alloced %d queued %d started %d\n",
|
2010-11-23 07:33:09 +03:00
|
|
|
device_xname(sc->sc_dev), fid, sc->sc_txd[cur].d_fid, cur,
|
2004-07-23 01:56:58 +04:00
|
|
|
sc->sc_txqueue, sc->sc_txstart, sc->sc_txalloced, sc->sc_txqueued, sc->sc_txstarted);
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
return;
|
2002-09-30 10:50:35 +04:00
|
|
|
}
|
2004-07-23 01:56:58 +04:00
|
|
|
#endif
|
|
|
|
--sc->sc_txstarted;
|
2004-07-23 00:30:43 +04:00
|
|
|
++sc->sc_txalloced;
|
2004-07-23 01:56:58 +04:00
|
|
|
sc->sc_txd[cur].d_fid = fid;
|
|
|
|
sc->sc_txalloc = (cur + 1) % WI_NTXBUF;
|
|
|
|
#ifdef WI_RING_DEBUG
|
|
|
|
printf("%s: alloc %04x, alloc %d queue %d start %d alloced %d queued %d started %d\n",
|
2010-11-23 07:33:09 +03:00
|
|
|
device_xname(sc->sc_dev), fid,
|
2004-07-23 01:56:58 +04:00
|
|
|
sc->sc_txalloc, sc->sc_txqueue, sc->sc_txstart,
|
|
|
|
sc->sc_txalloced, sc->sc_txqueued, sc->sc_txstarted);
|
|
|
|
#endif
|
2004-07-23 12:31:39 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
STATIC void
|
|
|
|
wi_cmd_intr(struct wi_softc *sc)
|
|
|
|
{
|
2005-06-22 10:14:51 +04:00
|
|
|
struct ifnet *ifp = &sc->sc_if;
|
2004-07-23 12:31:39 +04:00
|
|
|
|
2005-06-22 10:14:51 +04:00
|
|
|
if (sc->sc_invalid)
|
|
|
|
return;
|
2004-12-13 20:55:28 +03:00
|
|
|
#ifdef WI_DEBUG
|
2005-07-16 02:33:29 +04:00
|
|
|
if (wi_debug > 1)
|
2004-12-13 20:55:28 +03:00
|
|
|
printf("%s: %d txcmds outstanding\n", __func__, sc->sc_txcmds);
|
|
|
|
#endif
|
|
|
|
KASSERT(sc->sc_txcmds > 0);
|
|
|
|
|
|
|
|
--sc->sc_txcmds;
|
|
|
|
|
2004-07-23 00:30:43 +04:00
|
|
|
if (--sc->sc_txqueued == 0) {
|
|
|
|
sc->sc_tx_timer = 0;
|
2002-09-30 10:50:35 +04:00
|
|
|
ifp->if_flags &= ~IFF_OACTIVE;
|
2004-07-23 12:31:39 +04:00
|
|
|
#ifdef WI_RING_DEBUG
|
|
|
|
printf("%s: cmd , alloc %d queue %d start %d alloced %d queued %d started %d\n",
|
2010-11-23 07:33:09 +03:00
|
|
|
device_xname(sc->sc_dev),
|
2004-07-23 12:31:39 +04:00
|
|
|
sc->sc_txalloc, sc->sc_txqueue, sc->sc_txstart,
|
|
|
|
sc->sc_txalloced, sc->sc_txqueued, sc->sc_txstarted);
|
|
|
|
#endif
|
2004-07-23 01:56:58 +04:00
|
|
|
} else
|
|
|
|
wi_push_packet(sc);
|
|
|
|
}
|
|
|
|
|
|
|
|
STATIC void
|
|
|
|
wi_push_packet(struct wi_softc *sc)
|
|
|
|
{
|
2005-06-22 10:14:51 +04:00
|
|
|
struct ifnet *ifp = &sc->sc_if;
|
2004-07-23 01:56:58 +04:00
|
|
|
int cur, fid;
|
|
|
|
|
|
|
|
cur = sc->sc_txstart;
|
|
|
|
fid = sc->sc_txd[cur].d_fid;
|
2004-12-13 20:55:28 +03:00
|
|
|
|
|
|
|
KASSERT(sc->sc_txcmds == 0);
|
|
|
|
|
|
|
|
if (wi_cmd_start(sc, WI_CMD_TX | WI_RECLAIM, fid, 0, 0)) {
|
2010-11-23 07:33:09 +03:00
|
|
|
aprint_error_dev(sc->sc_dev, "xmit failed\n");
|
2004-07-23 01:56:58 +04:00
|
|
|
/* XXX ring might have a hole */
|
2001-05-06 07:26:38 +04:00
|
|
|
}
|
2004-12-13 20:55:28 +03:00
|
|
|
|
|
|
|
if (sc->sc_txcmds++ > 0)
|
|
|
|
printf("%s: %d tx cmds pending!!!\n", __func__, sc->sc_txcmds);
|
|
|
|
|
2004-07-23 01:56:58 +04:00
|
|
|
++sc->sc_txstarted;
|
|
|
|
#ifdef DIAGNOSTIC
|
|
|
|
if (sc->sc_txstarted > WI_NTXBUF)
|
2010-11-23 07:33:09 +03:00
|
|
|
aprint_error_dev(sc->sc_dev, "too many buffers started\n");
|
2004-07-23 01:56:58 +04:00
|
|
|
#endif
|
|
|
|
sc->sc_txstart = (cur + 1) % WI_NTXBUF;
|
|
|
|
sc->sc_tx_timer = 5;
|
|
|
|
ifp->if_timer = 1;
|
|
|
|
#ifdef WI_RING_DEBUG
|
|
|
|
printf("%s: push %04x, alloc %d queue %d start %d alloced %d queued %d started %d\n",
|
2010-11-23 07:33:09 +03:00
|
|
|
device_xname(sc->sc_dev), fid,
|
2004-07-23 01:56:58 +04:00
|
|
|
sc->sc_txalloc, sc->sc_txqueue, sc->sc_txstart,
|
|
|
|
sc->sc_txalloced, sc->sc_txqueued, sc->sc_txstarted);
|
|
|
|
#endif
|
1999-07-15 02:24:07 +04:00
|
|
|
}
|
|
|
|
|
2004-07-22 23:47:24 +04:00
|
|
|
STATIC void
|
2003-12-07 08:44:49 +03:00
|
|
|
wi_tx_intr(struct wi_softc *sc)
|
|
|
|
{
|
|
|
|
struct ieee80211com *ic = &sc->sc_ic;
|
2005-06-22 10:14:51 +04:00
|
|
|
struct ifnet *ifp = &sc->sc_if;
|
2003-12-07 08:44:49 +03:00
|
|
|
struct ieee80211_node *ni;
|
|
|
|
struct ieee80211_rssdesc *id;
|
|
|
|
struct wi_rssdesc *rssd;
|
|
|
|
struct wi_frame frmhdr;
|
|
|
|
int fid;
|
|
|
|
|
|
|
|
fid = CSR_READ_2(sc, WI_TX_CMP_FID);
|
|
|
|
/* Read in the frame header */
|
2004-12-13 20:24:09 +03:00
|
|
|
if (wi_read_bap(sc, fid, offsetof(struct wi_frame, wi_tx_swsup2),
|
|
|
|
&frmhdr.wi_tx_swsup2, 2) != 0) {
|
2010-11-23 07:33:09 +03:00
|
|
|
aprint_error_dev(sc->sc_dev, "%s read fid %x failed\n",
|
2004-02-10 04:08:05 +03:00
|
|
|
__func__, fid);
|
|
|
|
wi_rssdescs_reset(ic, &sc->sc_rssd, &sc->sc_rssdfree,
|
|
|
|
&sc->sc_txpending);
|
2003-12-07 08:44:49 +03:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (frmhdr.wi_tx_idx >= WI_NTXRSS) {
|
2010-11-23 07:33:09 +03:00
|
|
|
aprint_error_dev(sc->sc_dev, "%s bad idx %02x\n",
|
2008-04-08 16:07:25 +04:00
|
|
|
__func__, frmhdr.wi_tx_idx);
|
2004-02-10 04:08:05 +03:00
|
|
|
wi_rssdescs_reset(ic, &sc->sc_rssd, &sc->sc_rssdfree,
|
|
|
|
&sc->sc_txpending);
|
2003-12-07 08:44:49 +03:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
rssd = &sc->sc_rssd[frmhdr.wi_tx_idx];
|
|
|
|
id = &rssd->rd_desc;
|
|
|
|
wi_raise_rate(ic, id);
|
|
|
|
|
|
|
|
ni = id->id_node;
|
|
|
|
id->id_node = NULL;
|
|
|
|
|
2004-02-10 04:08:05 +03:00
|
|
|
if (ni == NULL) {
|
2010-11-23 07:33:09 +03:00
|
|
|
aprint_error_dev(sc->sc_dev, "%s null node, rssdesc %02x\n",
|
2008-04-08 16:07:25 +04:00
|
|
|
__func__, frmhdr.wi_tx_idx);
|
2004-02-10 04:08:05 +03:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
2003-12-07 08:44:49 +03:00
|
|
|
if (sc->sc_txpending[id->id_rateidx]-- == 0) {
|
2010-11-23 07:33:09 +03:00
|
|
|
aprint_error_dev(sc->sc_dev, "%s txpending[%i] wraparound",
|
2004-02-10 04:08:05 +03:00
|
|
|
__func__, id->id_rateidx);
|
2003-12-07 08:44:49 +03:00
|
|
|
sc->sc_txpending[id->id_rateidx] = 0;
|
|
|
|
}
|
2004-08-10 04:57:20 +04:00
|
|
|
if (ni != NULL)
|
2005-06-22 10:14:51 +04:00
|
|
|
ieee80211_free_node(ni);
|
2003-12-07 08:44:49 +03:00
|
|
|
SLIST_INSERT_HEAD(&sc->sc_rssdfree, rssd, rd_next);
|
|
|
|
out:
|
2004-02-10 04:08:05 +03:00
|
|
|
ifp->if_flags &= ~IFF_OACTIVE;
|
2003-12-07 08:44:49 +03:00
|
|
|
}
|
|
|
|
|
2004-07-22 23:47:24 +04:00
|
|
|
STATIC void
|
2002-09-30 10:50:35 +04:00
|
|
|
wi_info_intr(struct wi_softc *sc)
|
1999-07-15 02:24:07 +04:00
|
|
|
{
|
2002-09-30 10:50:35 +04:00
|
|
|
struct ieee80211com *ic = &sc->sc_ic;
|
2005-06-22 10:14:51 +04:00
|
|
|
struct ifnet *ifp = &sc->sc_if;
|
2002-09-30 10:50:35 +04:00
|
|
|
int i, fid, len, off;
|
|
|
|
u_int16_t ltbuf[2];
|
|
|
|
u_int16_t stat;
|
|
|
|
u_int32_t *ptr;
|
|
|
|
|
|
|
|
fid = CSR_READ_2(sc, WI_INFO_FID);
|
|
|
|
wi_read_bap(sc, fid, 0, ltbuf, sizeof(ltbuf));
|
|
|
|
|
|
|
|
switch (le16toh(ltbuf[1])) {
|
|
|
|
|
|
|
|
case WI_INFO_LINK_STAT:
|
|
|
|
wi_read_bap(sc, fid, sizeof(ltbuf), &stat, sizeof(stat));
|
|
|
|
DPRINTF(("wi_info_intr: LINK_STAT 0x%x\n", le16toh(stat)));
|
|
|
|
switch (le16toh(stat)) {
|
|
|
|
case CONNECTED:
|
2002-10-04 08:23:20 +04:00
|
|
|
sc->sc_flags &= ~WI_FLAGS_OUTRANGE;
|
2002-10-07 15:01:52 +04:00
|
|
|
if (ic->ic_state == IEEE80211_S_RUN &&
|
|
|
|
ic->ic_opmode != IEEE80211_M_IBSS)
|
2002-09-30 10:50:35 +04:00
|
|
|
break;
|
|
|
|
/* FALLTHROUGH */
|
|
|
|
case AP_CHANGE:
|
2003-10-13 12:07:21 +04:00
|
|
|
ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
|
2002-09-30 10:50:35 +04:00
|
|
|
break;
|
2002-10-01 13:48:02 +04:00
|
|
|
case AP_IN_RANGE:
|
2002-10-04 08:23:20 +04:00
|
|
|
sc->sc_flags &= ~WI_FLAGS_OUTRANGE;
|
2002-10-01 13:48:02 +04:00
|
|
|
break;
|
2002-09-30 10:50:35 +04:00
|
|
|
case AP_OUT_OF_RANGE:
|
|
|
|
if (sc->sc_firmware_type == WI_SYMBOL &&
|
|
|
|
sc->sc_scan_timer > 0) {
|
|
|
|
if (wi_cmd(sc, WI_CMD_INQUIRE,
|
|
|
|
WI_INFO_HOST_SCAN_RESULTS, 0, 0) != 0)
|
|
|
|
sc->sc_scan_timer = 0;
|
|
|
|
break;
|
|
|
|
}
|
2002-10-04 08:23:20 +04:00
|
|
|
if (ic->ic_opmode == IEEE80211_M_STA)
|
|
|
|
sc->sc_flags |= WI_FLAGS_OUTRANGE;
|
|
|
|
break;
|
2002-09-30 10:50:35 +04:00
|
|
|
case DISCONNECTED:
|
|
|
|
case ASSOC_FAILED:
|
2002-09-30 19:48:41 +04:00
|
|
|
if (ic->ic_opmode == IEEE80211_M_STA)
|
2003-10-13 12:07:21 +04:00
|
|
|
ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
|
2002-09-30 10:50:35 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
1999-07-15 02:24:07 +04:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
case WI_INFO_COUNTERS:
|
|
|
|
/* some card versions have a larger stats structure */
|
|
|
|
len = min(le16toh(ltbuf[0]) - 1, sizeof(sc->sc_stats) / 4);
|
|
|
|
ptr = (u_int32_t *)&sc->sc_stats;
|
|
|
|
off = sizeof(ltbuf);
|
|
|
|
for (i = 0; i < len; i++, off += 2, ptr++) {
|
|
|
|
wi_read_bap(sc, fid, off, &stat, sizeof(stat));
|
2003-11-16 12:41:01 +03:00
|
|
|
stat = le16toh(stat);
|
2002-09-30 10:50:35 +04:00
|
|
|
#ifdef WI_HERMES_STATS_WAR
|
|
|
|
if (stat & 0xf000)
|
|
|
|
stat = ~stat;
|
|
|
|
#endif
|
|
|
|
*ptr += stat;
|
|
|
|
}
|
|
|
|
ifp->if_collisions = sc->sc_stats.wi_tx_single_retries +
|
|
|
|
sc->sc_stats.wi_tx_multi_retries +
|
|
|
|
sc->sc_stats.wi_tx_retry_limit;
|
|
|
|
break;
|
1999-07-15 02:24:07 +04:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
case WI_INFO_SCAN_RESULTS:
|
|
|
|
case WI_INFO_HOST_SCAN_RESULTS:
|
|
|
|
wi_scan_result(sc, fid, le16toh(ltbuf[0]));
|
|
|
|
break;
|
1999-07-15 02:24:07 +04:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
default:
|
|
|
|
DPRINTF(("wi_info_intr: got fid %x type %x len %d\n", fid,
|
|
|
|
le16toh(ltbuf[1]), le16toh(ltbuf[0])));
|
|
|
|
break;
|
|
|
|
}
|
1999-07-15 02:24:07 +04:00
|
|
|
}
|
|
|
|
|
2004-07-22 23:47:24 +04:00
|
|
|
STATIC int
|
2002-09-30 10:50:35 +04:00
|
|
|
wi_write_multi(struct wi_softc *sc)
|
1999-07-15 02:24:07 +04:00
|
|
|
{
|
2005-06-22 10:14:51 +04:00
|
|
|
struct ifnet *ifp = &sc->sc_if;
|
2003-05-13 12:35:58 +04:00
|
|
|
int n;
|
2002-09-30 10:50:35 +04:00
|
|
|
struct wi_mcast mlist;
|
|
|
|
struct ether_multi *enm;
|
|
|
|
struct ether_multistep estep;
|
2001-05-16 14:45:36 +04:00
|
|
|
|
2003-05-31 23:38:08 +04:00
|
|
|
if ((ifp->if_flags & IFF_PROMISC) != 0) {
|
2002-09-30 10:50:35 +04:00
|
|
|
allmulti:
|
|
|
|
ifp->if_flags |= IFF_ALLMULTI;
|
|
|
|
memset(&mlist, 0, sizeof(mlist));
|
|
|
|
return wi_write_rid(sc, WI_RID_MCAST_LIST, &mlist,
|
|
|
|
sizeof(mlist));
|
2001-05-16 14:45:36 +04:00
|
|
|
}
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
n = 0;
|
2005-06-22 10:14:51 +04:00
|
|
|
ETHER_FIRST_MULTI(estep, &sc->sc_ec, enm);
|
2002-09-30 10:50:35 +04:00
|
|
|
while (enm != NULL) {
|
|
|
|
/* Punt on ranges or too many multicast addresses. */
|
|
|
|
if (!IEEE80211_ADDR_EQ(enm->enm_addrlo, enm->enm_addrhi) ||
|
|
|
|
n >= sizeof(mlist) / sizeof(mlist.wi_mcast[0]))
|
|
|
|
goto allmulti;
|
2000-02-12 19:08:04 +03:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
IEEE80211_ADDR_COPY(&mlist.wi_mcast[n], enm->enm_addrlo);
|
|
|
|
n++;
|
|
|
|
ETHER_NEXT_MULTI(estep, enm);
|
2000-02-12 19:08:04 +03:00
|
|
|
}
|
2002-09-30 10:50:35 +04:00
|
|
|
ifp->if_flags &= ~IFF_ALLMULTI;
|
|
|
|
return wi_write_rid(sc, WI_RID_MCAST_LIST, &mlist,
|
|
|
|
IEEE80211_ADDR_LEN * n);
|
2000-02-12 19:08:04 +03:00
|
|
|
}
|
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
|
2004-07-22 23:47:24 +04:00
|
|
|
STATIC void
|
2003-05-13 12:35:58 +04:00
|
|
|
wi_read_nicid(struct wi_softc *sc)
|
2001-05-15 08:14:06 +04:00
|
|
|
{
|
2002-09-30 10:50:35 +04:00
|
|
|
struct wi_card_ident *id;
|
|
|
|
char *p;
|
|
|
|
int len;
|
|
|
|
u_int16_t ver[4];
|
2001-05-15 08:14:06 +04:00
|
|
|
|
2001-05-15 13:01:27 +04:00
|
|
|
/* getting chip identity */
|
2002-09-30 10:50:35 +04:00
|
|
|
memset(ver, 0, sizeof(ver));
|
|
|
|
len = sizeof(ver);
|
|
|
|
wi_read_rid(sc, WI_RID_CARD_ID, ver, &len);
|
2010-11-23 07:33:09 +03:00
|
|
|
printf("%s: using ", device_xname(sc->sc_dev));
|
2002-09-30 10:50:35 +04:00
|
|
|
DPRINTF2(("wi_read_nicid: CARD_ID: %x %x %x %x\n", le16toh(ver[0]), le16toh(ver[1]), le16toh(ver[2]), le16toh(ver[3])));
|
2002-04-04 11:06:16 +04:00
|
|
|
|
2002-04-05 04:54:51 +04:00
|
|
|
sc->sc_firmware_type = WI_NOTYPE;
|
2002-04-04 11:06:16 +04:00
|
|
|
for (id = wi_card_ident; id->card_name != NULL; id++) {
|
2002-09-30 10:50:35 +04:00
|
|
|
if (le16toh(ver[0]) == id->card_id) {
|
2002-04-04 11:06:16 +04:00
|
|
|
printf("%s", id->card_name);
|
|
|
|
sc->sc_firmware_type = id->firm_type;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2002-04-05 04:54:51 +04:00
|
|
|
if (sc->sc_firmware_type == WI_NOTYPE) {
|
2002-09-30 10:50:35 +04:00
|
|
|
if (le16toh(ver[0]) & 0x8000) {
|
2002-03-27 11:01:22 +03:00
|
|
|
printf("Unknown PRISM2 chip");
|
|
|
|
sc->sc_firmware_type = WI_INTERSIL;
|
|
|
|
} else {
|
|
|
|
printf("Unknown Lucent chip");
|
|
|
|
sc->sc_firmware_type = WI_LUCENT;
|
|
|
|
}
|
2001-05-15 08:14:06 +04:00
|
|
|
}
|
2001-05-15 13:01:27 +04:00
|
|
|
|
2002-04-05 04:54:51 +04:00
|
|
|
/* get primary firmware version (Only Prism chips) */
|
2002-04-05 04:59:38 +04:00
|
|
|
if (sc->sc_firmware_type != WI_LUCENT) {
|
2002-09-30 10:50:35 +04:00
|
|
|
memset(ver, 0, sizeof(ver));
|
|
|
|
len = sizeof(ver);
|
|
|
|
wi_read_rid(sc, WI_RID_PRI_IDENTITY, ver, &len);
|
|
|
|
sc->sc_pri_firmware_ver = le16toh(ver[2]) * 10000 +
|
|
|
|
le16toh(ver[3]) * 100 + le16toh(ver[1]);
|
2002-04-05 04:54:51 +04:00
|
|
|
}
|
2002-03-30 19:44:59 +03:00
|
|
|
|
2002-03-30 18:58:45 +03:00
|
|
|
/* get station firmware version */
|
2002-09-30 10:50:35 +04:00
|
|
|
memset(ver, 0, sizeof(ver));
|
|
|
|
len = sizeof(ver);
|
|
|
|
wi_read_rid(sc, WI_RID_STA_IDENTITY, ver, &len);
|
|
|
|
sc->sc_sta_firmware_ver = le16toh(ver[2]) * 10000 +
|
|
|
|
le16toh(ver[3]) * 100 + le16toh(ver[1]);
|
2002-03-27 11:01:22 +03:00
|
|
|
if (sc->sc_firmware_type == WI_INTERSIL &&
|
2002-09-30 10:50:35 +04:00
|
|
|
(sc->sc_sta_firmware_ver == 10102 ||
|
|
|
|
sc->sc_sta_firmware_ver == 20102)) {
|
|
|
|
char ident[12];
|
|
|
|
memset(ident, 0, sizeof(ident));
|
|
|
|
len = sizeof(ident);
|
2002-04-14 23:55:23 +04:00
|
|
|
/* value should be the format like "V2.00-11" */
|
2002-09-30 10:50:35 +04:00
|
|
|
if (wi_read_rid(sc, WI_RID_SYMBOL_IDENTITY, ident, &len) == 0 &&
|
|
|
|
*(p = (char *)ident) >= 'A' &&
|
2002-03-27 11:01:22 +03:00
|
|
|
p[2] == '.' && p[5] == '-' && p[8] == '\0') {
|
|
|
|
sc->sc_firmware_type = WI_SYMBOL;
|
2002-03-30 19:44:59 +03:00
|
|
|
sc->sc_sta_firmware_ver = (p[1] - '0') * 10000 +
|
2002-03-27 11:01:22 +03:00
|
|
|
(p[3] - '0') * 1000 + (p[4] - '0') * 100 +
|
|
|
|
(p[6] - '0') * 10 + (p[7] - '0');
|
|
|
|
}
|
|
|
|
}
|
2002-03-30 19:44:59 +03:00
|
|
|
|
2010-11-23 07:33:09 +03:00
|
|
|
printf("\n%s: %s Firmware: ", device_xname(sc->sc_dev),
|
2002-03-30 19:44:59 +03:00
|
|
|
sc->sc_firmware_type == WI_LUCENT ? "Lucent" :
|
|
|
|
(sc->sc_firmware_type == WI_SYMBOL ? "Symbol" : "Intersil"));
|
|
|
|
if (sc->sc_firmware_type != WI_LUCENT) /* XXX */
|
2002-09-30 10:50:35 +04:00
|
|
|
printf("Primary (%u.%u.%u), ",
|
|
|
|
sc->sc_pri_firmware_ver / 10000,
|
2002-03-30 19:44:59 +03:00
|
|
|
(sc->sc_pri_firmware_ver % 10000) / 100,
|
|
|
|
sc->sc_pri_firmware_ver % 100);
|
|
|
|
printf("Station (%u.%u.%u)\n",
|
2002-09-30 10:50:35 +04:00
|
|
|
sc->sc_sta_firmware_ver / 10000,
|
|
|
|
(sc->sc_sta_firmware_ver % 10000) / 100,
|
2002-03-30 19:44:59 +03:00
|
|
|
sc->sc_sta_firmware_ver % 100);
|
2002-09-30 10:50:35 +04:00
|
|
|
}
|
|
|
|
|
2004-07-22 23:47:24 +04:00
|
|
|
STATIC int
|
2002-09-30 10:50:35 +04:00
|
|
|
wi_write_ssid(struct wi_softc *sc, int rid, u_int8_t *buf, int buflen)
|
|
|
|
{
|
|
|
|
struct wi_ssid ssid;
|
2001-05-15 13:01:27 +04:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
if (buflen > IEEE80211_NWID_LEN)
|
|
|
|
return ENOBUFS;
|
2002-10-01 20:11:19 +04:00
|
|
|
memset(&ssid, 0, sizeof(ssid));
|
2002-09-30 10:50:35 +04:00
|
|
|
ssid.wi_len = htole16(buflen);
|
|
|
|
memcpy(ssid.wi_ssid, buf, buflen);
|
2002-10-01 20:11:19 +04:00
|
|
|
return wi_write_rid(sc, rid, &ssid, sizeof(ssid));
|
2001-05-15 08:14:06 +04:00
|
|
|
}
|
|
|
|
|
2004-07-22 23:47:24 +04:00
|
|
|
STATIC int
|
2007-03-04 08:59:00 +03:00
|
|
|
wi_get_cfg(struct ifnet *ifp, u_long cmd, void *data)
|
2000-02-12 19:08:04 +03:00
|
|
|
{
|
2002-09-30 10:50:35 +04:00
|
|
|
struct wi_softc *sc = ifp->if_softc;
|
|
|
|
struct ieee80211com *ic = &sc->sc_ic;
|
|
|
|
struct ifreq *ifr = (struct ifreq *)data;
|
|
|
|
struct wi_req wreq;
|
|
|
|
int len, n, error;
|
2000-02-12 19:08:04 +03:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
|
|
|
|
if (error)
|
|
|
|
return error;
|
|
|
|
len = (wreq.wi_len - 1) * 2;
|
|
|
|
if (len < sizeof(u_int16_t))
|
|
|
|
return ENOSPC;
|
|
|
|
if (len > sizeof(wreq.wi_val))
|
|
|
|
len = sizeof(wreq.wi_val);
|
2000-03-06 13:31:27 +03:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
switch (wreq.wi_type) {
|
2000-02-12 19:08:04 +03:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
case WI_RID_IFACE_STATS:
|
|
|
|
memcpy(wreq.wi_val, &sc->sc_stats, sizeof(sc->sc_stats));
|
|
|
|
if (len < sizeof(sc->sc_stats))
|
|
|
|
error = ENOSPC;
|
|
|
|
else
|
|
|
|
len = sizeof(sc->sc_stats);
|
|
|
|
break;
|
2000-03-02 08:00:47 +03:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
case WI_RID_ENCRYPTION:
|
|
|
|
case WI_RID_TX_CRYPT_KEY:
|
|
|
|
case WI_RID_DEFLT_CRYPT_KEYS:
|
|
|
|
case WI_RID_TX_RATE:
|
2005-06-22 10:14:51 +04:00
|
|
|
return ieee80211_cfgget(ic, cmd, data);
|
2002-09-30 10:50:35 +04:00
|
|
|
|
|
|
|
case WI_RID_MICROWAVE_OVEN:
|
|
|
|
if (sc->sc_enabled && (sc->sc_flags & WI_FLAGS_HAS_MOR)) {
|
|
|
|
error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val,
|
|
|
|
&len);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
wreq.wi_val[0] = htole16(sc->sc_microwave_oven);
|
|
|
|
len = sizeof(u_int16_t);
|
|
|
|
break;
|
|
|
|
|
2002-12-27 10:54:35 +03:00
|
|
|
case WI_RID_DBM_ADJUST:
|
|
|
|
if (sc->sc_enabled && (sc->sc_flags & WI_FLAGS_HAS_DBMADJUST)) {
|
|
|
|
error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val,
|
|
|
|
&len);
|
|
|
|
break;
|
|
|
|
}
|
2003-07-06 11:15:55 +04:00
|
|
|
wreq.wi_val[0] = htole16(sc->sc_dbm_offset);
|
2002-12-27 10:54:35 +03:00
|
|
|
len = sizeof(u_int16_t);
|
|
|
|
break;
|
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
case WI_RID_ROAMING_MODE:
|
|
|
|
if (sc->sc_enabled && (sc->sc_flags & WI_FLAGS_HAS_ROAMING)) {
|
|
|
|
error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val,
|
|
|
|
&len);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
wreq.wi_val[0] = htole16(sc->sc_roaming_mode);
|
|
|
|
len = sizeof(u_int16_t);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WI_RID_SYSTEM_SCALE:
|
|
|
|
if (sc->sc_enabled && (sc->sc_flags & WI_FLAGS_HAS_SYSSCALE)) {
|
|
|
|
error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val,
|
|
|
|
&len);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
wreq.wi_val[0] = htole16(sc->sc_system_scale);
|
|
|
|
len = sizeof(u_int16_t);
|
|
|
|
break;
|
|
|
|
|
2002-11-18 18:10:22 +03:00
|
|
|
case WI_RID_FRAG_THRESH:
|
|
|
|
if (sc->sc_enabled && (sc->sc_flags & WI_FLAGS_HAS_FRAGTHR)) {
|
|
|
|
error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val,
|
|
|
|
&len);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
wreq.wi_val[0] = htole16(sc->sc_frag_thresh);
|
|
|
|
len = sizeof(u_int16_t);
|
|
|
|
break;
|
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
case WI_RID_READ_APS:
|
2005-06-26 08:37:25 +04:00
|
|
|
#ifndef IEEE80211_NO_HOSTAP
|
2002-09-30 10:50:35 +04:00
|
|
|
if (ic->ic_opmode == IEEE80211_M_HOSTAP)
|
2005-06-22 10:14:51 +04:00
|
|
|
return ieee80211_cfgget(ic, cmd, data);
|
2005-06-26 08:37:25 +04:00
|
|
|
#endif /* !IEEE80211_NO_HOSTAP */
|
2002-09-30 10:50:35 +04:00
|
|
|
if (sc->sc_scan_timer > 0) {
|
|
|
|
error = EINPROGRESS;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
n = sc->sc_naps;
|
|
|
|
if (len < sizeof(n)) {
|
|
|
|
error = ENOSPC;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (len < sizeof(n) + sizeof(struct wi_apinfo) * n)
|
|
|
|
n = (len - sizeof(n)) / sizeof(struct wi_apinfo);
|
|
|
|
len = sizeof(n) + sizeof(struct wi_apinfo) * n;
|
|
|
|
memcpy(wreq.wi_val, &n, sizeof(n));
|
2007-03-04 08:59:00 +03:00
|
|
|
memcpy((char *)wreq.wi_val + sizeof(n), sc->sc_aps,
|
2002-09-30 10:50:35 +04:00
|
|
|
sizeof(struct wi_apinfo) * n);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
if (sc->sc_enabled) {
|
|
|
|
error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val,
|
|
|
|
&len);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
switch (wreq.wi_type) {
|
|
|
|
case WI_RID_MAX_DATALEN:
|
|
|
|
wreq.wi_val[0] = htole16(sc->sc_max_datalen);
|
|
|
|
len = sizeof(u_int16_t);
|
|
|
|
break;
|
2003-02-25 03:47:11 +03:00
|
|
|
case WI_RID_FRAG_THRESH:
|
|
|
|
wreq.wi_val[0] = htole16(sc->sc_frag_thresh);
|
|
|
|
len = sizeof(u_int16_t);
|
|
|
|
break;
|
2002-09-30 10:50:35 +04:00
|
|
|
case WI_RID_RTS_THRESH:
|
|
|
|
wreq.wi_val[0] = htole16(sc->sc_rts_thresh);
|
|
|
|
len = sizeof(u_int16_t);
|
|
|
|
break;
|
|
|
|
case WI_RID_CNFAUTHMODE:
|
|
|
|
wreq.wi_val[0] = htole16(sc->sc_cnfauthmode);
|
|
|
|
len = sizeof(u_int16_t);
|
|
|
|
break;
|
|
|
|
case WI_RID_NODENAME:
|
|
|
|
if (len < sc->sc_nodelen + sizeof(u_int16_t)) {
|
|
|
|
error = ENOSPC;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
len = sc->sc_nodelen + sizeof(u_int16_t);
|
|
|
|
wreq.wi_val[0] = htole16((sc->sc_nodelen + 1) / 2);
|
|
|
|
memcpy(&wreq.wi_val[1], sc->sc_nodename,
|
|
|
|
sc->sc_nodelen);
|
|
|
|
break;
|
|
|
|
default:
|
2005-06-22 10:14:51 +04:00
|
|
|
return ieee80211_cfgget(ic, cmd, data);
|
2002-09-30 10:50:35 +04:00
|
|
|
}
|
|
|
|
break;
|
2001-05-06 07:26:38 +04:00
|
|
|
}
|
2002-09-30 10:50:35 +04:00
|
|
|
if (error)
|
|
|
|
return error;
|
|
|
|
wreq.wi_len = (len + 1) / 2 + 1;
|
|
|
|
return copyout(&wreq, ifr->ifr_data, (wreq.wi_len + 1) * 2);
|
2001-05-06 07:26:38 +04:00
|
|
|
}
|
2000-02-12 19:08:04 +03:00
|
|
|
|
2004-07-22 23:47:24 +04:00
|
|
|
STATIC int
|
2007-03-04 08:59:00 +03:00
|
|
|
wi_set_cfg(struct ifnet *ifp, u_long cmd, void *data)
|
2001-05-06 07:26:38 +04:00
|
|
|
{
|
2002-09-30 10:50:35 +04:00
|
|
|
struct wi_softc *sc = ifp->if_softc;
|
|
|
|
struct ieee80211com *ic = &sc->sc_ic;
|
|
|
|
struct ifreq *ifr = (struct ifreq *)data;
|
2003-10-13 12:07:21 +04:00
|
|
|
struct ieee80211_rateset *rs = &ic->ic_sup_rates[IEEE80211_MODE_11B];
|
2002-09-30 10:50:35 +04:00
|
|
|
struct wi_req wreq;
|
|
|
|
struct mbuf *m;
|
|
|
|
int i, len, error;
|
2001-05-06 07:26:38 +04:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
|
|
|
|
if (error)
|
|
|
|
return error;
|
|
|
|
len = (wreq.wi_len - 1) * 2;
|
|
|
|
switch (wreq.wi_type) {
|
2005-08-10 17:20:42 +04:00
|
|
|
case WI_RID_MAC_NODE:
|
*** Summary ***
When a link-layer address changes (e.g., ifconfig ex0 link
02:de:ad:be:ef:02 active), send a gratuitous ARP and/or a Neighbor
Advertisement to update the network-/link-layer address bindings
on our LAN peers.
Refuse a change of ethernet address to the address 00:00:00:00:00:00
or to any multicast/broadcast address. (Thanks matt@.)
Reorder ifnet ioctl operations so that driver ioctls may inherit
the functions of their "class"---ether_ioctl(), fddi_ioctl(), et
cetera---and the class ioctls may inherit from the generic ioctl,
ifioctl_common(), but both driver- and class-ioctls may override
the generic behavior. Make network drivers share more code.
Distinguish a "factory" link-layer address from others for the
purposes of both protecting that address from deletion and computing
EUI64.
Return consistent, appropriate error codes from network drivers.
Improve readability. KNF.
*** Details ***
In if_attach(), always initialize the interface ioctl routine,
ifnet->if_ioctl, if the driver has not already initialized it.
Delete if_ioctl == NULL tests everywhere else, because it cannot
happen.
In the ioctl routines of network interfaces, inherit common ioctl
behaviors by calling either ifioctl_common() or whichever ioctl
routine is appropriate for the class of interface---e.g., ether_ioctl()
for ethernets.
Stop (ab)using SIOCSIFADDR and start to use SIOCINITIFADDR. In
the user->kernel interface, SIOCSIFADDR's argument was an ifreq,
but on the protocol->ifnet interface, SIOCSIFADDR's argument was
an ifaddr. That was confusing, and it would work against me as I
make it possible for a network interface to overload most ioctls.
On the protocol->ifnet interface, replace SIOCSIFADDR with
SIOCINITIFADDR. In ifioctl(), return EPERM if userland tries to
invoke SIOCINITIFADDR.
In ifioctl(), give the interface the first shot at handling most
interface ioctls, and give the protocol the second shot, instead
of the other way around. Finally, let compatibility code (COMPAT_OSOCK)
take a shot.
Pull device initialization out of switch statements under
SIOCINITIFADDR. For example, pull ..._init() out of any switch
statement that looks like this:
switch (...->sa_family) {
case ...:
..._init();
...
break;
...
default:
..._init();
...
break;
}
Rewrite many if-else clauses that handle all permutations of IFF_UP
and IFF_RUNNING to use a switch statement,
switch (x & (IFF_UP|IFF_RUNNING)) {
case 0:
...
break;
case IFF_RUNNING:
...
break;
case IFF_UP:
...
break;
case IFF_UP|IFF_RUNNING:
...
break;
}
unifdef lots of code containing #ifdef FreeBSD, #ifdef NetBSD, and
#ifdef SIOCSIFMTU, especially in fwip(4) and in ndis(4).
In ipw(4), remove an if_set_sadl() call that is out of place.
In nfe(4), reuse the jumbo MTU logic in ether_ioctl().
Let ethernets register a callback for setting h/w state such as
promiscuous mode and the multicast filter in accord with a change
in the if_flags: ether_set_ifflags_cb() registers a callback that
returns ENETRESET if the caller should reset the ethernet by calling
if_init(), 0 on success, != 0 on failure. Pull common code from
ex(4), gem(4), nfe(4), sip(4), tlp(4), vge(4) into ether_ioctl(),
and register if_flags callbacks for those drivers.
Return ENOTTY instead of EINVAL for inappropriate ioctls. In
zyd(4), use ENXIO instead of ENOTTY to indicate that the device is
not any longer attached.
Add to if_set_sadl() a boolean 'factory' argument that indicates
whether a link-layer address was assigned by the factory or some
other source. In a comment, recommend using the factory address
for generating an EUI64, and update in6_get_hw_ifid() to prefer a
factory address to any other link-layer address.
Add a routing message, RTM_LLINFO_UPD, that tells protocols to
update the binding of network-layer addresses to link-layer addresses.
Implement this message in IPv4 and IPv6 by sending a gratuitous
ARP or a neighbor advertisement, respectively. Generate RTM_LLINFO_UPD
messages on a change of an interface's link-layer address.
In ether_ioctl(), do not let SIOCALIFADDR set a link-layer address
that is broadcast/multicast or equal to 00:00:00:00:00:00.
Make ether_ioctl() call ifioctl_common() to handle ioctls that it
does not understand.
In gif(4), initialize if_softc and use it, instead of assuming that
the gif_softc and ifp overlap.
Let ifioctl_common() handle SIOCGIFADDR.
Sprinkle rtcache_invariants(), which checks on DIAGNOSTIC kernels
that certain invariants on a struct route are satisfied.
In agr(4), rewrite agr_ioctl_filter() to be a bit more explicit
about the ioctls that we do not allow on an agr(4) member interface.
bzero -> memset. Delete unnecessary casts to void *. Use
sockaddr_in_init() and sockaddr_in6_init(). Compare pointers with
NULL instead of "testing truth". Replace some instances of (type
*)0 with NULL. Change some K&R prototypes to ANSI C, and join
lines.
2008-11-07 03:20:01 +03:00
|
|
|
/* XXX convert to SIOCALIFADDR, AF_LINK, IFLR_ACTIVE */
|
2005-08-10 17:20:42 +04:00
|
|
|
(void)memcpy(ic->ic_myaddr, wreq.wi_val, ETHER_ADDR_LEN);
|
*** Summary ***
When a link-layer address changes (e.g., ifconfig ex0 link
02:de:ad:be:ef:02 active), send a gratuitous ARP and/or a Neighbor
Advertisement to update the network-/link-layer address bindings
on our LAN peers.
Refuse a change of ethernet address to the address 00:00:00:00:00:00
or to any multicast/broadcast address. (Thanks matt@.)
Reorder ifnet ioctl operations so that driver ioctls may inherit
the functions of their "class"---ether_ioctl(), fddi_ioctl(), et
cetera---and the class ioctls may inherit from the generic ioctl,
ifioctl_common(), but both driver- and class-ioctls may override
the generic behavior. Make network drivers share more code.
Distinguish a "factory" link-layer address from others for the
purposes of both protecting that address from deletion and computing
EUI64.
Return consistent, appropriate error codes from network drivers.
Improve readability. KNF.
*** Details ***
In if_attach(), always initialize the interface ioctl routine,
ifnet->if_ioctl, if the driver has not already initialized it.
Delete if_ioctl == NULL tests everywhere else, because it cannot
happen.
In the ioctl routines of network interfaces, inherit common ioctl
behaviors by calling either ifioctl_common() or whichever ioctl
routine is appropriate for the class of interface---e.g., ether_ioctl()
for ethernets.
Stop (ab)using SIOCSIFADDR and start to use SIOCINITIFADDR. In
the user->kernel interface, SIOCSIFADDR's argument was an ifreq,
but on the protocol->ifnet interface, SIOCSIFADDR's argument was
an ifaddr. That was confusing, and it would work against me as I
make it possible for a network interface to overload most ioctls.
On the protocol->ifnet interface, replace SIOCSIFADDR with
SIOCINITIFADDR. In ifioctl(), return EPERM if userland tries to
invoke SIOCINITIFADDR.
In ifioctl(), give the interface the first shot at handling most
interface ioctls, and give the protocol the second shot, instead
of the other way around. Finally, let compatibility code (COMPAT_OSOCK)
take a shot.
Pull device initialization out of switch statements under
SIOCINITIFADDR. For example, pull ..._init() out of any switch
statement that looks like this:
switch (...->sa_family) {
case ...:
..._init();
...
break;
...
default:
..._init();
...
break;
}
Rewrite many if-else clauses that handle all permutations of IFF_UP
and IFF_RUNNING to use a switch statement,
switch (x & (IFF_UP|IFF_RUNNING)) {
case 0:
...
break;
case IFF_RUNNING:
...
break;
case IFF_UP:
...
break;
case IFF_UP|IFF_RUNNING:
...
break;
}
unifdef lots of code containing #ifdef FreeBSD, #ifdef NetBSD, and
#ifdef SIOCSIFMTU, especially in fwip(4) and in ndis(4).
In ipw(4), remove an if_set_sadl() call that is out of place.
In nfe(4), reuse the jumbo MTU logic in ether_ioctl().
Let ethernets register a callback for setting h/w state such as
promiscuous mode and the multicast filter in accord with a change
in the if_flags: ether_set_ifflags_cb() registers a callback that
returns ENETRESET if the caller should reset the ethernet by calling
if_init(), 0 on success, != 0 on failure. Pull common code from
ex(4), gem(4), nfe(4), sip(4), tlp(4), vge(4) into ether_ioctl(),
and register if_flags callbacks for those drivers.
Return ENOTTY instead of EINVAL for inappropriate ioctls. In
zyd(4), use ENXIO instead of ENOTTY to indicate that the device is
not any longer attached.
Add to if_set_sadl() a boolean 'factory' argument that indicates
whether a link-layer address was assigned by the factory or some
other source. In a comment, recommend using the factory address
for generating an EUI64, and update in6_get_hw_ifid() to prefer a
factory address to any other link-layer address.
Add a routing message, RTM_LLINFO_UPD, that tells protocols to
update the binding of network-layer addresses to link-layer addresses.
Implement this message in IPv4 and IPv6 by sending a gratuitous
ARP or a neighbor advertisement, respectively. Generate RTM_LLINFO_UPD
messages on a change of an interface's link-layer address.
In ether_ioctl(), do not let SIOCALIFADDR set a link-layer address
that is broadcast/multicast or equal to 00:00:00:00:00:00.
Make ether_ioctl() call ifioctl_common() to handle ioctls that it
does not understand.
In gif(4), initialize if_softc and use it, instead of assuming that
the gif_softc and ifp overlap.
Let ifioctl_common() handle SIOCGIFADDR.
Sprinkle rtcache_invariants(), which checks on DIAGNOSTIC kernels
that certain invariants on a struct route are satisfied.
In agr(4), rewrite agr_ioctl_filter() to be a bit more explicit
about the ioctls that we do not allow on an agr(4) member interface.
bzero -> memset. Delete unnecessary casts to void *. Use
sockaddr_in_init() and sockaddr_in6_init(). Compare pointers with
NULL instead of "testing truth". Replace some instances of (type
*)0 with NULL. Change some K&R prototypes to ANSI C, and join
lines.
2008-11-07 03:20:01 +03:00
|
|
|
if_set_sadl(ifp, ic->ic_myaddr, ETHER_ADDR_LEN, false);
|
2005-08-10 17:20:42 +04:00
|
|
|
wi_write_rid(sc, WI_RID_MAC_NODE, ic->ic_myaddr,
|
|
|
|
IEEE80211_ADDR_LEN);
|
|
|
|
break;
|
|
|
|
|
2002-12-27 10:54:35 +03:00
|
|
|
case WI_RID_DBM_ADJUST:
|
|
|
|
return ENODEV;
|
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
case WI_RID_NODENAME:
|
|
|
|
if (le16toh(wreq.wi_val[0]) * 2 > len ||
|
|
|
|
le16toh(wreq.wi_val[0]) > sizeof(sc->sc_nodename)) {
|
|
|
|
error = ENOSPC;
|
|
|
|
break;
|
|
|
|
}
|
2001-05-15 08:14:06 +04:00
|
|
|
if (sc->sc_enabled) {
|
2002-09-30 10:50:35 +04:00
|
|
|
error = wi_write_rid(sc, wreq.wi_type, wreq.wi_val,
|
|
|
|
len);
|
|
|
|
if (error)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
sc->sc_nodelen = le16toh(wreq.wi_val[0]) * 2;
|
|
|
|
memcpy(sc->sc_nodename, &wreq.wi_val[1], sc->sc_nodelen);
|
|
|
|
break;
|
2002-09-30 19:48:41 +04:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
case WI_RID_MICROWAVE_OVEN:
|
|
|
|
case WI_RID_ROAMING_MODE:
|
|
|
|
case WI_RID_SYSTEM_SCALE:
|
2002-11-18 18:10:22 +03:00
|
|
|
case WI_RID_FRAG_THRESH:
|
2002-09-30 10:50:35 +04:00
|
|
|
if (wreq.wi_type == WI_RID_MICROWAVE_OVEN &&
|
|
|
|
(sc->sc_flags & WI_FLAGS_HAS_MOR) == 0)
|
|
|
|
break;
|
|
|
|
if (wreq.wi_type == WI_RID_ROAMING_MODE &&
|
|
|
|
(sc->sc_flags & WI_FLAGS_HAS_ROAMING) == 0)
|
|
|
|
break;
|
|
|
|
if (wreq.wi_type == WI_RID_SYSTEM_SCALE &&
|
|
|
|
(sc->sc_flags & WI_FLAGS_HAS_SYSSCALE) == 0)
|
|
|
|
break;
|
2002-11-18 18:10:22 +03:00
|
|
|
if (wreq.wi_type == WI_RID_FRAG_THRESH &&
|
|
|
|
(sc->sc_flags & WI_FLAGS_HAS_FRAGTHR) == 0)
|
|
|
|
break;
|
2002-09-30 10:50:35 +04:00
|
|
|
/* FALLTHROUGH */
|
|
|
|
case WI_RID_RTS_THRESH:
|
|
|
|
case WI_RID_CNFAUTHMODE:
|
|
|
|
case WI_RID_MAX_DATALEN:
|
|
|
|
if (sc->sc_enabled) {
|
|
|
|
error = wi_write_rid(sc, wreq.wi_type, wreq.wi_val,
|
|
|
|
sizeof(u_int16_t));
|
|
|
|
if (error)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
switch (wreq.wi_type) {
|
2002-11-16 09:02:53 +03:00
|
|
|
case WI_RID_FRAG_THRESH:
|
|
|
|
sc->sc_frag_thresh = le16toh(wreq.wi_val[0]);
|
|
|
|
break;
|
2002-09-30 10:50:35 +04:00
|
|
|
case WI_RID_RTS_THRESH:
|
|
|
|
sc->sc_rts_thresh = le16toh(wreq.wi_val[0]);
|
|
|
|
break;
|
|
|
|
case WI_RID_MICROWAVE_OVEN:
|
|
|
|
sc->sc_microwave_oven = le16toh(wreq.wi_val[0]);
|
|
|
|
break;
|
|
|
|
case WI_RID_ROAMING_MODE:
|
|
|
|
sc->sc_roaming_mode = le16toh(wreq.wi_val[0]);
|
|
|
|
break;
|
|
|
|
case WI_RID_SYSTEM_SCALE:
|
|
|
|
sc->sc_system_scale = le16toh(wreq.wi_val[0]);
|
|
|
|
break;
|
|
|
|
case WI_RID_CNFAUTHMODE:
|
|
|
|
sc->sc_cnfauthmode = le16toh(wreq.wi_val[0]);
|
|
|
|
break;
|
|
|
|
case WI_RID_MAX_DATALEN:
|
|
|
|
sc->sc_max_datalen = le16toh(wreq.wi_val[0]);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
2002-09-30 19:48:41 +04:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
case WI_RID_TX_RATE:
|
|
|
|
switch (le16toh(wreq.wi_val[0])) {
|
|
|
|
case 3:
|
|
|
|
ic->ic_fixed_rate = -1;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
for (i = 0; i < IEEE80211_RATE_SIZE; i++) {
|
2003-10-13 12:07:21 +04:00
|
|
|
if ((rs->rs_rates[i] & IEEE80211_RATE_VAL)
|
2002-09-30 10:50:35 +04:00
|
|
|
/ 2 == le16toh(wreq.wi_val[0]))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (i == IEEE80211_RATE_SIZE)
|
|
|
|
return EINVAL;
|
|
|
|
ic->ic_fixed_rate = i;
|
2001-05-15 08:14:06 +04:00
|
|
|
}
|
2002-09-30 10:50:35 +04:00
|
|
|
if (sc->sc_enabled)
|
2003-10-16 14:57:35 +04:00
|
|
|
error = wi_cfg_txrate(sc);
|
2001-05-06 07:26:38 +04:00
|
|
|
break;
|
2002-09-30 19:48:41 +04:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
case WI_RID_SCAN_APS:
|
|
|
|
if (sc->sc_enabled && ic->ic_opmode != IEEE80211_M_HOSTAP)
|
2003-05-13 12:35:58 +04:00
|
|
|
error = wi_scan_ap(sc, 0x3fff, 0x000f);
|
2001-05-06 07:26:38 +04:00
|
|
|
break;
|
2002-09-30 19:48:41 +04:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
case WI_RID_MGMT_XMIT:
|
|
|
|
if (!sc->sc_enabled) {
|
|
|
|
error = ENETDOWN;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (ic->ic_mgtq.ifq_len > 5) {
|
|
|
|
error = EAGAIN;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* XXX wi_len looks in u_int8_t, not in u_int16_t */
|
|
|
|
m = m_devget((char *)&wreq.wi_val, wreq.wi_len, 0, ifp, NULL);
|
|
|
|
if (m == NULL) {
|
|
|
|
error = ENOMEM;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
IF_ENQUEUE(&ic->ic_mgtq, m);
|
|
|
|
break;
|
2002-09-30 19:48:41 +04:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
default:
|
|
|
|
if (sc->sc_enabled) {
|
|
|
|
error = wi_write_rid(sc, wreq.wi_type, wreq.wi_val,
|
|
|
|
len);
|
|
|
|
if (error)
|
|
|
|
break;
|
|
|
|
}
|
2005-06-22 10:14:51 +04:00
|
|
|
error = ieee80211_cfgset(ic, cmd, data);
|
2001-05-06 07:26:38 +04:00
|
|
|
break;
|
|
|
|
}
|
2002-09-30 10:50:35 +04:00
|
|
|
return error;
|
2000-02-12 19:08:04 +03:00
|
|
|
}
|
2000-03-02 08:00:47 +03:00
|
|
|
|
2003-10-16 14:57:35 +04:00
|
|
|
/* Rate is 0 for hardware auto-select, otherwise rate is
|
|
|
|
* 2, 4, 11, or 22 (units of 500Kbps).
|
|
|
|
*/
|
2004-07-22 23:47:24 +04:00
|
|
|
STATIC int
|
2003-10-16 14:57:35 +04:00
|
|
|
wi_write_txrate(struct wi_softc *sc, int rate)
|
2000-03-02 08:00:47 +03:00
|
|
|
{
|
2003-10-16 14:57:35 +04:00
|
|
|
u_int16_t hwrate;
|
2000-03-02 08:00:47 +03:00
|
|
|
|
2004-07-22 23:56:55 +04:00
|
|
|
/* rate: 0, 2, 4, 11, 22 */
|
2002-09-30 10:50:35 +04:00
|
|
|
switch (sc->sc_firmware_type) {
|
|
|
|
case WI_LUCENT:
|
2004-07-22 23:56:55 +04:00
|
|
|
switch (rate & IEEE80211_RATE_VAL) {
|
|
|
|
case 2:
|
|
|
|
hwrate = 1;
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
hwrate = 2;
|
|
|
|
break;
|
|
|
|
default:
|
2003-10-16 14:57:35 +04:00
|
|
|
hwrate = 3; /* auto */
|
|
|
|
break;
|
2004-07-22 23:56:55 +04:00
|
|
|
case 11:
|
2003-10-16 14:57:35 +04:00
|
|
|
hwrate = 4;
|
|
|
|
break;
|
2004-07-22 23:56:55 +04:00
|
|
|
case 22:
|
2003-10-16 14:57:35 +04:00
|
|
|
hwrate = 5;
|
|
|
|
break;
|
|
|
|
}
|
2002-09-30 10:50:35 +04:00
|
|
|
break;
|
|
|
|
default:
|
2004-07-22 23:56:55 +04:00
|
|
|
switch (rate & IEEE80211_RATE_VAL) {
|
|
|
|
case 2:
|
|
|
|
hwrate = 1;
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
hwrate = 2;
|
|
|
|
break;
|
|
|
|
case 11:
|
|
|
|
hwrate = 4;
|
|
|
|
break;
|
|
|
|
case 22:
|
|
|
|
hwrate = 8;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
hwrate = 15; /* auto */
|
|
|
|
break;
|
2002-09-30 10:50:35 +04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2003-10-16 14:57:35 +04:00
|
|
|
|
|
|
|
if (sc->sc_tx_rate == hwrate)
|
|
|
|
return 0;
|
|
|
|
|
2003-11-02 02:57:05 +03:00
|
|
|
if (sc->sc_if.if_flags & IFF_DEBUG)
|
|
|
|
printf("%s: tx rate %d -> %d (%d)\n", __func__, sc->sc_tx_rate,
|
|
|
|
hwrate, rate);
|
|
|
|
|
2003-10-16 14:57:35 +04:00
|
|
|
sc->sc_tx_rate = hwrate;
|
|
|
|
|
|
|
|
return wi_write_val(sc, WI_RID_TX_RATE, sc->sc_tx_rate);
|
|
|
|
}
|
|
|
|
|
2004-07-22 23:47:24 +04:00
|
|
|
STATIC int
|
2003-10-16 14:57:35 +04:00
|
|
|
wi_cfg_txrate(struct wi_softc *sc)
|
|
|
|
{
|
|
|
|
struct ieee80211com *ic = &sc->sc_ic;
|
|
|
|
struct ieee80211_rateset *rs;
|
|
|
|
int rate;
|
|
|
|
|
|
|
|
rs = &ic->ic_sup_rates[IEEE80211_MODE_11B];
|
|
|
|
|
|
|
|
sc->sc_tx_rate = 0; /* force write to RID */
|
|
|
|
|
|
|
|
if (ic->ic_fixed_rate < 0)
|
|
|
|
rate = 0; /* auto */
|
|
|
|
else
|
2003-11-02 02:57:05 +03:00
|
|
|
rate = rs->rs_rates[ic->ic_fixed_rate];
|
2003-10-16 14:57:35 +04:00
|
|
|
|
|
|
|
return wi_write_txrate(sc, rate);
|
2000-03-02 08:00:47 +03:00
|
|
|
}
|
|
|
|
|
2005-06-25 07:56:53 +04:00
|
|
|
STATIC int
|
|
|
|
wi_key_delete(struct ieee80211com *ic, const struct ieee80211_key *k)
|
|
|
|
{
|
|
|
|
struct wi_softc *sc = ic->ic_ifp->if_softc;
|
|
|
|
u_int keyix = k->wk_keyix;
|
|
|
|
|
|
|
|
DPRINTF(("%s: delete key %u\n", __func__, keyix));
|
|
|
|
|
|
|
|
if (keyix >= IEEE80211_WEP_NKID)
|
|
|
|
return 0;
|
|
|
|
if (k->wk_keylen != 0)
|
|
|
|
sc->sc_flags &= ~WI_FLAGS_WEP_VALID;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
wi_key_set(struct ieee80211com *ic, const struct ieee80211_key *k,
|
2006-11-16 04:32:37 +03:00
|
|
|
const u_int8_t mac[IEEE80211_ADDR_LEN])
|
2005-06-25 07:56:53 +04:00
|
|
|
{
|
|
|
|
struct wi_softc *sc = ic->ic_ifp->if_softc;
|
|
|
|
|
|
|
|
DPRINTF(("%s: set key %u\n", __func__, k->wk_keyix));
|
|
|
|
|
|
|
|
if (k->wk_keyix >= IEEE80211_WEP_NKID)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
sc->sc_flags &= ~WI_FLAGS_WEP_VALID;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
STATIC void
|
2006-11-16 04:32:37 +03:00
|
|
|
wi_key_update_begin(struct ieee80211com *ic)
|
2005-06-25 07:56:53 +04:00
|
|
|
{
|
|
|
|
DPRINTF(("%s:\n", __func__));
|
|
|
|
}
|
|
|
|
|
|
|
|
STATIC void
|
|
|
|
wi_key_update_end(struct ieee80211com *ic)
|
|
|
|
{
|
|
|
|
struct ifnet *ifp = ic->ic_ifp;
|
|
|
|
struct wi_softc *sc = ifp->if_softc;
|
|
|
|
|
|
|
|
DPRINTF(("%s:\n", __func__));
|
|
|
|
|
|
|
|
if ((sc->sc_flags & WI_FLAGS_WEP_VALID) != 0)
|
|
|
|
return;
|
2005-07-06 10:49:25 +04:00
|
|
|
if ((ic->ic_caps & IEEE80211_C_WEP) != 0 && sc->sc_enabled &&
|
|
|
|
!sc->sc_invalid)
|
2005-06-25 07:56:53 +04:00
|
|
|
(void)wi_write_wep(sc);
|
|
|
|
}
|
|
|
|
|
2004-07-22 23:47:24 +04:00
|
|
|
STATIC int
|
2002-09-30 10:50:35 +04:00
|
|
|
wi_write_wep(struct wi_softc *sc)
|
2000-07-31 07:25:11 +04:00
|
|
|
{
|
2005-06-25 07:56:53 +04:00
|
|
|
struct ifnet *ifp = &sc->sc_if;
|
2002-09-30 10:50:35 +04:00
|
|
|
struct ieee80211com *ic = &sc->sc_ic;
|
|
|
|
int error = 0;
|
|
|
|
int i, keylen;
|
|
|
|
u_int16_t val;
|
|
|
|
struct wi_key wkey[IEEE80211_WEP_NKID];
|
2000-07-31 07:25:11 +04:00
|
|
|
|
2005-06-25 07:56:53 +04:00
|
|
|
if ((ifp->if_flags & IFF_RUNNING) != 0)
|
|
|
|
wi_cmd(sc, WI_CMD_DISABLE | sc->sc_portnum, 0, 0, 0);
|
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
switch (sc->sc_firmware_type) {
|
|
|
|
case WI_LUCENT:
|
2004-07-23 12:31:39 +04:00
|
|
|
val = (ic->ic_flags & IEEE80211_F_PRIVACY) ? 1 : 0;
|
2002-09-30 10:50:35 +04:00
|
|
|
error = wi_write_val(sc, WI_RID_ENCRYPTION, val);
|
|
|
|
if (error)
|
|
|
|
break;
|
2005-06-22 10:14:51 +04:00
|
|
|
error = wi_write_val(sc, WI_RID_TX_CRYPT_KEY, ic->ic_def_txkey);
|
2002-09-30 10:50:35 +04:00
|
|
|
if (error)
|
|
|
|
break;
|
|
|
|
memset(wkey, 0, sizeof(wkey));
|
|
|
|
for (i = 0; i < IEEE80211_WEP_NKID; i++) {
|
2005-06-22 10:14:51 +04:00
|
|
|
keylen = ic->ic_nw_keys[i].wk_keylen;
|
2002-09-30 10:50:35 +04:00
|
|
|
wkey[i].wi_keylen = htole16(keylen);
|
|
|
|
memcpy(wkey[i].wi_keydat, ic->ic_nw_keys[i].wk_key,
|
|
|
|
keylen);
|
|
|
|
}
|
|
|
|
error = wi_write_rid(sc, WI_RID_DEFLT_CRYPT_KEYS,
|
|
|
|
wkey, sizeof(wkey));
|
2000-07-31 07:25:11 +04:00
|
|
|
break;
|
2002-08-11 05:30:28 +04:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
case WI_INTERSIL:
|
|
|
|
case WI_SYMBOL:
|
2004-07-23 12:31:39 +04:00
|
|
|
if (ic->ic_flags & IEEE80211_F_PRIVACY) {
|
2002-09-30 10:50:35 +04:00
|
|
|
/*
|
|
|
|
* ONLY HWB3163 EVAL-CARD Firmware version
|
|
|
|
* less than 0.8 variant2
|
|
|
|
*
|
|
|
|
* If promiscuous mode disable, Prism2 chip
|
|
|
|
* does not work with WEP .
|
|
|
|
* It is under investigation for details.
|
2003-12-04 16:57:30 +03:00
|
|
|
* (ichiro@NetBSD.org)
|
2002-09-30 10:50:35 +04:00
|
|
|
*/
|
|
|
|
if (sc->sc_firmware_type == WI_INTERSIL &&
|
|
|
|
sc->sc_sta_firmware_ver < 802 ) {
|
|
|
|
/* firm ver < 0.8 variant 2 */
|
|
|
|
wi_write_val(sc, WI_RID_PROMISC, 1);
|
|
|
|
}
|
|
|
|
wi_write_val(sc, WI_RID_CNFAUTHMODE,
|
|
|
|
sc->sc_cnfauthmode);
|
2005-06-25 07:56:53 +04:00
|
|
|
val = PRIVACY_INVOKED;
|
|
|
|
if ((sc->sc_ic_flags & IEEE80211_F_DROPUNENC) != 0)
|
|
|
|
val |= EXCLUDE_UNENCRYPTED;
|
2005-06-26 08:37:25 +04:00
|
|
|
#ifndef IEEE80211_NO_HOSTAP
|
2002-10-15 12:53:46 +04:00
|
|
|
/*
|
|
|
|
* Encryption firmware has a bug for HostAP mode.
|
|
|
|
*/
|
|
|
|
if (sc->sc_firmware_type == WI_INTERSIL &&
|
|
|
|
ic->ic_opmode == IEEE80211_M_HOSTAP)
|
2002-09-30 10:50:35 +04:00
|
|
|
val |= HOST_ENCRYPT;
|
2005-06-26 08:37:25 +04:00
|
|
|
#endif /* !IEEE80211_NO_HOSTAP */
|
2002-09-30 10:50:35 +04:00
|
|
|
} else {
|
2002-10-15 12:53:46 +04:00
|
|
|
wi_write_val(sc, WI_RID_CNFAUTHMODE,
|
|
|
|
IEEE80211_AUTH_OPEN);
|
2002-09-30 10:50:35 +04:00
|
|
|
val = HOST_ENCRYPT | HOST_DECRYPT;
|
|
|
|
}
|
|
|
|
error = wi_write_val(sc, WI_RID_P2_ENCRYPTION, val);
|
|
|
|
if (error)
|
|
|
|
break;
|
|
|
|
error = wi_write_val(sc, WI_RID_P2_TX_CRYPT_KEY,
|
2005-06-22 10:14:51 +04:00
|
|
|
ic->ic_def_txkey);
|
2002-09-30 10:50:35 +04:00
|
|
|
if (error)
|
|
|
|
break;
|
2002-10-15 12:53:46 +04:00
|
|
|
/*
|
|
|
|
* It seems that the firmware accept 104bit key only if
|
|
|
|
* all the keys have 104bit length. We get the length of
|
|
|
|
* the transmit key and use it for all other keys.
|
|
|
|
* Perhaps we should use software WEP for such situation.
|
|
|
|
*/
|
2005-06-27 01:51:37 +04:00
|
|
|
if (ic->ic_def_txkey == IEEE80211_KEYIX_NONE ||
|
|
|
|
IEEE80211_KEY_UNDEFINED(ic->ic_nw_keys[ic->ic_def_txkey]))
|
|
|
|
keylen = 13; /* No keys => 104bit ok */
|
|
|
|
else
|
|
|
|
keylen = ic->ic_nw_keys[ic->ic_def_txkey].wk_keylen;
|
|
|
|
|
2002-10-15 12:53:46 +04:00
|
|
|
if (keylen > IEEE80211_WEP_KEYLEN)
|
|
|
|
keylen = 13; /* 104bit keys */
|
|
|
|
else
|
|
|
|
keylen = IEEE80211_WEP_KEYLEN;
|
2002-09-30 10:50:35 +04:00
|
|
|
for (i = 0; i < IEEE80211_WEP_NKID; i++) {
|
|
|
|
error = wi_write_rid(sc, WI_RID_P2_CRYPT_KEY0 + i,
|
|
|
|
ic->ic_nw_keys[i].wk_key, keylen);
|
|
|
|
if (error)
|
|
|
|
break;
|
|
|
|
}
|
2000-07-31 07:25:11 +04:00
|
|
|
break;
|
|
|
|
}
|
2005-06-25 07:56:53 +04:00
|
|
|
if ((ifp->if_flags & IFF_RUNNING) != 0)
|
|
|
|
wi_cmd(sc, WI_CMD_ENABLE | sc->sc_portnum, 0, 0, 0);
|
|
|
|
if (error == 0)
|
|
|
|
sc->sc_flags |= WI_FLAGS_WEP_VALID;
|
2002-09-30 10:50:35 +04:00
|
|
|
return error;
|
2000-07-31 07:25:11 +04:00
|
|
|
}
|
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
/* Must be called at proper protection level! */
|
2004-07-23 12:31:39 +04:00
|
|
|
STATIC int
|
2004-12-13 20:55:28 +03:00
|
|
|
wi_cmd_start(struct wi_softc *sc, int cmd, int val0, int val1, int val2)
|
2000-03-02 08:00:47 +03:00
|
|
|
{
|
2004-07-23 00:34:52 +04:00
|
|
|
#ifdef WI_HISTOGRAM
|
|
|
|
static int hist1[11];
|
|
|
|
static int hist1count;
|
|
|
|
#endif
|
2004-12-13 20:55:28 +03:00
|
|
|
int i;
|
2002-08-11 05:30:28 +04:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
/* wait for the busy bit to clear */
|
2003-05-13 10:15:47 +04:00
|
|
|
for (i = 500; i > 0; i--) { /* 5s */
|
2002-09-30 10:50:35 +04:00
|
|
|
if ((CSR_READ_2(sc, WI_COMMAND) & WI_CMD_BUSY) == 0)
|
|
|
|
break;
|
2005-06-22 10:14:51 +04:00
|
|
|
if (sc->sc_invalid)
|
|
|
|
return ENXIO;
|
2004-07-23 00:36:11 +04:00
|
|
|
DELAY(1000); /* 1 m sec */
|
2002-08-11 05:30:28 +04:00
|
|
|
}
|
2003-05-13 10:15:47 +04:00
|
|
|
if (i == 0) {
|
2010-11-23 07:33:09 +03:00
|
|
|
aprint_error_dev(sc->sc_dev, "wi_cmd: busy bit won't clear.\n");
|
2003-05-13 10:15:47 +04:00
|
|
|
return(ETIMEDOUT);
|
|
|
|
}
|
2004-07-23 00:34:52 +04:00
|
|
|
#ifdef WI_HISTOGRAM
|
|
|
|
if (i > 490)
|
|
|
|
hist1[500 - i]++;
|
|
|
|
else
|
|
|
|
hist1[10]++;
|
|
|
|
if (++hist1count == 1000) {
|
|
|
|
hist1count = 0;
|
|
|
|
printf("%s: hist1: %d %d %d %d %d %d %d %d %d %d %d\n",
|
2010-11-23 07:33:09 +03:00
|
|
|
device_xname(sc->sc_dev),
|
2004-07-23 00:34:52 +04:00
|
|
|
hist1[0], hist1[1], hist1[2], hist1[3], hist1[4],
|
|
|
|
hist1[5], hist1[6], hist1[7], hist1[8], hist1[9],
|
|
|
|
hist1[10]);
|
|
|
|
}
|
|
|
|
#endif
|
2002-09-30 10:50:35 +04:00
|
|
|
CSR_WRITE_2(sc, WI_PARAM0, val0);
|
|
|
|
CSR_WRITE_2(sc, WI_PARAM1, val1);
|
|
|
|
CSR_WRITE_2(sc, WI_PARAM2, val2);
|
|
|
|
CSR_WRITE_2(sc, WI_COMMAND, cmd);
|
2000-03-02 08:00:47 +03:00
|
|
|
|
2004-12-13 20:55:28 +03:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
STATIC int
|
|
|
|
wi_cmd(struct wi_softc *sc, int cmd, int val0, int val1, int val2)
|
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
#ifdef WI_DEBUG
|
|
|
|
if (wi_debug) {
|
|
|
|
printf("%s: [enter] %d txcmds outstanding\n", __func__,
|
|
|
|
sc->sc_txcmds);
|
|
|
|
}
|
|
|
|
#endif
|
2004-12-14 22:53:46 +03:00
|
|
|
if (sc->sc_txcmds > 0)
|
|
|
|
wi_txcmd_wait(sc);
|
2004-12-13 20:55:28 +03:00
|
|
|
|
|
|
|
if ((rc = wi_cmd_start(sc, cmd, val0, val1, val2)) != 0)
|
|
|
|
return rc;
|
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
if (cmd == WI_CMD_INI) {
|
|
|
|
/* XXX: should sleep here. */
|
2005-06-22 10:14:51 +04:00
|
|
|
if (sc->sc_invalid)
|
|
|
|
return ENXIO;
|
2002-09-30 10:50:35 +04:00
|
|
|
DELAY(100*1000);
|
|
|
|
}
|
2004-12-13 20:55:28 +03:00
|
|
|
rc = wi_cmd_wait(sc, cmd, val0);
|
|
|
|
|
|
|
|
#ifdef WI_DEBUG
|
|
|
|
if (wi_debug) {
|
|
|
|
printf("%s: [ ] %d txcmds outstanding\n", __func__,
|
|
|
|
sc->sc_txcmds);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
if (sc->sc_txcmds > 0)
|
|
|
|
wi_cmd_intr(sc);
|
|
|
|
|
|
|
|
#ifdef WI_DEBUG
|
|
|
|
if (wi_debug) {
|
|
|
|
printf("%s: [leave] %d txcmds outstanding\n", __func__,
|
|
|
|
sc->sc_txcmds);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
STATIC int
|
|
|
|
wi_cmd_wait(struct wi_softc *sc, int cmd, int val0)
|
|
|
|
{
|
|
|
|
#ifdef WI_HISTOGRAM
|
|
|
|
static int hist2[11];
|
|
|
|
static int hist2count;
|
|
|
|
#endif
|
|
|
|
int i, status;
|
|
|
|
#ifdef WI_DEBUG
|
|
|
|
if (wi_debug > 1)
|
|
|
|
printf("%s: cmd=%#x, arg=%#x\n", __func__, cmd, val0);
|
|
|
|
#endif /* WI_DEBUG */
|
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
/* wait for the cmd completed bit */
|
|
|
|
for (i = 0; i < WI_TIMEOUT; i++) {
|
|
|
|
if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_CMD)
|
|
|
|
break;
|
2005-06-22 10:14:51 +04:00
|
|
|
if (sc->sc_invalid)
|
|
|
|
return ENXIO;
|
2003-05-13 12:35:58 +04:00
|
|
|
DELAY(WI_DELAY);
|
2000-03-02 08:00:47 +03:00
|
|
|
}
|
2004-12-13 20:55:28 +03:00
|
|
|
|
2004-07-23 00:34:52 +04:00
|
|
|
#ifdef WI_HISTOGRAM
|
|
|
|
if (i < 100)
|
|
|
|
hist2[i/10]++;
|
|
|
|
else
|
|
|
|
hist2[10]++;
|
|
|
|
if (++hist2count == 1000) {
|
|
|
|
hist2count = 0;
|
|
|
|
printf("%s: hist2: %d %d %d %d %d %d %d %d %d %d %d\n",
|
2010-11-23 07:33:09 +03:00
|
|
|
device_xname(sc->sc_dev),
|
2004-07-23 00:34:52 +04:00
|
|
|
hist2[0], hist2[1], hist2[2], hist2[3], hist2[4],
|
|
|
|
hist2[5], hist2[6], hist2[7], hist2[8], hist2[9],
|
|
|
|
hist2[10]);
|
|
|
|
}
|
|
|
|
#endif
|
2000-03-02 08:00:47 +03:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
status = CSR_READ_2(sc, WI_STATUS);
|
|
|
|
|
|
|
|
if (i == WI_TIMEOUT) {
|
2010-11-23 07:33:09 +03:00
|
|
|
aprint_error_dev(sc->sc_dev,
|
|
|
|
"command timed out, cmd=0x%x, arg=0x%x\n",
|
2008-04-08 16:07:25 +04:00
|
|
|
cmd, val0);
|
2002-09-30 10:50:35 +04:00
|
|
|
return ETIMEDOUT;
|
|
|
|
}
|
|
|
|
|
2004-12-13 20:55:28 +03:00
|
|
|
CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_CMD);
|
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
if (status & WI_STAT_CMD_RESULT) {
|
2010-11-23 07:33:09 +03:00
|
|
|
aprint_error_dev(sc->sc_dev,
|
|
|
|
"command failed, cmd=0x%x, arg=0x%x\n",
|
2008-04-08 16:07:25 +04:00
|
|
|
cmd, val0);
|
2002-09-30 10:50:35 +04:00
|
|
|
return EIO;
|
|
|
|
}
|
|
|
|
return 0;
|
2000-03-02 08:00:47 +03:00
|
|
|
}
|
|
|
|
|
2004-07-22 23:47:24 +04:00
|
|
|
STATIC int
|
2002-09-30 10:50:35 +04:00
|
|
|
wi_seek_bap(struct wi_softc *sc, int id, int off)
|
2000-03-02 08:00:47 +03:00
|
|
|
{
|
2004-07-23 00:34:52 +04:00
|
|
|
#ifdef WI_HISTOGRAM
|
|
|
|
static int hist4[11];
|
|
|
|
static int hist4count;
|
|
|
|
#endif
|
2002-09-30 10:50:35 +04:00
|
|
|
int i, status;
|
2000-03-02 08:00:47 +03:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
CSR_WRITE_2(sc, WI_SEL0, id);
|
|
|
|
CSR_WRITE_2(sc, WI_OFF0, off);
|
2000-03-02 08:00:47 +03:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
for (i = 0; ; i++) {
|
|
|
|
status = CSR_READ_2(sc, WI_OFF0);
|
|
|
|
if ((status & WI_OFF_BUSY) == 0)
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
break;
|
2002-09-30 10:50:35 +04:00
|
|
|
if (i == WI_TIMEOUT) {
|
2010-11-23 07:33:09 +03:00
|
|
|
aprint_error_dev(sc->sc_dev,
|
|
|
|
"timeout in wi_seek to %x/%x\n",
|
2008-04-08 16:07:25 +04:00
|
|
|
id, off);
|
2002-09-30 10:50:35 +04:00
|
|
|
sc->sc_bap_off = WI_OFF_ERR; /* invalidate */
|
|
|
|
return ETIMEDOUT;
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
}
|
2005-06-22 10:14:51 +04:00
|
|
|
if (sc->sc_invalid)
|
|
|
|
return ENXIO;
|
2004-07-23 00:36:11 +04:00
|
|
|
DELAY(2);
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
}
|
2004-07-23 00:34:52 +04:00
|
|
|
#ifdef WI_HISTOGRAM
|
|
|
|
if (i < 100)
|
|
|
|
hist4[i/10]++;
|
|
|
|
else
|
|
|
|
hist4[10]++;
|
|
|
|
if (++hist4count == 2500) {
|
|
|
|
hist4count = 0;
|
|
|
|
printf("%s: hist4: %d %d %d %d %d %d %d %d %d %d %d\n",
|
2010-11-23 07:33:09 +03:00
|
|
|
device_xname(sc->sc_dev),
|
2004-07-23 00:34:52 +04:00
|
|
|
hist4[0], hist4[1], hist4[2], hist4[3], hist4[4],
|
|
|
|
hist4[5], hist4[6], hist4[7], hist4[8], hist4[9],
|
|
|
|
hist4[10]);
|
|
|
|
}
|
|
|
|
#endif
|
2002-09-30 10:50:35 +04:00
|
|
|
if (status & WI_OFF_ERR) {
|
|
|
|
printf("%s: failed in wi_seek to %x/%x\n",
|
2010-11-23 07:33:09 +03:00
|
|
|
device_xname(sc->sc_dev), id, off);
|
2002-09-30 10:50:35 +04:00
|
|
|
sc->sc_bap_off = WI_OFF_ERR; /* invalidate */
|
|
|
|
return EIO;
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
}
|
2002-09-30 10:50:35 +04:00
|
|
|
sc->sc_bap_id = id;
|
|
|
|
sc->sc_bap_off = off;
|
|
|
|
return 0;
|
2000-03-02 08:00:47 +03:00
|
|
|
}
|
2000-07-21 08:48:55 +04:00
|
|
|
|
2004-07-22 23:47:24 +04:00
|
|
|
STATIC int
|
2002-09-30 10:50:35 +04:00
|
|
|
wi_read_bap(struct wi_softc *sc, int id, int off, void *buf, int buflen)
|
2000-07-21 08:48:55 +04:00
|
|
|
{
|
2002-09-30 10:50:35 +04:00
|
|
|
int error, cnt;
|
2000-07-21 08:48:55 +04:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
if (buflen == 0)
|
|
|
|
return 0;
|
|
|
|
if (id != sc->sc_bap_id || off != sc->sc_bap_off) {
|
|
|
|
if ((error = wi_seek_bap(sc, id, off)) != 0)
|
2000-07-21 08:48:55 +04:00
|
|
|
return error;
|
|
|
|
}
|
2002-09-30 10:50:35 +04:00
|
|
|
cnt = (buflen + 1) / 2;
|
|
|
|
CSR_READ_MULTI_STREAM_2(sc, WI_DATA0, (u_int16_t *)buf, cnt);
|
|
|
|
sc->sc_bap_off += cnt * 2;
|
|
|
|
return 0;
|
|
|
|
}
|
2000-07-21 08:48:55 +04:00
|
|
|
|
2004-07-22 23:47:24 +04:00
|
|
|
STATIC int
|
2002-09-30 10:50:35 +04:00
|
|
|
wi_write_bap(struct wi_softc *sc, int id, int off, void *buf, int buflen)
|
|
|
|
{
|
|
|
|
int error, cnt;
|
2000-07-21 08:48:55 +04:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
if (buflen == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
#ifdef WI_HERMES_AUTOINC_WAR
|
|
|
|
again:
|
|
|
|
#endif
|
|
|
|
if (id != sc->sc_bap_id || off != sc->sc_bap_off) {
|
|
|
|
if ((error = wi_seek_bap(sc, id, off)) != 0)
|
2000-07-21 08:48:55 +04:00
|
|
|
return error;
|
|
|
|
}
|
2002-09-30 10:50:35 +04:00
|
|
|
cnt = (buflen + 1) / 2;
|
|
|
|
CSR_WRITE_MULTI_STREAM_2(sc, WI_DATA0, (u_int16_t *)buf, cnt);
|
|
|
|
sc->sc_bap_off += cnt * 2;
|
2000-07-21 08:48:55 +04:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
#ifdef WI_HERMES_AUTOINC_WAR
|
|
|
|
/*
|
|
|
|
* According to the comments in the HCF Light code, there is a bug
|
|
|
|
* in the Hermes (or possibly in certain Hermes firmware revisions)
|
|
|
|
* where the chip's internal autoincrement counter gets thrown off
|
|
|
|
* during data writes: the autoincrement is missed, causing one
|
|
|
|
* data word to be overwritten and subsequent words to be written to
|
|
|
|
* the wrong memory locations. The end result is that we could end
|
|
|
|
* up transmitting bogus frames without realizing it. The workaround
|
|
|
|
* for this is to write a couple of extra guard words after the end
|
|
|
|
* of the transfer, then attempt to read then back. If we fail to
|
|
|
|
* locate the guard words where we expect them, we preform the
|
|
|
|
* transfer over again.
|
|
|
|
*/
|
|
|
|
if ((sc->sc_flags & WI_FLAGS_BUG_AUTOINC) && (id & 0xf000) == 0) {
|
|
|
|
CSR_WRITE_2(sc, WI_DATA0, 0x1234);
|
|
|
|
CSR_WRITE_2(sc, WI_DATA0, 0x5678);
|
|
|
|
wi_seek_bap(sc, id, sc->sc_bap_off);
|
|
|
|
sc->sc_bap_off = WI_OFF_ERR; /* invalidate */
|
|
|
|
if (CSR_READ_2(sc, WI_DATA0) != 0x1234 ||
|
|
|
|
CSR_READ_2(sc, WI_DATA0) != 0x5678) {
|
2010-11-23 07:33:09 +03:00
|
|
|
aprint_error_dev(sc->sc_dev,
|
|
|
|
"detect auto increment bug, try again\n");
|
2002-09-30 10:50:35 +04:00
|
|
|
goto again;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2000-07-21 08:48:55 +04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2004-07-22 23:47:24 +04:00
|
|
|
STATIC int
|
2003-01-09 11:49:39 +03:00
|
|
|
wi_mwrite_bap(struct wi_softc *sc, int id, int off, struct mbuf *m0, int totlen)
|
|
|
|
{
|
|
|
|
int error, len;
|
|
|
|
struct mbuf *m;
|
|
|
|
|
|
|
|
for (m = m0; m != NULL && totlen > 0; m = m->m_next) {
|
|
|
|
if (m->m_len == 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
len = min(m->m_len, totlen);
|
|
|
|
|
|
|
|
if (((u_long)m->m_data) % 2 != 0 || len % 2 != 0) {
|
2007-03-04 08:59:00 +03:00
|
|
|
m_copydata(m, 0, totlen, (void *)&sc->sc_txbuf);
|
|
|
|
return wi_write_bap(sc, id, off, (void *)&sc->sc_txbuf,
|
2003-01-09 11:49:39 +03:00
|
|
|
totlen);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((error = wi_write_bap(sc, id, off, m->m_data, len)) != 0)
|
|
|
|
return error;
|
|
|
|
|
|
|
|
off += m->m_len;
|
|
|
|
totlen -= len;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2004-07-22 23:47:24 +04:00
|
|
|
STATIC int
|
2002-09-30 10:50:35 +04:00
|
|
|
wi_alloc_fid(struct wi_softc *sc, int len, int *idp)
|
2000-07-21 08:48:55 +04:00
|
|
|
{
|
2002-09-30 10:50:35 +04:00
|
|
|
int i;
|
2000-07-21 08:48:55 +04:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
if (wi_cmd(sc, WI_CMD_ALLOC_MEM, len, 0, 0)) {
|
2010-11-23 07:33:09 +03:00
|
|
|
aprint_error_dev(sc->sc_dev, "failed to allocate %d bytes on NIC\n", len);
|
2002-09-30 10:50:35 +04:00
|
|
|
return ENOMEM;
|
|
|
|
}
|
2000-07-21 08:48:55 +04:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
for (i = 0; i < WI_TIMEOUT; i++) {
|
|
|
|
if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_ALLOC)
|
|
|
|
break;
|
|
|
|
DELAY(1);
|
2000-07-21 08:48:55 +04:00
|
|
|
}
|
2005-03-27 04:49:14 +04:00
|
|
|
if (i == WI_TIMEOUT) {
|
2010-11-23 07:33:09 +03:00
|
|
|
aprint_error_dev(sc->sc_dev, "timeout in alloc\n");
|
2005-03-27 04:49:14 +04:00
|
|
|
return ETIMEDOUT;
|
|
|
|
}
|
2002-09-30 10:50:35 +04:00
|
|
|
*idp = CSR_READ_2(sc, WI_ALLOC_FID);
|
|
|
|
CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
|
2000-07-21 08:48:55 +04:00
|
|
|
return 0;
|
|
|
|
}
|
2000-12-12 07:04:29 +03:00
|
|
|
|
2004-07-22 23:47:24 +04:00
|
|
|
STATIC int
|
2002-09-30 10:50:35 +04:00
|
|
|
wi_read_rid(struct wi_softc *sc, int rid, void *buf, int *buflenp)
|
2000-12-12 07:04:29 +03:00
|
|
|
{
|
2002-09-30 10:50:35 +04:00
|
|
|
int error, len;
|
|
|
|
u_int16_t ltbuf[2];
|
2000-12-12 07:04:29 +03:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
/* Tell the NIC to enter record read mode. */
|
|
|
|
error = wi_cmd(sc, WI_CMD_ACCESS | WI_ACCESS_READ, rid, 0, 0);
|
|
|
|
if (error)
|
|
|
|
return error;
|
2000-12-12 07:04:29 +03:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
error = wi_read_bap(sc, rid, 0, ltbuf, sizeof(ltbuf));
|
|
|
|
if (error)
|
|
|
|
return error;
|
2000-12-12 07:04:29 +03:00
|
|
|
|
2004-08-07 21:12:44 +04:00
|
|
|
if (le16toh(ltbuf[0]) == 0)
|
|
|
|
return EOPNOTSUPP;
|
2002-09-30 10:50:35 +04:00
|
|
|
if (le16toh(ltbuf[1]) != rid) {
|
2010-11-23 07:33:09 +03:00
|
|
|
aprint_error_dev(sc->sc_dev,
|
|
|
|
"record read mismatch, rid=%x, got=%x\n",
|
2008-04-08 16:07:25 +04:00
|
|
|
rid, le16toh(ltbuf[1]));
|
2002-09-30 10:50:35 +04:00
|
|
|
return EIO;
|
|
|
|
}
|
2004-08-07 21:12:44 +04:00
|
|
|
len = (le16toh(ltbuf[0]) - 1) * 2; /* already got rid */
|
2002-09-30 10:50:35 +04:00
|
|
|
if (*buflenp < len) {
|
2010-11-23 07:33:09 +03:00
|
|
|
aprint_error_dev(sc->sc_dev, "record buffer is too small, "
|
2002-09-30 10:50:35 +04:00
|
|
|
"rid=%x, size=%d, len=%d\n",
|
2008-04-08 16:07:25 +04:00
|
|
|
rid, *buflenp, len);
|
2002-09-30 10:50:35 +04:00
|
|
|
return ENOSPC;
|
|
|
|
}
|
|
|
|
*buflenp = len;
|
|
|
|
return wi_read_bap(sc, rid, sizeof(ltbuf), buf, len);
|
2000-12-12 07:04:29 +03:00
|
|
|
}
|
|
|
|
|
2004-07-22 23:47:24 +04:00
|
|
|
STATIC int
|
2002-09-30 10:50:35 +04:00
|
|
|
wi_write_rid(struct wi_softc *sc, int rid, void *buf, int buflen)
|
2000-12-12 07:04:29 +03:00
|
|
|
{
|
2002-09-30 10:50:35 +04:00
|
|
|
int error;
|
|
|
|
u_int16_t ltbuf[2];
|
|
|
|
|
|
|
|
ltbuf[0] = htole16((buflen + 1) / 2 + 1); /* includes rid */
|
|
|
|
ltbuf[1] = htole16(rid);
|
2000-12-12 07:04:29 +03:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
error = wi_write_bap(sc, rid, 0, ltbuf, sizeof(ltbuf));
|
|
|
|
if (error)
|
|
|
|
return error;
|
|
|
|
error = wi_write_bap(sc, rid, sizeof(ltbuf), buf, buflen);
|
|
|
|
if (error)
|
|
|
|
return error;
|
2000-12-12 07:04:29 +03:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
return wi_cmd(sc, WI_CMD_ACCESS | WI_ACCESS_WRITE, rid, 0, 0);
|
2000-12-12 07:04:29 +03:00
|
|
|
}
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
|
2004-07-22 23:47:24 +04:00
|
|
|
STATIC void
|
2006-11-16 04:32:37 +03:00
|
|
|
wi_rssadapt_updatestats_cb(void *arg, struct ieee80211_node *ni)
|
2003-12-07 08:44:49 +03:00
|
|
|
{
|
|
|
|
struct wi_node *wn = (void*)ni;
|
|
|
|
ieee80211_rssadapt_updatestats(&wn->wn_rssadapt);
|
|
|
|
}
|
|
|
|
|
2004-07-22 23:47:24 +04:00
|
|
|
STATIC void
|
2003-12-07 08:44:49 +03:00
|
|
|
wi_rssadapt_updatestats(void *arg)
|
|
|
|
{
|
|
|
|
struct wi_softc *sc = arg;
|
|
|
|
struct ieee80211com *ic = &sc->sc_ic;
|
2005-06-22 10:14:51 +04:00
|
|
|
ieee80211_iterate_nodes(&ic->ic_sta, wi_rssadapt_updatestats_cb, arg);
|
2003-12-07 08:44:49 +03:00
|
|
|
if (ic->ic_opmode != IEEE80211_M_MONITOR &&
|
|
|
|
ic->ic_state == IEEE80211_S_RUN)
|
|
|
|
callout_reset(&sc->sc_rssadapt_ch, hz / 10,
|
|
|
|
wi_rssadapt_updatestats, arg);
|
|
|
|
}
|
|
|
|
|
2005-06-25 07:56:53 +04:00
|
|
|
/*
|
|
|
|
* In HOSTAP mode, restore IEEE80211_F_DROPUNENC when operating
|
|
|
|
* with WEP enabled so that the AP drops unencoded frames at the
|
|
|
|
* 802.11 layer.
|
|
|
|
*
|
|
|
|
* In all other modes, clear IEEE80211_F_DROPUNENC when operating
|
|
|
|
* with WEP enabled so we don't drop unencoded frames at the 802.11
|
|
|
|
* layer. This is necessary because we must strip the WEP bit from
|
|
|
|
* the 802.11 header before passing frames to ieee80211_input
|
|
|
|
* because the card has already stripped the WEP crypto header from
|
|
|
|
* the packet.
|
|
|
|
*/
|
|
|
|
STATIC void
|
2005-07-14 04:28:51 +04:00
|
|
|
wi_mend_flags(struct wi_softc *sc, enum ieee80211_state nstate)
|
2005-06-25 07:56:53 +04:00
|
|
|
{
|
|
|
|
struct ieee80211com *ic = &sc->sc_ic;
|
|
|
|
|
2005-07-14 04:28:51 +04:00
|
|
|
if (nstate == IEEE80211_S_RUN &&
|
2005-06-25 07:56:53 +04:00
|
|
|
(ic->ic_flags & IEEE80211_F_PRIVACY) != 0 &&
|
|
|
|
ic->ic_opmode != IEEE80211_M_HOSTAP)
|
|
|
|
ic->ic_flags &= ~IEEE80211_F_DROPUNENC;
|
|
|
|
else
|
2005-07-14 04:28:51 +04:00
|
|
|
ic->ic_flags |= sc->sc_ic_flags;
|
|
|
|
|
|
|
|
DPRINTF(("%s: state %d, "
|
|
|
|
"ic->ic_flags & IEEE80211_F_DROPUNENC = %#" PRIx32 ", "
|
|
|
|
"sc->sc_ic_flags & IEEE80211_F_DROPUNENC = %#" PRIx32 "\n",
|
|
|
|
__func__, nstate,
|
|
|
|
ic->ic_flags & IEEE80211_F_DROPUNENC,
|
|
|
|
sc->sc_ic_flags & IEEE80211_F_DROPUNENC));
|
2005-06-25 07:56:53 +04:00
|
|
|
}
|
|
|
|
|
2004-07-22 23:47:24 +04:00
|
|
|
STATIC int
|
2003-10-13 12:07:21 +04:00
|
|
|
wi_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
{
|
2005-06-22 10:14:51 +04:00
|
|
|
struct ifnet *ifp = ic->ic_ifp;
|
|
|
|
struct wi_softc *sc = ifp->if_softc;
|
2003-10-13 12:07:21 +04:00
|
|
|
struct ieee80211_node *ni = ic->ic_bss;
|
2002-09-30 10:50:35 +04:00
|
|
|
u_int16_t val;
|
|
|
|
struct wi_ssid ssid;
|
2003-10-25 03:58:22 +04:00
|
|
|
struct wi_macaddr bssid, old_bssid;
|
2002-09-30 10:50:35 +04:00
|
|
|
enum ieee80211_state ostate;
|
|
|
|
#ifdef WI_DEBUG
|
|
|
|
static const char *stname[] =
|
|
|
|
{ "INIT", "SCAN", "AUTH", "ASSOC", "RUN" };
|
|
|
|
#endif /* WI_DEBUG */
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
ostate = ic->ic_state;
|
|
|
|
DPRINTF(("wi_newstate: %s -> %s\n", stname[ostate], stname[nstate]));
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
|
2002-09-30 10:50:35 +04:00
|
|
|
switch (nstate) {
|
|
|
|
case IEEE80211_S_INIT:
|
2003-12-07 08:44:49 +03:00
|
|
|
if (ic->ic_opmode != IEEE80211_M_MONITOR)
|
|
|
|
callout_stop(&sc->sc_rssadapt_ch);
|
2002-09-30 10:50:35 +04:00
|
|
|
ic->ic_flags &= ~IEEE80211_F_SIBSS;
|
2002-10-04 08:23:20 +04:00
|
|
|
sc->sc_flags &= ~WI_FLAGS_OUTRANGE;
|
2005-06-25 07:56:53 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case IEEE80211_S_SCAN:
|
|
|
|
case IEEE80211_S_AUTH:
|
|
|
|
case IEEE80211_S_ASSOC:
|
|
|
|
ic->ic_state = nstate; /* NB: skip normal ieee80211 handling */
|
2005-07-14 04:28:51 +04:00
|
|
|
wi_mend_flags(sc, nstate);
|
2005-06-25 07:56:53 +04:00
|
|
|
return 0;
|
2002-09-30 10:50:35 +04:00
|
|
|
|
|
|
|
case IEEE80211_S_RUN:
|
2002-10-04 08:23:20 +04:00
|
|
|
sc->sc_flags &= ~WI_FLAGS_OUTRANGE;
|
2003-10-25 03:58:22 +04:00
|
|
|
IEEE80211_ADDR_COPY(old_bssid.wi_mac_addr, ni->ni_bssid);
|
2004-12-13 20:21:35 +03:00
|
|
|
wi_read_xrid(sc, WI_RID_CURRENT_BSSID, &bssid,
|
|
|
|
IEEE80211_ADDR_LEN);
|
2003-10-25 03:58:22 +04:00
|
|
|
IEEE80211_ADDR_COPY(ni->ni_bssid, &bssid);
|
|
|
|
IEEE80211_ADDR_COPY(ni->ni_macaddr, &bssid);
|
2004-12-13 20:21:35 +03:00
|
|
|
wi_read_xrid(sc, WI_RID_CURRENT_CHAN, &val, sizeof(val));
|
2003-10-13 12:07:21 +04:00
|
|
|
if (!isset(ic->ic_chan_avail, le16toh(val)))
|
2010-11-23 07:33:09 +03:00
|
|
|
panic("%s: invalid channel %d\n",
|
|
|
|
device_xname(sc->sc_dev), le16toh(val));
|
2003-10-13 12:07:21 +04:00
|
|
|
ni->ni_chan = &ic->ic_channels[le16toh(val)];
|
2002-09-30 10:50:35 +04:00
|
|
|
|
2002-10-02 21:11:34 +04:00
|
|
|
if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
|
2005-06-26 08:37:25 +04:00
|
|
|
#ifndef IEEE80211_NO_HOSTAP
|
2002-10-02 21:11:34 +04:00
|
|
|
ni->ni_esslen = ic->ic_des_esslen;
|
|
|
|
memcpy(ni->ni_essid, ic->ic_des_essid, ni->ni_esslen);
|
2003-10-13 12:07:21 +04:00
|
|
|
ni->ni_rates = ic->ic_sup_rates[
|
|
|
|
ieee80211_chan2mode(ic, ni->ni_chan)];
|
2002-10-02 21:11:34 +04:00
|
|
|
ni->ni_intval = ic->ic_lintval;
|
|
|
|
ni->ni_capinfo = IEEE80211_CAPINFO_ESS;
|
2004-07-23 12:31:39 +04:00
|
|
|
if (ic->ic_flags & IEEE80211_F_PRIVACY)
|
2002-10-02 21:11:34 +04:00
|
|
|
ni->ni_capinfo |= IEEE80211_CAPINFO_PRIVACY;
|
2005-06-26 08:37:25 +04:00
|
|
|
#endif /* !IEEE80211_NO_HOSTAP */
|
2002-10-02 21:11:34 +04:00
|
|
|
} else {
|
2004-12-13 20:21:35 +03:00
|
|
|
wi_read_xrid(sc, WI_RID_CURRENT_SSID, &ssid,
|
|
|
|
sizeof(ssid));
|
2002-10-02 21:11:34 +04:00
|
|
|
ni->ni_esslen = le16toh(ssid.wi_len);
|
|
|
|
if (ni->ni_esslen > IEEE80211_NWID_LEN)
|
|
|
|
ni->ni_esslen = IEEE80211_NWID_LEN; /*XXX*/
|
|
|
|
memcpy(ni->ni_essid, ssid.wi_ssid, ni->ni_esslen);
|
2003-12-07 08:44:49 +03:00
|
|
|
ni->ni_rates = ic->ic_sup_rates[
|
|
|
|
ieee80211_chan2mode(ic, ni->ni_chan)]; /*XXX*/
|
2002-10-02 21:11:34 +04:00
|
|
|
}
|
2003-12-07 08:44:49 +03:00
|
|
|
if (ic->ic_opmode != IEEE80211_M_MONITOR)
|
|
|
|
callout_reset(&sc->sc_rssadapt_ch, hz / 10,
|
|
|
|
wi_rssadapt_updatestats, sc);
|
2005-06-25 07:56:53 +04:00
|
|
|
/* Trigger routing socket messages. XXX Copied from
|
|
|
|
* ieee80211_newstate.
|
|
|
|
*/
|
|
|
|
if (ic->ic_opmode == IEEE80211_M_STA)
|
|
|
|
ieee80211_notify_node_join(ic, ic->ic_bss,
|
|
|
|
arg == IEEE80211_FC0_SUBTYPE_ASSOC_RESP);
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
break;
|
|
|
|
}
|
2005-07-14 04:28:51 +04:00
|
|
|
wi_mend_flags(sc, nstate);
|
2005-06-25 07:56:53 +04:00
|
|
|
return (*sc->sc_newstate)(ic, nstate, arg);
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
}
|
|
|
|
|
2005-06-22 10:14:51 +04:00
|
|
|
STATIC void
|
2005-11-18 19:53:56 +03:00
|
|
|
wi_set_tim(struct ieee80211_node *ni, int set)
|
2003-04-08 08:31:23 +04:00
|
|
|
{
|
2005-11-18 19:53:56 +03:00
|
|
|
struct ieee80211com *ic = ni->ni_ic;
|
2005-06-22 10:14:51 +04:00
|
|
|
struct wi_softc *sc = ic->ic_ifp->if_softc;
|
|
|
|
|
2005-11-18 19:53:56 +03:00
|
|
|
(*sc->sc_set_tim)(ni, set);
|
2005-06-22 10:14:51 +04:00
|
|
|
|
|
|
|
if ((ic->ic_flags & IEEE80211_F_TIMUPDATE) == 0)
|
|
|
|
return;
|
2003-04-08 08:31:23 +04:00
|
|
|
|
2005-06-22 10:14:51 +04:00
|
|
|
ic->ic_flags &= ~IEEE80211_F_TIMUPDATE;
|
2003-04-08 08:31:23 +04:00
|
|
|
|
2005-06-22 10:14:51 +04:00
|
|
|
(void)wi_write_val(sc, WI_RID_SET_TIM,
|
|
|
|
IEEE80211_AID(ni->ni_associd) | (set ? 0x8000 : 0));
|
2003-04-08 08:31:23 +04:00
|
|
|
}
|
|
|
|
|
2004-07-22 23:47:24 +04:00
|
|
|
STATIC int
|
2003-05-13 12:35:58 +04:00
|
|
|
wi_scan_ap(struct wi_softc *sc, u_int16_t chanmask, u_int16_t txrate)
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
{
|
2002-09-30 10:50:35 +04:00
|
|
|
int error = 0;
|
|
|
|
u_int16_t val[2];
|
|
|
|
|
|
|
|
if (!sc->sc_enabled)
|
|
|
|
return ENXIO;
|
|
|
|
switch (sc->sc_firmware_type) {
|
|
|
|
case WI_LUCENT:
|
|
|
|
(void)wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_SCAN_RESULTS, 0, 0);
|
|
|
|
break;
|
|
|
|
case WI_INTERSIL:
|
2003-11-16 12:41:01 +03:00
|
|
|
val[0] = htole16(chanmask); /* channel */
|
|
|
|
val[1] = htole16(txrate); /* tx rate */
|
2002-09-30 10:50:35 +04:00
|
|
|
error = wi_write_rid(sc, WI_RID_SCAN_REQ, val, sizeof(val));
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
break;
|
2002-09-30 10:50:35 +04:00
|
|
|
case WI_SYMBOL:
|
|
|
|
/*
|
|
|
|
* XXX only supported on 3.x ?
|
|
|
|
*/
|
2004-11-26 20:55:41 +03:00
|
|
|
val[0] = htole16(BSCAN_BCAST | BSCAN_ONETIME);
|
2002-09-30 10:50:35 +04:00
|
|
|
error = wi_write_rid(sc, WI_RID_BCAST_SCAN_REQ,
|
|
|
|
val, sizeof(val[0]));
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
break;
|
|
|
|
}
|
2002-09-30 10:50:35 +04:00
|
|
|
if (error == 0) {
|
|
|
|
sc->sc_scan_timer = WI_SCAN_WAIT;
|
2005-06-22 10:14:51 +04:00
|
|
|
sc->sc_if.if_timer = 1;
|
2003-05-13 12:35:58 +04:00
|
|
|
DPRINTF(("wi_scan_ap: start scanning, "
|
|
|
|
"chanmask 0x%x txrate 0x%x\n", chanmask, txrate));
|
2002-09-30 10:50:35 +04:00
|
|
|
}
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
2004-07-22 23:47:24 +04:00
|
|
|
STATIC void
|
2002-09-30 10:50:35 +04:00
|
|
|
wi_scan_result(struct wi_softc *sc, int fid, int cnt)
|
|
|
|
{
|
2003-05-13 12:35:58 +04:00
|
|
|
#define N(a) (sizeof (a) / sizeof (a[0]))
|
2002-09-30 10:50:35 +04:00
|
|
|
int i, naps, off, szbuf;
|
|
|
|
struct wi_scan_header ws_hdr; /* Prism2 header */
|
|
|
|
struct wi_scan_data_p2 ws_dat; /* Prism2 scantable*/
|
|
|
|
struct wi_apinfo *ap;
|
|
|
|
|
|
|
|
off = sizeof(u_int16_t) * 2;
|
|
|
|
memset(&ws_hdr, 0, sizeof(ws_hdr));
|
|
|
|
switch (sc->sc_firmware_type) {
|
|
|
|
case WI_INTERSIL:
|
|
|
|
wi_read_bap(sc, fid, off, &ws_hdr, sizeof(ws_hdr));
|
|
|
|
off += sizeof(ws_hdr);
|
|
|
|
szbuf = sizeof(struct wi_scan_data_p2);
|
|
|
|
break;
|
|
|
|
case WI_SYMBOL:
|
|
|
|
szbuf = sizeof(struct wi_scan_data_p2) + 6;
|
|
|
|
break;
|
|
|
|
case WI_LUCENT:
|
|
|
|
szbuf = sizeof(struct wi_scan_data);
|
|
|
|
break;
|
2003-05-13 12:35:58 +04:00
|
|
|
default:
|
2010-11-23 07:33:09 +03:00
|
|
|
aprint_error_dev(sc->sc_dev,
|
|
|
|
"wi_scan_result: unknown firmware type %u\n",
|
2008-04-08 16:07:25 +04:00
|
|
|
sc->sc_firmware_type);
|
2003-05-13 12:35:58 +04:00
|
|
|
naps = 0;
|
|
|
|
goto done;
|
2002-09-30 10:50:35 +04:00
|
|
|
}
|
|
|
|
naps = (cnt * 2 + 2 - off) / szbuf;
|
2003-05-13 12:35:58 +04:00
|
|
|
if (naps > N(sc->sc_aps))
|
|
|
|
naps = N(sc->sc_aps);
|
2002-09-30 10:50:35 +04:00
|
|
|
sc->sc_naps = naps;
|
|
|
|
/* Read Data */
|
|
|
|
ap = sc->sc_aps;
|
|
|
|
memset(&ws_dat, 0, sizeof(ws_dat));
|
|
|
|
for (i = 0; i < naps; i++, ap++) {
|
|
|
|
wi_read_bap(sc, fid, off, &ws_dat,
|
|
|
|
(sizeof(ws_dat) < szbuf ? sizeof(ws_dat) : szbuf));
|
|
|
|
DPRINTF2(("wi_scan_result: #%d: off %d bssid %s\n", i, off,
|
|
|
|
ether_sprintf(ws_dat.wi_bssid)));
|
|
|
|
off += szbuf;
|
|
|
|
ap->scanreason = le16toh(ws_hdr.wi_reason);
|
|
|
|
memcpy(ap->bssid, ws_dat.wi_bssid, sizeof(ap->bssid));
|
|
|
|
ap->channel = le16toh(ws_dat.wi_chid);
|
|
|
|
ap->signal = le16toh(ws_dat.wi_signal);
|
|
|
|
ap->noise = le16toh(ws_dat.wi_noise);
|
|
|
|
ap->quality = ap->signal - ap->noise;
|
|
|
|
ap->capinfo = le16toh(ws_dat.wi_capinfo);
|
|
|
|
ap->interval = le16toh(ws_dat.wi_interval);
|
|
|
|
ap->rate = le16toh(ws_dat.wi_rate);
|
|
|
|
ap->namelen = le16toh(ws_dat.wi_namelen);
|
|
|
|
if (ap->namelen > sizeof(ap->name))
|
|
|
|
ap->namelen = sizeof(ap->name);
|
|
|
|
memcpy(ap->name, ws_dat.wi_name, ap->namelen);
|
|
|
|
}
|
2003-05-13 12:35:58 +04:00
|
|
|
done:
|
2002-09-30 10:50:35 +04:00
|
|
|
/* Done scanning */
|
|
|
|
sc->sc_scan_timer = 0;
|
|
|
|
DPRINTF(("wi_scan_result: scan complete: ap %d\n", naps));
|
2003-05-13 12:35:58 +04:00
|
|
|
#undef N
|
Jumbo patch, from David Young <dyoung@ojctech.com>, with small tweaks
by me:
* Speed up reading/writing buffers from the hardware by avoiding
slow forward seeks. In preparation to use the optimization, do
not read overlapping bytes. This is currently disabled, but can
be enabled with OPTIMIZE_RW_DATA.
* Hand 802.11 and Prism-specific frames to BPF. User can watch these
frames by specifying an alternate DLT to e.g. tcpdump(8).
* Add support for SIOC[SG]80211BSSID and SIOC[SG]80211CHANNEL.
* Issue join requests and track join/create state through link-status
notifications.
* Split wi_rxeof into separate routines for receiving Ethernet II,
802.11 data, and 802.11 management frames.
* Bug fix: Account for aligning m_data to a word boundary in the Rx
buffer size check.
* Bug fix: Check for LLC/SNAP even if the firmware tells us the frame
is Ethernet II, as the firmware sometimes gets this wrong.
* Process as many events as possible when we get an interrupt, using
a simple heuristic to avoid reprocessing an event (which can have
bad side-effects). Clamp the time spent in the interrupt handler
to 4ms.
* Redo the timeout loops to be consistent and less prone to error.
* Add delays to timeout loops which were missing them, so that a
fast CPU won't win the race.
* Borrow some timeout loop values from the linux-wlan-ng driver,
which seems to reflect a high level of clue (due to direct support
from Intersil).
* Get rid of silly wi_read_data(..., len + 2) idiom; simply round up
in wi_read_data() and wi_write_data(). Also, protect against a
length of 0.
* Name some frequently-used constants. Correct spelling. Other style nits.
* Bug fix: On Prism, set Create IBSS register to 0 *always*. The meaning
of Create IBSS == 1 is join an IBSS or *ESS*, and we do not want to
join an ESS, because that would put us in an inconsistent state. 0
is the right value for Prism.
* Bug fix: Clean up state at the top of wi_init(), in the event that
we don't reach the bottom.
* Simplify wi_start() by always providing an RFC1042-encoded 802.11
frame to the firmware.
* Larval powersave support for HostAP mode, enabled by WI_HOSTAP_POWERSAVE.
* Bug fix: Call wi_stop() from wi_shutdown().
* Bug fix: sync media options with HostAP mode in wi_sync_media().
* In wi_media_status(), inquire firmware for current media state if
media == auto. From FreeBSD.
* Clean up the way buffer lengths are computed by using pointer
arithmetic rather than magic constants.
* Swap the order of comparisons in addr_cmp() for speed.
* Bug fix: Send ReAssoc Response instead of Assoc Response to a
ReAssoc Request.
* Bug fix: Copy SSID using the correct size.
* Give more meaningful names to offsets in a wi_frame.
* Bug fix: Assign the right values to the named constants for
Rx frame encoding.
* Get rid of useless SNAP constants.
2002-09-23 18:31:27 +04:00
|
|
|
}
|
2003-05-13 10:48:56 +04:00
|
|
|
|
2004-07-22 23:47:24 +04:00
|
|
|
STATIC void
|
2003-05-13 10:48:56 +04:00
|
|
|
wi_dump_pkt(struct wi_frame *wh, struct ieee80211_node *ni, int rssi)
|
|
|
|
{
|
|
|
|
ieee80211_dump_pkt((u_int8_t *) &wh->wi_whdr, sizeof(wh->wi_whdr),
|
2003-10-13 12:07:21 +04:00
|
|
|
ni ? ni->ni_rates.rs_rates[ni->ni_txrate] & IEEE80211_RATE_VAL
|
|
|
|
: -1,
|
|
|
|
rssi);
|
2003-05-13 10:48:56 +04:00
|
|
|
printf(" status 0x%x rx_tstamp1 %u rx_tstamp0 0x%u rx_silence %u\n",
|
|
|
|
le16toh(wh->wi_status), le16toh(wh->wi_rx_tstamp1),
|
|
|
|
le16toh(wh->wi_rx_tstamp0), wh->wi_rx_silence);
|
|
|
|
printf(" rx_signal %u rx_rate %u rx_flow %u\n",
|
|
|
|
wh->wi_rx_signal, wh->wi_rx_rate, wh->wi_rx_flow);
|
|
|
|
printf(" tx_rtry %u tx_rate %u tx_ctl 0x%x dat_len %u\n",
|
|
|
|
wh->wi_tx_rtry, wh->wi_tx_rate,
|
|
|
|
le16toh(wh->wi_tx_ctl), le16toh(wh->wi_dat_len));
|
|
|
|
printf(" ehdr dst %s src %s type 0x%x\n",
|
|
|
|
ether_sprintf(wh->wi_ehdr.ether_dhost),
|
|
|
|
ether_sprintf(wh->wi_ehdr.ether_shost),
|
|
|
|
wh->wi_ehdr.ether_type);
|
|
|
|
}
|