Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 18 Mar 2008 19:23:31 GMT
From:      Sam Leffler <sam@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 138040 for review
Message-ID:  <200803181923.m2IJNV4c083003@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=138040

Change 138040 by sam@sam_ebb on 2008/03/18 19:22:30

	checkpoint; still not usable

Affected files ...

.. //depot/projects/vap/sys/dev/wi/if_wi.c#12 edit
.. //depot/projects/vap/sys/dev/wi/if_wi_pccard.c#6 edit
.. //depot/projects/vap/sys/dev/wi/if_wivar.h#9 edit
.. //depot/projects/vap/sys/dev/wi/spectrum24t_cf.h#3 delete

Differences ...

==== //depot/projects/vap/sys/dev/wi/if_wi.c#12 (text+ko) ====

@@ -1,5 +1,3 @@
-/*	$NetBSD: wi.c,v 1.109 2003/01/09 08:52:19 dyoung Exp $	*/
-
 /*-
  * Copyright (c) 1997, 1998, 1999
  *	Bill Paul <wpaul@ctr.columbia.edu>.  All rights reserved.
@@ -64,7 +62,6 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD: src/sys/dev/wi/if_wi.c,v 1.214 2007/09/16 20:02:29 thompsa Exp $");
 
-#define WI_HERMES_AUTOINC_WAR	/* Work around data write autoinc bug. */
 #define WI_HERMES_STATS_WAR	/* Work around stats counter bug. */
 
 #define	NBPFILTER	1
@@ -112,16 +109,22 @@
 #include <dev/wi/if_wireg.h>
 #include <dev/wi/if_wivar.h>
 
+static struct ieee80211vap *wi_vap_create(struct ieee80211com *ic,
+		const char name[IFNAMSIZ], int unit, int opmode, int flags,
+		const uint8_t bssid[IEEE80211_ADDR_LEN],
+		const uint8_t mac[IEEE80211_ADDR_LEN]);
+static void wi_vap_delete(struct ieee80211vap *vap);
 static void wi_start_locked(struct ifnet *);
 static void wi_start(struct ifnet *);
 static int  wi_start_tx(struct ifnet *ifp, struct wi_frame *frmhdr,
 		struct mbuf *m0);
 static int  wi_raw_xmit(struct ieee80211_node *, struct mbuf *,
 		const struct ieee80211_bpf_params *);
+static void wi_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m,
+		int subtype, int rssi, int noise, u_int32_t rstamp);
 static int  wi_reset(struct ifnet *);
 static void wi_watchdog(void *);
 static int  wi_ioctl(struct ifnet *, u_long, caddr_t);
-static int  wi_media_change(struct ifnet *);
 static void wi_media_status(struct ifnet *, struct ifmediareq *);
 
 static void wi_rx_intr(struct wi_softc *);
@@ -129,16 +132,13 @@
 static void wi_tx_ex_intr(struct wi_softc *);
 static void wi_info_intr(struct wi_softc *);
 
-static int  wi_key_alloc(struct ieee80211com *, const struct ieee80211_key *,
+static int  wi_key_alloc(struct ieee80211vap *, const struct ieee80211_key *,
 		ieee80211_keyix *, ieee80211_keyix *);
 
-#if 0
-static int  wi_get_cfg(struct ifnet *, u_long, caddr_t);
-static int  wi_set_cfg(struct ifnet *, u_long, caddr_t);
-#endif
-static int  wi_write_txrate(struct wi_softc *);
-static int  wi_write_wep(struct wi_softc *);
+static int  wi_write_txrate(struct wi_softc *, struct ieee80211vap *);
+static int  wi_write_wep(struct wi_softc *, struct ieee80211vap *);
 static int  wi_write_multi(struct wi_softc *);
+static void wi_update_mcast(struct ifnet *);
 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);
@@ -151,32 +151,13 @@
 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);
-
-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 int  wi_newstate(struct ieee80211vap *, enum ieee80211_state, int);
 
 static void wi_dump_pkt(struct wi_frame *, struct ieee80211_node *, int rssi);
 
-#if 0
-static int wi_get_debug(struct wi_softc *, struct wi_req *);
-static int wi_set_debug(struct wi_softc *, struct wi_req *);
-#endif
-
-/* support to download firmware for symbol CF card */
-static int wi_symbol_write_firm(struct wi_softc *, const void *, int,
-		const void *, int);
-static int wi_symbol_set_hcr(struct wi_softc *, int);
-
 static void wi_scan_start(struct ieee80211com *);
-static void wi_scan_curchan(struct ieee80211com *, unsigned long);
-static void wi_scan_mindwell(struct ieee80211com *);
 static void wi_scan_end(struct ieee80211com *);
 static void wi_set_channel(struct ieee80211com *);
-static void wi_update_slot(struct ifnet *);
-static struct ieee80211_node *wi_node_alloc(struct ieee80211_node_table *);
-static int wi_ioctl_get(struct ifnet *ifp, u_long command, caddr_t data);
-static int wi_ioctl_set(struct ifnet *ifp, u_long command, caddr_t data);
 	
 static __inline int
 wi_write_val(struct wi_softc *sc, int rid, u_int16_t val)
@@ -270,7 +251,7 @@
 	if (ifp == NULL) {
 		device_printf(dev, "can not if_alloc\n");
 		wi_free(dev);
-		return (ENOSPC);
+		return ENOSPC;
 	}
 	ifp->if_softc = sc;
 
@@ -284,19 +265,41 @@
 	if (error) {
 		device_printf(dev, "bus_setup_intr() failed! (%d)\n", error);
 		wi_free(dev);
-		return (error);
+		return error;
 	}
 
-	mtx_init(&sc->sc_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
-	    MTX_DEF | MTX_RECURSE);
-	callout_init_mtx(&sc->sc_watchdog, &sc->sc_mtx, 0);
-
 	sc->sc_firmware_type = WI_NOTYPE;
 	sc->wi_cmd_count = 500;
 	/* Reset the NIC. */
-	if (wi_reset(ifp) != 0)
+	if (wi_reset(ifp) != 0) {
+		wi_free(dev);
 		return ENXIO;		/* XXX */
+	}
 
+	/* Read NIC identification */
+	wi_read_nicid(sc);
+	switch (sc->sc_firmware_type) {
+	case WI_LUCENT:
+		if (sc->sc_sta_firmware_ver < 60006)
+			goto reject;
+		break;
+	case WI_INTERSIL:
+		if (sc->sc_sta_firmware_ver < 800)
+			goto reject;
+		break;
+	default:
+	reject:
+		device_printf(dev, "Sorry, this card is not supported "
+		    "(type %d, firmware ver %d)\n",
+		    sc->sc_firmware_type, sc->sc_sta_firmware_ver);
+		wi_free(dev);
+		return EOPNOTSUPP; 
+	}
+
+	mtx_init(&sc->sc_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
+	    MTX_DEF | MTX_RECURSE);
+	callout_init_mtx(&sc->sc_watchdog, &sc->sc_mtx, 0);
+
 	/*
 	 * Read the station address.
 	 * And do it twice. I've seen PRISM-based cards that return
@@ -320,9 +323,6 @@
 		return (error);
 	}
 
-	/* Read NIC identification */
-	wi_read_nicid(sc);
-
 	if_initname(ifp, device_get_name(dev), device_get_unit(dev));
 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
 	ifp->if_ioctl = wi_ioctl;
@@ -334,10 +334,11 @@
 
 	ic->ic_ifp = ifp;
 	ic->ic_phytype = IEEE80211_T_DS;
+	ic->ic_opmode = IEEE80211_M_STA;
 	ic->ic_caps = IEEE80211_C_PMGT
+		    | IEEE80211_C_MONITOR
 		    | IEEE80211_C_WEP		/* everyone supports WEP */
 		    ;
-	ic->ic_max_aid = WI_MAX_AID;
 
 	/*
 	 * Query the card for available channels and setup the
@@ -358,61 +359,29 @@
 		c->ic_freq = ieee80211_ieee2mhz(i, IEEE80211_CHAN_B);
 		c->ic_flags = IEEE80211_CHAN_B;
 		c->ic_ieee = i;
+		/* XXX txpowers? */
 	}
 
 	/*
-	 * Read the default channel from the NIC. This may vary
-	 * depending on the country where the NIC was purchased, so
-	 * we can't hard-code a default and expect it to work for
-	 * everyone.
-	 *
-	 * If no channel is specified, let the 802.11 code select.
-	 */
-	buflen = sizeof(val);
-	if (wi_read_rid(sc, WI_RID_OWN_CHNL, &val, &buflen) == 0) {
-		val = le16toh(val);
-		ic->ic_bsschan = ieee80211_find_channel(ic,
-			ieee80211_ieee2mhz(val, IEEE80211_CHAN_B),
-			IEEE80211_CHAN_B);
-		if (ic->ic_bsschan == NULL)
-			ic->ic_bsschan = &ic->ic_channels[0];
-	} else {
-		device_printf(dev,
-			"WI_RID_OWN_CHNL failed, using first channel!\n");
-		ic->ic_bsschan = &ic->ic_channels[0];
-	}
-
-	/*
 	 * Set flags based on firmware version.
 	 */
 	switch (sc->sc_firmware_type) {
 	case WI_LUCENT:
 		sc->sc_ntxbuf = 1;
-		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;
-		}
-#endif
-		if (sc->sc_sta_firmware_ver >= 60000)
-			sc->sc_flags |= WI_FLAGS_HAS_MOR;
-		if (sc->sc_sta_firmware_ver >= 60006) {
-			ic->ic_caps |= IEEE80211_C_IBSS;
-			ic->ic_caps |= IEEE80211_C_MONITOR;
-		}
+		sc->sc_flags |= WI_FLAGS_HAS_SYSSCALE
+			     |  WI_FLAGS_HAS_MOR;
+		ic->ic_caps |= IEEE80211_C_IBSS;
+
 		sc->sc_ibss_port = htole16(1);
-
 		sc->sc_min_rssi = WI_LUCENT_MIN_RSSI;
 		sc->sc_max_rssi = WI_LUCENT_MAX_RSSI;
 		sc->sc_dbm_offset = WI_LUCENT_DBM_OFFSET;
 		break;
-
 	case WI_INTERSIL:
 		sc->sc_ntxbuf = WI_NTXBUF;
-		sc->sc_flags |= WI_FLAGS_HAS_FRAGTHR;
-		sc->sc_flags |= WI_FLAGS_HAS_ROAMING;
-		sc->sc_flags |= WI_FLAGS_HAS_SYSSCALE;
+		sc->sc_flags |= WI_FLAGS_HAS_FRAGTHR
+			     |  WI_FLAGS_HAS_ROAMING
+			     |  WI_FLAGS_HAS_SYSSCALE;
 		/*
 		 * Old firmware are slow, so give peace a chance.
 		 */
@@ -420,35 +389,20 @@
 			sc->wi_cmd_count = 5000;
 		if (sc->sc_sta_firmware_ver > 10101)
 			sc->sc_flags |= WI_FLAGS_HAS_DBMADJUST;
-		if (sc->sc_sta_firmware_ver >= 800) {
-			ic->ic_caps |= IEEE80211_C_IBSS;
-			ic->ic_caps |= IEEE80211_C_MONITOR;
-		}
+		ic->ic_caps |= IEEE80211_C_IBSS;
 		/*
 		 * version 0.8.3 and newer are the only ones that are known
 		 * to currently work.  Earlier versions can be made to work,
-		 * at least according to the Linux driver.
+		 * at least according to the Linux driver but we require
+		 * monitor mode so this is irrelevant.
 		 */
-		if (sc->sc_sta_firmware_ver >= 803)
-			ic->ic_caps |= IEEE80211_C_HOSTAP;
+		ic->ic_caps |= IEEE80211_C_HOSTAP;
+
 		sc->sc_ibss_port = htole16(0);
-
 		sc->sc_min_rssi = WI_PRISM_MIN_RSSI;
 		sc->sc_max_rssi = WI_PRISM_MAX_RSSI;
 		sc->sc_dbm_offset = WI_PRISM_DBM_OFFSET;
 		break;
-
-	case WI_SYMBOL:
-		sc->sc_ntxbuf = 1;
-		sc->sc_flags |= WI_FLAGS_HAS_DIVERSITY;
-		if (sc->sc_sta_firmware_ver >= 25000)
-			ic->ic_caps |= IEEE80211_C_IBSS;
-		sc->sc_ibss_port = htole16(4);
-
-		sc->sc_min_rssi = WI_PRISM_MIN_RSSI;
-		sc->sc_max_rssi = WI_PRISM_MAX_RSSI;
-		sc->sc_dbm_offset = WI_PRISM_DBM_OFFSET;
-		break;
 	}
 
 	/*
@@ -484,39 +438,18 @@
 	sc->sc_system_scale = 1;
 	sc->sc_cnfauthmode = IEEE80211_AUTH_OPEN;
 	sc->sc_roaming_mode = 1;
-	sc->wi_channel = IEEE80211_CHAN_ANYC;
 	sc->sc_portnum = WI_DEFAULT_PORT;
 	sc->sc_authtype = WI_DEFAULT_AUTHTYPE;
 
-	bzero(sc->sc_nodename, sizeof(sc->sc_nodename));
-	sc->sc_nodelen = sizeof(WI_DEFAULT_NODENAME) - 1;
-	bcopy(WI_DEFAULT_NODENAME, sc->sc_nodename, sc->sc_nodelen);
-
-	bzero(sc->sc_net_name, sizeof(sc->sc_net_name));
-	bcopy(WI_DEFAULT_NETNAME, sc->sc_net_name,
-	    sizeof(WI_DEFAULT_NETNAME) - 1);
-
-	/*
-	 * Call MI attach routine.
-	 */
 	ieee80211_ifattach(ic);
-	/* override state transition method */
-	sc->sc_newstate = ic->ic_newstate;
-	sc->sc_key_alloc = ic->ic_crypto.cs_key_alloc;
-	ic->ic_crypto.cs_key_alloc = wi_key_alloc;
-	ic->ic_newstate = wi_newstate;
 	ic->ic_raw_xmit = wi_raw_xmit;
-
 	ic->ic_scan_start = wi_scan_start;
-	ic->ic_scan_curchan = wi_scan_curchan;
-	ic->ic_scan_mindwell = wi_scan_mindwell;
 	ic->ic_scan_end = wi_scan_end;
 	ic->ic_set_channel = wi_set_channel;
-	ic->ic_node_alloc = wi_node_alloc;
-	ic->ic_updateslot = wi_update_slot;
-	ic->ic_reset = wi_reset;
 
-	ieee80211_media_init(ic, wi_media_change, wi_media_status);
+	ic->ic_vap_create = wi_vap_create;
+	ic->ic_vap_delete = wi_vap_delete;
+	ic->ic_update_mcast = wi_update_mcast;
 
 #if NBPFILTER > 0
 	bpfattach(ifp, DLT_IEEE802_11_RADIO,
@@ -558,11 +491,11 @@
 
 	wi_stop(ifp, 0);
 	WI_UNLOCK(sc);
-
 #if NBPFILTER > 0
 	bpfdetach(ifp);
 #endif
 	ieee80211_ifdetach(&sc->sc_ic);
+
 	bus_teardown_intr(dev, sc->irq, sc->wi_intrhand);
 	if_free(sc->sc_ifp);
 	wi_free(dev);
@@ -570,6 +503,75 @@
 	return (0);
 }
 
+static struct ieee80211vap *
+wi_vap_create(struct ieee80211com *ic,
+	const char name[IFNAMSIZ], int unit, int opmode, int flags,
+	const uint8_t bssid[IEEE80211_ADDR_LEN],
+	const uint8_t mac[IEEE80211_ADDR_LEN])
+{
+	struct wi_softc *sc = ic->ic_ifp->if_softc;
+	struct wi_vap *wvp;
+	struct ieee80211vap *vap;
+
+	if (!TAILQ_EMPTY(&ic->ic_vaps))		/* only one at a time */
+		return NULL;
+	wvp = (struct wi_vap *) malloc(sizeof(struct wi_vap),
+	    M_80211_VAP, M_NOWAIT | M_ZERO);
+	if (wvp == NULL)
+		return NULL;
+	vap = &wvp->wv_vap;
+	ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
+
+	wvp->wv_recv_mgmt = vap->iv_recv_mgmt;
+	vap->iv_recv_mgmt = wi_recv_mgmt;
+	wvp->wv_newstate = vap->iv_newstate;
+	vap->iv_newstate = wi_newstate;
+	wvp->wv_key_alloc = vap->iv_key_alloc;
+	vap->iv_key_alloc = wi_key_alloc;
+	vap->iv_max_aid = WI_MAX_AID;
+
+	switch (opmode) {
+	case IEEE80211_M_STA:
+		sc->sc_porttype = WI_PORTTYPE_BSS;
+		break;
+	case IEEE80211_M_IBSS:
+		sc->sc_porttype = sc->sc_ibss_port;
+		break;
+	case IEEE80211_M_AHDEMO:
+		sc->sc_porttype = WI_PORTTYPE_ADHOC;
+		break;
+	case IEEE80211_M_HOSTAP:
+		sc->sc_porttype = WI_PORTTYPE_HOSTAP;
+		break;
+	case IEEE80211_M_MONITOR:
+		switch (sc->sc_firmware_type) {
+		case WI_LUCENT:
+			sc->sc_porttype = WI_PORTTYPE_ADHOC;
+			break;
+		case WI_INTERSIL:
+			sc->sc_porttype = WI_PORTTYPE_APSILENT;
+			break;
+		}
+		break;
+	default:
+		break;
+	}
+
+	/* complete setup */
+	ieee80211_vap_attach(vap, ieee80211_media_change, wi_media_status);
+	ic->ic_opmode = opmode;
+	return vap;
+}
+
+static void
+wi_vap_delete(struct ieee80211vap *vap)
+{
+	struct wi_vap *wvp = WI_VAP(vap);
+
+	ieee80211_vap_detach(vap);
+	free(wvp, M_80211_VAP);
+}
+
 void
 wi_shutdown(device_t dev)
 {
@@ -607,7 +609,6 @@
 	if (status & WI_EV_INFO)
 		wi_info_intr(sc);
 	if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0 &&
-	    (sc->sc_flags & WI_FLAGS_OUTRANGE) == 0 &&
 	    !IFQ_DRV_IS_EMPTY(&ifp->if_snd))
 		wi_start_locked(ifp);
 
@@ -625,13 +626,9 @@
 	struct wi_softc *sc = arg;
 	struct ifnet *ifp = sc->sc_ifp;
 	struct ieee80211com *ic = &sc->sc_ic;
-	struct wi_joinreq join;
-	struct ieee80211_channel *chan;
 	int i;
 	int error = 0, wasenabled;
 
-
-
 	if (sc->wi_gone) 
 		return;
 
@@ -641,126 +638,26 @@
 	WI_LOCK(sc);
 	wi_reset(ifp);
 
-	/* common 802.11 configuration */
-	ic->ic_flags &= ~IEEE80211_F_IBSSON;
-	sc->sc_flags &= ~WI_FLAGS_OUTRANGE;
-	switch (ic->ic_opmode) {
-	case IEEE80211_M_STA:
-		wi_write_val(sc, WI_RID_PORTTYPE, WI_PORTTYPE_BSS);
-		break;
-	case IEEE80211_M_IBSS:
-		wi_write_val(sc, WI_RID_PORTTYPE, sc->sc_ibss_port);
-		ic->ic_flags |= IEEE80211_F_IBSSON;
-		break;
-	case IEEE80211_M_AHDEMO:
-		wi_write_val(sc, WI_RID_PORTTYPE, WI_PORTTYPE_ADHOC);
-		break;
-	case IEEE80211_M_HOSTAP:
-		/*
-		 * For PRISM cards, override the empty SSID, because in
-		 * HostAP mode the controller will lock up otherwise.
-		 */
-		if (sc->sc_firmware_type == WI_INTERSIL &&
-		    ic->ic_des_ssid[0].len == 0) {
-			ic->ic_des_ssid[0].ssid[0] = ' ';
-			ic->ic_des_ssid[0].len = 1;
-		}
-		wi_write_val(sc, WI_RID_PORTTYPE, WI_PORTTYPE_HOSTAP);
-		break;
-	case IEEE80211_M_MONITOR:
-		switch (sc->sc_firmware_type) {
-		case WI_LUCENT:
-			wi_write_val(sc, WI_RID_PORTTYPE, WI_PORTTYPE_ADHOC);
-			break;
-		
-		case WI_INTERSIL:
-			wi_write_val(sc, WI_RID_PORTTYPE, WI_PORTTYPE_APSILENT);
-			break;
-		}
-
-		wi_cmd(sc, WI_CMD_DEBUG | (WI_TEST_MONITOR << 8), 0, 0, 0);
-		break;
-	case IEEE80211_M_WDS:
-		/* XXXX */
-		break;
-	}
-
-	/* 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_ssid[0].len > 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_ssid[0].ssid,
-	    ic->ic_des_ssid[0].len);
-	wi_write_val(sc, WI_RID_OWN_CHNL,
-		ieee80211_chan2ieee(ic, ic->ic_bsschan));
-	wi_write_ssid(sc, WI_RID_OWN_SSID, ic->ic_des_ssid[0].ssid,
-		ic->ic_des_ssid[0].len);
-
-	IEEE80211_ADDR_COPY(ic->ic_myaddr, IF_LLADDR(ifp));
-	wi_write_rid(sc, WI_RID_MAC_NODE, ic->ic_myaddr, IEEE80211_ADDR_LEN);
-
-	if (ic->ic_caps & IEEE80211_C_PMGT)
-		wi_write_val(sc, WI_RID_PM_ENABLED,
-		    (ic->ic_flags & IEEE80211_F_PMGTON) ? 1 : 0);
-
-	/* not yet common 802.11 configuration */
+	wi_write_val(sc, WI_RID_PORTTYPE, sc->sc_porttype);
+	wi_write_val(sc, WI_RID_CREATE_IBSS, 0);
 	wi_write_val(sc, WI_RID_MAX_DATALEN, sc->sc_max_datalen);
-	wi_write_val(sc, WI_RID_RTS_THRESH, ic->ic_rtsthreshold);
-	if (sc->sc_flags & WI_FLAGS_HAS_FRAGTHR)
-		wi_write_val(sc, WI_RID_FRAG_THRESH, ic->ic_fragthreshold);
-
-	/* driver specific 802.11 configuration */
+#if 0
+	/* NB: for IEEE80211_BPF_NOACK */
+	wi_write_val(sc, WI_RID_ALT_RETRY_CNT, 0);
+#endif
 	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);
-	wi_write_txrate(sc);
-	wi_write_ssid(sc, WI_RID_NODENAME, sc->sc_nodename, sc->sc_nodelen);
-	wi_write_val(sc, WI_RID_ALT_RETRY_CNT, 0); /* for IEEE80211_BPF_NOACK */
 
-	if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
-	    sc->sc_firmware_type == WI_INTERSIL) {
-		wi_write_val(sc, WI_RID_OWN_BEACON_INT, ic->ic_bintval);
-		wi_write_val(sc, WI_RID_BASIC_RATE, 0x03);   /* 1, 2 */
-		wi_write_val(sc, WI_RID_SUPPORT_RATE, 0x0f); /* 1, 2, 5.5, 11 */
-		wi_write_val(sc, WI_RID_DTIM_PERIOD, ic->ic_dtim_period);
-	}
-
-	/*
-	 * Initialize promisc mode.
-	 *	Being in the Host-AP mode causes a great
-	 *	deal of pain if primisc mode is set.
-	 *	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);
-	}
+	IEEE80211_ADDR_COPY(ic->ic_myaddr, IF_LLADDR(ifp));
+	wi_write_rid(sc, WI_RID_MAC_NODE, ic->ic_myaddr, IEEE80211_ADDR_LEN);
 
-	/* Configure WEP. */
-	if (ic->ic_caps & IEEE80211_C_WEP) {
-		sc->sc_cnfauthmode = ic->ic_bss->ni_authmode;
-		wi_write_wep(sc);
-	} else
-		sc->sc_encryption = 0;
-
-	/* Set multicast filter. */
-	wi_write_multi(sc);
-
 	/* Allocate fids for the card */
-	if (sc->sc_firmware_type != WI_SYMBOL || !wasenabled) {
+	if (!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 < sc->sc_ntxbuf; i++) {
 			error = wi_alloc_fid(sc, sc->sc_buflen,
 			    &sc->sc_txd[i].d_fid);
@@ -781,42 +678,14 @@
 	sc->sc_enabled = 1;
 	ifp->if_drv_flags |= IFF_DRV_RUNNING;
 	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
-	if (ic->ic_opmode == IEEE80211_M_AHDEMO ||
-	    ic->ic_opmode == IEEE80211_M_IBSS ||
-	    ic->ic_opmode == IEEE80211_M_MONITOR ||
-	    ic->ic_opmode == IEEE80211_M_HOSTAP) {
-		chan = (sc->wi_channel == IEEE80211_CHAN_ANYC) ? 
-			ic->ic_curchan : sc->wi_channel;
-		ieee80211_create_ibss(ic, chan);
-	}
+
 	/* Enable interrupts */
 	CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
+	WI_UNLOCK(sc);
 
-	if (!wasenabled &&
-	    ic->ic_opmode == IEEE80211_M_HOSTAP &&
-	    sc->sc_firmware_type == WI_INTERSIL) {
-		/* 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);
-	}
-
-	if (ic->ic_opmode == IEEE80211_M_STA &&
-	    ((ic->ic_flags & IEEE80211_F_DESBSSID) ||
-	    ic->ic_des_chan != IEEE80211_CHAN_ANYC)) {
-		memset(&join, 0, sizeof(join));
-		if (ic->ic_flags & IEEE80211_F_DESBSSID)
-			IEEE80211_ADDR_COPY(&join.wi_bssid, ic->ic_des_bssid);
-		if (ic->ic_des_chan != IEEE80211_CHAN_ANYC)
-			join.wi_chan = htole16(
-				ieee80211_chan2ieee(ic, ic->ic_des_chan));
-		/* 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));
-	}
+	ieee80211_start_all(ic);
 
 	callout_reset(&sc->sc_watchdog, hz, wi_watchdog, sc);
-
-	WI_UNLOCK(sc);
 	return;
 out:
 	if (error) {
@@ -832,11 +701,7 @@
 wi_stop(struct ifnet *ifp, int disable)
 {
 	struct wi_softc *sc = ifp->if_softc;
-	struct ieee80211com *ic = &sc->sc_ic;
-
-	ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
 
-	DELAY(100000);
 	WI_LOCK(sc);
 	if (sc->sc_enabled && !sc->wi_gone) {
 		CSR_WRITE_2(sc, WI_INT_EN, 0);
@@ -844,26 +709,177 @@
 		if (disable)
 			sc->sc_enabled = 0;
 	} else if (sc->wi_gone && disable)	/* gone --> not enabled */
-	    sc->sc_enabled = 0;
+		sc->sc_enabled = 0;
 
 	callout_stop(&sc->sc_watchdog);		/* XXX drain */
 	sc->sc_tx_timer = 0;
-	sc->sc_scan_timer = 0;
 	sc->sc_false_syns = 0;
-	sc->sc_naps = 0;
+
 	ifp->if_drv_flags &= ~(IFF_DRV_OACTIVE | IFF_DRV_RUNNING);
 
 	WI_UNLOCK(sc);
 }
 
 static void
+wi_set_channel(struct ieee80211com *ic)
+{
+	struct ifnet *ifp = ic->ic_ifp;
+	struct wi_softc *sc = ifp->if_softc;
+
+	WI_LOCK(sc);
+	wi_write_val(sc, WI_RID_OWN_CHNL,
+	    ieee80211_chan2ieee(ic, ic->ic_curchan));
+
+#if NBPFILTER > 0
+	sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq =
+		htole16(ic->ic_curchan->ic_freq);
+	sc->sc_tx_th.wt_chan_flags = sc->sc_rx_th.wr_chan_flags =
+		htole16(ic->ic_curchan->ic_flags);
+#endif
+
+	if ((ic->ic_flags & IEEE80211_F_SCAN) == 0 &&
+	    ic->ic_opmode == IEEE80211_M_HOSTAP &&
+	    sc->sc_firmware_type == WI_INTERSIL) {
+		/* XXX: some cards need to be re-enabled */
+		wi_cmd(sc, WI_CMD_DISABLE | WI_PORT0, 0, 0, 0);
+		wi_cmd(sc, WI_CMD_ENABLE | WI_PORT0, 0, 0, 0);
+	}
+	WI_UNLOCK(sc);
+}
+
+static void
+wi_scan_start(struct ieee80211com *ic)
+{
+	struct ifnet *ifp = ic->ic_ifp;
+	struct wi_softc *sc = ifp->if_softc;
+	struct ieee80211_scan_state *ss = ic->ic_scan;
+
+	WI_LOCK(sc);
+	/*
+	 * Switch device to monitor mode.
+	 */
+	switch (sc->sc_firmware_type) {
+	case WI_LUCENT:
+		wi_write_val(sc, WI_RID_PORTTYPE, WI_PORTTYPE_ADHOC);
+		break;
+	case WI_INTERSIL:
+		wi_write_val(sc, WI_RID_PORTTYPE, WI_PORTTYPE_APSILENT);
+		break;
+	}
+	wi_cmd(sc, WI_CMD_DEBUG | (WI_TEST_MONITOR << 8), 0, 0, 0);
+
+	ss->ss_mindwell = ss->ss_maxdwell = msecs_to_ticks(400); /* 400ms */
+	WI_UNLOCK(sc);
+
+}
+
+static void
+wi_scan_end(struct ieee80211com *ic)
+{
+	struct ifnet *ifp = ic->ic_ifp;
+	struct wi_softc *sc = ifp->if_softc;
+
+	WI_LOCK(sc);
+	wi_cmd(sc, WI_CMD_DEBUG, 0, 0, 0);
+	wi_write_val(sc, WI_RID_PORTTYPE, sc->sc_porttype);
+	WI_UNLOCK(sc);
+}
+
+static void
+wi_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m,
+	int subtype, int rssi, int noise, u_int32_t rstamp)
+{
+	struct ieee80211vap *vap = ni->ni_vap;
+
+	switch (subtype) {
+	case IEEE80211_FC0_SUBTYPE_AUTH:
+	case IEEE80211_FC0_SUBTYPE_ASSOC_RESP:
+	case IEEE80211_FC0_SUBTYPE_REASSOC_RESP:
+		/* NB: filter frames that trigger state changes */
+		return;
+	}
+	WI_VAP(vap)->wv_recv_mgmt(ni, m, subtype, rssi, noise, rstamp);
+}
+
+static int
+wi_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
+{
+	struct ieee80211com *ic = vap->iv_ic;
+	struct ifnet *ifp = ic->ic_ifp;
+	struct wi_softc *sc = ifp->if_softc;
+	int error;
+
+	DPRINTF(("%s: %s -> %s\n", __func__,
+		ieee80211_state_name[vap->iv_state],
+		ieee80211_state_name[nstate]));
+
+	if (nstate == IEEE80211_S_AUTH) {
+		struct ieee80211_node *bss = vap->iv_bss;
+
+		wi_write_ssid(sc, WI_RID_DESIRED_SSID,
+		    bss->ni_essid, bss->ni_esslen);
+		/* Lucent firmware does not support the JOIN RID. */
+		if (sc->sc_firmware_type == WI_INTERSIL) {
+			struct wi_joinreq join;
+
+			memset(&join, 0, sizeof(join));
+			IEEE80211_ADDR_COPY(&join.wi_bssid, bss->ni_bssid);
+			join.wi_chan = htole16(
+			    ieee80211_chan2ieee(ic, bss->ni_chan));
+			wi_write_rid(sc, WI_RID_JOIN_REQ, &join, sizeof(join));
+		} else {
+			wi_write_val(sc, WI_RID_CREATE_IBSS, 0);
+		}
+		/* NB: don't go through 802.11 layer, it'll send auth frame */
+		vap->iv_state = nstate;
+		return EINPROGRESS;
+	}
+
+	error = WI_VAP(vap)->wv_newstate(vap, nstate, arg);
+
+	if (nstate == IEEE80211_S_RUN && vap->iv_state != IEEE80211_S_RUN) {
+		if (vap->iv_opmode == IEEE80211_M_MONITOR)
+			wi_cmd(sc, WI_CMD_DEBUG | (WI_TEST_MONITOR << 8), 0, 0, 0);
+		wi_write_val(sc, WI_RID_MAX_SLEEP, ic->ic_lintval);
+		if (ic->ic_caps & IEEE80211_C_PMGT)
+			wi_write_val(sc, WI_RID_PM_ENABLED,
+			    (vap->iv_flags & IEEE80211_F_PMGTON) ? 1 : 0);
+		wi_write_val(sc, WI_RID_RTS_THRESH, vap->iv_rtsthreshold);
+		if (sc->sc_flags & WI_FLAGS_HAS_FRAGTHR)
+			wi_write_val(sc, WI_RID_FRAG_THRESH,
+			    vap->iv_fragthreshold);
+		wi_write_txrate(sc, vap);
+
+		/* Configure WEP. */
+		if (ic->ic_caps & IEEE80211_C_WEP) {
+			sc->sc_cnfauthmode = vap->iv_bss->ni_authmode;
+			wi_write_wep(sc, vap);
+		} else
+			sc->sc_encryption = 0;
+
+		if (vap->iv_opmode == IEEE80211_M_HOSTAP &&
+		    sc->sc_firmware_type == WI_INTERSIL) {
+			wi_write_ssid(sc, WI_RID_OWN_SSID,
+			    vap->iv_des_ssid[0].ssid, vap->iv_des_ssid[0].len);
+			wi_write_val(sc, WI_RID_OWN_BEACON_INT, ic->ic_bintval);
+			wi_write_val(sc, WI_RID_BASIC_RATE, 0x03);   /* 1, 2 */
+			wi_write_val(sc, WI_RID_SUPPORT_RATE, 0x0f); /* 1, 2, 5.5, 11 */
+			wi_write_val(sc, WI_RID_DTIM_PERIOD, vap->iv_dtim_period);
+			/* 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);
+		}
+		return WI_VAP(vap)->wv_newstate(vap, nstate, arg);
+	}
+	return 0;
+}
+
+static void
 wi_start_locked(struct ifnet *ifp)
 {
 	struct wi_softc	*sc = ifp->if_softc;
-	struct ieee80211com *ic = &sc->sc_ic;
 	struct ieee80211_node *ni;
 	struct ieee80211_frame *wh;
-	struct ether_header *eh;
 	struct mbuf *m0;
 	struct wi_frame frmhdr;
 	int cur;
@@ -872,83 +888,37 @@
 
 	if (sc->wi_gone)
 		return;
-	if (sc->sc_flags & WI_FLAGS_OUTRANGE)
-		return;
 
 	memset(&frmhdr, 0, sizeof(frmhdr));
 	cur = sc->sc_txnext;
 	for (;;) {
-		IF_POLL(&ic->ic_mgtq, m0);
-		if (m0 != NULL) {
-			if (sc->sc_txd[cur].d_len != 0) {
-				ifp->if_drv_flags |= IFF_DRV_OACTIVE;
-				break;
-			}
-			IF_DEQUEUE(&ic->ic_mgtq, m0);
-			/*
-			 * Hack!  The referenced node pointer is in the
-			 * rcvif field of the packet header.  This is
-			 * placed there by ieee80211_mgmt_output because
-			 * we need to hold the reference with the frame
-			 * and there's no other way (other than packet
-			 * tags which we consider too expensive to use)
-			 * to pass it along.
-			 */
-			ni = (struct ieee80211_node *) m0->m_pkthdr.rcvif;
-			m0->m_pkthdr.rcvif = NULL;
+		IFQ_DRV_DEQUEUE(&ifp->if_snd, m0);
+		if (m0 == NULL)
+			break;
+		if (sc->sc_txd[cur].d_len != 0) {
+			IFQ_DRV_PREPEND(&ifp->if_snd, m0);
+			ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+			break;
+		}
+		/* NB: copy before 802.11 header is prepended */
+		m_copydata(m0, 0, ETHER_HDR_LEN, 
+		    (caddr_t)&frmhdr.wi_ehdr);
 
-			m_copydata(m0, 4, ETHER_ADDR_LEN * 2,
-			    (caddr_t)&frmhdr.wi_ehdr);
-			frmhdr.wi_ehdr.ether_type = 0;
-                        wh = mtod(m0, struct ieee80211_frame *);
-		} else {
-			if (ic->ic_state != IEEE80211_S_RUN)
-				break;
-			IFQ_DRV_DEQUEUE(&ifp->if_snd, m0);
-			if (m0 == NULL)
-				break;
-			if (sc->sc_txd[cur].d_len != 0) {
-				IFQ_DRV_PREPEND(&ifp->if_snd, m0);
-				ifp->if_drv_flags |= IFF_DRV_OACTIVE;
-				break;
-			}
-			if (m0->m_len < sizeof(struct ether_header) &&
-			    (m0 = m_pullup(m0, sizeof(struct ether_header))) == NULL) {
-				ifp->if_oerrors++;
-				continue;
-			}
-			eh = mtod(m0, struct ether_header *);
-			ni = ieee80211_find_txnode(ic, eh->ether_dhost);
-			if (ni == NULL) {
-				m_freem(m0);
-				continue;
-			}
-			ifp->if_opackets++;
-			m_copydata(m0, 0, ETHER_HDR_LEN, 
-			    (caddr_t)&frmhdr.wi_ehdr);
-#if NBPFILTER > 0
-			BPF_MTAP(ifp, m0);
-#endif
-
-			m0 = ieee80211_encap(ic, m0, ni);
-			if (m0 == NULL) {
-				ifp->if_oerrors++;
-				ieee80211_free_node(ni);
-				continue;
-			}
-                        wh = mtod(m0, struct ieee80211_frame *);
+		ni = (struct ieee80211_node *) m0->m_pkthdr.rcvif;
+		m0 = ieee80211_encap(ni, m0);
+		if (m0 == NULL) {
+			ifp->if_oerrors++;
+			ieee80211_free_node(ni);
+			continue;
 		}
-#if NBPFILTER > 0
-		if (bpf_peers_present(ic->ic_rawbpf))
-			bpf_mtap(ic->ic_rawbpf, m0);
-#endif
+		wh = mtod(m0, struct ieee80211_frame *);
 		frmhdr.wi_tx_ctl = htole16(WI_ENC_TX_802_11|WI_TXCNTL_TX_EX);
 		/* XXX check key for SWCRYPT instead of using operating mode */
 		if ((wh->i_fc[1] & IEEE80211_FC1_WEP) &&
 		    (sc->sc_encryption & HOST_ENCRYPT)) {
 			struct ieee80211_key *k;
 
-			k = ieee80211_crypto_encap(ic, ni, m0);
+			k = ieee80211_crypto_encap(ni, m0);
 			if (k == NULL) {
 				ieee80211_free_node(ni);
 				m_freem(m0);
@@ -958,8 +928,7 @@
 		}
 #if NBPFILTER > 0
 		if (bpf_peers_present(ifp->if_bpf)) {
-			sc->sc_tx_th.wt_rate =
-				ni->ni_rates.rs_rates[ni->ni_txrate];
+			sc->sc_tx_th.wt_rate = ni->ni_txrate;
 			bpf_mtap2(ifp->if_bpf,
 			    &sc->sc_tx_th, sc->sc_tx_th_len, m0);
 		}
@@ -973,7 +942,9 @@
 		ieee80211_free_node(ni);
 		if (wi_start_tx(ifp, &frmhdr, m0))
 			continue;
+
 		sc->sc_txnext = cur = (cur + 1) % sc->sc_ntxbuf;
+		ifp->if_opackets++;
 	}
 }
 
@@ -1033,11 +1004,6 @@
 		rc = ENETDOWN;
 		goto out;
 	}
-	if (sc->sc_flags & WI_FLAGS_OUTRANGE) {
-		rc = ENETDOWN;
-		goto out;
-	}
-
 	memset(&frmhdr, 0, sizeof(frmhdr));
 	cur = sc->sc_txnext;
 	if (sc->sc_txd[cur].d_len != 0) {
@@ -1052,10 +1018,6 @@
 	frmhdr.wi_ehdr.ether_type = 0;
 	wh = mtod(m0, struct ieee80211_frame *);
 			
-#if NBPFILTER > 0
-	if (bpf_peers_present(ic->ic_rawbpf))
-		bpf_mtap(ic->ic_rawbpf, m0);
-#endif
 	frmhdr.wi_tx_ctl = htole16(WI_ENC_TX_802_11|WI_TXCNTL_TX_EX);
 	if (params && (params->ibp_flags & IEEE80211_BPF_NOACK))
 		frmhdr.wi_tx_ctl |= htole16(WI_TXCNTL_ALTRTRY);
@@ -1066,7 +1028,7 @@
 		    (params && (params->ibp_flags & IEEE80211_BPF_CRYPTO))) {
 			struct ieee80211_key *k;
 
-			k = ieee80211_crypto_encap(ic, ni, m0);
+			k = ieee80211_crypto_encap(ni, m0);
 			if (k == NULL) {
 				rc = ENOMEM;
 				goto out;
@@ -1076,8 +1038,7 @@
 	}
 #if NBPFILTER > 0
 	if (bpf_peers_present(ifp->if_bpf)) {
-		sc->sc_tx_th.wt_rate =
-			ni->ni_rates.rs_rates[ni->ni_txrate];
+		sc->sc_tx_th.wt_rate = ni->ni_txrate;
 		bpf_mtap2(ifp->if_bpf, &sc->sc_tx_th, sc->sc_tx_th_len, m0);
 	}
 #endif
@@ -1107,30 +1068,20 @@
 static int
 wi_reset(struct ifnet *ifp)
 {
+#define WI_INIT_TRIES 3

>>> TRUNCATED FOR MAIL (1000 lines) <<<



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200803181923.m2IJNV4c083003>