Home | History | Annotate | Line # | Download | only in ic
wi.c revision 1.80
      1 /*	$NetBSD: wi.c,v 1.80 2002/08/11 21:54:19 thorpej Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1997, 1998, 1999
      5  *	Bill Paul <wpaul (at) ctr.columbia.edu>.  All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. All advertising materials mentioning features or use of this software
     16  *    must display the following acknowledgement:
     17  *	This product includes software developed by Bill Paul.
     18  * 4. Neither the name of the author nor the names of any co-contributors
     19  *    may be used to endorse or promote products derived from this software
     20  *    without specific prior written permission.
     21  *
     22  * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
     23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     25  * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
     26  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     27  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     28  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     29  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     30  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     31  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
     32  * THE POSSIBILITY OF SUCH DAMAGE.
     33  */
     34 
     35 /*
     36  * Lucent WaveLAN/IEEE 802.11 PCMCIA driver for NetBSD.
     37  *
     38  * Original FreeBSD driver written by Bill Paul <wpaul (at) ctr.columbia.edu>
     39  * Electrical Engineering Department
     40  * Columbia University, New York City
     41  */
     42 
     43 /*
     44  * The WaveLAN/IEEE adapter is the second generation of the WaveLAN
     45  * from Lucent. Unlike the older cards, the new ones are programmed
     46  * entirely via a firmware-driven controller called the Hermes.
     47  * Unfortunately, Lucent will not release the Hermes programming manual
     48  * without an NDA (if at all). What they do release is an API library
     49  * called the HCF (Hardware Control Functions) which is supposed to
     50  * do the device-specific operations of a device driver for you. The
     51  * publically available version of the HCF library (the 'HCF Light') is
     52  * a) extremely gross, b) lacks certain features, particularly support
     53  * for 802.11 frames, and c) is contaminated by the GNU Public License.
     54  *
     55  * This driver does not use the HCF or HCF Light at all. Instead, it
     56  * programs the Hermes controller directly, using information gleaned
     57  * from the HCF Light code and corresponding documentation.
     58  *
     59  * This driver supports both the PCMCIA and ISA versions of the
     60  * WaveLAN/IEEE cards. Note however that the ISA card isn't really
     61  * anything of the sort: it's actually a PCMCIA bridge adapter
     62  * that fits into an ISA slot, into which a PCMCIA WaveLAN card is
     63  * inserted. Consequently, you need to use the pccard support for
     64  * both the ISA and PCMCIA adapters.
     65  */
     66 
     67 /*
     68  * FreeBSD driver ported to NetBSD by Bill Sommerfeld in the back of the
     69  * Oslo IETF plenary meeting.
     70  */
     71 
     72 #include <sys/cdefs.h>
     73 __KERNEL_RCSID(0, "$NetBSD: wi.c,v 1.80 2002/08/11 21:54:19 thorpej Exp $");
     74 
     75 #define WI_HERMES_AUTOINC_WAR	/* Work around data write autoinc bug. */
     76 #define WI_HERMES_STATS_WAR	/* Work around stats counter bug. */
     77 
     78 #include "bpfilter.h"
     79 
     80 #include <sys/param.h>
     81 #include <sys/systm.h>
     82 #include <sys/callout.h>
     83 #include <sys/device.h>
     84 #include <sys/socket.h>
     85 #include <sys/mbuf.h>
     86 #include <sys/ioctl.h>
     87 #include <sys/kernel.h>		/* for hz */
     88 #include <sys/proc.h>
     89 
     90 #include <net/if.h>
     91 #include <net/if_dl.h>
     92 #include <net/if_media.h>
     93 #include <net/if_ether.h>
     94 #include <net/if_ieee80211.h>
     95 
     96 #if NBPFILTER > 0
     97 #include <net/bpf.h>
     98 #include <net/bpfdesc.h>
     99 #endif
    100 
    101 #include <machine/bus.h>
    102 
    103 #include <dev/ic/wi_ieee.h>
    104 #include <dev/ic/wireg.h>
    105 #include <dev/ic/wivar.h>
    106 
    107 static void wi_reset		__P((struct wi_softc *));
    108 static int wi_ioctl		__P((struct ifnet *, u_long, caddr_t));
    109 static void wi_start		__P((struct ifnet *));
    110 static void wi_watchdog		__P((struct ifnet *));
    111 static int wi_init		__P((struct ifnet *));
    112 static void wi_stop		__P((struct ifnet *, int));
    113 static void wi_rxeof		__P((struct wi_softc *));
    114 static void wi_txeof		__P((struct wi_softc *, int));
    115 static void wi_update_stats	__P((struct wi_softc *));
    116 static void wi_setmulti		__P((struct wi_softc *));
    117 
    118 static int wi_cmd		__P((struct wi_softc *, int, int));
    119 static int wi_read_record	__P((struct wi_softc *, struct wi_ltv_gen *));
    120 static int wi_write_record	__P((struct wi_softc *, struct wi_ltv_gen *));
    121 static int wi_read_data		__P((struct wi_softc *, int,
    122 					int, caddr_t, int));
    123 static int wi_write_data	__P((struct wi_softc *, int,
    124 					int, caddr_t, int));
    125 static int wi_seek		__P((struct wi_softc *, int, int, int));
    126 static int wi_alloc_nicmem	__P((struct wi_softc *, int, int *));
    127 static void wi_inquire		__P((void *));
    128 static void wi_wait_scan	__P((void *));
    129 static int wi_setdef		__P((struct wi_softc *, struct wi_req *));
    130 static int wi_getdef		__P((struct wi_softc *, struct wi_req *));
    131 
    132 static int wi_media_change __P((struct ifnet *));
    133 static void wi_media_status __P((struct ifnet *, struct ifmediareq *));
    134 
    135 static void wi_get_id		__P((struct wi_softc *));
    136 
    137 static int wi_set_ssid __P((struct ieee80211_nwid *, u_int8_t *, int));
    138 static void wi_request_fill_ssid __P((struct wi_req *,
    139     struct ieee80211_nwid *));
    140 static int wi_write_ssid __P((struct wi_softc *, int, struct wi_req *,
    141     struct ieee80211_nwid *));
    142 static int wi_set_nwkey __P((struct wi_softc *, struct ieee80211_nwkey *));
    143 static int wi_get_nwkey __P((struct wi_softc *, struct ieee80211_nwkey *));
    144 static int wi_sync_media __P((struct wi_softc *, int, int));
    145 static int wi_set_pm(struct wi_softc *, struct ieee80211_power *);
    146 static int wi_get_pm(struct wi_softc *, struct ieee80211_power *);
    147 
    148 struct wi_card_ident wi_card_ident[] = {
    149 	/* CARD_ID			CARD_NAME		FIRM_TYPE */
    150 	{ WI_NIC_LUCENT_ID,		WI_NIC_LUCENT_STR,	WI_LUCENT },
    151 	{ WI_NIC_SONY_ID,		WI_NIC_SONY_STR,	WI_LUCENT },
    152 	{ WI_NIC_LUCENT_EMB_ID,		WI_NIC_LUCENT_EMB_STR,	WI_LUCENT },
    153 	{ WI_NIC_EVB2_ID,		WI_NIC_EVB2_STR,	WI_INTERSIL },
    154 	{ WI_NIC_HWB3763_ID,		WI_NIC_HWB3763_STR,	WI_INTERSIL },
    155 	{ WI_NIC_HWB3163_ID,		WI_NIC_HWB3163_STR,	WI_INTERSIL },
    156 	{ WI_NIC_HWB3163B_ID,		WI_NIC_HWB3163B_STR,	WI_INTERSIL },
    157 	{ WI_NIC_EVB3_ID,		WI_NIC_EVB3_STR,	WI_INTERSIL },
    158 	{ WI_NIC_HWB1153_ID,		WI_NIC_HWB1153_STR,	WI_INTERSIL },
    159 	{ WI_NIC_P2_SST_ID,		WI_NIC_P2_SST_STR,	WI_INTERSIL },
    160 	{ WI_NIC_EVB2_SST_ID,		WI_NIC_EVB2_SST_STR,	WI_INTERSIL },
    161 	{ WI_NIC_3842_EVA_ID,		WI_NIC_3842_EVA_STR,	WI_INTERSIL },
    162 	{ WI_NIC_3842_PCMCIA_AMD_ID,	WI_NIC_3842_PCMCIA_STR,	WI_INTERSIL },
    163 	{ WI_NIC_3842_PCMCIA_SST_ID,	WI_NIC_3842_PCMCIA_STR,	WI_INTERSIL },
    164 	{ WI_NIC_3842_PCMCIA_ATM_ID,	WI_NIC_3842_PCMCIA_STR,	WI_INTERSIL },
    165 	{ WI_NIC_3842_MINI_AMD_ID,	WI_NIC_3842_MINI_STR,	WI_INTERSIL },
    166 	{ WI_NIC_3842_MINI_SST_ID,	WI_NIC_3842_MINI_STR,	WI_INTERSIL },
    167 	{ WI_NIC_3842_MINI_ATM_ID,	WI_NIC_3842_MINI_STR,	WI_INTERSIL },
    168 	{ WI_NIC_3842_PCI_AMD_ID,	WI_NIC_3842_PCI_STR,	WI_INTERSIL },
    169 	{ WI_NIC_3842_PCI_SST_ID,	WI_NIC_3842_PCI_STR,	WI_INTERSIL },
    170 	{ WI_NIC_3842_PCI_ATM_ID,	WI_NIC_3842_PCI_STR,	WI_INTERSIL },
    171 	{ WI_NIC_P3_PCMCIA_AMD_ID,	WI_NIC_P3_PCMCIA_STR,	WI_INTERSIL },
    172 	{ WI_NIC_P3_PCMCIA_SST_ID,	WI_NIC_P3_PCMCIA_STR,	WI_INTERSIL },
    173 	{ WI_NIC_P3_MINI_AMD_ID,	WI_NIC_P3_MINI_STR,	WI_INTERSIL },
    174 	{ WI_NIC_P3_MINI_SST_ID,	WI_NIC_P3_MINI_STR,	WI_INTERSIL },
    175 	{ 0,	NULL,	0 },
    176 };
    177 
    178 int
    179 wi_attach(sc)
    180 	struct wi_softc *sc;
    181 {
    182 	struct ifnet *ifp = sc->sc_ifp;
    183 	const char *sep = "";
    184 	struct wi_ltv_macaddr   mac;
    185 	struct wi_ltv_gen       gen;
    186 	static const u_int8_t empty_macaddr[ETHER_ADDR_LEN] = {
    187 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00
    188 	};
    189 	int s;
    190 
    191 	s = splnet();
    192 
    193 	callout_init(&sc->wi_inquire_ch);
    194 	callout_init(&sc->wi_scan_sh);
    195 
    196 	/* Make sure interrupts are disabled. */
    197 	CSR_WRITE_2(sc, WI_INT_EN, 0);
    198 	CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
    199 
    200 	/* Reset the NIC. */
    201 	wi_reset(sc);
    202 
    203 	memset(&mac, 0, sizeof(mac));
    204 	/* Read the station address. */
    205 	mac.wi_type = WI_RID_MAC_NODE;
    206 	mac.wi_len = 4;
    207 	wi_read_record(sc, (struct wi_ltv_gen *)&mac);
    208 	memcpy(sc->sc_macaddr, mac.wi_mac_addr, ETHER_ADDR_LEN);
    209 
    210 	/*
    211 	 * Check if we got anything meaningful.
    212 	 *
    213 	 * Is it really enough just checking against null ethernet address?
    214 	 * Or, check against possible vendor?  XXX.
    215 	 */
    216 	if (memcmp(sc->sc_macaddr, empty_macaddr, ETHER_ADDR_LEN) == 0) {
    217 		printf("could not get mac address, attach failed\n");
    218 		splx(s);
    219 		return 1;
    220 	}
    221 
    222 	printf(" 802.11 address %s\n", ether_sprintf(sc->sc_macaddr));
    223 
    224 	/* Read NIC identification */
    225 	wi_get_id(sc);
    226 
    227 	memcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ);
    228 	ifp->if_softc = sc;
    229 	ifp->if_start = wi_start;
    230 	ifp->if_ioctl = wi_ioctl;
    231 	ifp->if_watchdog = wi_watchdog;
    232 	ifp->if_init = wi_init;
    233 	ifp->if_stop = wi_stop;
    234 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
    235 #ifdef IFF_NOTRAILERS
    236 	ifp->if_flags |= IFF_NOTRAILERS;
    237 #endif
    238 	IFQ_SET_READY(&ifp->if_snd);
    239 
    240 	(void)wi_set_ssid(&sc->wi_nodeid, WI_DEFAULT_NODENAME,
    241 	    sizeof(WI_DEFAULT_NODENAME) - 1);
    242 	(void)wi_set_ssid(&sc->wi_netid, WI_DEFAULT_NETNAME,
    243 	    sizeof(WI_DEFAULT_NETNAME) - 1);
    244 	(void)wi_set_ssid(&sc->wi_ibssid, WI_DEFAULT_IBSS,
    245 	    sizeof(WI_DEFAULT_IBSS) - 1);
    246 
    247 	sc->wi_portnum = WI_DEFAULT_PORT;
    248 	sc->wi_ptype = WI_PORTTYPE_BSS;
    249 	sc->wi_ap_density = WI_DEFAULT_AP_DENSITY;
    250 	sc->wi_rts_thresh = WI_DEFAULT_RTS_THRESH;
    251 	sc->wi_tx_rate = WI_DEFAULT_TX_RATE;
    252 	sc->wi_max_data_len = WI_DEFAULT_DATALEN;
    253 	sc->wi_create_ibss = WI_DEFAULT_CREATE_IBSS;
    254 	sc->wi_pm_enabled = WI_DEFAULT_PM_ENABLED;
    255 	sc->wi_max_sleep = WI_DEFAULT_MAX_SLEEP;
    256 	sc->wi_roaming = WI_DEFAULT_ROAMING;
    257 	sc->wi_authtype = WI_DEFAULT_AUTHTYPE;
    258 
    259 	/*
    260 	 * Read the default channel from the NIC. This may vary
    261 	 * depending on the country where the NIC was purchased, so
    262 	 * we can't hard-code a default and expect it to work for
    263 	 * everyone.
    264 	 */
    265 	gen.wi_type = WI_RID_OWN_CHNL;
    266 	gen.wi_len = 2;
    267 	wi_read_record(sc, &gen);
    268 	sc->wi_channel = le16toh(gen.wi_val);
    269 
    270 	memset((char *)&sc->wi_stats, 0, sizeof(sc->wi_stats));
    271 
    272 	/* AP info was filled with 0 */
    273 	memset((char *)&sc->wi_aps, 0, sizeof(sc->wi_aps));
    274 	sc->wi_scanning = 0;
    275 	sc->wi_naps = 0;
    276 
    277 	/*
    278 	 * Set flags based on firmware version.
    279 	 */
    280 	switch (sc->sc_firmware_type) {
    281 	case WI_LUCENT:
    282 		sc->wi_flags |= WI_FLAGS_HAS_ROAMING;
    283 		if (sc->sc_sta_firmware_ver >= 60000)
    284 			sc->wi_flags |= WI_FLAGS_HAS_MOR;
    285 		if (sc->sc_sta_firmware_ver >= 60006) {
    286 			sc->wi_flags |= WI_FLAGS_HAS_IBSS;
    287 			sc->wi_flags |= WI_FLAGS_HAS_CREATE_IBSS;
    288 		}
    289 		sc->wi_ibss_port = htole16(1);
    290 		break;
    291 
    292 	case WI_INTERSIL:
    293 		sc->wi_flags |= WI_FLAGS_HAS_ROAMING;
    294 		if (sc->sc_sta_firmware_ver >= 800) {
    295 			sc->wi_flags |= WI_FLAGS_HAS_HOSTAP;
    296 			sc->wi_flags |= WI_FLAGS_HAS_IBSS;
    297 			sc->wi_flags |= WI_FLAGS_HAS_CREATE_IBSS;
    298 		}
    299 		sc->wi_ibss_port = htole16(0);
    300 		break;
    301 
    302 	case WI_SYMBOL:
    303 		sc->wi_flags |= WI_FLAGS_HAS_DIVERSITY;
    304 		if (sc->sc_sta_firmware_ver >= 20000)
    305 			sc->wi_flags |= WI_FLAGS_HAS_IBSS;
    306 		if (sc->sc_sta_firmware_ver >= 25000)
    307 			sc->wi_flags |= WI_FLAGS_HAS_CREATE_IBSS;
    308 		sc->wi_ibss_port = htole16(4);
    309 		break;
    310 	}
    311 
    312 	/*
    313 	 * Find out if we support WEP on this card.
    314 	 */
    315 	gen.wi_type = WI_RID_WEP_AVAIL;
    316 	gen.wi_len = 2;
    317 	if (wi_read_record(sc, &gen) == 0 &&
    318 	    gen.wi_val != le16toh(0))
    319 		sc->wi_flags |= WI_FLAGS_HAS_WEP;
    320 
    321 	/* Find supported rates. */
    322 	gen.wi_type = WI_RID_DATA_RATES;
    323 	gen.wi_len = 2;
    324 	if (wi_read_record(sc, &gen))
    325 		sc->wi_supprates = WI_SUPPRATES_1M | WI_SUPPRATES_2M |
    326 		    WI_SUPPRATES_5M | WI_SUPPRATES_11M;
    327 	else
    328 		sc->wi_supprates = le16toh(gen.wi_val);
    329 
    330 	ifmedia_init(&sc->sc_media, 0, wi_media_change, wi_media_status);
    331 	if (sc->wi_supprates != 0)
    332 		printf("%s: supported rates: ", sc->sc_dev.dv_xname);
    333 #define	ADD(m, c)	ifmedia_add(&sc->sc_media, (m), (c), NULL)
    334 #define	PRINT(n)	printf("%s%s", sep, (n)); sep = ", "
    335 	ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 0, 0), 0);
    336 	ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, IFM_IEEE80211_ADHOC, 0), 0);
    337 	if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
    338 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, IFM_IEEE80211_IBSS,
    339 		    0), 0);
    340 	if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
    341 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO,
    342 		    IFM_IEEE80211_IBSSMASTER, 0), 0);
    343 	if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)
    344 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO,
    345 		    IFM_IEEE80211_HOSTAP, 0), 0);
    346 	if (sc->wi_supprates & WI_SUPPRATES_1M) {
    347 		PRINT("1Mbps");
    348 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1, 0, 0), 0);
    349 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
    350 		    IFM_IEEE80211_ADHOC, 0), 0);
    351 		if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
    352 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
    353 			    IFM_IEEE80211_IBSS, 0), 0);
    354 		if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
    355 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
    356 			    IFM_IEEE80211_IBSSMASTER, 0), 0);
    357 		if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)
    358 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
    359 			    IFM_IEEE80211_HOSTAP, 0), 0);
    360 	}
    361 	if (sc->wi_supprates & WI_SUPPRATES_2M) {
    362 		PRINT("2Mbps");
    363 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2, 0, 0), 0);
    364 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
    365 		    IFM_IEEE80211_ADHOC, 0), 0);
    366 		if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
    367 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
    368 			    IFM_IEEE80211_IBSS, 0), 0);
    369 		if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
    370 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
    371 			    IFM_IEEE80211_IBSSMASTER, 0), 0);
    372 		if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)
    373 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
    374 			    IFM_IEEE80211_HOSTAP, 0), 0);
    375 	}
    376 	if (sc->wi_supprates & WI_SUPPRATES_5M) {
    377 		PRINT("5.5Mbps");
    378 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5, 0, 0), 0);
    379 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
    380 		    IFM_IEEE80211_ADHOC, 0), 0);
    381 		if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
    382 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
    383 			    IFM_IEEE80211_IBSS, 0), 0);
    384 		if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
    385 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
    386 			    IFM_IEEE80211_IBSSMASTER, 0), 0);
    387 		if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)
    388 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
    389 			    IFM_IEEE80211_HOSTAP, 0), 0);
    390 	}
    391 	if (sc->wi_supprates & WI_SUPPRATES_11M) {
    392 		PRINT("11Mbps");
    393 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11, 0, 0), 0);
    394 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
    395 		    IFM_IEEE80211_ADHOC, 0), 0);
    396 		if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
    397 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
    398 			    IFM_IEEE80211_IBSS, 0), 0);
    399 		if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
    400 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
    401 			    IFM_IEEE80211_IBSSMASTER, 0), 0);
    402 		if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)
    403 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
    404 			    IFM_IEEE80211_HOSTAP, 0), 0);
    405 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_MANUAL, 0, 0), 0);
    406 	}
    407 	if (sc->wi_supprates != 0)
    408 		printf("\n");
    409 	ifmedia_set(&sc->sc_media,
    410 	    IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 0, 0));
    411 #undef ADD
    412 #undef PRINT
    413 
    414 	/*
    415 	 * Call MI attach routines.
    416 	 */
    417 	if_attach(ifp);
    418 	ether_ifattach(ifp, mac.wi_mac_addr);
    419 
    420 	ifp->if_baudrate = IF_Mbps(2);
    421 
    422 	/* Attach is successful. */
    423 	sc->sc_attached = 1;
    424 
    425 	splx(s);
    426 	return 0;
    427 }
    428 
    429 static void wi_rxeof(sc)
    430 	struct wi_softc		*sc;
    431 {
    432 	struct ifnet		*ifp;
    433 	struct ether_header	*eh;
    434 	struct wi_frame		rx_frame;
    435 	struct mbuf		*m;
    436 	int			id;
    437 
    438 	ifp = sc->sc_ifp;
    439 
    440 	id = CSR_READ_2(sc, WI_RX_FID);
    441 
    442 	/* First read in the frame header */
    443 	if (wi_read_data(sc, id, 0, (caddr_t)&rx_frame, sizeof(rx_frame))) {
    444 		ifp->if_ierrors++;
    445 		return;
    446 	}
    447 
    448 	/*
    449 	 * Drop undecryptable or packets with receive errors here
    450 	 */
    451 	if (le16toh(rx_frame.wi_status) & WI_STAT_ERRSTAT) {
    452 		ifp->if_ierrors++;
    453 		return;
    454 	}
    455 
    456 	MGETHDR(m, M_DONTWAIT, MT_DATA);
    457 	if (m == NULL) {
    458 		ifp->if_ierrors++;
    459 		return;
    460 	}
    461 	MCLGET(m, M_DONTWAIT);
    462 	if (!(m->m_flags & M_EXT)) {
    463 		m_freem(m);
    464 		ifp->if_ierrors++;
    465 		return;
    466 	}
    467 
    468 	/* Align the data after the ethernet header */
    469 	m->m_data = (caddr_t) ALIGN(m->m_data + sizeof(struct ether_header))
    470 	    - sizeof(struct ether_header);
    471 
    472 	eh = mtod(m, struct ether_header *);
    473 	m->m_pkthdr.rcvif = ifp;
    474 
    475 	if ((le16toh(rx_frame.wi_status) & WI_RXSTAT_MSG_TYPE) == WI_STAT_MGMT &&
    476 	    sc->wi_ptype == WI_PORTTYPE_HOSTAP) {
    477 		if ((le16toh(rx_frame.wi_dat_len) + WI_802_11_OFFSET_RAW + 2) >
    478 		    MCLBYTES) {
    479 			printf("%s: oversized packet received in "
    480 			    "Host-AP mode (wi_dat_len=%d, wi_status=0x%x)\n",
    481 			    sc->sc_dev.dv_xname,
    482 			    le16toh(rx_frame.wi_dat_len),
    483 			    le16toh(rx_frame.wi_status));
    484 			m_freem(m);
    485 			ifp->if_ierrors++;
    486 			return;
    487 		}
    488 
    489 		/* Put the whole header in there. */
    490 		memcpy(mtod(m, void *), &rx_frame, sizeof(rx_frame));
    491 		if (wi_read_data(sc, id, WI_802_11_OFFSET_RAW,
    492 		    mtod(m, caddr_t) + WI_802_11_OFFSET_RAW,
    493 		    le16toh(rx_frame.wi_dat_len) + 2)) {
    494 			m_freem(m);
    495 			if (sc->sc_ethercom.ec_if.if_flags & IFF_DEBUG)
    496 				printf("%s: Host-AP: failed to copy header\n",
    497 				    sc->sc_dev.dv_xname);
    498 			ifp->if_ierrors++;
    499 			return;
    500 		}
    501 
    502 		m->m_pkthdr.len = m->m_len =
    503 		    WI_802_11_OFFSET_RAW + le16toh(rx_frame.wi_dat_len);
    504 
    505 		/* XXX Consider giving packet to bhp? */
    506 
    507 		wihap_mgmt_input(sc, &rx_frame, m);
    508 		return;
    509 	}
    510 
    511 	if ((le16toh(rx_frame.wi_status) & WI_RXSTAT_MSG_TYPE) == WI_STAT_1042 ||
    512 	    (le16toh(rx_frame.wi_status) & WI_RXSTAT_MSG_TYPE) == WI_STAT_TUNNEL ||
    513 	    (le16toh(rx_frame.wi_status) & WI_RXSTAT_MSG_TYPE) == WI_STAT_WMP_MSG) {
    514 		if ((le16toh(rx_frame.wi_dat_len) + WI_SNAPHDR_LEN) > MCLBYTES) {
    515 			printf("%s: oversized packet received "
    516 			    "(wi_dat_len=%d, wi_status=0x%x)\n",
    517 			    sc->sc_dev.dv_xname,
    518 			    le16toh(rx_frame.wi_dat_len), le16toh(rx_frame.wi_status));
    519 			m_freem(m);
    520 			ifp->if_ierrors++;
    521 			return;
    522 		}
    523 		m->m_pkthdr.len = m->m_len =
    524 		    le16toh(rx_frame.wi_dat_len) + WI_SNAPHDR_LEN;
    525 
    526 		memcpy((char *)&eh->ether_dhost, (char *)&rx_frame.wi_dst_addr,
    527 		    ETHER_ADDR_LEN);
    528 		memcpy((char *)&eh->ether_shost, (char *)&rx_frame.wi_src_addr,
    529 		    ETHER_ADDR_LEN);
    530 		memcpy((char *)&eh->ether_type, (char *)&rx_frame.wi_type,
    531 		    sizeof(u_int16_t));
    532 
    533 		if (wi_read_data(sc, id, WI_802_11_OFFSET,
    534 		    mtod(m, caddr_t) + sizeof(struct ether_header),
    535 		    m->m_len + 2)) {
    536 			m_freem(m);
    537 			ifp->if_ierrors++;
    538 			return;
    539 		}
    540 	} else {
    541 		if ((le16toh(rx_frame.wi_dat_len) +
    542 		    sizeof(struct ether_header)) > MCLBYTES) {
    543 			printf("%s: oversized packet received "
    544 			    "(wi_dat_len=%d, wi_status=0x%x)\n",
    545 			    sc->sc_dev.dv_xname,
    546 			    le16toh(rx_frame.wi_dat_len), le16toh(rx_frame.wi_status));
    547 			m_freem(m);
    548 			ifp->if_ierrors++;
    549 			return;
    550 		}
    551 		m->m_pkthdr.len = m->m_len =
    552 		    le16toh(rx_frame.wi_dat_len) + sizeof(struct ether_header);
    553 
    554 		if (wi_read_data(sc, id, WI_802_3_OFFSET,
    555 		    mtod(m, caddr_t), m->m_len + 2)) {
    556 			m_freem(m);
    557 			ifp->if_ierrors++;
    558 			return;
    559 		}
    560 	}
    561 
    562 	ifp->if_ipackets++;
    563 
    564 	if (sc->wi_ptype == WI_PORTTYPE_HOSTAP) {
    565 		/*
    566 		 * Give Host-AP first crack at data packets.  If it
    567 		 * decides to handle it (or drop it), it will return
    568 		 * non-zero.  Otherwise, it is destined for this host.
    569 		 */
    570 		if (wihap_data_input(sc, &rx_frame, m))
    571 			return;
    572 	}
    573 
    574 #if NBPFILTER > 0
    575 	/* Handle BPF listeners. */
    576 	if (ifp->if_bpf)
    577 		bpf_mtap(ifp->if_bpf, m);
    578 #endif
    579 
    580 	/* Receive packet. */
    581 	(*ifp->if_input)(ifp, m);
    582 }
    583 
    584 static void wi_txeof(sc, status)
    585 	struct wi_softc	*sc;
    586 	int		status;
    587 {
    588 	struct ifnet	*ifp = sc->sc_ifp;
    589 
    590 	ifp->if_timer = 0;
    591 	ifp->if_flags &= ~IFF_OACTIVE;
    592 
    593 	if (status & WI_EV_TX_EXC)
    594 		ifp->if_oerrors++;
    595 	else
    596 		ifp->if_opackets++;
    597 
    598 	return;
    599 }
    600 
    601 void wi_inquire(xsc)
    602 	void			*xsc;
    603 {
    604 	struct wi_softc		*sc;
    605 	struct ifnet		*ifp;
    606 	int			s;
    607 
    608 	sc = xsc;
    609 	ifp = &sc->sc_ethercom.ec_if;
    610 
    611 	if ((sc->sc_dev.dv_flags & DVF_ACTIVE) == 0)
    612 		return;
    613 
    614 	KASSERT(sc->sc_enabled);
    615 
    616 	callout_reset(&sc->wi_inquire_ch, hz * 60, wi_inquire, sc);
    617 
    618 	/* Don't do this while we're transmitting */
    619 	if (ifp->if_flags & IFF_OACTIVE)
    620 		return;
    621 
    622 	s = splnet();
    623 	wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_COUNTERS);
    624 	splx(s);
    625 }
    626 
    627 void wi_wait_scan(xsc)
    628 	void			*xsc;
    629 {
    630 	struct wi_softc         *sc;
    631 	struct ifnet            *ifp;
    632 	int			s, result;
    633 
    634 	sc = xsc;
    635 	ifp = &sc->sc_ethercom.ec_if;
    636 
    637 	/* If not scanning, ignore */
    638 	if (!sc->wi_scanning)
    639 		return;
    640 
    641 	s = splnet();
    642 
    643 	/* Wait for sending complete to make INQUIRE */
    644 	if (ifp->if_flags & IFF_OACTIVE) {
    645 		callout_reset(&sc->wi_scan_sh, hz * 1, wi_wait_scan, sc);
    646 		splx(s);
    647 		return;
    648 	}
    649 
    650 	/* try INQUIRE */
    651 	result = wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_SCAN_RESULTS);
    652 	if (result == ETIMEDOUT)
    653 		callout_reset(&sc->wi_scan_sh, hz * 1, wi_wait_scan, sc);
    654 
    655 	splx(s);
    656 }
    657 
    658 void wi_update_stats(sc)
    659 	struct wi_softc		*sc;
    660 {
    661 	struct wi_ltv_gen	gen;
    662 	struct wi_scan_header	ap2_header;	/* Prism2 header */
    663 	struct wi_scan_data_p2	ap2;		/* Prism2 scantable*/
    664 	struct wi_scan_data	ap;		/* Lucent scantable */
    665 	struct wi_assoc		assoc;		/* Association Status */
    666 	u_int16_t		id;
    667 	struct ifnet		*ifp;
    668 	u_int32_t		*ptr;
    669 	int			len, naps, i, j;
    670 	u_int16_t		t;
    671 
    672 	ifp = &sc->sc_ethercom.ec_if;
    673 
    674 	id = CSR_READ_2(sc, WI_INFO_FID);
    675 
    676 	if (wi_seek(sc, id, 0, WI_BAP1)) {
    677 		return;
    678 	}
    679 
    680 	gen.wi_len = CSR_READ_2(sc, WI_DATA1);
    681 	gen.wi_type = CSR_READ_2(sc, WI_DATA1);
    682 
    683 	switch (gen.wi_type) {
    684 	case WI_INFO_SCAN_RESULTS:
    685 	case WI_INFO_HOST_SCAN_RESULTS:
    686 		if (gen.wi_len <= 3) {
    687 			sc->wi_naps = 0;
    688 			sc->wi_scanning = 0;
    689 			break;
    690 		}
    691 		switch (sc->sc_firmware_type) {
    692 		case WI_INTERSIL:
    693 		case WI_SYMBOL:
    694 			if (sc->sc_firmware_type == WI_INTERSIL) {
    695 				naps = 2 * (gen.wi_len - 3) / sizeof(ap2);
    696 				/* Read Header */
    697 				for(j=0; j < sizeof(ap2_header) / 2; j++)
    698 					((u_int16_t *)&ap2_header)[j] =
    699 					    CSR_READ_2(sc, WI_DATA1);
    700 			} else {	/* WI_SYMBOL */
    701 				naps = 2 * (gen.wi_len - 1) / (sizeof(ap2) + 6);
    702 				ap2_header.wi_reason = 0;
    703 			}
    704 			naps = naps > MAXAPINFO ? MAXAPINFO : naps;
    705 			sc->wi_naps = naps;
    706 			/* Read Data */
    707 			for (i=0; i < naps; i++) {
    708 				for(j=0; j < sizeof(ap2) / 2; j++)
    709 					((u_int16_t *)&ap2)[j] =
    710 						CSR_READ_2(sc, WI_DATA1);
    711 				if (sc->sc_firmware_type == WI_SYMBOL) {
    712 					/* 3 more words */
    713 					for (j = 0; j < 3; j++)
    714 						CSR_READ_2(sc, WI_DATA1);
    715 				}
    716 				/* unswap 8 bit data fields: */
    717 				for(j=0;j<sizeof(ap.wi_bssid)/2;j++)
    718 					LE16TOH(((u_int16_t *)&ap.wi_bssid[0])[j]);
    719 				for(j=0;j<sizeof(ap.wi_name)/2;j++)
    720 					LE16TOH(((u_int16_t *)&ap.wi_name[0])[j]);
    721 				sc->wi_aps[i].scanreason = ap2_header.wi_reason;
    722 				memcpy(sc->wi_aps[i].bssid, ap2.wi_bssid, 6);
    723 				sc->wi_aps[i].channel = ap2.wi_chid;
    724 				sc->wi_aps[i].signal  = ap2.wi_signal;
    725 				sc->wi_aps[i].noise   = ap2.wi_noise;
    726 				sc->wi_aps[i].quality = ap2.wi_signal - ap2.wi_noise;
    727 				sc->wi_aps[i].capinfo = ap2.wi_capinfo;
    728 				sc->wi_aps[i].interval = ap2.wi_interval;
    729 				sc->wi_aps[i].rate    = ap2.wi_rate;
    730 				if (ap2.wi_namelen > 32)
    731 					ap2.wi_namelen = 32;
    732 				sc->wi_aps[i].namelen = ap2.wi_namelen;
    733 				memcpy(sc->wi_aps[i].name, ap2.wi_name,
    734 				       ap2.wi_namelen);
    735 			}
    736 			break;
    737 
    738 		case WI_LUCENT:
    739 			naps = 2 * gen.wi_len / sizeof(ap);
    740 			naps = naps > MAXAPINFO ? MAXAPINFO : naps;
    741 			sc->wi_naps = naps;
    742 			/* Read Data*/
    743 			for (i=0; i < naps; i++) {
    744 				for(j=0; j < sizeof(ap) / 2; j++)
    745 					((u_int16_t *)&ap)[j] =
    746 						CSR_READ_2(sc, WI_DATA1);
    747 				/* unswap 8 bit data fields: */
    748 				for(j=0;j<sizeof(ap.wi_bssid)/2;j++)
    749 					HTOLE16(((u_int16_t *)&ap.wi_bssid[0])[j]);
    750 				for(j=0;j<sizeof(ap.wi_name)/2;j++)
    751 					HTOLE16(((u_int16_t *)&ap.wi_name[0])[j]);
    752 				memcpy(sc->wi_aps[i].bssid, ap.wi_bssid, 6);
    753 				sc->wi_aps[i].channel = ap.wi_chid;
    754 				sc->wi_aps[i].signal  = ap.wi_signal;
    755 				sc->wi_aps[i].noise   = ap.wi_noise;
    756 				sc->wi_aps[i].quality = ap.wi_signal - ap.wi_noise;
    757 				sc->wi_aps[i].capinfo = ap.wi_capinfo;
    758 				sc->wi_aps[i].interval = ap.wi_interval;
    759 				if (ap.wi_namelen > 32)
    760 					ap.wi_namelen = 32;
    761 				sc->wi_aps[i].namelen = ap.wi_namelen;
    762 				memcpy(sc->wi_aps[i].name, ap.wi_name,
    763 				       ap.wi_namelen);
    764 			}
    765 			break;
    766 		}
    767 		/* Done scanning */
    768 		sc->wi_scanning = 0;
    769 		break;
    770 
    771 	case WI_INFO_COUNTERS:
    772 		/* some card versions have a larger stats structure */
    773 		len = (gen.wi_len - 1 < sizeof(sc->wi_stats) / 4) ?
    774 			gen.wi_len - 1 : sizeof(sc->wi_stats) / 4;
    775 		ptr = (u_int32_t *)&sc->wi_stats;
    776 
    777 		for (i = 0; i < len; i++) {
    778 			t = CSR_READ_2(sc, WI_DATA1);
    779 #ifdef WI_HERMES_STATS_WAR
    780 			if (t > 0xF000)
    781 				t = ~t & 0xFFFF;
    782 #endif
    783 			ptr[i] += t;
    784 		}
    785 
    786 		ifp->if_collisions = sc->wi_stats.wi_tx_single_retries +
    787 			sc->wi_stats.wi_tx_multi_retries +
    788 			sc->wi_stats.wi_tx_retry_limit;
    789 		break;
    790 
    791 	case WI_INFO_LINK_STAT: {
    792 		static char *msg[] = {
    793 			"connected",
    794 			"disconnected",
    795 			"AP change",
    796 			"AP out of range",
    797 			"AP in range",
    798 			"Association Failed"
    799 		};
    800 
    801 		if (gen.wi_len != 2) {
    802 #ifdef WI_DEBUG
    803 			printf("WI_INFO_LINK_STAT: len=%d\n", gen.wi_len);
    804 #endif
    805 			break;
    806 		}
    807 		t = CSR_READ_2(sc, WI_DATA1);
    808 		if ((t < 1) || (t > 6)) {
    809 #ifdef WI_DEBUG
    810 			printf("WI_INFO_LINK_STAT: status %d\n", t);
    811 #endif
    812 			break;
    813 		}
    814 		if (sc->sc_firmware_type == WI_SYMBOL && t == 4) {
    815 			wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_HOST_SCAN_RESULTS);
    816 			break;
    817 		}
    818 		/*
    819 		 * Some cards issue streams of "connected" messages while
    820 		 * trying to find a peer. Don't bother the user with this
    821 		 * unless he is debugging.
    822 		 */
    823 		if (ifp->if_flags & IFF_DEBUG)
    824 			printf("%s: %s\n", sc->sc_dev.dv_xname, msg[t - 1]);
    825 		break;
    826 		}
    827 
    828 	case WI_INFO_ASSOC_STAT: {
    829 		static char *msg[] = {
    830 			"STA Associated",
    831 			"STA Reassociated",
    832 			"STA Disassociated",
    833 			"Association Failure",
    834 			"Authentication Failed"
    835 		};
    836 		if (gen.wi_len != 10)
    837                         break;
    838 		for (i=0; i < gen.wi_len - 1; i++)
    839 			((u_int16_t *)&assoc)[i] = CSR_READ_2(sc, WI_DATA1);
    840 		/* unswap 8 bit data fields: */
    841 		for(j=0;j<sizeof(assoc.wi_assoc_sta)/2;j++)
    842 			HTOLE16(((u_int16_t *)&assoc.wi_assoc_sta[0])[j]);
    843 		for(j=0;j<sizeof(assoc.wi_assoc_osta)/2;j++)
    844 			HTOLE16(((u_int16_t *)&assoc.wi_assoc_osta[0])[j]);
    845 		switch (assoc.wi_assoc_stat) {
    846 		case ASSOC:
    847 		case DISASSOC:
    848 		case ASSOCFAIL:
    849 		case AUTHFAIL:
    850 			printf("%s: %s, AP = %02x:%02x:%02x:%02x:%02x:%02x\n",
    851 				sc->sc_dev.dv_xname,
    852 				msg[assoc.wi_assoc_stat - 1],
    853 				assoc.wi_assoc_sta[0]&0xff, assoc.wi_assoc_sta[1]&0xff,
    854 				assoc.wi_assoc_sta[2]&0xff, assoc.wi_assoc_sta[3]&0xff,
    855 				assoc.wi_assoc_sta[4]&0xff, assoc.wi_assoc_sta[5]&0xff);
    856 			break;
    857 		case REASSOC:
    858 			printf("%s: %s, AP = %02x:%02x:%02x:%02x:%02x:%02x, "
    859 				"OldAP = %02x:%02x:%02x:%02x:%02x:%02x\n",
    860 				sc->sc_dev.dv_xname, msg[assoc.wi_assoc_stat - 1],
    861 				assoc.wi_assoc_sta[0]&0xff, assoc.wi_assoc_sta[1]&0xff,
    862 				assoc.wi_assoc_sta[2]&0xff, assoc.wi_assoc_sta[3]&0xff,
    863 				assoc.wi_assoc_sta[4]&0xff, assoc.wi_assoc_sta[5]&0xff,
    864 				assoc.wi_assoc_osta[0]&0xff, assoc.wi_assoc_osta[1]&0xff,
    865 				assoc.wi_assoc_osta[2]&0xff, assoc.wi_assoc_osta[3]&0xff,
    866 				assoc.wi_assoc_osta[4]&0xff, assoc.wi_assoc_osta[5]&0xff);
    867 			break;
    868 		}
    869 		}
    870 
    871 	default:
    872 #ifdef WI_DEBUG
    873 		printf("%s: got info type: 0x%04x len=0x%04x\n",
    874       sc->sc_dev.dv_xname, gen.wi_type,gen.wi_len);
    875 #endif
    876 #if 0
    877 		for (i = 0; i < gen.wi_len; i++) {
    878 			t = CSR_READ_2(sc, WI_DATA1);
    879 			printf("[0x%02x] = 0x%04x\n", i, t);
    880 		}
    881 #endif
    882 		break;
    883 	}
    884 }
    885 
    886 int wi_intr(arg)
    887 	void *arg;
    888 {
    889 	struct wi_softc		*sc = arg;
    890 	struct ifnet		*ifp;
    891 	u_int16_t		status;
    892 
    893 	if (sc->sc_enabled == 0 ||
    894 	    (sc->sc_dev.dv_flags & DVF_ACTIVE) == 0 ||
    895 	    (sc->sc_ethercom.ec_if.if_flags & IFF_RUNNING) == 0)
    896 		return (0);
    897 
    898 	ifp = &sc->sc_ethercom.ec_if;
    899 
    900 	if (!(ifp->if_flags & IFF_UP)) {
    901 		CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
    902 		CSR_WRITE_2(sc, WI_INT_EN, 0);
    903 		return 1;
    904 	}
    905 
    906 	/* Disable interrupts. */
    907 	CSR_WRITE_2(sc, WI_INT_EN, 0);
    908 
    909 	status = CSR_READ_2(sc, WI_EVENT_STAT);
    910 	CSR_WRITE_2(sc, WI_EVENT_ACK, ~WI_INTRS);
    911 
    912 	if (status & WI_EV_RX) {
    913 		wi_rxeof(sc);
    914 		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
    915 	}
    916 
    917 	if (status & WI_EV_TX) {
    918 		wi_txeof(sc, status);
    919 		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX);
    920 	}
    921 
    922 	if (status & WI_EV_ALLOC) {
    923 		int			id;
    924 		id = CSR_READ_2(sc, WI_ALLOC_FID);
    925 		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
    926 		if (id == sc->wi_tx_data_id)
    927 			wi_txeof(sc, status);
    928 	}
    929 
    930 	if (status & WI_EV_INFO) {
    931 		wi_update_stats(sc);
    932 		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO);
    933 	}
    934 
    935 	if (status & WI_EV_TX_EXC) {
    936 		wi_txeof(sc, status);
    937 		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX_EXC);
    938 	}
    939 
    940 	if (status & WI_EV_INFO_DROP) {
    941 		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO_DROP);
    942 	}
    943 
    944 	/* Re-enable interrupts. */
    945 	CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
    946 
    947 	if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
    948 		wi_start(ifp);
    949 
    950 	return 1;
    951 }
    952 
    953 /* Must be called at proper protection level! */
    954 static int
    955 wi_cmd(sc, cmd, val)
    956 	struct wi_softc		*sc;
    957 	int			cmd;
    958 	int			val;
    959 {
    960 	int			i, s = 0;
    961 
    962 	/* wait for the busy bit to clear */
    963 	for (i = 0; i < WI_TIMEOUT; i++) {
    964 		if (!(CSR_READ_2(sc, WI_COMMAND) & WI_CMD_BUSY))
    965 			break;
    966 	}
    967 
    968 	if (i == WI_TIMEOUT) {
    969 		printf("%s: wi_cmd: BUSY did not clear, cmd=0x%x\n",
    970 			sc->sc_dev.dv_xname, cmd);
    971 		return EIO;
    972 	}
    973 
    974 	CSR_WRITE_2(sc, WI_PARAM0, val);
    975 	CSR_WRITE_2(sc, WI_PARAM1, 0);
    976 	CSR_WRITE_2(sc, WI_PARAM2, 0);
    977 	CSR_WRITE_2(sc, WI_COMMAND, cmd);
    978 
    979 	/* wait for the cmd completed bit */
    980 	for (i = 0; i < WI_TIMEOUT; i++) {
    981 		if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_CMD)
    982 			break;
    983 		DELAY(1);
    984 	}
    985 
    986 	/* Ack the command */
    987 	CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_CMD);
    988 
    989 	s = CSR_READ_2(sc, WI_STATUS);
    990 	if (s & WI_STAT_CMD_RESULT)
    991 		return(EIO);
    992 
    993 	if (i == WI_TIMEOUT) {
    994 		if (!sc->wi_scanning)
    995 		    printf("%s: command timed out, cmd=0x%x\n",
    996 			sc->sc_dev.dv_xname, cmd);
    997 		return(ETIMEDOUT);
    998 	}
    999 
   1000 	return(0);
   1001 }
   1002 
   1003 static void
   1004 wi_reset(sc)
   1005 	struct wi_softc		*sc;
   1006 {
   1007 
   1008 	DELAY(100*1000); /* 100 m sec */
   1009 	if (wi_cmd(sc, WI_CMD_INI, 0))
   1010 		printf("%s: init failed\n", sc->sc_dev.dv_xname);
   1011 	CSR_WRITE_2(sc, WI_INT_EN, 0);
   1012 	CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
   1013 
   1014 	/* Calibrate timer. */
   1015 	WI_SETVAL(WI_RID_TICK_TIME, 8);
   1016 
   1017 	return;
   1018 }
   1019 
   1020 /*
   1021  * Read an LTV record from the NIC.
   1022  */
   1023 static int wi_read_record(sc, ltv)
   1024 	struct wi_softc		*sc;
   1025 	struct wi_ltv_gen	*ltv;
   1026 {
   1027 	u_int16_t		*ptr;
   1028 	int			len, code;
   1029 	struct wi_ltv_gen	*oltv, p2ltv;
   1030 
   1031 	if (sc->sc_firmware_type != WI_LUCENT) {
   1032 		oltv = ltv;
   1033 		switch (ltv->wi_type) {
   1034 		case WI_RID_ENCRYPTION:
   1035 			p2ltv.wi_type = WI_RID_P2_ENCRYPTION;
   1036 			p2ltv.wi_len = 2;
   1037 			ltv = &p2ltv;
   1038 			break;
   1039 		case WI_RID_TX_CRYPT_KEY:
   1040 			p2ltv.wi_type = WI_RID_P2_TX_CRYPT_KEY;
   1041 			p2ltv.wi_len = 2;
   1042 			ltv = &p2ltv;
   1043 			break;
   1044 		case WI_RID_ROAMING_MODE:
   1045 			if (sc->sc_firmware_type == WI_INTERSIL)
   1046 				break;
   1047 			/* not supported */
   1048 			ltv->wi_len = 1;
   1049 			return 0;
   1050 		case WI_RID_MICROWAVE_OVEN:
   1051 			/* not supported */
   1052 			ltv->wi_len = 1;
   1053 			return 0;
   1054 		}
   1055 	}
   1056 
   1057 	/* Tell the NIC to enter record read mode. */
   1058 	if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_READ, ltv->wi_type))
   1059 		return(EIO);
   1060 
   1061 	/* Seek to the record. */
   1062 	if (wi_seek(sc, ltv->wi_type, 0, WI_BAP1))
   1063 		return(EIO);
   1064 
   1065 	/*
   1066 	 * Read the length and record type and make sure they
   1067 	 * match what we expect (this verifies that we have enough
   1068 	 * room to hold all of the returned data).
   1069 	 */
   1070 	len = CSR_READ_2(sc, WI_DATA1);
   1071 	if (len > ltv->wi_len)
   1072 		return(ENOSPC);
   1073 	code = CSR_READ_2(sc, WI_DATA1);
   1074 	if (code != ltv->wi_type)
   1075 		return(EIO);
   1076 
   1077 	ltv->wi_len = len;
   1078 	ltv->wi_type = code;
   1079 
   1080 	/* Now read the data. */
   1081 	ptr = &ltv->wi_val;
   1082 	if (ltv->wi_len > 1)
   1083 		CSR_READ_MULTI_STREAM_2(sc, WI_DATA1, ptr, ltv->wi_len - 1);
   1084 
   1085 	if (ltv->wi_type == WI_RID_PORTTYPE &&
   1086 	    sc->wi_ptype == WI_PORTTYPE_IBSS &&
   1087 	    ltv->wi_val == sc->wi_ibss_port) {
   1088 		/*
   1089 		 * Convert vendor IBSS port type to WI_PORTTYPE_IBSS.
   1090 		 * Since Lucent uses port type 1 for BSS *and* IBSS we
   1091 		 * have to rely on wi_ptype to distinguish this for us.
   1092 		 */
   1093 		ltv->wi_val = htole16(WI_PORTTYPE_IBSS);
   1094 	} else if (sc->sc_firmware_type != WI_LUCENT) {
   1095 		int v;
   1096 
   1097 		switch (oltv->wi_type) {
   1098 		case WI_RID_TX_RATE:
   1099 		case WI_RID_CUR_TX_RATE:
   1100 			switch (le16toh(ltv->wi_val)) {
   1101 			case 1: v = 1; break;
   1102 			case 2: v = 2; break;
   1103 			case 3:	v = 6; break;
   1104 			case 4: v = 5; break;
   1105 			case 7: v = 7; break;
   1106 			case 8: v = 11; break;
   1107 			case 15: v = 3; break;
   1108 			default: v = 0x100 + le16toh(ltv->wi_val); break;
   1109 			}
   1110 			oltv->wi_val = htole16(v);
   1111 			break;
   1112 		case WI_RID_ENCRYPTION:
   1113 			oltv->wi_len = 2;
   1114 			if (le16toh(ltv->wi_val) & 0x01)
   1115 				oltv->wi_val = htole16(1);
   1116 			else
   1117 				oltv->wi_val = htole16(0);
   1118 			break;
   1119 		case WI_RID_TX_CRYPT_KEY:
   1120 			oltv->wi_len = 2;
   1121 			oltv->wi_val = ltv->wi_val;
   1122 			break;
   1123 		case WI_RID_CNFAUTHMODE:
   1124 			oltv->wi_len = 2;
   1125 			if (le16toh(ltv->wi_val) & 0x01)
   1126 				oltv->wi_val = htole16(1);
   1127 			else if (le16toh(ltv->wi_val) & 0x02)
   1128 				oltv->wi_val = htole16(2);
   1129 			break;
   1130 		}
   1131 	}
   1132 
   1133 	return(0);
   1134 }
   1135 
   1136 /*
   1137  * Same as read, except we inject data instead of reading it.
   1138  */
   1139 static int wi_write_record(sc, ltv)
   1140 	struct wi_softc		*sc;
   1141 	struct wi_ltv_gen	*ltv;
   1142 {
   1143 	u_int16_t		*ptr;
   1144 	int			i;
   1145 	struct wi_ltv_gen	p2ltv;
   1146 
   1147 	if (ltv->wi_type == WI_RID_PORTTYPE &&
   1148 	    ltv->wi_val == le16toh(WI_PORTTYPE_IBSS)) {
   1149 		/* Convert WI_PORTTYPE_IBSS to vendor IBSS port type. */
   1150 		p2ltv.wi_type = WI_RID_PORTTYPE;
   1151 		p2ltv.wi_len = 2;
   1152 		p2ltv.wi_val = sc->wi_ibss_port;
   1153 		ltv = &p2ltv;
   1154 	} else if (sc->sc_firmware_type != WI_LUCENT) {
   1155 		int v;
   1156 
   1157 		switch (ltv->wi_type) {
   1158 		case WI_RID_TX_RATE:
   1159 			p2ltv.wi_type = WI_RID_TX_RATE;
   1160 			p2ltv.wi_len = 2;
   1161 			switch (le16toh(ltv->wi_val)) {
   1162 			case 1: v = 1; break;
   1163 			case 2: v = 2; break;
   1164 			case 3:	v = 15; break;
   1165 			case 5: v = 4; break;
   1166 			case 6: v = 3; break;
   1167 			case 7: v = 7; break;
   1168 			case 11: v = 8; break;
   1169 			default: return EINVAL;
   1170 			}
   1171 			p2ltv.wi_val = htole16(v);
   1172 			ltv = &p2ltv;
   1173 			break;
   1174 		case WI_RID_ENCRYPTION:
   1175 			p2ltv.wi_type = WI_RID_P2_ENCRYPTION;
   1176 			p2ltv.wi_len = 2;
   1177 			if (le16toh(ltv->wi_val)) {
   1178 				uint16_t val = PRIVACY_INVOKED;
   1179 				/*
   1180 				 * If using shared key WEP we must set the
   1181 				 * EXCLUDE_UNENCRYPTED bit.  Symbol cards
   1182 				 * need this bit even when not using shared
   1183 				 * key.  We can't just test for
   1184 				 * IEEE80211_AUTH_SHARED since Symbol cards
   1185 				 * have 2 shared key modes.
   1186 				 */
   1187 				if (sc->wi_authtype != IEEE80211_AUTH_OPEN ||
   1188 				    sc->sc_firmware_type == WI_SYMBOL)
   1189 					val |= EXCLUDE_UNENCRYPTED;
   1190 				/* Tx encryption is broken in Host-AP mode. */
   1191 				if (sc->wi_ptype == WI_PORTTYPE_HOSTAP)
   1192 					val |= HOST_ENCRYPT;
   1193 				p2ltv.wi_val = htole16(val);
   1194 			} else
   1195 				p2ltv.wi_val =
   1196 				    htole16(HOST_ENCRYPT | HOST_DECRYPT);
   1197 			ltv = &p2ltv;
   1198 			break;
   1199 		case WI_RID_TX_CRYPT_KEY:
   1200 			p2ltv.wi_type = WI_RID_P2_TX_CRYPT_KEY;
   1201 			p2ltv.wi_len = 2;
   1202 			p2ltv.wi_val = ltv->wi_val;
   1203 			ltv = &p2ltv;
   1204 			break;
   1205 		case WI_RID_DEFLT_CRYPT_KEYS:
   1206 		    {
   1207 			int error;
   1208 			int keylen;
   1209 			struct wi_ltv_str	ws;
   1210 			struct wi_ltv_keys	*wk = (struct wi_ltv_keys *)ltv;
   1211 
   1212 			keylen = wk->wi_keys[sc->wi_tx_key].wi_keylen;
   1213 
   1214 			for (i = 0; i < 4; i++) {
   1215 				memset(&ws, 0, sizeof(ws));
   1216 				ws.wi_len = (keylen > 5) ? 8 : 4;
   1217 				ws.wi_type = WI_RID_P2_CRYPT_KEY0 + i;
   1218 				memcpy(ws.wi_str,
   1219 					&wk->wi_keys[i].wi_keydat, keylen);
   1220 				error = wi_write_record(sc,
   1221 					(struct wi_ltv_gen *)&ws);
   1222 				if (error)
   1223 					return error;
   1224 			}
   1225 			return 0;
   1226 		    }
   1227 		case WI_RID_CNFAUTHMODE:
   1228 			p2ltv.wi_type = WI_RID_CNFAUTHMODE;
   1229 			p2ltv.wi_len = 2;
   1230 			if (le16toh(ltv->wi_val) == 1)
   1231 				p2ltv.wi_val = htole16(0x01);
   1232 			else if (le16toh(ltv->wi_val) == 2)
   1233 				p2ltv.wi_val = htole16(0x02);
   1234 			ltv = &p2ltv;
   1235 			break;
   1236 
   1237 		case WI_RID_ROAMING_MODE:
   1238 			if (sc->sc_firmware_type == WI_INTERSIL)
   1239 				break;
   1240 			/* not supported */
   1241 			return 0;
   1242 
   1243 		case WI_RID_MICROWAVE_OVEN:
   1244 			/* not supported */
   1245 			return 0;
   1246 		}
   1247 	}
   1248 
   1249 	if (wi_seek(sc, ltv->wi_type, 0, WI_BAP1))
   1250 		return(EIO);
   1251 
   1252 	CSR_WRITE_2(sc, WI_DATA1, ltv->wi_len);
   1253 	CSR_WRITE_2(sc, WI_DATA1, ltv->wi_type);
   1254 
   1255 	/* Write data */
   1256 	ptr = &ltv->wi_val;
   1257 	if (ltv->wi_len > 1)
   1258 		CSR_WRITE_MULTI_STREAM_2(sc, WI_DATA1, ptr, ltv->wi_len - 1);
   1259 
   1260 	if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_WRITE, ltv->wi_type))
   1261 		return(EIO);
   1262 
   1263 	return(0);
   1264 }
   1265 
   1266 static int wi_seek(sc, id, off, chan)
   1267 	struct wi_softc		*sc;
   1268 	int			id, off, chan;
   1269 {
   1270 	int			i;
   1271 	int			selreg, offreg;
   1272 	int 			status;
   1273 
   1274 	switch (chan) {
   1275 	case WI_BAP0:
   1276 		selreg = WI_SEL0;
   1277 		offreg = WI_OFF0;
   1278 		break;
   1279 	case WI_BAP1:
   1280 		selreg = WI_SEL1;
   1281 		offreg = WI_OFF1;
   1282 		break;
   1283 	default:
   1284 		printf("%s: invalid data path: %x\n",
   1285 		    sc->sc_dev.dv_xname, chan);
   1286 		return(EIO);
   1287 	}
   1288 
   1289 	CSR_WRITE_2(sc, selreg, id);
   1290 	CSR_WRITE_2(sc, offreg, off);
   1291 
   1292 	for (i = 0; i < WI_TIMEOUT; i++) {
   1293 	  	status = CSR_READ_2(sc, offreg);
   1294 		if (!(status & (WI_OFF_BUSY|WI_OFF_ERR)))
   1295 			break;
   1296 	}
   1297 
   1298 	if (i == WI_TIMEOUT) {
   1299 		printf("%s: timeout in wi_seek to %x/%x; last status %x\n",
   1300 		       sc->sc_dev.dv_xname, id, off, status);
   1301 		return(ETIMEDOUT);
   1302 	}
   1303 	return(0);
   1304 }
   1305 
   1306 static int wi_read_data(sc, id, off, buf, len)
   1307 	struct wi_softc		*sc;
   1308 	int			id, off;
   1309 	caddr_t			buf;
   1310 	int			len;
   1311 {
   1312 	u_int16_t		*ptr;
   1313 
   1314 	if (wi_seek(sc, id, off, WI_BAP1))
   1315 		return(EIO);
   1316 
   1317 	ptr = (u_int16_t *)buf;
   1318 	CSR_READ_MULTI_STREAM_2(sc, WI_DATA1, ptr, len / 2);
   1319 
   1320 	return(0);
   1321 }
   1322 
   1323 /*
   1324  * According to the comments in the HCF Light code, there is a bug in
   1325  * the Hermes (or possibly in certain Hermes firmware revisions) where
   1326  * the chip's internal autoincrement counter gets thrown off during
   1327  * data writes: the autoincrement is missed, causing one data word to
   1328  * be overwritten and subsequent words to be written to the wrong memory
   1329  * locations. The end result is that we could end up transmitting bogus
   1330  * frames without realizing it. The workaround for this is to write a
   1331  * couple of extra guard words after the end of the transfer, then
   1332  * attempt to read then back. If we fail to locate the guard words where
   1333  * we expect them, we preform the transfer over again.
   1334  */
   1335 static int wi_write_data(sc, id, off, buf, len)
   1336 	struct wi_softc		*sc;
   1337 	int			id, off;
   1338 	caddr_t			buf;
   1339 	int			len;
   1340 {
   1341 	u_int16_t		*ptr;
   1342 
   1343 #ifdef WI_HERMES_AUTOINC_WAR
   1344 again:
   1345 #endif
   1346 
   1347 	if (wi_seek(sc, id, off, WI_BAP0))
   1348 		return(EIO);
   1349 
   1350 	ptr = (u_int16_t *)buf;
   1351 	CSR_WRITE_MULTI_STREAM_2(sc, WI_DATA0, ptr, len / 2);
   1352 
   1353 #ifdef WI_HERMES_AUTOINC_WAR
   1354 	CSR_WRITE_2(sc, WI_DATA0, 0x1234);
   1355 	CSR_WRITE_2(sc, WI_DATA0, 0x5678);
   1356 
   1357 	if (wi_seek(sc, id, off + len, WI_BAP0))
   1358 		return(EIO);
   1359 
   1360 	if (CSR_READ_2(sc, WI_DATA0) != 0x1234 ||
   1361 	    CSR_READ_2(sc, WI_DATA0) != 0x5678)
   1362 		goto again;
   1363 #endif
   1364 
   1365 	return(0);
   1366 }
   1367 
   1368 /*
   1369  * Allocate a region of memory inside the NIC and zero
   1370  * it out.
   1371  */
   1372 static int wi_alloc_nicmem(sc, len, id)
   1373 	struct wi_softc		*sc;
   1374 	int			len;
   1375 	int			*id;
   1376 {
   1377 	int			i;
   1378 
   1379 	if (wi_cmd(sc, WI_CMD_ALLOC_MEM, len)) {
   1380 		printf("%s: failed to allocate %d bytes on NIC\n",
   1381 		    sc->sc_dev.dv_xname, len);
   1382 		return(ENOMEM);
   1383 	}
   1384 
   1385 	for (i = 0; i < WI_TIMEOUT; i++) {
   1386 		if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_ALLOC)
   1387 			break;
   1388 	}
   1389 
   1390 	if (i == WI_TIMEOUT) {
   1391 		printf("%s: TIMED OUT in alloc\n", sc->sc_dev.dv_xname);
   1392 		return(ETIMEDOUT);
   1393 	}
   1394 
   1395 	*id = CSR_READ_2(sc, WI_ALLOC_FID);
   1396 	CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
   1397 
   1398 	if (wi_seek(sc, *id, 0, WI_BAP0)) {
   1399 		printf("%s: seek failed in alloc\n", sc->sc_dev.dv_xname);
   1400 		return(EIO);
   1401 	}
   1402 
   1403 	for (i = 0; i < len / 2; i++)
   1404 		CSR_WRITE_2(sc, WI_DATA0, 0);
   1405 
   1406 	return(0);
   1407 }
   1408 
   1409 static void wi_setmulti(sc)
   1410 	struct wi_softc		*sc;
   1411 {
   1412 	struct ifnet		*ifp;
   1413 	int			i = 0;
   1414 	struct wi_ltv_mcast	mcast;
   1415 	struct ether_multi *enm;
   1416 	struct ether_multistep estep;
   1417 	struct ethercom *ec = &sc->sc_ethercom;
   1418 
   1419 	ifp = &sc->sc_ethercom.ec_if;
   1420 
   1421 	if ((ifp->if_flags & IFF_PROMISC) != 0) {
   1422 allmulti:
   1423 		ifp->if_flags |= IFF_ALLMULTI;
   1424 		memset((char *)&mcast, 0, sizeof(mcast));
   1425 		mcast.wi_type = WI_RID_MCAST_LIST;
   1426 		mcast.wi_len = ((ETHER_ADDR_LEN / 2) * 16) + 1;
   1427 
   1428 		wi_write_record(sc, (struct wi_ltv_gen *)&mcast);
   1429 		return;
   1430 	}
   1431 
   1432 	i = 0;
   1433 	ETHER_FIRST_MULTI(estep, ec, enm);
   1434 	while (enm != NULL) {
   1435 		/* Punt on ranges or too many multicast addresses. */
   1436 		if (memcmp(enm->enm_addrlo, enm->enm_addrhi,
   1437 		    ETHER_ADDR_LEN) != 0 ||
   1438 		    i >= 16)
   1439 			goto allmulti;
   1440 
   1441 		memcpy((char *)&mcast.wi_mcast[i], enm->enm_addrlo,
   1442 		    ETHER_ADDR_LEN);
   1443 		i++;
   1444 		ETHER_NEXT_MULTI(estep, enm);
   1445 	}
   1446 
   1447 	ifp->if_flags &= ~IFF_ALLMULTI;
   1448 	mcast.wi_type = WI_RID_MCAST_LIST;
   1449 	mcast.wi_len = ((ETHER_ADDR_LEN / 2) * i) + 1;
   1450 	wi_write_record(sc, (struct wi_ltv_gen *)&mcast);
   1451 }
   1452 
   1453 static int
   1454 wi_setdef(sc, wreq)
   1455 	struct wi_softc		*sc;
   1456 	struct wi_req		*wreq;
   1457 {
   1458 	struct sockaddr_dl	*sdl;
   1459 	struct ifnet		*ifp;
   1460 	int error = 0;
   1461 
   1462 	ifp = &sc->sc_ethercom.ec_if;
   1463 
   1464 	switch(wreq->wi_type) {
   1465 	case WI_RID_MAC_NODE:
   1466 		sdl = (struct sockaddr_dl *)ifp->if_sadl;
   1467 		memcpy((char *)&sc->sc_macaddr, (char *)&wreq->wi_val,
   1468 		    ETHER_ADDR_LEN);
   1469 		memcpy(LLADDR(sdl), (char *)&wreq->wi_val, ETHER_ADDR_LEN);
   1470 		break;
   1471 	case WI_RID_PORTTYPE:
   1472 		error = wi_sync_media(sc, le16toh(wreq->wi_val[0]),
   1473 		    sc->wi_tx_rate);
   1474 		break;
   1475 	case WI_RID_TX_RATE:
   1476 		error = wi_sync_media(sc, sc->wi_ptype,
   1477 		    le16toh(wreq->wi_val[0]));
   1478 		break;
   1479 	case WI_RID_MAX_DATALEN:
   1480 		sc->wi_max_data_len = le16toh(wreq->wi_val[0]);
   1481 		break;
   1482 	case WI_RID_RTS_THRESH:
   1483 		sc->wi_rts_thresh = le16toh(wreq->wi_val[0]);
   1484 		break;
   1485 	case WI_RID_SYSTEM_SCALE:
   1486 		sc->wi_ap_density = le16toh(wreq->wi_val[0]);
   1487 		break;
   1488 	case WI_RID_CREATE_IBSS:
   1489 		sc->wi_create_ibss = le16toh(wreq->wi_val[0]);
   1490 		error = wi_sync_media(sc, sc->wi_ptype, sc->wi_tx_rate);
   1491 		break;
   1492 	case WI_RID_OWN_CHNL:
   1493 		sc->wi_channel = le16toh(wreq->wi_val[0]);
   1494 		break;
   1495 	case WI_RID_NODENAME:
   1496 		error = wi_set_ssid(&sc->wi_nodeid,
   1497 		    (u_int8_t *)&wreq->wi_val[1], le16toh(wreq->wi_val[0]));
   1498 		break;
   1499 	case WI_RID_DESIRED_SSID:
   1500 		error = wi_set_ssid(&sc->wi_netid,
   1501 		    (u_int8_t *)&wreq->wi_val[1], le16toh(wreq->wi_val[0]));
   1502 		break;
   1503 	case WI_RID_OWN_SSID:
   1504 		error = wi_set_ssid(&sc->wi_ibssid,
   1505 		    (u_int8_t *)&wreq->wi_val[1], le16toh(wreq->wi_val[0]));
   1506 		break;
   1507 	case WI_RID_PM_ENABLED:
   1508 		sc->wi_pm_enabled = le16toh(wreq->wi_val[0]);
   1509 		break;
   1510 	case WI_RID_MICROWAVE_OVEN:
   1511 		sc->wi_mor_enabled = le16toh(wreq->wi_val[0]);
   1512 		break;
   1513 	case WI_RID_MAX_SLEEP:
   1514 		sc->wi_max_sleep = le16toh(wreq->wi_val[0]);
   1515 		break;
   1516 	case WI_RID_CNFAUTHMODE:
   1517 		sc->wi_authtype = le16toh(wreq->wi_val[0]);
   1518 		break;
   1519 	case WI_RID_ROAMING_MODE:
   1520 		sc->wi_roaming = le16toh(wreq->wi_val[0]);
   1521 		break;
   1522 	case WI_RID_ENCRYPTION:
   1523 		sc->wi_use_wep = le16toh(wreq->wi_val[0]);
   1524 		break;
   1525 	case WI_RID_TX_CRYPT_KEY:
   1526 		sc->wi_tx_key = le16toh(wreq->wi_val[0]);
   1527 		break;
   1528 	case WI_RID_DEFLT_CRYPT_KEYS:
   1529 		memcpy((char *)&sc->wi_keys, (char *)wreq,
   1530 		    sizeof(struct wi_ltv_keys));
   1531 		break;
   1532 	default:
   1533 		error = EINVAL;
   1534 		break;
   1535 	}
   1536 
   1537 	return (error);
   1538 }
   1539 
   1540 static int
   1541 wi_getdef(sc, wreq)
   1542 	struct wi_softc		*sc;
   1543 	struct wi_req		*wreq;
   1544 {
   1545 	struct sockaddr_dl	*sdl;
   1546 	struct ifnet		*ifp;
   1547 	int error = 0;
   1548 
   1549 	ifp = &sc->sc_ethercom.ec_if;
   1550 
   1551 	wreq->wi_len = 2;			/* XXX */
   1552 	switch (wreq->wi_type) {
   1553 	case WI_RID_MAC_NODE:
   1554 		wreq->wi_len += ETHER_ADDR_LEN / 2 - 1;
   1555 		sdl = (struct sockaddr_dl *)ifp->if_sadl;
   1556 		memcpy(&wreq->wi_val, &sc->sc_macaddr, ETHER_ADDR_LEN);
   1557 		memcpy(&wreq->wi_val, LLADDR(sdl), ETHER_ADDR_LEN);
   1558 		break;
   1559 	case WI_RID_PORTTYPE:
   1560 		wreq->wi_val[0] = htole16(sc->wi_ptype);
   1561 		break;
   1562 	case WI_RID_TX_RATE:
   1563 		wreq->wi_val[0] = htole16(sc->wi_tx_rate);
   1564 		break;
   1565 	case WI_RID_MAX_DATALEN:
   1566 		wreq->wi_val[0] = htole16(sc->wi_max_data_len);
   1567 		break;
   1568 	case WI_RID_RTS_THRESH:
   1569 		wreq->wi_val[0] = htole16(sc->wi_rts_thresh);
   1570 		break;
   1571 	case WI_RID_SYSTEM_SCALE:
   1572 		wreq->wi_val[0] = htole16(sc->wi_ap_density);
   1573 		break;
   1574 	case WI_RID_CREATE_IBSS:
   1575 		wreq->wi_val[0] = htole16(sc->wi_create_ibss);
   1576 		break;
   1577 	case WI_RID_OWN_CHNL:
   1578 		wreq->wi_val[0] = htole16(sc->wi_channel);
   1579 		break;
   1580 	case WI_RID_NODENAME:
   1581 		wi_request_fill_ssid(wreq, &sc->wi_nodeid);
   1582 		break;
   1583 	case WI_RID_DESIRED_SSID:
   1584 		wi_request_fill_ssid(wreq, &sc->wi_netid);
   1585 		break;
   1586 	case WI_RID_OWN_SSID:
   1587 		wi_request_fill_ssid(wreq, &sc->wi_ibssid);
   1588 		break;
   1589 	case WI_RID_PM_ENABLED:
   1590 		wreq->wi_val[0] = htole16(sc->wi_pm_enabled);
   1591 		break;
   1592 	case WI_RID_MICROWAVE_OVEN:
   1593 		wreq->wi_val[0] = htole16(sc->wi_mor_enabled);
   1594 		break;
   1595 	case WI_RID_MAX_SLEEP:
   1596 		wreq->wi_val[0] = htole16(sc->wi_max_sleep);
   1597 		break;
   1598 	case WI_RID_CNFAUTHMODE:
   1599 		wreq->wi_val[0] = htole16(sc->wi_authtype);
   1600 		break;
   1601 	case WI_RID_ROAMING_MODE:
   1602 		wreq->wi_val[0] = htole16(sc->wi_roaming);
   1603 		break;
   1604 	case WI_RID_WEP_AVAIL:
   1605 		wreq->wi_val[0] = (sc->wi_flags & WI_FLAGS_HAS_WEP) ?
   1606 		    htole16(1) : htole16(0);
   1607 		break;
   1608 	case WI_RID_ENCRYPTION:
   1609 		wreq->wi_val[0] = htole16(sc->wi_use_wep);
   1610 		break;
   1611 	case WI_RID_TX_CRYPT_KEY:
   1612 		wreq->wi_val[0] = htole16(sc->wi_tx_key);
   1613 		break;
   1614 	case WI_RID_DEFLT_CRYPT_KEYS:
   1615 		wreq->wi_len += sizeof(struct wi_ltv_keys) / 2 - 1;
   1616 		memcpy(wreq, &sc->wi_keys, sizeof(struct wi_ltv_keys));
   1617 		break;
   1618 	default:
   1619 #if 0
   1620 		error = EIO;
   1621 #else
   1622 #ifdef WI_DEBUG
   1623 		printf("%s: wi_getdef: unknown request %d\n",
   1624 		    sc->sc_dev.dv_xname, wreq->wi_type);
   1625 #endif
   1626 #endif
   1627 		break;
   1628 	}
   1629 
   1630 	return (error);
   1631 }
   1632 
   1633 static int
   1634 wi_ioctl(ifp, command, data)
   1635 	struct ifnet		*ifp;
   1636 	u_long			command;
   1637 	caddr_t			data;
   1638 {
   1639 	int			s, error = 0;
   1640 	int			len;
   1641 	struct wi_softc		*sc = ifp->if_softc;
   1642 	struct wi_req		wreq;
   1643 	struct ifreq		*ifr;
   1644 	struct proc *p = curproc;
   1645 	struct ieee80211_nwid nwid;
   1646 
   1647 	if ((sc->sc_dev.dv_flags & DVF_ACTIVE) == 0)
   1648 		return (ENXIO);
   1649 
   1650 	s = splnet();
   1651 
   1652 	ifr = (struct ifreq *)data;
   1653 	switch (command) {
   1654 	case SIOCSIFADDR:
   1655 	case SIOCGIFADDR:
   1656 	case SIOCSIFMTU:
   1657 		error = ether_ioctl(ifp, command, data);
   1658 		break;
   1659 	case SIOCSIFFLAGS:
   1660 		if (ifp->if_flags & IFF_UP) {
   1661 			if (ifp->if_flags & IFF_RUNNING &&
   1662 			    ifp->if_flags & IFF_PROMISC &&
   1663 			    !(sc->wi_if_flags & IFF_PROMISC)) {
   1664 				if (sc->wi_ptype != WI_PORTTYPE_HOSTAP)
   1665 					WI_SETVAL(WI_RID_PROMISC, 1);
   1666 			} else if (ifp->if_flags & IFF_RUNNING &&
   1667 			    !(ifp->if_flags & IFF_PROMISC) &&
   1668 			    sc->wi_if_flags & IFF_PROMISC) {
   1669 				if (sc->wi_ptype != WI_PORTTYPE_HOSTAP)
   1670 					WI_SETVAL(WI_RID_PROMISC, 0);
   1671 			} else
   1672 				wi_init(ifp);
   1673 		} else if (ifp->if_flags & IFF_RUNNING)
   1674 			wi_stop(ifp, 0);
   1675 		sc->wi_if_flags = ifp->if_flags;
   1676 
   1677 		if (!(ifp->if_flags & IFF_UP)) {
   1678 			if (sc->sc_enabled) {
   1679 				if (sc->sc_disable)
   1680 					(*sc->sc_disable)(sc);
   1681 				sc->sc_enabled = 0;
   1682 				ifp->if_flags &= ~IFF_RUNNING;
   1683 			}
   1684 		}
   1685 		error = 0;
   1686 		break;
   1687 	case SIOCADDMULTI:
   1688 	case SIOCDELMULTI:
   1689 		error = (command == SIOCADDMULTI) ?
   1690 			ether_addmulti(ifr, &sc->sc_ethercom) :
   1691 			ether_delmulti(ifr, &sc->sc_ethercom);
   1692 		if (error == ENETRESET) {
   1693 			if (sc->sc_enabled != 0) {
   1694 				/*
   1695 				 * Multicast list has changed.  Set the
   1696 				 * hardware filter accordingly.
   1697 				 */
   1698 				wi_setmulti(sc);
   1699 			}
   1700 			error = 0;
   1701 		}
   1702 		break;
   1703 	case SIOCSIFMEDIA:
   1704 	case SIOCGIFMEDIA:
   1705 		error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, command);
   1706 		break;
   1707 	case SIOCGWAVELAN:
   1708 		error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
   1709 		if (error)
   1710 			break;
   1711 		if (wreq.wi_type == WI_RID_IFACE_STATS) {
   1712 			memcpy((char *)&wreq.wi_val, (char *)&sc->wi_stats,
   1713 			    sizeof(sc->wi_stats));
   1714 			wreq.wi_len = (sizeof(sc->wi_stats) / 2) + 1;
   1715 		} else if (wreq.wi_type == WI_RID_READ_APS) {
   1716 			if (sc->wi_scanning) {
   1717 				error = EINPROGRESS;
   1718 				break;
   1719 			} else {
   1720 				len = sc->wi_naps * sizeof(struct wi_apinfo);
   1721 				len = len > WI_MAX_DATALEN ? WI_MAX_DATALEN : len;
   1722 				len = len / sizeof(struct wi_apinfo);
   1723 				memcpy((char *)&wreq.wi_val, (char *)&len, sizeof(len));
   1724 				memcpy((char *)&wreq.wi_val + sizeof(len),
   1725 					(char *)&sc->wi_aps,
   1726 					len * sizeof(struct wi_apinfo));
   1727 			}
   1728 		} else if (wreq.wi_type == WI_RID_DEFLT_CRYPT_KEYS) {
   1729 			/* For non-root user, return all-zeroes keys */
   1730 			if (suser(p->p_ucred, &p->p_acflag))
   1731 				memset((char *)&wreq, 0,
   1732 				    sizeof(struct wi_ltv_keys));
   1733 			else
   1734 				memcpy((char *)&wreq, (char *)&sc->wi_keys,
   1735 				    sizeof(struct wi_ltv_keys));
   1736 		} else {
   1737 			if (sc->sc_enabled == 0)
   1738 				error = wi_getdef(sc, &wreq);
   1739 			else if (wreq.wi_len > WI_MAX_DATALEN)
   1740 				error = EINVAL;
   1741 			else if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq))
   1742 				error = EINVAL;
   1743 		}
   1744 		if (error == 0)
   1745 			error = copyout(&wreq, ifr->ifr_data, sizeof(wreq));
   1746 		break;
   1747 	case SIOCSWAVELAN:
   1748 		error = suser(p->p_ucred, &p->p_acflag);
   1749 		if (error)
   1750 			break;
   1751 		error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
   1752 		if (error)
   1753 			break;
   1754 		if (wreq.wi_type == WI_RID_IFACE_STATS) {
   1755 			if (sc->sc_enabled)
   1756 				wi_inquire(sc);
   1757 			break;
   1758 		} else if (wreq.wi_type == WI_RID_MGMT_XMIT) {
   1759 			error = wi_mgmt_xmit(sc, (caddr_t)&wreq.wi_val,
   1760 			    wreq.wi_len);
   1761 		} else if (wreq.wi_type == WI_RID_SCAN_APS) {
   1762 			if (wreq.wi_len != 4) {
   1763 				error = EINVAL;
   1764 				break;
   1765 			}
   1766 			if (!sc->wi_scanning) {
   1767 				switch (sc->sc_firmware_type) {
   1768 				case WI_LUCENT:
   1769 					break;
   1770 				case WI_INTERSIL:
   1771 					wreq.wi_type = WI_RID_SCAN_REQ;
   1772 					error = wi_write_record(sc,
   1773 					    (struct wi_ltv_gen *)&wreq);
   1774 					break;
   1775 				case WI_SYMBOL:
   1776 					/*
   1777 					 * XXX only supported on 3.x ?
   1778 					 */
   1779 					wreq.wi_type = WI_RID_BCAST_SCAN_REQ;
   1780 					wreq.wi_val[0] =
   1781 					    BSCAN_BCAST | BSCAN_ONETIME;
   1782 					wreq.wi_len = 2;
   1783 					error = wi_write_record(sc,
   1784 					    (struct wi_ltv_gen *)&wreq);
   1785 					break;
   1786 				}
   1787 				if (!error) {
   1788 					sc->wi_scanning = 1;
   1789 					callout_reset(&sc->wi_scan_sh, hz * 1,
   1790 						wi_wait_scan, sc);
   1791 				}
   1792 			}
   1793 		} else {
   1794 			/*
   1795 			 * Filter stuff out based on what the
   1796 			 * card can do.
   1797 			 */
   1798 			if ((wreq.wi_type == WI_RID_ROAMING_MODE &&
   1799 			     (sc->wi_flags & WI_FLAGS_HAS_ROAMING) == 0) ||
   1800 			    (wreq.wi_type == WI_RID_CREATE_IBSS &&
   1801 			     (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS) == 0) ||
   1802 			    (wreq.wi_type == WI_RID_MICROWAVE_OVEN &&
   1803 			     (sc->wi_flags & WI_FLAGS_HAS_MOR) == 0))
   1804 				break;
   1805 
   1806 			if (wreq.wi_len > WI_MAX_DATALEN)
   1807 				error = EINVAL;
   1808 			else if (sc->sc_enabled != 0)
   1809 				error = wi_write_record(sc,
   1810 				    (struct wi_ltv_gen *)&wreq);
   1811 			if (error == 0)
   1812 				error = wi_setdef(sc, &wreq);
   1813 			if (error == 0 && sc->sc_enabled != 0)
   1814 				/* Reinitialize WaveLAN. */
   1815 				wi_init(ifp);
   1816 		}
   1817 		break;
   1818 	case SIOCG80211NWID:
   1819 		if (sc->sc_enabled == 0) {
   1820 			/* Return the desired ID */
   1821 			error = copyout(&sc->wi_netid, ifr->ifr_data,
   1822 			    sizeof(sc->wi_netid));
   1823 		} else {
   1824 			wreq.wi_type = WI_RID_CURRENT_SSID;
   1825 			wreq.wi_len = WI_MAX_DATALEN;
   1826 			if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq) ||
   1827 			    le16toh(wreq.wi_val[0]) > IEEE80211_NWID_LEN)
   1828 				error = EINVAL;
   1829 			else {
   1830 				wi_set_ssid(&nwid, (u_int8_t *)&wreq.wi_val[1],
   1831 				    le16toh(wreq.wi_val[0]));
   1832 				error = copyout(&nwid, ifr->ifr_data,
   1833 				    sizeof(nwid));
   1834 			}
   1835 		}
   1836 		break;
   1837 	case SIOCS80211NWID:
   1838 		error = copyin(ifr->ifr_data, &nwid, sizeof(nwid));
   1839 		if (error != 0)
   1840 			break;
   1841 		if (nwid.i_len > IEEE80211_NWID_LEN) {
   1842 			error = EINVAL;
   1843 			break;
   1844 		}
   1845 		if (sc->wi_netid.i_len == nwid.i_len &&
   1846 		    memcmp(sc->wi_netid.i_nwid, nwid.i_nwid, nwid.i_len) == 0)
   1847 			break;
   1848 		wi_set_ssid(&sc->wi_netid, nwid.i_nwid, nwid.i_len);
   1849 		if (sc->sc_enabled != 0)
   1850 			/* Reinitialize WaveLAN. */
   1851 			wi_init(ifp);
   1852 		break;
   1853 	case SIOCS80211NWKEY:
   1854 		error = wi_set_nwkey(sc, (struct ieee80211_nwkey *)data);
   1855 		break;
   1856 	case SIOCG80211NWKEY:
   1857 		error = wi_get_nwkey(sc, (struct ieee80211_nwkey *)data);
   1858 		break;
   1859 	case SIOCS80211POWER:
   1860 		error = wi_set_pm(sc, (struct ieee80211_power *)data);
   1861 		break;
   1862 	case SIOCG80211POWER:
   1863 		error = wi_get_pm(sc, (struct ieee80211_power *)data);
   1864 		break;
   1865 	case SIOCHOSTAP_ADD:
   1866 	case SIOCHOSTAP_DEL:
   1867 	case SIOCHOSTAP_GET:
   1868 	case SIOCHOSTAP_GETALL:
   1869 	case SIOCHOSTAP_GFLAGS:
   1870 	case SIOCHOSTAP_SFLAGS:
   1871 		/* Send all Host-AP specific ioctls to the Host-AP code. */
   1872 		error = wihap_ioctl(sc, command, data);
   1873 		break;
   1874 
   1875 	default:
   1876 		error = EINVAL;
   1877 		break;
   1878 	}
   1879 
   1880 	splx(s);
   1881 	return (error);
   1882 }
   1883 
   1884 static int
   1885 wi_init(ifp)
   1886 	struct ifnet *ifp;
   1887 {
   1888 	struct wi_softc *sc = ifp->if_softc;
   1889 	struct wi_req wreq;
   1890 	struct wi_ltv_macaddr mac;
   1891 	int error, id = 0, wasenabled;
   1892 
   1893 	wasenabled = sc->sc_enabled;
   1894 	if (!sc->sc_enabled) {
   1895 		if ((error = (*sc->sc_enable)(sc)) != 0)
   1896 			goto out;
   1897 		sc->sc_enabled = 1;
   1898 	}
   1899 
   1900 	wi_stop(ifp, 0);
   1901 	/* Symbol firmware cannot be initialized more than once */
   1902 	if (!(sc->sc_firmware_type == WI_SYMBOL && wasenabled))
   1903 		wi_reset(sc);
   1904 
   1905 	/* Program max data length. */
   1906 	WI_SETVAL(WI_RID_MAX_DATALEN, sc->wi_max_data_len);
   1907 
   1908 	/* Enable/disable IBSS creation. */
   1909 	WI_SETVAL(WI_RID_CREATE_IBSS, sc->wi_create_ibss);
   1910 
   1911 	/* Set the port type. */
   1912 	WI_SETVAL(WI_RID_PORTTYPE, sc->wi_ptype);
   1913 
   1914 	/* Program the RTS/CTS threshold. */
   1915 	WI_SETVAL(WI_RID_RTS_THRESH, sc->wi_rts_thresh);
   1916 
   1917 	/* Program the TX rate */
   1918 	WI_SETVAL(WI_RID_TX_RATE, sc->wi_tx_rate);
   1919 
   1920 	/* Access point density */
   1921 	WI_SETVAL(WI_RID_SYSTEM_SCALE, sc->wi_ap_density);
   1922 
   1923 	/* Power Management Enabled */
   1924 	WI_SETVAL(WI_RID_PM_ENABLED, sc->wi_pm_enabled);
   1925 
   1926 	/* Power Managment Max Sleep */
   1927 	WI_SETVAL(WI_RID_MAX_SLEEP, sc->wi_max_sleep);
   1928 
   1929 	/* Roaming type */
   1930 	if (sc->wi_flags & WI_FLAGS_HAS_ROAMING)
   1931 		WI_SETVAL(WI_RID_ROAMING_MODE, sc->wi_roaming);
   1932 
   1933 	/* Specify the network name */
   1934 	wi_write_ssid(sc, WI_RID_DESIRED_SSID, &wreq, &sc->wi_netid);
   1935 
   1936 	/* Specify the IBSS name */
   1937 	if (sc->wi_netid.i_len != 0 &&
   1938 	    (sc->wi_ptype == WI_PORTTYPE_HOSTAP ||
   1939 	     (sc->wi_create_ibss && sc->wi_ptype == WI_PORTTYPE_IBSS)))
   1940 		wi_write_ssid(sc, WI_RID_OWN_SSID, &wreq, &sc->wi_netid);
   1941 	else
   1942 		wi_write_ssid(sc, WI_RID_OWN_SSID, &wreq, &sc->wi_ibssid);
   1943 
   1944 	/* Specify the frequency to use */
   1945 	WI_SETVAL(WI_RID_OWN_CHNL, sc->wi_channel);
   1946 
   1947 	/* Program the nodename. */
   1948 	wi_write_ssid(sc, WI_RID_NODENAME, &wreq, &sc->wi_nodeid);
   1949 
   1950 	/* Set our MAC address. */
   1951 	mac.wi_len = 4;
   1952 	mac.wi_type = WI_RID_MAC_NODE;
   1953 	memcpy(&mac.wi_mac_addr, sc->sc_macaddr, ETHER_ADDR_LEN);
   1954 	wi_write_record(sc, (struct wi_ltv_gen *)&mac);
   1955 
   1956 	/*
   1957 	 * Initialize promisc mode.
   1958 	 *	Being in the Host-AP mode causes a great
   1959 	 *	deal of pain if primisc mode is set.
   1960 	 *	Therefore we avoid confusing the firmware
   1961 	 *	and always reset promisc mode in Host-AP
   1962 	 *	mode.  Host-AP sees all the packets anyway.
   1963 	 */
   1964 	if (sc->wi_ptype != WI_PORTTYPE_HOSTAP &&
   1965 	    (ifp->if_flags & IFF_PROMISC) != 0) {
   1966 		WI_SETVAL(WI_RID_PROMISC, 1);
   1967 	} else {
   1968 		WI_SETVAL(WI_RID_PROMISC, 0);
   1969 	}
   1970 
   1971 	/* Configure WEP. */
   1972 	if (sc->wi_flags & WI_FLAGS_HAS_WEP) {
   1973 		WI_SETVAL(WI_RID_ENCRYPTION, sc->wi_use_wep);
   1974 		WI_SETVAL(WI_RID_TX_CRYPT_KEY, sc->wi_tx_key);
   1975 		sc->wi_keys.wi_len = (sizeof(struct wi_ltv_keys) / 2) + 1;
   1976 		sc->wi_keys.wi_type = WI_RID_DEFLT_CRYPT_KEYS;
   1977 		wi_write_record(sc, (struct wi_ltv_gen *)&sc->wi_keys);
   1978 		if (sc->sc_firmware_type != WI_LUCENT && sc->wi_use_wep) {
   1979 			/*
   1980 			 * ONLY HWB3163 EVAL-CARD Firmware version
   1981 			 * less than 0.8 variant2
   1982 			 *
   1983 			 *   If promiscuous mode disable, Prism2 chip
   1984 			 *  does not work with WEP .
   1985 			 * It is under investigation for details.
   1986 			 * (ichiro (at) netbsd.org)
   1987 			 */
   1988 			if (sc->sc_firmware_type == WI_INTERSIL &&
   1989 			    sc->sc_sta_firmware_ver < 802 ) {
   1990 				/* firm ver < 0.8 variant 2 */
   1991 				WI_SETVAL(WI_RID_PROMISC, 1);
   1992 			}
   1993 			WI_SETVAL(WI_RID_CNFAUTHMODE, sc->wi_authtype);
   1994 		}
   1995 	}
   1996 
   1997 	/* Set multicast filter. */
   1998 	wi_setmulti(sc);
   1999 
   2000 	/* Enable desired port */
   2001 	wi_cmd(sc, WI_CMD_ENABLE | sc->wi_portnum, 0);
   2002 
   2003 	/*  scanning variable is modal, therefore reinit to OFF, in case it was on. */
   2004 	sc->wi_scanning=0;
   2005 	sc->wi_naps=0;
   2006 
   2007 	if ((error = wi_alloc_nicmem(sc,
   2008 	    1518 + sizeof(struct wi_frame) + 8, &id)) != 0) {
   2009 		printf("%s: tx buffer allocation failed\n",
   2010 		    sc->sc_dev.dv_xname);
   2011 		goto out;
   2012 	}
   2013 	sc->wi_tx_data_id = id;
   2014 
   2015 	if ((error = wi_alloc_nicmem(sc,
   2016 	    1518 + sizeof(struct wi_frame) + 8, &id)) != 0) {
   2017 		printf("%s: mgmt. buffer allocation failed\n",
   2018 		    sc->sc_dev.dv_xname);
   2019 		goto out;
   2020 	}
   2021 	sc->wi_tx_mgmt_id = id;
   2022 
   2023 	/* Enable interrupts */
   2024 	CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
   2025 
   2026 	wihap_init(sc);
   2027 
   2028 	ifp->if_flags |= IFF_RUNNING;
   2029 	ifp->if_flags &= ~IFF_OACTIVE;
   2030 
   2031 	callout_reset(&sc->wi_inquire_ch, hz * 60, wi_inquire, sc);
   2032 
   2033  out:
   2034 	if (error) {
   2035 		ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
   2036 		ifp->if_timer = 0;
   2037 		printf("%s: interface not running\n", sc->sc_dev.dv_xname);
   2038 	}
   2039 	return (error);
   2040 }
   2041 
   2042 static const u_int32_t crc32_tab[] = {
   2043 	0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
   2044 	0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
   2045 	0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
   2046 	0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
   2047 	0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
   2048 	0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
   2049 	0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
   2050 	0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
   2051 	0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
   2052 	0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
   2053 	0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
   2054 	0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
   2055 	0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
   2056 	0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
   2057 	0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
   2058 	0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
   2059 	0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
   2060 	0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
   2061 	0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
   2062 	0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
   2063 	0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
   2064 	0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
   2065 	0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
   2066 	0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
   2067 	0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
   2068 	0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
   2069 	0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
   2070 	0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
   2071 	0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
   2072 	0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
   2073 	0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
   2074 	0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
   2075 	0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
   2076 	0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
   2077 	0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
   2078 	0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
   2079 	0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
   2080 	0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
   2081 	0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
   2082 	0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
   2083 	0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
   2084 	0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
   2085 	0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
   2086 	0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
   2087 	0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
   2088 	0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
   2089 	0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
   2090 	0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
   2091 	0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
   2092 	0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
   2093 	0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
   2094 	0x2d02ef8dL
   2095 };
   2096 
   2097 #define RC4STATE 256
   2098 #define RC4KEYLEN 16
   2099 #define RC4SWAP(x,y) \
   2100     do { u_int8_t t = state[x]; state[x] = state[y]; state[y] = t; } while(0)
   2101 
   2102 static void
   2103 wi_do_hostencrypt(struct wi_softc *sc, caddr_t buf, int len)
   2104 {
   2105 	u_int32_t i, crc, klen;
   2106 	u_int8_t state[RC4STATE], key[RC4KEYLEN];
   2107 	u_int8_t x, y, *dat;
   2108 
   2109 	if (!sc->wi_icv_flag) {
   2110 		sc->wi_icv = arc4random();
   2111 		sc->wi_icv_flag++;
   2112 	} else
   2113 		sc->wi_icv++;
   2114 	/*
   2115 	 * Skip 'bad' IVs from Fluhrer/Mantin/Shamir:
   2116 	 * (B, 255, N) with 3 <= B < 8
   2117 	 */
   2118 	if (sc->wi_icv >= 0x03ff00 &&
   2119             (sc->wi_icv & 0xf8ff00) == 0x00ff00)
   2120                 sc->wi_icv += 0x000100;
   2121 
   2122 	/* prepend 24bit IV to tx key, byte order does not matter */
   2123 	key[0] = sc->wi_icv >> 16;
   2124 	key[1] = sc->wi_icv >> 8;
   2125 	key[2] = sc->wi_icv;
   2126 
   2127 	klen = sc->wi_keys.wi_keys[sc->wi_tx_key].wi_keylen +
   2128 	    IEEE80211_WEP_IVLEN;
   2129 	klen = (klen >= RC4KEYLEN) ? RC4KEYLEN : RC4KEYLEN/2;
   2130 	bcopy((char *)&sc->wi_keys.wi_keys[sc->wi_tx_key].wi_keydat,
   2131 	    (char *)key + IEEE80211_WEP_IVLEN, klen - IEEE80211_WEP_IVLEN);
   2132 
   2133 	/* rc4 keysetup */
   2134 	x = y = 0;
   2135 	for (i = 0; i < RC4STATE; i++)
   2136 		state[i] = i;
   2137 	for (i = 0; i < RC4STATE; i++) {
   2138 		y = (key[x] + state[i] + y) % RC4STATE;
   2139 		RC4SWAP(i, y);
   2140 		x = (x + 1) % klen;
   2141 	}
   2142 
   2143 	/* output: IV, tx keyid, rc4(data), rc4(crc32(data)) */
   2144 	dat = buf;
   2145 	dat[0] = key[0];
   2146 	dat[1] = key[1];
   2147 	dat[2] = key[2];
   2148 	dat[3] = sc->wi_tx_key << 6;		/* pad and keyid */
   2149 	dat += 4;
   2150 
   2151 	/* compute rc4 over data, crc32 over data */
   2152 	crc = ~0;
   2153 	x = y = 0;
   2154 	for (i = 0; i < len; i++) {
   2155 		x = (x + 1) % RC4STATE;
   2156 		y = (state[x] + y) % RC4STATE;
   2157 		RC4SWAP(x, y);
   2158 		crc = crc32_tab[(crc ^ dat[i]) & 0xff] ^ (crc >> 8);
   2159 		dat[i] ^= state[(state[x] + state[y]) % RC4STATE];
   2160 	}
   2161 	crc = ~crc;
   2162 	dat += len;
   2163 
   2164 	/* append little-endian crc32 and encrypt */
   2165 	dat[0] = crc;
   2166 	dat[1] = crc >> 8;
   2167 	dat[2] = crc >> 16;
   2168 	dat[3] = crc >> 24;
   2169 	for (i = 0; i < IEEE80211_WEP_CRCLEN; i++) {
   2170 		x = (x + 1) % RC4STATE;
   2171 		y = (state[x] + y) % RC4STATE;
   2172 		RC4SWAP(x, y);
   2173 		dat[i] ^= state[(state[x] + state[y]) % RC4STATE];
   2174 	}
   2175 }
   2176 
   2177 static void
   2178 wi_start(ifp)
   2179 	struct ifnet		*ifp;
   2180 {
   2181 	struct wi_softc		*sc;
   2182 	struct mbuf		*m0;
   2183 	struct wi_frame		tx_frame;
   2184 	struct ether_header	*eh;
   2185 	int			id;
   2186 
   2187 	sc = ifp->if_softc;
   2188 
   2189 	if (ifp->if_flags & IFF_OACTIVE)
   2190 		return;
   2191 
   2192  nextpkt:
   2193 	IFQ_DEQUEUE(&ifp->if_snd, m0);
   2194 	if (m0 == NULL)
   2195 		return;
   2196 
   2197 	memset((char *)&tx_frame, 0, sizeof(tx_frame));
   2198 	tx_frame.wi_frame_ctl = htole16(WI_FTYPE_DATA);
   2199 	id = sc->wi_tx_data_id;
   2200 	eh = mtod(m0, struct ether_header *);
   2201 
   2202 	if (sc->wi_ptype == WI_PORTTYPE_HOSTAP) {
   2203 		if (wihap_check_tx(&sc->wi_hostap_info, eh->ether_dhost,
   2204 				   &tx_frame.wi_tx_rate) == 0 &&
   2205 		    (ifp->if_flags & IFF_PROMISC) == 0) {
   2206 			if (ifp->if_flags & IFF_DEBUG)
   2207 				printf("%s: Host-AP: dropping unassoc "
   2208 				    "dst %s\n", sc->sc_dev.dv_xname,
   2209 				    ether_sprintf(eh->ether_dhost));
   2210 			m_freem(m0);
   2211 			goto nextpkt;
   2212 		}
   2213 	}
   2214 
   2215 	/*
   2216 	 * Use RFC1042 encoding for IP and ARP datagrams,
   2217 	 * 802.3 for anything else.
   2218 	 */
   2219 	if (eh->ether_type == htons(ETHERTYPE_IP) ||
   2220 	    eh->ether_type == htons(ETHERTYPE_ARP) ||
   2221 	    eh->ether_type == htons(ETHERTYPE_REVARP) ||
   2222 	    eh->ether_type == htons(ETHERTYPE_IPV6)) {
   2223 		memcpy((char *)&tx_frame.wi_addr1, (char *)&eh->ether_dhost,
   2224 		    ETHER_ADDR_LEN);
   2225 		if (sc->wi_ptype == WI_PORTTYPE_HOSTAP) {
   2226 			tx_frame.wi_tx_ctl |= htole16(WI_ENC_TX_MGMT);/* XXX */
   2227 			tx_frame.wi_frame_ctl |= htole16(WI_FCTL_FROMDS);
   2228 			if (sc->wi_use_wep)
   2229 				tx_frame.wi_frame_ctl |= htole16(WI_FCTL_WEP);
   2230 			memcpy((char *)&tx_frame.wi_addr2,
   2231 			    (char *)LLADDR(ifp->if_sadl), ETHER_ADDR_LEN);
   2232 			memcpy((char *)&tx_frame.wi_addr3,
   2233 			    (char *)&eh->ether_shost, ETHER_ADDR_LEN);
   2234 		} else
   2235 			memcpy((char *)&tx_frame.wi_addr2,
   2236 			    (char *)&eh->ether_shost, ETHER_ADDR_LEN);
   2237 		memcpy((char *)&tx_frame.wi_dst_addr, (char *)&eh->ether_dhost,
   2238 		    ETHER_ADDR_LEN);
   2239 		memcpy((char *)&tx_frame.wi_src_addr, (char *)&eh->ether_shost,
   2240 		    ETHER_ADDR_LEN);
   2241 
   2242 		tx_frame.wi_dat_len = m0->m_pkthdr.len - WI_SNAPHDR_LEN;
   2243 		tx_frame.wi_dat[0] = htons(WI_SNAP_WORD0);
   2244 		tx_frame.wi_dat[1] = htons(WI_SNAP_WORD1);
   2245 		tx_frame.wi_len = htons(m0->m_pkthdr.len - WI_SNAPHDR_LEN);
   2246 		tx_frame.wi_type = eh->ether_type;
   2247 
   2248 		if (sc->wi_ptype == WI_PORTTYPE_HOSTAP && sc->wi_use_wep) {
   2249 			/* Do host encryption. */
   2250 			memcpy(&sc->wi_txbuf[4], &tx_frame.wi_dat[0], 8);
   2251 
   2252 			m_copydata(m0, sizeof(struct ether_header),
   2253 			    m0->m_pkthdr.len - sizeof(struct ether_header),
   2254 			    (caddr_t)&sc->wi_txbuf[12]);
   2255 
   2256 			wi_do_hostencrypt(sc, (caddr_t)&sc->wi_txbuf,
   2257 			    tx_frame.wi_dat_len);
   2258 
   2259 			tx_frame.wi_dat_len += IEEE80211_WEP_IVLEN +
   2260 			    IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN;
   2261 
   2262 			tx_frame.wi_dat_len = htole16(tx_frame.wi_dat_len);
   2263 
   2264 			wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
   2265 			    sizeof(struct wi_frame));
   2266 			wi_write_data(sc, id, WI_802_11_OFFSET_RAW,
   2267 			    (caddr_t)&sc->wi_txbuf,
   2268 			    (m0->m_pkthdr.len -
   2269 			     sizeof(struct ether_header)) + 18);
   2270 		} else {
   2271 			m_copydata(m0, sizeof(struct ether_header),
   2272 			    m0->m_pkthdr.len - sizeof(struct ether_header),
   2273 			    (caddr_t)&sc->wi_txbuf);
   2274 
   2275 			tx_frame.wi_dat_len = htole16(tx_frame.wi_dat_len);
   2276 
   2277 			wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
   2278 			    sizeof(struct wi_frame));
   2279 			wi_write_data(sc, id, WI_802_11_OFFSET,
   2280 			    (caddr_t)&sc->wi_txbuf,
   2281 			    (m0->m_pkthdr.len -
   2282 			     sizeof(struct ether_header)) + 2);
   2283 		}
   2284 	} else {
   2285 		tx_frame.wi_dat_len = htole16(m0->m_pkthdr.len);
   2286 
   2287 		if (sc->wi_ptype == WI_PORTTYPE_HOSTAP && sc->wi_use_wep) {
   2288 			/* Do host encryption.  (XXX - not implemented) */
   2289 			printf("%s: host encryption not implemented "
   2290 			    "for 802.3\n", sc->sc_dev.dv_xname);
   2291 		} else {
   2292 			m_copydata(m0, 0, m0->m_pkthdr.len,
   2293 			    (caddr_t)&sc->wi_txbuf);
   2294 
   2295 			wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
   2296 			    sizeof(struct wi_frame));
   2297 			wi_write_data(sc, id, WI_802_3_OFFSET,
   2298 			    (caddr_t)&sc->wi_txbuf, m0->m_pkthdr.len + 2);
   2299 		}
   2300 	}
   2301 
   2302 #if NBPFILTER > 0
   2303 	/*
   2304 	 * If there's a BPF listener, bounce a copy of
   2305 	 * this frame to him.
   2306 	 */
   2307 	if (ifp->if_bpf)
   2308 		bpf_mtap(ifp->if_bpf, m0);
   2309 #endif
   2310 
   2311 	m_freem(m0);
   2312 
   2313 	if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id))
   2314 		printf("%s: xmit failed\n", sc->sc_dev.dv_xname);
   2315 
   2316 	ifp->if_flags |= IFF_OACTIVE;
   2317 
   2318 	/*
   2319 	 * Set a timeout in case the chip goes out to lunch.
   2320 	 */
   2321 	ifp->if_timer = 5;
   2322 
   2323 	return;
   2324 }
   2325 
   2326 int
   2327 wi_mgmt_xmit(sc, data, len)
   2328 	struct wi_softc		*sc;
   2329 	caddr_t			data;
   2330 	int			len;
   2331 {
   2332 	struct wi_frame		tx_frame;
   2333 	int			id;
   2334 	struct wi_80211_hdr	*hdr;
   2335 	caddr_t			dptr;
   2336 
   2337 	hdr = (struct wi_80211_hdr *)data;
   2338 	dptr = data + sizeof(struct wi_80211_hdr);
   2339 
   2340 	memset((char *)&tx_frame, 0, sizeof(tx_frame));
   2341 	id = sc->wi_tx_mgmt_id;
   2342 
   2343 	memcpy((char *)&tx_frame.wi_frame_ctl, (char *)hdr,
   2344 	   sizeof(struct wi_80211_hdr));
   2345 
   2346 	tx_frame.wi_tx_ctl = htole16(WI_ENC_TX_MGMT);
   2347 	tx_frame.wi_dat_len = len - sizeof(struct wi_80211_hdr);
   2348 	tx_frame.wi_len = htole16(tx_frame.wi_dat_len);
   2349 
   2350 	tx_frame.wi_dat_len = htole16(tx_frame.wi_dat_len);
   2351 
   2352 	wi_write_data(sc, id, 0, (caddr_t)&tx_frame, sizeof(struct wi_frame));
   2353 	wi_write_data(sc, id, WI_802_11_OFFSET_RAW, dptr,
   2354 	    (len - sizeof(struct wi_80211_hdr)) + 2);
   2355 
   2356 	if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id)) {
   2357 		printf("%s: xmit failed\n", sc->sc_dev.dv_xname);
   2358 		return(EIO);
   2359 	}
   2360 
   2361 	return(0);
   2362 }
   2363 
   2364 static void
   2365 wi_stop(ifp, disable)
   2366 	struct ifnet *ifp;
   2367 {
   2368 	struct wi_softc	*sc = ifp->if_softc;
   2369 
   2370 	wihap_shutdown(sc);
   2371 
   2372 	CSR_WRITE_2(sc, WI_INT_EN, 0);
   2373 	wi_cmd(sc, WI_CMD_DISABLE|sc->wi_portnum, 0);
   2374 
   2375 	callout_stop(&sc->wi_inquire_ch);
   2376 	callout_stop(&sc->wi_scan_sh);
   2377 
   2378 	if (disable) {
   2379 		if (sc->sc_enabled) {
   2380 			if (sc->sc_disable)
   2381 				(*sc->sc_disable)(sc);
   2382 			sc->sc_enabled = 0;
   2383 		}
   2384 	}
   2385 
   2386 	ifp->if_flags &= ~(IFF_OACTIVE | IFF_RUNNING);
   2387 	ifp->if_timer = 0;
   2388 }
   2389 
   2390 static void
   2391 wi_watchdog(ifp)
   2392 	struct ifnet		*ifp;
   2393 {
   2394 	struct wi_softc		*sc;
   2395 
   2396 	sc = ifp->if_softc;
   2397 
   2398 	printf("%s: device timeout\n", sc->sc_dev.dv_xname);
   2399 
   2400 	wi_init(ifp);
   2401 
   2402 	ifp->if_oerrors++;
   2403 
   2404 	return;
   2405 }
   2406 
   2407 void
   2408 wi_shutdown(sc)
   2409 	struct wi_softc *sc;
   2410 {
   2411 	int s;
   2412 
   2413 	s = splnet();
   2414 	if (sc->sc_enabled) {
   2415 		if (sc->sc_disable)
   2416 			(*sc->sc_disable)(sc);
   2417 		sc->sc_enabled = 0;
   2418 	}
   2419 	splx(s);
   2420 }
   2421 
   2422 int
   2423 wi_activate(self, act)
   2424 	struct device *self;
   2425 	enum devact act;
   2426 {
   2427 	struct wi_softc *sc = (struct wi_softc *)self;
   2428 	int rv = 0, s;
   2429 
   2430 	s = splnet();
   2431 	switch (act) {
   2432 	case DVACT_ACTIVATE:
   2433 		rv = EOPNOTSUPP;
   2434 		break;
   2435 
   2436 	case DVACT_DEACTIVATE:
   2437 		if_deactivate(&sc->sc_ethercom.ec_if);
   2438 		break;
   2439 	}
   2440 	splx(s);
   2441 	return (rv);
   2442 }
   2443 
   2444 static void
   2445 wi_get_id(sc)
   2446 	struct wi_softc *sc;
   2447 {
   2448 	struct wi_ltv_ver       ver;
   2449 	struct wi_card_ident	*id;
   2450 
   2451 	/* getting chip identity */
   2452 	memset(&ver, 0, sizeof(ver));
   2453 	ver.wi_type = WI_RID_CARD_ID;
   2454 	ver.wi_len = 5;
   2455 	wi_read_record(sc, (struct wi_ltv_gen *)&ver);
   2456 	printf("%s: using ", sc->sc_dev.dv_xname);
   2457 
   2458 	sc->sc_firmware_type = WI_NOTYPE;
   2459 	for (id = wi_card_ident; id->card_name != NULL; id++) {
   2460 		if (le16toh(ver.wi_ver[0]) == id->card_id) {
   2461 			printf("%s", id->card_name);
   2462 			sc->sc_firmware_type = id->firm_type;
   2463 			break;
   2464 		}
   2465 	}
   2466 	if (sc->sc_firmware_type == WI_NOTYPE) {
   2467 		if (le16toh(ver.wi_ver[0]) & 0x8000) {
   2468 			printf("Unknown PRISM2 chip");
   2469 			sc->sc_firmware_type = WI_INTERSIL;
   2470 		} else {
   2471 			printf("Unknown Lucent chip");
   2472 			sc->sc_firmware_type = WI_LUCENT;
   2473 		}
   2474 	}
   2475 
   2476 	/* get primary firmware version (Only Prism chips) */
   2477 	if (sc->sc_firmware_type != WI_LUCENT) {
   2478 		memset(&ver, 0, sizeof(ver));
   2479 		ver.wi_type = WI_RID_PRI_IDENTITY;
   2480 		ver.wi_len = 5;
   2481 		wi_read_record(sc, (struct wi_ltv_gen *)&ver);
   2482 		LE16TOH(ver.wi_ver[1]);
   2483 		LE16TOH(ver.wi_ver[2]);
   2484 		LE16TOH(ver.wi_ver[3]);
   2485 		sc->sc_pri_firmware_ver = ver.wi_ver[2] * 10000 +
   2486 		    ver.wi_ver[3] * 100 + ver.wi_ver[1];
   2487 	}
   2488 
   2489 	/* get station firmware version */
   2490 	memset(&ver, 0, sizeof(ver));
   2491 	ver.wi_type = WI_RID_STA_IDENTITY;
   2492 	ver.wi_len = 5;
   2493 	wi_read_record(sc, (struct wi_ltv_gen *)&ver);
   2494 	LE16TOH(ver.wi_ver[1]);
   2495 	LE16TOH(ver.wi_ver[2]);
   2496 	LE16TOH(ver.wi_ver[3]);
   2497 	sc->sc_sta_firmware_ver = ver.wi_ver[2] * 10000 +
   2498 	    ver.wi_ver[3] * 100 + ver.wi_ver[1];
   2499 	if (sc->sc_firmware_type == WI_INTERSIL &&
   2500 	    (sc->sc_sta_firmware_ver == 10102 || sc->sc_sta_firmware_ver == 20102)) {
   2501 		struct wi_ltv_str sver;
   2502 		char *p;
   2503 
   2504 		memset(&sver, 0, sizeof(sver));
   2505 		sver.wi_type = WI_RID_SYMBOL_IDENTITY;
   2506 		sver.wi_len = 7;
   2507 		/* value should be the format like "V2.00-11" */
   2508 		if (wi_read_record(sc, (struct wi_ltv_gen *)&sver) == 0 &&
   2509 		    *(p = (char *)sver.wi_str) >= 'A' &&
   2510 		    p[2] == '.' && p[5] == '-' && p[8] == '\0') {
   2511 			sc->sc_firmware_type = WI_SYMBOL;
   2512 			sc->sc_sta_firmware_ver = (p[1] - '0') * 10000 +
   2513 			    (p[3] - '0') * 1000 + (p[4] - '0') * 100 +
   2514 			    (p[6] - '0') * 10 + (p[7] - '0');
   2515 		}
   2516 	}
   2517 
   2518 	printf("\n%s: %s Firmware: ", sc->sc_dev.dv_xname,
   2519 	     sc->sc_firmware_type == WI_LUCENT ? "Lucent" :
   2520 	    (sc->sc_firmware_type == WI_SYMBOL ? "Symbol" : "Intersil"));
   2521 	if (sc->sc_firmware_type != WI_LUCENT)	/* XXX */
   2522 	    printf("Primary (%u.%u.%u), ", sc->sc_pri_firmware_ver / 10000,
   2523 		    (sc->sc_pri_firmware_ver % 10000) / 100,
   2524 		    sc->sc_pri_firmware_ver % 100);
   2525 	printf("Station (%u.%u.%u)\n",
   2526 	    sc->sc_sta_firmware_ver / 10000, (sc->sc_sta_firmware_ver % 10000) / 100,
   2527 	    sc->sc_sta_firmware_ver % 100);
   2528 
   2529 	return;
   2530 }
   2531 
   2532 int
   2533 wi_detach(sc)
   2534 	struct wi_softc *sc;
   2535 {
   2536 	struct ifnet *ifp = sc->sc_ifp;
   2537 	int s;
   2538 
   2539 	if (!sc->sc_attached)
   2540 		return (0);
   2541 
   2542 	s = splnet();
   2543 	callout_stop(&sc->wi_inquire_ch);
   2544 
   2545 	/* Delete all remaining media. */
   2546 	ifmedia_delete_instance(&sc->sc_media, IFM_INST_ANY);
   2547 
   2548 	ether_ifdetach(ifp);
   2549 	if_detach(ifp);
   2550 	if (sc->sc_enabled) {
   2551 		if (sc->sc_disable)
   2552 			(*sc->sc_disable)(sc);
   2553 		sc->sc_enabled = 0;
   2554 	}
   2555 	splx(s);
   2556 	return (0);
   2557 }
   2558 
   2559 void
   2560 wi_power(sc, why)
   2561 	struct wi_softc *sc;
   2562 	int why;
   2563 {
   2564 	int s;
   2565 
   2566 	if (!sc->sc_enabled)
   2567 		return;
   2568 
   2569 	s = splnet();
   2570 	switch (why) {
   2571 	case PWR_SUSPEND:
   2572 	case PWR_STANDBY:
   2573 		wi_stop(sc->sc_ifp, 0);
   2574 		if (sc->sc_enabled) {
   2575 			if (sc->sc_disable)
   2576 				(*sc->sc_disable)(sc);
   2577 		}
   2578 		break;
   2579 	case PWR_RESUME:
   2580 		sc->sc_enabled = 0;
   2581 		wi_init(sc->sc_ifp);
   2582 		(void)wi_intr(sc);
   2583 		break;
   2584 	case PWR_SOFTSUSPEND:
   2585 	case PWR_SOFTSTANDBY:
   2586 	case PWR_SOFTRESUME:
   2587 		break;
   2588 	}
   2589 	splx(s);
   2590 }
   2591 
   2592 static int
   2593 wi_set_ssid(ws, id, len)
   2594 	struct ieee80211_nwid *ws;
   2595 	u_int8_t *id;
   2596 	int len;
   2597 {
   2598 
   2599 	if (len > IEEE80211_NWID_LEN)
   2600 		return (EINVAL);
   2601 	ws->i_len = len;
   2602 	memcpy(ws->i_nwid, id, len);
   2603 	return (0);
   2604 }
   2605 
   2606 static void
   2607 wi_request_fill_ssid(wreq, ws)
   2608 	struct wi_req *wreq;
   2609 	struct ieee80211_nwid *ws;
   2610 {
   2611 	int len = ws->i_len;
   2612 
   2613 	memset(&wreq->wi_val[0], 0, sizeof(wreq->wi_val));
   2614 	wreq->wi_val[0] = htole16(len);
   2615 	wreq->wi_len = roundup(len, 2) / 2 + 2;
   2616 	memcpy(&wreq->wi_val[1], ws->i_nwid, len);
   2617 }
   2618 
   2619 static int
   2620 wi_write_ssid(sc, type, wreq, ws)
   2621 	struct wi_softc *sc;
   2622 	int type;
   2623 	struct wi_req *wreq;
   2624 	struct ieee80211_nwid *ws;
   2625 {
   2626 
   2627 	wreq->wi_type = type;
   2628 	wi_request_fill_ssid(wreq, ws);
   2629 	return (wi_write_record(sc, (struct wi_ltv_gen *)wreq));
   2630 }
   2631 
   2632 static int
   2633 wi_sync_media(sc, ptype, txrate)
   2634 	struct wi_softc *sc;
   2635 	int ptype;
   2636 	int txrate;
   2637 {
   2638 	int media = sc->sc_media.ifm_cur->ifm_media;
   2639 	int options = IFM_OPTIONS(media);
   2640 	int subtype;
   2641 
   2642 	switch (txrate) {
   2643 	case 1:
   2644 		subtype = IFM_IEEE80211_DS1;
   2645 		break;
   2646 	case 2:
   2647 		subtype = IFM_IEEE80211_DS2;
   2648 		break;
   2649 	case 3:
   2650 		subtype = IFM_AUTO;
   2651 		break;
   2652 	case 5:
   2653 		subtype = IFM_IEEE80211_DS5;
   2654 		break;
   2655 	case 11:
   2656 		subtype = IFM_IEEE80211_DS11;
   2657 		break;
   2658 	default:
   2659 		subtype = IFM_MANUAL;		/* Unable to represent */
   2660 		break;
   2661 	}
   2662 
   2663 	options &= ~IFM_OMASK;
   2664 	switch (ptype) {
   2665 	case WI_PORTTYPE_BSS:
   2666 		/* default port type */
   2667 		break;
   2668 	case WI_PORTTYPE_ADHOC:
   2669 		options |= IFM_IEEE80211_ADHOC;
   2670 		break;
   2671 	case WI_PORTTYPE_IBSS:
   2672 		if (sc->wi_create_ibss)
   2673 			options |= IFM_IEEE80211_IBSSMASTER;
   2674 		else
   2675 			options |= IFM_IEEE80211_IBSS;
   2676 		break;
   2677 	default:
   2678 		subtype = IFM_MANUAL;		/* Unable to represent */
   2679 		break;
   2680 	}
   2681 	media = IFM_MAKEWORD(IFM_TYPE(media), subtype, options,
   2682 	    IFM_INST(media));
   2683 	if (ifmedia_match(&sc->sc_media, media, sc->sc_media.ifm_mask) == NULL)
   2684 		return (EINVAL);
   2685 	ifmedia_set(&sc->sc_media, media);
   2686 	sc->wi_ptype = ptype;
   2687 	sc->wi_tx_rate = txrate;
   2688 	return (0);
   2689 }
   2690 
   2691 static int
   2692 wi_media_change(ifp)
   2693 	struct ifnet *ifp;
   2694 {
   2695 	struct wi_softc *sc = ifp->if_softc;
   2696 	int otype = sc->wi_ptype;
   2697 	int orate = sc->wi_tx_rate;
   2698 	int ocreate_ibss = sc->wi_create_ibss;
   2699 
   2700 	sc->wi_create_ibss = 0;
   2701 
   2702 	switch (sc->sc_media.ifm_cur->ifm_media & IFM_OMASK) {
   2703 	case 0:
   2704 		sc->wi_ptype = WI_PORTTYPE_BSS;
   2705 		break;
   2706 	case IFM_IEEE80211_ADHOC:
   2707 		sc->wi_ptype = WI_PORTTYPE_ADHOC;
   2708 		break;
   2709 	case IFM_IEEE80211_HOSTAP:
   2710 		sc->wi_ptype = WI_PORTTYPE_HOSTAP;
   2711 		break;
   2712 	case IFM_IEEE80211_IBSSMASTER:
   2713 	case IFM_IEEE80211_IBSSMASTER|IFM_IEEE80211_IBSS:
   2714 		if ((sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS) == 0)
   2715 			return (EINVAL);
   2716 		sc->wi_create_ibss = 1;
   2717 		/* FALLTHROUGH */
   2718 	case IFM_IEEE80211_IBSS:
   2719 		sc->wi_ptype = WI_PORTTYPE_IBSS;
   2720 		break;
   2721 	default:
   2722 		/* Invalid combination. */
   2723 		sc->wi_create_ibss = ocreate_ibss;
   2724 		return (EINVAL);
   2725 	}
   2726 
   2727 	switch (IFM_SUBTYPE(sc->sc_media.ifm_cur->ifm_media)) {
   2728 	case IFM_IEEE80211_DS1:
   2729 		sc->wi_tx_rate = 1;
   2730 		break;
   2731 	case IFM_IEEE80211_DS2:
   2732 		sc->wi_tx_rate = 2;
   2733 		break;
   2734 	case IFM_AUTO:
   2735 		sc->wi_tx_rate = 3;
   2736 		break;
   2737 	case IFM_IEEE80211_DS5:
   2738 		sc->wi_tx_rate = 5;
   2739 		break;
   2740 	case IFM_IEEE80211_DS11:
   2741 		sc->wi_tx_rate = 11;
   2742 		break;
   2743 	}
   2744 
   2745 	if (sc->sc_enabled != 0) {
   2746 		if (otype != sc->wi_ptype ||
   2747 		    orate != sc->wi_tx_rate ||
   2748 		    ocreate_ibss != sc->wi_create_ibss)
   2749 			wi_init(ifp);
   2750 	}
   2751 
   2752 	ifp->if_baudrate = ifmedia_baudrate(sc->sc_media.ifm_cur->ifm_media);
   2753 
   2754 	return (0);
   2755 }
   2756 
   2757 static void
   2758 wi_media_status(ifp, imr)
   2759 	struct ifnet *ifp;
   2760 	struct ifmediareq *imr;
   2761 {
   2762 	struct wi_softc *sc = ifp->if_softc;
   2763 
   2764 	if (sc->sc_enabled == 0) {
   2765 		imr->ifm_active = IFM_IEEE80211|IFM_NONE;
   2766 		imr->ifm_status = 0;
   2767 		return;
   2768 	}
   2769 
   2770 	imr->ifm_active = sc->sc_media.ifm_cur->ifm_media;
   2771 	imr->ifm_status = IFM_AVALID|IFM_ACTIVE;
   2772 }
   2773 
   2774 static int
   2775 wi_set_nwkey(sc, nwkey)
   2776 	struct wi_softc *sc;
   2777 	struct ieee80211_nwkey *nwkey;
   2778 {
   2779 	int i, error;
   2780 	size_t len;
   2781 	struct wi_req wreq;
   2782 	struct wi_ltv_keys *wk = (struct wi_ltv_keys *)&wreq;
   2783 
   2784 	if ((sc->wi_flags & WI_FLAGS_HAS_WEP) == 0)
   2785 		return ENODEV;
   2786 	if (nwkey->i_defkid <= 0 ||
   2787 	    nwkey->i_defkid > IEEE80211_WEP_NKID)
   2788 		return EINVAL;
   2789 	memcpy(wk, &sc->wi_keys, sizeof(*wk));
   2790 	for (i = 0; i < IEEE80211_WEP_NKID; i++) {
   2791 		if (nwkey->i_key[i].i_keydat == NULL)
   2792 			continue;
   2793 		len = nwkey->i_key[i].i_keylen;
   2794 		if (len > sizeof(wk->wi_keys[i].wi_keydat))
   2795 			return EINVAL;
   2796 		error = copyin(nwkey->i_key[i].i_keydat,
   2797 		    wk->wi_keys[i].wi_keydat, len);
   2798 		if (error)
   2799 			return error;
   2800 		wk->wi_keys[i].wi_keylen = htole16(len);
   2801 	}
   2802 
   2803 	wk->wi_len = (sizeof(*wk) / 2) + 1;
   2804 	wk->wi_type = WI_RID_DEFLT_CRYPT_KEYS;
   2805 	if (sc->sc_enabled != 0) {
   2806 		error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
   2807 		if (error)
   2808 			return error;
   2809 	}
   2810 	error = wi_setdef(sc, &wreq);
   2811 	if (error)
   2812 		return error;
   2813 
   2814 	wreq.wi_len = 2;
   2815 	wreq.wi_type = WI_RID_TX_CRYPT_KEY;
   2816 	wreq.wi_val[0] = htole16(nwkey->i_defkid - 1);
   2817 	if (sc->sc_enabled != 0) {
   2818 		error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
   2819 		if (error)
   2820 			return error;
   2821 	}
   2822 	error = wi_setdef(sc, &wreq);
   2823 	if (error)
   2824 		return error;
   2825 
   2826 	wreq.wi_type = WI_RID_ENCRYPTION;
   2827 	wreq.wi_val[0] = htole16(nwkey->i_wepon);
   2828 	if (sc->sc_enabled != 0) {
   2829 		error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
   2830 		if (error)
   2831 			return error;
   2832 	}
   2833 	error = wi_setdef(sc, &wreq);
   2834 	if (error)
   2835 		return error;
   2836 
   2837 	if (sc->sc_enabled != 0)
   2838 		wi_init(&sc->sc_ethercom.ec_if);
   2839 	return 0;
   2840 }
   2841 
   2842 static int
   2843 wi_get_nwkey(sc, nwkey)
   2844 	struct wi_softc *sc;
   2845 	struct ieee80211_nwkey *nwkey;
   2846 {
   2847 	int i, len, error;
   2848 	struct wi_ltv_keys *wk = &sc->wi_keys;
   2849 
   2850 	if ((sc->wi_flags & WI_FLAGS_HAS_WEP) == 0)
   2851 		return ENODEV;
   2852 	nwkey->i_wepon = sc->wi_use_wep;
   2853 	nwkey->i_defkid = sc->wi_tx_key + 1;
   2854 
   2855 	/* do not show any keys to non-root user */
   2856 	error = suser(curproc->p_ucred, &curproc->p_acflag);
   2857 	for (i = 0; i < IEEE80211_WEP_NKID; i++) {
   2858 		if (nwkey->i_key[i].i_keydat == NULL)
   2859 			continue;
   2860 		/* error holds results of suser() for the first time */
   2861 		if (error)
   2862 			return error;
   2863 		len = le16toh(wk->wi_keys[i].wi_keylen);
   2864 		if (nwkey->i_key[i].i_keylen < len)
   2865 			return ENOSPC;
   2866 		nwkey->i_key[i].i_keylen = len;
   2867 		error = copyout(wk->wi_keys[i].wi_keydat,
   2868 		    nwkey->i_key[i].i_keydat, len);
   2869 		if (error)
   2870 			return error;
   2871 	}
   2872 	return 0;
   2873 }
   2874 
   2875 static int
   2876 wi_set_pm(struct wi_softc *sc, struct ieee80211_power *power)
   2877 {
   2878 
   2879 	sc->wi_pm_enabled = power->i_enabled;
   2880 	sc->wi_max_sleep = power->i_maxsleep;
   2881 
   2882 	if (sc->sc_enabled)
   2883 		return (wi_init(&sc->sc_ethercom.ec_if));
   2884 
   2885 	return (0);
   2886 }
   2887 
   2888 static int
   2889 wi_get_pm(struct wi_softc *sc, struct ieee80211_power *power)
   2890 {
   2891 
   2892 	power->i_enabled = sc->wi_pm_enabled;
   2893 	power->i_maxsleep = sc->wi_max_sleep;
   2894 
   2895 	return (0);
   2896 }
   2897