Home | History | Annotate | Line # | Download | only in ic
wi.c revision 1.82
      1 /*	$NetBSD: wi.c,v 1.82 2002/08/12 16:56:39 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.82 2002/08/12 16:56:39 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, 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, 0, 0);
    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, 0, 0);
    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 			    0, 0);
    817 			break;
    818 		}
    819 		/*
    820 		 * Some cards issue streams of "connected" messages while
    821 		 * trying to find a peer. Don't bother the user with this
    822 		 * unless he is debugging.
    823 		 */
    824 		if (ifp->if_flags & IFF_DEBUG)
    825 			printf("%s: %s\n", sc->sc_dev.dv_xname, msg[t - 1]);
    826 		break;
    827 		}
    828 
    829 	case WI_INFO_ASSOC_STAT: {
    830 		static char *msg[] = {
    831 			"STA Associated",
    832 			"STA Reassociated",
    833 			"STA Disassociated",
    834 			"Association Failure",
    835 			"Authentication Failed"
    836 		};
    837 		if (gen.wi_len != 10)
    838                         break;
    839 		for (i=0; i < gen.wi_len - 1; i++)
    840 			((u_int16_t *)&assoc)[i] = CSR_READ_2(sc, WI_DATA1);
    841 		/* unswap 8 bit data fields: */
    842 		for(j=0;j<sizeof(assoc.wi_assoc_sta)/2;j++)
    843 			HTOLE16(((u_int16_t *)&assoc.wi_assoc_sta[0])[j]);
    844 		for(j=0;j<sizeof(assoc.wi_assoc_osta)/2;j++)
    845 			HTOLE16(((u_int16_t *)&assoc.wi_assoc_osta[0])[j]);
    846 		switch (assoc.wi_assoc_stat) {
    847 		case ASSOC:
    848 		case DISASSOC:
    849 		case ASSOCFAIL:
    850 		case AUTHFAIL:
    851 			printf("%s: %s, AP = %02x:%02x:%02x:%02x:%02x:%02x\n",
    852 				sc->sc_dev.dv_xname,
    853 				msg[assoc.wi_assoc_stat - 1],
    854 				assoc.wi_assoc_sta[0]&0xff, assoc.wi_assoc_sta[1]&0xff,
    855 				assoc.wi_assoc_sta[2]&0xff, assoc.wi_assoc_sta[3]&0xff,
    856 				assoc.wi_assoc_sta[4]&0xff, assoc.wi_assoc_sta[5]&0xff);
    857 			break;
    858 		case REASSOC:
    859 			printf("%s: %s, AP = %02x:%02x:%02x:%02x:%02x:%02x, "
    860 				"OldAP = %02x:%02x:%02x:%02x:%02x:%02x\n",
    861 				sc->sc_dev.dv_xname, msg[assoc.wi_assoc_stat - 1],
    862 				assoc.wi_assoc_sta[0]&0xff, assoc.wi_assoc_sta[1]&0xff,
    863 				assoc.wi_assoc_sta[2]&0xff, assoc.wi_assoc_sta[3]&0xff,
    864 				assoc.wi_assoc_sta[4]&0xff, assoc.wi_assoc_sta[5]&0xff,
    865 				assoc.wi_assoc_osta[0]&0xff, assoc.wi_assoc_osta[1]&0xff,
    866 				assoc.wi_assoc_osta[2]&0xff, assoc.wi_assoc_osta[3]&0xff,
    867 				assoc.wi_assoc_osta[4]&0xff, assoc.wi_assoc_osta[5]&0xff);
    868 			break;
    869 		}
    870 		}
    871 
    872 	default:
    873 #ifdef WI_DEBUG
    874 		printf("%s: got info type: 0x%04x len=0x%04x\n",
    875       sc->sc_dev.dv_xname, gen.wi_type,gen.wi_len);
    876 #endif
    877 #if 0
    878 		for (i = 0; i < gen.wi_len; i++) {
    879 			t = CSR_READ_2(sc, WI_DATA1);
    880 			printf("[0x%02x] = 0x%04x\n", i, t);
    881 		}
    882 #endif
    883 		break;
    884 	}
    885 }
    886 
    887 int wi_intr(arg)
    888 	void *arg;
    889 {
    890 	struct wi_softc		*sc = arg;
    891 	struct ifnet		*ifp;
    892 	u_int16_t		status;
    893 
    894 	if (sc->sc_enabled == 0 ||
    895 	    (sc->sc_dev.dv_flags & DVF_ACTIVE) == 0 ||
    896 	    (sc->sc_ethercom.ec_if.if_flags & IFF_RUNNING) == 0)
    897 		return (0);
    898 
    899 	ifp = &sc->sc_ethercom.ec_if;
    900 
    901 	if (!(ifp->if_flags & IFF_UP)) {
    902 		CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
    903 		CSR_WRITE_2(sc, WI_INT_EN, 0);
    904 		return 1;
    905 	}
    906 
    907 	/* Disable interrupts. */
    908 	CSR_WRITE_2(sc, WI_INT_EN, 0);
    909 
    910 	status = CSR_READ_2(sc, WI_EVENT_STAT);
    911 	CSR_WRITE_2(sc, WI_EVENT_ACK, ~WI_INTRS);
    912 
    913 	if (status & WI_EV_RX) {
    914 		wi_rxeof(sc);
    915 		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
    916 	}
    917 
    918 	if (status & WI_EV_TX) {
    919 		wi_txeof(sc, status);
    920 		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX);
    921 	}
    922 
    923 	if (status & WI_EV_ALLOC) {
    924 		int			id;
    925 		id = CSR_READ_2(sc, WI_ALLOC_FID);
    926 		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
    927 		if (id == sc->wi_tx_data_id)
    928 			wi_txeof(sc, status);
    929 	}
    930 
    931 	if (status & WI_EV_INFO) {
    932 		wi_update_stats(sc);
    933 		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO);
    934 	}
    935 
    936 	if (status & WI_EV_TX_EXC) {
    937 		wi_txeof(sc, status);
    938 		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX_EXC);
    939 	}
    940 
    941 	if (status & WI_EV_INFO_DROP) {
    942 		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO_DROP);
    943 	}
    944 
    945 	/* Re-enable interrupts. */
    946 	CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
    947 
    948 	if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
    949 		wi_start(ifp);
    950 
    951 	return 1;
    952 }
    953 
    954 /* Must be called at proper protection level! */
    955 static int
    956 wi_cmd(sc, cmd, val0, val1, val2)
    957 	struct wi_softc		*sc;
    958 	int			cmd;
    959 	int			val0;
    960 	int			val1;
    961 	int			val2;
    962 {
    963 	int			i, s = 0;
    964 
    965 	/* wait for the busy bit to clear */
    966 	for (i = 0; i < WI_TIMEOUT; i++) {
    967 		if (!(CSR_READ_2(sc, WI_COMMAND) & WI_CMD_BUSY))
    968 			break;
    969 	}
    970 
    971 	if (i == WI_TIMEOUT) {
    972 		printf("%s: wi_cmd: BUSY did not clear, cmd=0x%x\n",
    973 			sc->sc_dev.dv_xname, cmd);
    974 		return EIO;
    975 	}
    976 
    977 	CSR_WRITE_2(sc, WI_PARAM0, val0);
    978 	CSR_WRITE_2(sc, WI_PARAM1, val1);
    979 	CSR_WRITE_2(sc, WI_PARAM2, val2);
    980 	CSR_WRITE_2(sc, WI_COMMAND, cmd);
    981 
    982 	/* wait for the cmd completed bit */
    983 	for (i = 0; i < WI_TIMEOUT; i++) {
    984 		if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_CMD)
    985 			break;
    986 		DELAY(1);
    987 	}
    988 
    989 	/* Ack the command */
    990 	CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_CMD);
    991 
    992 	s = CSR_READ_2(sc, WI_STATUS);
    993 	if (s & WI_STAT_CMD_RESULT)
    994 		return(EIO);
    995 
    996 	if (i == WI_TIMEOUT) {
    997 		if (!sc->wi_scanning)
    998 		    printf("%s: command timed out, cmd=0x%x\n",
    999 			sc->sc_dev.dv_xname, cmd);
   1000 		return(ETIMEDOUT);
   1001 	}
   1002 
   1003 	return(0);
   1004 }
   1005 
   1006 static void
   1007 wi_reset(sc)
   1008 	struct wi_softc		*sc;
   1009 {
   1010 
   1011 	DELAY(100*1000); /* 100 m sec */
   1012 	if (wi_cmd(sc, WI_CMD_INI, 0, 0, 0))
   1013 		printf("%s: init failed\n", sc->sc_dev.dv_xname);
   1014 	CSR_WRITE_2(sc, WI_INT_EN, 0);
   1015 	CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
   1016 
   1017 	/* Calibrate timer. */
   1018 	WI_SETVAL(WI_RID_TICK_TIME, 8);
   1019 
   1020 	return;
   1021 }
   1022 
   1023 /*
   1024  * Read an LTV record from the NIC.
   1025  */
   1026 static int wi_read_record(sc, ltv)
   1027 	struct wi_softc		*sc;
   1028 	struct wi_ltv_gen	*ltv;
   1029 {
   1030 	u_int16_t		*ptr;
   1031 	int			len, code;
   1032 	struct wi_ltv_gen	*oltv, p2ltv;
   1033 
   1034 	if (sc->sc_firmware_type != WI_LUCENT) {
   1035 		oltv = ltv;
   1036 		switch (ltv->wi_type) {
   1037 		case WI_RID_ENCRYPTION:
   1038 			p2ltv.wi_type = WI_RID_P2_ENCRYPTION;
   1039 			p2ltv.wi_len = 2;
   1040 			ltv = &p2ltv;
   1041 			break;
   1042 		case WI_RID_TX_CRYPT_KEY:
   1043 			p2ltv.wi_type = WI_RID_P2_TX_CRYPT_KEY;
   1044 			p2ltv.wi_len = 2;
   1045 			ltv = &p2ltv;
   1046 			break;
   1047 		case WI_RID_ROAMING_MODE:
   1048 			if (sc->sc_firmware_type == WI_INTERSIL)
   1049 				break;
   1050 			/* not supported */
   1051 			ltv->wi_len = 1;
   1052 			return 0;
   1053 		case WI_RID_MICROWAVE_OVEN:
   1054 			/* not supported */
   1055 			ltv->wi_len = 1;
   1056 			return 0;
   1057 		}
   1058 	}
   1059 
   1060 	/* Tell the NIC to enter record read mode. */
   1061 	if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_READ, ltv->wi_type, 0, 0))
   1062 		return(EIO);
   1063 
   1064 	/* Seek to the record. */
   1065 	if (wi_seek(sc, ltv->wi_type, 0, WI_BAP1))
   1066 		return(EIO);
   1067 
   1068 	/*
   1069 	 * Read the length and record type and make sure they
   1070 	 * match what we expect (this verifies that we have enough
   1071 	 * room to hold all of the returned data).
   1072 	 */
   1073 	len = CSR_READ_2(sc, WI_DATA1);
   1074 	if (len > ltv->wi_len)
   1075 		return(ENOSPC);
   1076 	code = CSR_READ_2(sc, WI_DATA1);
   1077 	if (code != ltv->wi_type)
   1078 		return(EIO);
   1079 
   1080 	ltv->wi_len = len;
   1081 	ltv->wi_type = code;
   1082 
   1083 	/* Now read the data. */
   1084 	ptr = &ltv->wi_val;
   1085 	if (ltv->wi_len > 1)
   1086 		CSR_READ_MULTI_STREAM_2(sc, WI_DATA1, ptr, ltv->wi_len - 1);
   1087 
   1088 	if (ltv->wi_type == WI_RID_PORTTYPE &&
   1089 	    sc->wi_ptype == WI_PORTTYPE_IBSS &&
   1090 	    ltv->wi_val == sc->wi_ibss_port) {
   1091 		/*
   1092 		 * Convert vendor IBSS port type to WI_PORTTYPE_IBSS.
   1093 		 * Since Lucent uses port type 1 for BSS *and* IBSS we
   1094 		 * have to rely on wi_ptype to distinguish this for us.
   1095 		 */
   1096 		ltv->wi_val = htole16(WI_PORTTYPE_IBSS);
   1097 	} else if (sc->sc_firmware_type != WI_LUCENT) {
   1098 		int v;
   1099 
   1100 		switch (oltv->wi_type) {
   1101 		case WI_RID_TX_RATE:
   1102 		case WI_RID_CUR_TX_RATE:
   1103 			switch (le16toh(ltv->wi_val)) {
   1104 			case 1: v = 1; break;
   1105 			case 2: v = 2; break;
   1106 			case 3:	v = 6; break;
   1107 			case 4: v = 5; break;
   1108 			case 7: v = 7; break;
   1109 			case 8: v = 11; break;
   1110 			case 15: v = 3; break;
   1111 			default: v = 0x100 + le16toh(ltv->wi_val); break;
   1112 			}
   1113 			oltv->wi_val = htole16(v);
   1114 			break;
   1115 		case WI_RID_ENCRYPTION:
   1116 			oltv->wi_len = 2;
   1117 			if (le16toh(ltv->wi_val) & 0x01)
   1118 				oltv->wi_val = htole16(1);
   1119 			else
   1120 				oltv->wi_val = htole16(0);
   1121 			break;
   1122 		case WI_RID_TX_CRYPT_KEY:
   1123 			oltv->wi_len = 2;
   1124 			oltv->wi_val = ltv->wi_val;
   1125 			break;
   1126 		case WI_RID_CNFAUTHMODE:
   1127 			oltv->wi_len = 2;
   1128 			if (le16toh(ltv->wi_val) & 0x01)
   1129 				oltv->wi_val = htole16(1);
   1130 			else if (le16toh(ltv->wi_val) & 0x02)
   1131 				oltv->wi_val = htole16(2);
   1132 			break;
   1133 		}
   1134 	}
   1135 
   1136 	return(0);
   1137 }
   1138 
   1139 /*
   1140  * Same as read, except we inject data instead of reading it.
   1141  */
   1142 static int wi_write_record(sc, ltv)
   1143 	struct wi_softc		*sc;
   1144 	struct wi_ltv_gen	*ltv;
   1145 {
   1146 	u_int16_t		*ptr;
   1147 	int			i;
   1148 	struct wi_ltv_gen	p2ltv;
   1149 
   1150 	if (ltv->wi_type == WI_RID_PORTTYPE &&
   1151 	    ltv->wi_val == le16toh(WI_PORTTYPE_IBSS)) {
   1152 		/* Convert WI_PORTTYPE_IBSS to vendor IBSS port type. */
   1153 		p2ltv.wi_type = WI_RID_PORTTYPE;
   1154 		p2ltv.wi_len = 2;
   1155 		p2ltv.wi_val = sc->wi_ibss_port;
   1156 		ltv = &p2ltv;
   1157 	} else if (sc->sc_firmware_type != WI_LUCENT) {
   1158 		int v;
   1159 
   1160 		switch (ltv->wi_type) {
   1161 		case WI_RID_TX_RATE:
   1162 			p2ltv.wi_type = WI_RID_TX_RATE;
   1163 			p2ltv.wi_len = 2;
   1164 			switch (le16toh(ltv->wi_val)) {
   1165 			case 1: v = 1; break;
   1166 			case 2: v = 2; break;
   1167 			case 3:	v = 15; break;
   1168 			case 5: v = 4; break;
   1169 			case 6: v = 3; break;
   1170 			case 7: v = 7; break;
   1171 			case 11: v = 8; break;
   1172 			default: return EINVAL;
   1173 			}
   1174 			p2ltv.wi_val = htole16(v);
   1175 			ltv = &p2ltv;
   1176 			break;
   1177 		case WI_RID_ENCRYPTION:
   1178 			p2ltv.wi_type = WI_RID_P2_ENCRYPTION;
   1179 			p2ltv.wi_len = 2;
   1180 			if (le16toh(ltv->wi_val)) {
   1181 				uint16_t val = PRIVACY_INVOKED;
   1182 				/*
   1183 				 * If using shared key WEP we must set the
   1184 				 * EXCLUDE_UNENCRYPTED bit.  Symbol cards
   1185 				 * need this bit even when not using shared
   1186 				 * key.  We can't just test for
   1187 				 * IEEE80211_AUTH_SHARED since Symbol cards
   1188 				 * have 2 shared key modes.
   1189 				 */
   1190 				if (sc->wi_authtype != IEEE80211_AUTH_OPEN ||
   1191 				    sc->sc_firmware_type == WI_SYMBOL)
   1192 					val |= EXCLUDE_UNENCRYPTED;
   1193 				/* Tx encryption is broken in Host-AP mode. */
   1194 				if (sc->wi_ptype == WI_PORTTYPE_HOSTAP)
   1195 					val |= HOST_ENCRYPT;
   1196 				p2ltv.wi_val = htole16(val);
   1197 			} else
   1198 				p2ltv.wi_val =
   1199 				    htole16(HOST_ENCRYPT | HOST_DECRYPT);
   1200 			ltv = &p2ltv;
   1201 			break;
   1202 		case WI_RID_TX_CRYPT_KEY:
   1203 			p2ltv.wi_type = WI_RID_P2_TX_CRYPT_KEY;
   1204 			p2ltv.wi_len = 2;
   1205 			p2ltv.wi_val = ltv->wi_val;
   1206 			ltv = &p2ltv;
   1207 			break;
   1208 		case WI_RID_DEFLT_CRYPT_KEYS:
   1209 		    {
   1210 			int error;
   1211 			int keylen;
   1212 			struct wi_ltv_str	ws;
   1213 			struct wi_ltv_keys	*wk = (struct wi_ltv_keys *)ltv;
   1214 
   1215 			keylen = le16toh(wk->wi_keys[sc->wi_tx_key].wi_keylen);
   1216 
   1217 			for (i = 0; i < 4; i++) {
   1218 				memset(&ws, 0, sizeof(ws));
   1219 				ws.wi_len = (keylen > 5) ? 8 : 4;
   1220 				ws.wi_type = WI_RID_P2_CRYPT_KEY0 + i;
   1221 				memcpy(ws.wi_str,
   1222 					&wk->wi_keys[i].wi_keydat, keylen);
   1223 				error = wi_write_record(sc,
   1224 					(struct wi_ltv_gen *)&ws);
   1225 				if (error)
   1226 					return error;
   1227 			}
   1228 			return 0;
   1229 		    }
   1230 		case WI_RID_CNFAUTHMODE:
   1231 			p2ltv.wi_type = WI_RID_CNFAUTHMODE;
   1232 			p2ltv.wi_len = 2;
   1233 			if (le16toh(ltv->wi_val) == 1)
   1234 				p2ltv.wi_val = htole16(0x01);
   1235 			else if (le16toh(ltv->wi_val) == 2)
   1236 				p2ltv.wi_val = htole16(0x02);
   1237 			ltv = &p2ltv;
   1238 			break;
   1239 
   1240 		case WI_RID_ROAMING_MODE:
   1241 			if (sc->sc_firmware_type == WI_INTERSIL)
   1242 				break;
   1243 			/* not supported */
   1244 			return 0;
   1245 
   1246 		case WI_RID_MICROWAVE_OVEN:
   1247 			/* not supported */
   1248 			return 0;
   1249 		}
   1250 	}
   1251 
   1252 	if (wi_seek(sc, ltv->wi_type, 0, WI_BAP1))
   1253 		return(EIO);
   1254 
   1255 	CSR_WRITE_2(sc, WI_DATA1, ltv->wi_len);
   1256 	CSR_WRITE_2(sc, WI_DATA1, ltv->wi_type);
   1257 
   1258 	/* Write data */
   1259 	ptr = &ltv->wi_val;
   1260 	if (ltv->wi_len > 1)
   1261 		CSR_WRITE_MULTI_STREAM_2(sc, WI_DATA1, ptr, ltv->wi_len - 1);
   1262 
   1263 	if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_WRITE, ltv->wi_type, 0, 0))
   1264 		return(EIO);
   1265 
   1266 	return(0);
   1267 }
   1268 
   1269 static int wi_seek(sc, id, off, chan)
   1270 	struct wi_softc		*sc;
   1271 	int			id, off, chan;
   1272 {
   1273 	int			i;
   1274 	int			selreg, offreg;
   1275 	int 			status;
   1276 
   1277 	switch (chan) {
   1278 	case WI_BAP0:
   1279 		selreg = WI_SEL0;
   1280 		offreg = WI_OFF0;
   1281 		break;
   1282 	case WI_BAP1:
   1283 		selreg = WI_SEL1;
   1284 		offreg = WI_OFF1;
   1285 		break;
   1286 	default:
   1287 		printf("%s: invalid data path: %x\n",
   1288 		    sc->sc_dev.dv_xname, chan);
   1289 		return(EIO);
   1290 	}
   1291 
   1292 	CSR_WRITE_2(sc, selreg, id);
   1293 	CSR_WRITE_2(sc, offreg, off);
   1294 
   1295 	for (i = 0; i < WI_TIMEOUT; i++) {
   1296 	  	status = CSR_READ_2(sc, offreg);
   1297 		if (!(status & (WI_OFF_BUSY|WI_OFF_ERR)))
   1298 			break;
   1299 	}
   1300 
   1301 	if (i == WI_TIMEOUT) {
   1302 		printf("%s: timeout in wi_seek to %x/%x; last status %x\n",
   1303 		       sc->sc_dev.dv_xname, id, off, status);
   1304 		return(ETIMEDOUT);
   1305 	}
   1306 	return(0);
   1307 }
   1308 
   1309 static int wi_read_data(sc, id, off, buf, len)
   1310 	struct wi_softc		*sc;
   1311 	int			id, off;
   1312 	caddr_t			buf;
   1313 	int			len;
   1314 {
   1315 	u_int16_t		*ptr;
   1316 
   1317 	if (wi_seek(sc, id, off, WI_BAP1))
   1318 		return(EIO);
   1319 
   1320 	ptr = (u_int16_t *)buf;
   1321 	CSR_READ_MULTI_STREAM_2(sc, WI_DATA1, ptr, len / 2);
   1322 
   1323 	return(0);
   1324 }
   1325 
   1326 /*
   1327  * According to the comments in the HCF Light code, there is a bug in
   1328  * the Hermes (or possibly in certain Hermes firmware revisions) where
   1329  * the chip's internal autoincrement counter gets thrown off during
   1330  * data writes: the autoincrement is missed, causing one data word to
   1331  * be overwritten and subsequent words to be written to the wrong memory
   1332  * locations. The end result is that we could end up transmitting bogus
   1333  * frames without realizing it. The workaround for this is to write a
   1334  * couple of extra guard words after the end of the transfer, then
   1335  * attempt to read then back. If we fail to locate the guard words where
   1336  * we expect them, we preform the transfer over again.
   1337  */
   1338 static int wi_write_data(sc, id, off, buf, len)
   1339 	struct wi_softc		*sc;
   1340 	int			id, off;
   1341 	caddr_t			buf;
   1342 	int			len;
   1343 {
   1344 	u_int16_t		*ptr;
   1345 
   1346 #ifdef WI_HERMES_AUTOINC_WAR
   1347 again:
   1348 #endif
   1349 
   1350 	if (wi_seek(sc, id, off, WI_BAP0))
   1351 		return(EIO);
   1352 
   1353 	ptr = (u_int16_t *)buf;
   1354 	CSR_WRITE_MULTI_STREAM_2(sc, WI_DATA0, ptr, len / 2);
   1355 
   1356 #ifdef WI_HERMES_AUTOINC_WAR
   1357 	CSR_WRITE_2(sc, WI_DATA0, 0x1234);
   1358 	CSR_WRITE_2(sc, WI_DATA0, 0x5678);
   1359 
   1360 	if (wi_seek(sc, id, off + len, WI_BAP0))
   1361 		return(EIO);
   1362 
   1363 	if (CSR_READ_2(sc, WI_DATA0) != 0x1234 ||
   1364 	    CSR_READ_2(sc, WI_DATA0) != 0x5678)
   1365 		goto again;
   1366 #endif
   1367 
   1368 	return(0);
   1369 }
   1370 
   1371 /*
   1372  * Allocate a region of memory inside the NIC and zero
   1373  * it out.
   1374  */
   1375 static int wi_alloc_nicmem(sc, len, id)
   1376 	struct wi_softc		*sc;
   1377 	int			len;
   1378 	int			*id;
   1379 {
   1380 	int			i;
   1381 
   1382 	if (wi_cmd(sc, WI_CMD_ALLOC_MEM, len, 0, 0)) {
   1383 		printf("%s: failed to allocate %d bytes on NIC\n",
   1384 		    sc->sc_dev.dv_xname, len);
   1385 		return(ENOMEM);
   1386 	}
   1387 
   1388 	for (i = 0; i < WI_TIMEOUT; i++) {
   1389 		if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_ALLOC)
   1390 			break;
   1391 	}
   1392 
   1393 	if (i == WI_TIMEOUT) {
   1394 		printf("%s: TIMED OUT in alloc\n", sc->sc_dev.dv_xname);
   1395 		return(ETIMEDOUT);
   1396 	}
   1397 
   1398 	*id = CSR_READ_2(sc, WI_ALLOC_FID);
   1399 	CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
   1400 
   1401 	if (wi_seek(sc, *id, 0, WI_BAP0)) {
   1402 		printf("%s: seek failed in alloc\n", sc->sc_dev.dv_xname);
   1403 		return(EIO);
   1404 	}
   1405 
   1406 	for (i = 0; i < len / 2; i++)
   1407 		CSR_WRITE_2(sc, WI_DATA0, 0);
   1408 
   1409 	return(0);
   1410 }
   1411 
   1412 static void wi_setmulti(sc)
   1413 	struct wi_softc		*sc;
   1414 {
   1415 	struct ifnet		*ifp;
   1416 	int			i = 0;
   1417 	struct wi_ltv_mcast	mcast;
   1418 	struct ether_multi *enm;
   1419 	struct ether_multistep estep;
   1420 	struct ethercom *ec = &sc->sc_ethercom;
   1421 
   1422 	ifp = &sc->sc_ethercom.ec_if;
   1423 
   1424 	if ((ifp->if_flags & IFF_PROMISC) != 0) {
   1425 allmulti:
   1426 		ifp->if_flags |= IFF_ALLMULTI;
   1427 		memset((char *)&mcast, 0, sizeof(mcast));
   1428 		mcast.wi_type = WI_RID_MCAST_LIST;
   1429 		mcast.wi_len = ((ETHER_ADDR_LEN / 2) * 16) + 1;
   1430 
   1431 		wi_write_record(sc, (struct wi_ltv_gen *)&mcast);
   1432 		return;
   1433 	}
   1434 
   1435 	i = 0;
   1436 	ETHER_FIRST_MULTI(estep, ec, enm);
   1437 	while (enm != NULL) {
   1438 		/* Punt on ranges or too many multicast addresses. */
   1439 		if (memcmp(enm->enm_addrlo, enm->enm_addrhi,
   1440 		    ETHER_ADDR_LEN) != 0 ||
   1441 		    i >= 16)
   1442 			goto allmulti;
   1443 
   1444 		memcpy((char *)&mcast.wi_mcast[i], enm->enm_addrlo,
   1445 		    ETHER_ADDR_LEN);
   1446 		i++;
   1447 		ETHER_NEXT_MULTI(estep, enm);
   1448 	}
   1449 
   1450 	ifp->if_flags &= ~IFF_ALLMULTI;
   1451 	mcast.wi_type = WI_RID_MCAST_LIST;
   1452 	mcast.wi_len = ((ETHER_ADDR_LEN / 2) * i) + 1;
   1453 	wi_write_record(sc, (struct wi_ltv_gen *)&mcast);
   1454 }
   1455 
   1456 static int
   1457 wi_setdef(sc, wreq)
   1458 	struct wi_softc		*sc;
   1459 	struct wi_req		*wreq;
   1460 {
   1461 	struct sockaddr_dl	*sdl;
   1462 	struct ifnet		*ifp;
   1463 	int error = 0;
   1464 
   1465 	ifp = &sc->sc_ethercom.ec_if;
   1466 
   1467 	switch(wreq->wi_type) {
   1468 	case WI_RID_MAC_NODE:
   1469 		sdl = (struct sockaddr_dl *)ifp->if_sadl;
   1470 		memcpy((char *)&sc->sc_macaddr, (char *)&wreq->wi_val,
   1471 		    ETHER_ADDR_LEN);
   1472 		memcpy(LLADDR(sdl), (char *)&wreq->wi_val, ETHER_ADDR_LEN);
   1473 		break;
   1474 	case WI_RID_PORTTYPE:
   1475 		error = wi_sync_media(sc, le16toh(wreq->wi_val[0]),
   1476 		    sc->wi_tx_rate);
   1477 		break;
   1478 	case WI_RID_TX_RATE:
   1479 		error = wi_sync_media(sc, sc->wi_ptype,
   1480 		    le16toh(wreq->wi_val[0]));
   1481 		break;
   1482 	case WI_RID_MAX_DATALEN:
   1483 		sc->wi_max_data_len = le16toh(wreq->wi_val[0]);
   1484 		break;
   1485 	case WI_RID_RTS_THRESH:
   1486 		sc->wi_rts_thresh = le16toh(wreq->wi_val[0]);
   1487 		break;
   1488 	case WI_RID_SYSTEM_SCALE:
   1489 		sc->wi_ap_density = le16toh(wreq->wi_val[0]);
   1490 		break;
   1491 	case WI_RID_CREATE_IBSS:
   1492 		sc->wi_create_ibss = le16toh(wreq->wi_val[0]);
   1493 		error = wi_sync_media(sc, sc->wi_ptype, sc->wi_tx_rate);
   1494 		break;
   1495 	case WI_RID_OWN_CHNL:
   1496 		sc->wi_channel = le16toh(wreq->wi_val[0]);
   1497 		break;
   1498 	case WI_RID_NODENAME:
   1499 		error = wi_set_ssid(&sc->wi_nodeid,
   1500 		    (u_int8_t *)&wreq->wi_val[1], le16toh(wreq->wi_val[0]));
   1501 		break;
   1502 	case WI_RID_DESIRED_SSID:
   1503 		error = wi_set_ssid(&sc->wi_netid,
   1504 		    (u_int8_t *)&wreq->wi_val[1], le16toh(wreq->wi_val[0]));
   1505 		break;
   1506 	case WI_RID_OWN_SSID:
   1507 		error = wi_set_ssid(&sc->wi_ibssid,
   1508 		    (u_int8_t *)&wreq->wi_val[1], le16toh(wreq->wi_val[0]));
   1509 		break;
   1510 	case WI_RID_PM_ENABLED:
   1511 		sc->wi_pm_enabled = le16toh(wreq->wi_val[0]);
   1512 		break;
   1513 	case WI_RID_MICROWAVE_OVEN:
   1514 		sc->wi_mor_enabled = le16toh(wreq->wi_val[0]);
   1515 		break;
   1516 	case WI_RID_MAX_SLEEP:
   1517 		sc->wi_max_sleep = le16toh(wreq->wi_val[0]);
   1518 		break;
   1519 	case WI_RID_CNFAUTHMODE:
   1520 		sc->wi_authtype = le16toh(wreq->wi_val[0]);
   1521 		break;
   1522 	case WI_RID_ROAMING_MODE:
   1523 		sc->wi_roaming = le16toh(wreq->wi_val[0]);
   1524 		break;
   1525 	case WI_RID_ENCRYPTION:
   1526 		sc->wi_use_wep = le16toh(wreq->wi_val[0]);
   1527 		break;
   1528 	case WI_RID_TX_CRYPT_KEY:
   1529 		sc->wi_tx_key = le16toh(wreq->wi_val[0]);
   1530 		break;
   1531 	case WI_RID_DEFLT_CRYPT_KEYS:
   1532 		memcpy((char *)&sc->wi_keys, (char *)wreq,
   1533 		    sizeof(struct wi_ltv_keys));
   1534 		break;
   1535 	default:
   1536 		error = EINVAL;
   1537 		break;
   1538 	}
   1539 
   1540 	return (error);
   1541 }
   1542 
   1543 static int
   1544 wi_getdef(sc, wreq)
   1545 	struct wi_softc		*sc;
   1546 	struct wi_req		*wreq;
   1547 {
   1548 	struct sockaddr_dl	*sdl;
   1549 	struct ifnet		*ifp;
   1550 	int error = 0;
   1551 
   1552 	ifp = &sc->sc_ethercom.ec_if;
   1553 
   1554 	wreq->wi_len = 2;			/* XXX */
   1555 	switch (wreq->wi_type) {
   1556 	case WI_RID_MAC_NODE:
   1557 		wreq->wi_len += ETHER_ADDR_LEN / 2 - 1;
   1558 		sdl = (struct sockaddr_dl *)ifp->if_sadl;
   1559 		memcpy(&wreq->wi_val, &sc->sc_macaddr, ETHER_ADDR_LEN);
   1560 		memcpy(&wreq->wi_val, LLADDR(sdl), ETHER_ADDR_LEN);
   1561 		break;
   1562 	case WI_RID_PORTTYPE:
   1563 		wreq->wi_val[0] = htole16(sc->wi_ptype);
   1564 		break;
   1565 	case WI_RID_TX_RATE:
   1566 		wreq->wi_val[0] = htole16(sc->wi_tx_rate);
   1567 		break;
   1568 	case WI_RID_MAX_DATALEN:
   1569 		wreq->wi_val[0] = htole16(sc->wi_max_data_len);
   1570 		break;
   1571 	case WI_RID_RTS_THRESH:
   1572 		wreq->wi_val[0] = htole16(sc->wi_rts_thresh);
   1573 		break;
   1574 	case WI_RID_SYSTEM_SCALE:
   1575 		wreq->wi_val[0] = htole16(sc->wi_ap_density);
   1576 		break;
   1577 	case WI_RID_CREATE_IBSS:
   1578 		wreq->wi_val[0] = htole16(sc->wi_create_ibss);
   1579 		break;
   1580 	case WI_RID_OWN_CHNL:
   1581 		wreq->wi_val[0] = htole16(sc->wi_channel);
   1582 		break;
   1583 	case WI_RID_NODENAME:
   1584 		wi_request_fill_ssid(wreq, &sc->wi_nodeid);
   1585 		break;
   1586 	case WI_RID_DESIRED_SSID:
   1587 		wi_request_fill_ssid(wreq, &sc->wi_netid);
   1588 		break;
   1589 	case WI_RID_OWN_SSID:
   1590 		wi_request_fill_ssid(wreq, &sc->wi_ibssid);
   1591 		break;
   1592 	case WI_RID_PM_ENABLED:
   1593 		wreq->wi_val[0] = htole16(sc->wi_pm_enabled);
   1594 		break;
   1595 	case WI_RID_MICROWAVE_OVEN:
   1596 		wreq->wi_val[0] = htole16(sc->wi_mor_enabled);
   1597 		break;
   1598 	case WI_RID_MAX_SLEEP:
   1599 		wreq->wi_val[0] = htole16(sc->wi_max_sleep);
   1600 		break;
   1601 	case WI_RID_CNFAUTHMODE:
   1602 		wreq->wi_val[0] = htole16(sc->wi_authtype);
   1603 		break;
   1604 	case WI_RID_ROAMING_MODE:
   1605 		wreq->wi_val[0] = htole16(sc->wi_roaming);
   1606 		break;
   1607 	case WI_RID_WEP_AVAIL:
   1608 		wreq->wi_val[0] = (sc->wi_flags & WI_FLAGS_HAS_WEP) ?
   1609 		    htole16(1) : htole16(0);
   1610 		break;
   1611 	case WI_RID_ENCRYPTION:
   1612 		wreq->wi_val[0] = htole16(sc->wi_use_wep);
   1613 		break;
   1614 	case WI_RID_TX_CRYPT_KEY:
   1615 		wreq->wi_val[0] = htole16(sc->wi_tx_key);
   1616 		break;
   1617 	case WI_RID_DEFLT_CRYPT_KEYS:
   1618 		wreq->wi_len += sizeof(struct wi_ltv_keys) / 2 - 1;
   1619 		memcpy(wreq, &sc->wi_keys, sizeof(struct wi_ltv_keys));
   1620 		break;
   1621 	default:
   1622 #if 0
   1623 		error = EIO;
   1624 #else
   1625 #ifdef WI_DEBUG
   1626 		printf("%s: wi_getdef: unknown request %d\n",
   1627 		    sc->sc_dev.dv_xname, wreq->wi_type);
   1628 #endif
   1629 #endif
   1630 		break;
   1631 	}
   1632 
   1633 	return (error);
   1634 }
   1635 
   1636 static int
   1637 wi_ioctl(ifp, command, data)
   1638 	struct ifnet		*ifp;
   1639 	u_long			command;
   1640 	caddr_t			data;
   1641 {
   1642 	int			s, error = 0;
   1643 	int			len;
   1644 	struct wi_softc		*sc = ifp->if_softc;
   1645 	struct wi_req		wreq;
   1646 	struct ifreq		*ifr;
   1647 	struct proc *p = curproc;
   1648 	struct ieee80211_nwid nwid;
   1649 
   1650 	if ((sc->sc_dev.dv_flags & DVF_ACTIVE) == 0)
   1651 		return (ENXIO);
   1652 
   1653 	s = splnet();
   1654 
   1655 	ifr = (struct ifreq *)data;
   1656 	switch (command) {
   1657 	case SIOCSIFADDR:
   1658 	case SIOCGIFADDR:
   1659 	case SIOCSIFMTU:
   1660 		error = ether_ioctl(ifp, command, data);
   1661 		break;
   1662 	case SIOCSIFFLAGS:
   1663 		if (ifp->if_flags & IFF_UP) {
   1664 			if (ifp->if_flags & IFF_RUNNING &&
   1665 			    ifp->if_flags & IFF_PROMISC &&
   1666 			    !(sc->wi_if_flags & IFF_PROMISC)) {
   1667 				if (sc->wi_ptype != WI_PORTTYPE_HOSTAP)
   1668 					WI_SETVAL(WI_RID_PROMISC, 1);
   1669 			} else if (ifp->if_flags & IFF_RUNNING &&
   1670 			    !(ifp->if_flags & IFF_PROMISC) &&
   1671 			    sc->wi_if_flags & IFF_PROMISC) {
   1672 				if (sc->wi_ptype != WI_PORTTYPE_HOSTAP)
   1673 					WI_SETVAL(WI_RID_PROMISC, 0);
   1674 			} else
   1675 				wi_init(ifp);
   1676 		} else if (ifp->if_flags & IFF_RUNNING)
   1677 			wi_stop(ifp, 0);
   1678 		sc->wi_if_flags = ifp->if_flags;
   1679 
   1680 		if (!(ifp->if_flags & IFF_UP)) {
   1681 			if (sc->sc_enabled) {
   1682 				if (sc->sc_disable)
   1683 					(*sc->sc_disable)(sc);
   1684 				sc->sc_enabled = 0;
   1685 				ifp->if_flags &= ~IFF_RUNNING;
   1686 			}
   1687 		}
   1688 		error = 0;
   1689 		break;
   1690 	case SIOCADDMULTI:
   1691 	case SIOCDELMULTI:
   1692 		error = (command == SIOCADDMULTI) ?
   1693 			ether_addmulti(ifr, &sc->sc_ethercom) :
   1694 			ether_delmulti(ifr, &sc->sc_ethercom);
   1695 		if (error == ENETRESET) {
   1696 			if (sc->sc_enabled != 0) {
   1697 				/*
   1698 				 * Multicast list has changed.  Set the
   1699 				 * hardware filter accordingly.
   1700 				 */
   1701 				wi_setmulti(sc);
   1702 			}
   1703 			error = 0;
   1704 		}
   1705 		break;
   1706 	case SIOCSIFMEDIA:
   1707 	case SIOCGIFMEDIA:
   1708 		error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, command);
   1709 		break;
   1710 	case SIOCGWAVELAN:
   1711 		error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
   1712 		if (error)
   1713 			break;
   1714 		if (wreq.wi_type == WI_RID_IFACE_STATS) {
   1715 			memcpy((char *)&wreq.wi_val, (char *)&sc->wi_stats,
   1716 			    sizeof(sc->wi_stats));
   1717 			wreq.wi_len = (sizeof(sc->wi_stats) / 2) + 1;
   1718 		} else if (wreq.wi_type == WI_RID_READ_APS) {
   1719 			if (sc->wi_scanning) {
   1720 				error = EINPROGRESS;
   1721 				break;
   1722 			} else {
   1723 				len = sc->wi_naps * sizeof(struct wi_apinfo);
   1724 				len = len > WI_MAX_DATALEN ? WI_MAX_DATALEN : len;
   1725 				len = len / sizeof(struct wi_apinfo);
   1726 				memcpy((char *)&wreq.wi_val, (char *)&len, sizeof(len));
   1727 				memcpy((char *)&wreq.wi_val + sizeof(len),
   1728 					(char *)&sc->wi_aps,
   1729 					len * sizeof(struct wi_apinfo));
   1730 			}
   1731 		} else if (wreq.wi_type == WI_RID_DEFLT_CRYPT_KEYS) {
   1732 			/* For non-root user, return all-zeroes keys */
   1733 			if (suser(p->p_ucred, &p->p_acflag))
   1734 				memset((char *)&wreq, 0,
   1735 				    sizeof(struct wi_ltv_keys));
   1736 			else
   1737 				memcpy((char *)&wreq, (char *)&sc->wi_keys,
   1738 				    sizeof(struct wi_ltv_keys));
   1739 		} else {
   1740 			if (sc->sc_enabled == 0)
   1741 				error = wi_getdef(sc, &wreq);
   1742 			else if (wreq.wi_len > WI_MAX_DATALEN)
   1743 				error = EINVAL;
   1744 			else if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq))
   1745 				error = EINVAL;
   1746 		}
   1747 		if (error == 0)
   1748 			error = copyout(&wreq, ifr->ifr_data, sizeof(wreq));
   1749 		break;
   1750 	case SIOCSWAVELAN:
   1751 		error = suser(p->p_ucred, &p->p_acflag);
   1752 		if (error)
   1753 			break;
   1754 		error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
   1755 		if (error)
   1756 			break;
   1757 		if (wreq.wi_type == WI_RID_IFACE_STATS) {
   1758 			if (sc->sc_enabled)
   1759 				wi_inquire(sc);
   1760 			break;
   1761 		} else if (wreq.wi_type == WI_RID_MGMT_XMIT) {
   1762 			error = wi_mgmt_xmit(sc, (caddr_t)&wreq.wi_val,
   1763 			    wreq.wi_len);
   1764 		} else if (wreq.wi_type == WI_RID_SCAN_APS) {
   1765 			if (wreq.wi_len != 4) {
   1766 				error = EINVAL;
   1767 				break;
   1768 			}
   1769 			if (!sc->wi_scanning) {
   1770 				switch (sc->sc_firmware_type) {
   1771 				case WI_LUCENT:
   1772 					break;
   1773 				case WI_INTERSIL:
   1774 					wreq.wi_type = WI_RID_SCAN_REQ;
   1775 					error = wi_write_record(sc,
   1776 					    (struct wi_ltv_gen *)&wreq);
   1777 					break;
   1778 				case WI_SYMBOL:
   1779 					/*
   1780 					 * XXX only supported on 3.x ?
   1781 					 */
   1782 					wreq.wi_type = WI_RID_BCAST_SCAN_REQ;
   1783 					wreq.wi_val[0] =
   1784 					    BSCAN_BCAST | BSCAN_ONETIME;
   1785 					wreq.wi_len = 2;
   1786 					error = wi_write_record(sc,
   1787 					    (struct wi_ltv_gen *)&wreq);
   1788 					break;
   1789 				}
   1790 				if (!error) {
   1791 					sc->wi_scanning = 1;
   1792 					callout_reset(&sc->wi_scan_sh, hz * 1,
   1793 						wi_wait_scan, sc);
   1794 				}
   1795 			}
   1796 		} else {
   1797 			/*
   1798 			 * Filter stuff out based on what the
   1799 			 * card can do.
   1800 			 */
   1801 			if ((wreq.wi_type == WI_RID_ROAMING_MODE &&
   1802 			     (sc->wi_flags & WI_FLAGS_HAS_ROAMING) == 0) ||
   1803 			    (wreq.wi_type == WI_RID_CREATE_IBSS &&
   1804 			     (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS) == 0) ||
   1805 			    (wreq.wi_type == WI_RID_MICROWAVE_OVEN &&
   1806 			     (sc->wi_flags & WI_FLAGS_HAS_MOR) == 0))
   1807 				break;
   1808 
   1809 			if (wreq.wi_len > WI_MAX_DATALEN)
   1810 				error = EINVAL;
   1811 			else if (sc->sc_enabled != 0)
   1812 				error = wi_write_record(sc,
   1813 				    (struct wi_ltv_gen *)&wreq);
   1814 			if (error == 0)
   1815 				error = wi_setdef(sc, &wreq);
   1816 			if (error == 0 && sc->sc_enabled != 0)
   1817 				/* Reinitialize WaveLAN. */
   1818 				wi_init(ifp);
   1819 		}
   1820 		break;
   1821 	case SIOCG80211NWID:
   1822 		if (sc->sc_enabled == 0) {
   1823 			/* Return the desired ID */
   1824 			error = copyout(&sc->wi_netid, ifr->ifr_data,
   1825 			    sizeof(sc->wi_netid));
   1826 		} else {
   1827 			wreq.wi_type = WI_RID_CURRENT_SSID;
   1828 			wreq.wi_len = WI_MAX_DATALEN;
   1829 			if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq) ||
   1830 			    le16toh(wreq.wi_val[0]) > IEEE80211_NWID_LEN)
   1831 				error = EINVAL;
   1832 			else {
   1833 				wi_set_ssid(&nwid, (u_int8_t *)&wreq.wi_val[1],
   1834 				    le16toh(wreq.wi_val[0]));
   1835 				error = copyout(&nwid, ifr->ifr_data,
   1836 				    sizeof(nwid));
   1837 			}
   1838 		}
   1839 		break;
   1840 	case SIOCS80211NWID:
   1841 		error = copyin(ifr->ifr_data, &nwid, sizeof(nwid));
   1842 		if (error != 0)
   1843 			break;
   1844 		if (nwid.i_len > IEEE80211_NWID_LEN) {
   1845 			error = EINVAL;
   1846 			break;
   1847 		}
   1848 		if (sc->wi_netid.i_len == nwid.i_len &&
   1849 		    memcmp(sc->wi_netid.i_nwid, nwid.i_nwid, nwid.i_len) == 0)
   1850 			break;
   1851 		wi_set_ssid(&sc->wi_netid, nwid.i_nwid, nwid.i_len);
   1852 		if (sc->sc_enabled != 0)
   1853 			/* Reinitialize WaveLAN. */
   1854 			wi_init(ifp);
   1855 		break;
   1856 	case SIOCS80211NWKEY:
   1857 		error = wi_set_nwkey(sc, (struct ieee80211_nwkey *)data);
   1858 		break;
   1859 	case SIOCG80211NWKEY:
   1860 		error = wi_get_nwkey(sc, (struct ieee80211_nwkey *)data);
   1861 		break;
   1862 	case SIOCS80211POWER:
   1863 		error = wi_set_pm(sc, (struct ieee80211_power *)data);
   1864 		break;
   1865 	case SIOCG80211POWER:
   1866 		error = wi_get_pm(sc, (struct ieee80211_power *)data);
   1867 		break;
   1868 	case SIOCHOSTAP_ADD:
   1869 	case SIOCHOSTAP_DEL:
   1870 	case SIOCHOSTAP_GET:
   1871 	case SIOCHOSTAP_GETALL:
   1872 	case SIOCHOSTAP_GFLAGS:
   1873 	case SIOCHOSTAP_SFLAGS:
   1874 		/* Send all Host-AP specific ioctls to the Host-AP code. */
   1875 		error = wihap_ioctl(sc, command, data);
   1876 		break;
   1877 
   1878 	default:
   1879 		error = EINVAL;
   1880 		break;
   1881 	}
   1882 
   1883 	splx(s);
   1884 	return (error);
   1885 }
   1886 
   1887 static int
   1888 wi_init(ifp)
   1889 	struct ifnet *ifp;
   1890 {
   1891 	struct wi_softc *sc = ifp->if_softc;
   1892 	struct wi_req wreq;
   1893 	struct wi_ltv_macaddr mac;
   1894 	int error, id = 0, wasenabled;
   1895 
   1896 	wasenabled = sc->sc_enabled;
   1897 	if (!sc->sc_enabled) {
   1898 		if ((error = (*sc->sc_enable)(sc)) != 0)
   1899 			goto out;
   1900 		sc->sc_enabled = 1;
   1901 	}
   1902 
   1903 	wi_stop(ifp, 0);
   1904 	/* Symbol firmware cannot be initialized more than once */
   1905 	if (!(sc->sc_firmware_type == WI_SYMBOL && wasenabled))
   1906 		wi_reset(sc);
   1907 
   1908 	/* Program max data length. */
   1909 	WI_SETVAL(WI_RID_MAX_DATALEN, sc->wi_max_data_len);
   1910 
   1911 	/* Enable/disable IBSS creation. */
   1912 	WI_SETVAL(WI_RID_CREATE_IBSS, sc->wi_create_ibss);
   1913 
   1914 	/* Set the port type. */
   1915 	WI_SETVAL(WI_RID_PORTTYPE, sc->wi_ptype);
   1916 
   1917 	/* Program the RTS/CTS threshold. */
   1918 	WI_SETVAL(WI_RID_RTS_THRESH, sc->wi_rts_thresh);
   1919 
   1920 	/* Program the TX rate */
   1921 	WI_SETVAL(WI_RID_TX_RATE, sc->wi_tx_rate);
   1922 
   1923 	/* Access point density */
   1924 	WI_SETVAL(WI_RID_SYSTEM_SCALE, sc->wi_ap_density);
   1925 
   1926 	/* Power Management Enabled */
   1927 	WI_SETVAL(WI_RID_PM_ENABLED, sc->wi_pm_enabled);
   1928 
   1929 	/* Power Managment Max Sleep */
   1930 	WI_SETVAL(WI_RID_MAX_SLEEP, sc->wi_max_sleep);
   1931 
   1932 	/* Roaming type */
   1933 	if (sc->wi_flags & WI_FLAGS_HAS_ROAMING)
   1934 		WI_SETVAL(WI_RID_ROAMING_MODE, sc->wi_roaming);
   1935 
   1936 	/* Specify the network name */
   1937 	wi_write_ssid(sc, WI_RID_DESIRED_SSID, &wreq, &sc->wi_netid);
   1938 
   1939 	/* Specify the IBSS name */
   1940 	if (sc->wi_netid.i_len != 0 &&
   1941 	    (sc->wi_ptype == WI_PORTTYPE_HOSTAP ||
   1942 	     (sc->wi_create_ibss && sc->wi_ptype == WI_PORTTYPE_IBSS)))
   1943 		wi_write_ssid(sc, WI_RID_OWN_SSID, &wreq, &sc->wi_netid);
   1944 	else
   1945 		wi_write_ssid(sc, WI_RID_OWN_SSID, &wreq, &sc->wi_ibssid);
   1946 
   1947 	/* Specify the frequency to use */
   1948 	WI_SETVAL(WI_RID_OWN_CHNL, sc->wi_channel);
   1949 
   1950 	/* Program the nodename. */
   1951 	wi_write_ssid(sc, WI_RID_NODENAME, &wreq, &sc->wi_nodeid);
   1952 
   1953 	/* Set our MAC address. */
   1954 	mac.wi_len = 4;
   1955 	mac.wi_type = WI_RID_MAC_NODE;
   1956 	memcpy(&mac.wi_mac_addr, sc->sc_macaddr, ETHER_ADDR_LEN);
   1957 	wi_write_record(sc, (struct wi_ltv_gen *)&mac);
   1958 
   1959 	/*
   1960 	 * Initialize promisc mode.
   1961 	 *	Being in the Host-AP mode causes a great
   1962 	 *	deal of pain if primisc mode is set.
   1963 	 *	Therefore we avoid confusing the firmware
   1964 	 *	and always reset promisc mode in Host-AP
   1965 	 *	mode.  Host-AP sees all the packets anyway.
   1966 	 */
   1967 	if (sc->wi_ptype != WI_PORTTYPE_HOSTAP &&
   1968 	    (ifp->if_flags & IFF_PROMISC) != 0) {
   1969 		WI_SETVAL(WI_RID_PROMISC, 1);
   1970 	} else {
   1971 		WI_SETVAL(WI_RID_PROMISC, 0);
   1972 	}
   1973 
   1974 	/* Configure WEP. */
   1975 	if (sc->wi_flags & WI_FLAGS_HAS_WEP) {
   1976 		WI_SETVAL(WI_RID_ENCRYPTION, sc->wi_use_wep);
   1977 		WI_SETVAL(WI_RID_TX_CRYPT_KEY, sc->wi_tx_key);
   1978 		sc->wi_keys.wi_len = (sizeof(struct wi_ltv_keys) / 2) + 1;
   1979 		sc->wi_keys.wi_type = WI_RID_DEFLT_CRYPT_KEYS;
   1980 		wi_write_record(sc, (struct wi_ltv_gen *)&sc->wi_keys);
   1981 		if (sc->sc_firmware_type != WI_LUCENT && sc->wi_use_wep) {
   1982 			/*
   1983 			 * ONLY HWB3163 EVAL-CARD Firmware version
   1984 			 * less than 0.8 variant2
   1985 			 *
   1986 			 *   If promiscuous mode disable, Prism2 chip
   1987 			 *  does not work with WEP .
   1988 			 * It is under investigation for details.
   1989 			 * (ichiro (at) netbsd.org)
   1990 			 */
   1991 			if (sc->sc_firmware_type == WI_INTERSIL &&
   1992 			    sc->sc_sta_firmware_ver < 802 ) {
   1993 				/* firm ver < 0.8 variant 2 */
   1994 				WI_SETVAL(WI_RID_PROMISC, 1);
   1995 			}
   1996 			WI_SETVAL(WI_RID_CNFAUTHMODE, sc->wi_authtype);
   1997 		}
   1998 	}
   1999 
   2000 	/* Set multicast filter. */
   2001 	wi_setmulti(sc);
   2002 
   2003 	/* Enable desired port */
   2004 	wi_cmd(sc, WI_CMD_ENABLE | sc->wi_portnum, 0, 0, 0);
   2005 
   2006 	/*  scanning variable is modal, therefore reinit to OFF, in case it was on. */
   2007 	sc->wi_scanning=0;
   2008 	sc->wi_naps=0;
   2009 
   2010 	if ((error = wi_alloc_nicmem(sc,
   2011 	    1518 + sizeof(struct wi_frame) + 8, &id)) != 0) {
   2012 		printf("%s: tx buffer allocation failed\n",
   2013 		    sc->sc_dev.dv_xname);
   2014 		goto out;
   2015 	}
   2016 	sc->wi_tx_data_id = id;
   2017 
   2018 	if ((error = wi_alloc_nicmem(sc,
   2019 	    1518 + sizeof(struct wi_frame) + 8, &id)) != 0) {
   2020 		printf("%s: mgmt. buffer allocation failed\n",
   2021 		    sc->sc_dev.dv_xname);
   2022 		goto out;
   2023 	}
   2024 	sc->wi_tx_mgmt_id = id;
   2025 
   2026 	/* Enable interrupts */
   2027 	CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
   2028 
   2029 	wihap_init(sc);
   2030 
   2031 	ifp->if_flags |= IFF_RUNNING;
   2032 	ifp->if_flags &= ~IFF_OACTIVE;
   2033 
   2034 	callout_reset(&sc->wi_inquire_ch, hz * 60, wi_inquire, sc);
   2035 
   2036  out:
   2037 	if (error) {
   2038 		ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
   2039 		ifp->if_timer = 0;
   2040 		printf("%s: interface not running\n", sc->sc_dev.dv_xname);
   2041 	}
   2042 	return (error);
   2043 }
   2044 
   2045 static const u_int32_t crc32_tab[] = {
   2046 	0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
   2047 	0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
   2048 	0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
   2049 	0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
   2050 	0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
   2051 	0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
   2052 	0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
   2053 	0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
   2054 	0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
   2055 	0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
   2056 	0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
   2057 	0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
   2058 	0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
   2059 	0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
   2060 	0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
   2061 	0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
   2062 	0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
   2063 	0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
   2064 	0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
   2065 	0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
   2066 	0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
   2067 	0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
   2068 	0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
   2069 	0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
   2070 	0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
   2071 	0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
   2072 	0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
   2073 	0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
   2074 	0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
   2075 	0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
   2076 	0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
   2077 	0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
   2078 	0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
   2079 	0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
   2080 	0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
   2081 	0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
   2082 	0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
   2083 	0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
   2084 	0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
   2085 	0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
   2086 	0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
   2087 	0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
   2088 	0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
   2089 	0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
   2090 	0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
   2091 	0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
   2092 	0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
   2093 	0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
   2094 	0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
   2095 	0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
   2096 	0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
   2097 	0x2d02ef8dL
   2098 };
   2099 
   2100 #define RC4STATE 256
   2101 #define RC4KEYLEN 16
   2102 #define RC4SWAP(x,y) \
   2103     do { u_int8_t t = state[x]; state[x] = state[y]; state[y] = t; } while(0)
   2104 
   2105 static void
   2106 wi_do_hostencrypt(struct wi_softc *sc, caddr_t buf, int len)
   2107 {
   2108 	u_int32_t i, crc, klen;
   2109 	u_int8_t state[RC4STATE], key[RC4KEYLEN];
   2110 	u_int8_t x, y, *dat;
   2111 
   2112 	if (!sc->wi_icv_flag) {
   2113 		sc->wi_icv = arc4random();
   2114 		sc->wi_icv_flag++;
   2115 	} else
   2116 		sc->wi_icv++;
   2117 	/*
   2118 	 * Skip 'bad' IVs from Fluhrer/Mantin/Shamir:
   2119 	 * (B, 255, N) with 3 <= B < 8
   2120 	 */
   2121 	if (sc->wi_icv >= 0x03ff00 &&
   2122             (sc->wi_icv & 0xf8ff00) == 0x00ff00)
   2123                 sc->wi_icv += 0x000100;
   2124 
   2125 	/* prepend 24bit IV to tx key, byte order does not matter */
   2126 	key[0] = sc->wi_icv >> 16;
   2127 	key[1] = sc->wi_icv >> 8;
   2128 	key[2] = sc->wi_icv;
   2129 
   2130 	klen = le16toh(sc->wi_keys.wi_keys[sc->wi_tx_key].wi_keylen) +
   2131 	    IEEE80211_WEP_IVLEN;
   2132 	klen = (klen >= RC4KEYLEN) ? RC4KEYLEN : RC4KEYLEN/2;
   2133 	bcopy((char *)&sc->wi_keys.wi_keys[sc->wi_tx_key].wi_keydat,
   2134 	    (char *)key + IEEE80211_WEP_IVLEN, klen - IEEE80211_WEP_IVLEN);
   2135 
   2136 	/* rc4 keysetup */
   2137 	x = y = 0;
   2138 	for (i = 0; i < RC4STATE; i++)
   2139 		state[i] = i;
   2140 	for (i = 0; i < RC4STATE; i++) {
   2141 		y = (key[x] + state[i] + y) % RC4STATE;
   2142 		RC4SWAP(i, y);
   2143 		x = (x + 1) % klen;
   2144 	}
   2145 
   2146 	/* output: IV, tx keyid, rc4(data), rc4(crc32(data)) */
   2147 	dat = buf;
   2148 	dat[0] = key[0];
   2149 	dat[1] = key[1];
   2150 	dat[2] = key[2];
   2151 	dat[3] = sc->wi_tx_key << 6;		/* pad and keyid */
   2152 	dat += 4;
   2153 
   2154 	/* compute rc4 over data, crc32 over data */
   2155 	crc = ~0;
   2156 	x = y = 0;
   2157 	for (i = 0; i < len; i++) {
   2158 		x = (x + 1) % RC4STATE;
   2159 		y = (state[x] + y) % RC4STATE;
   2160 		RC4SWAP(x, y);
   2161 		crc = crc32_tab[(crc ^ dat[i]) & 0xff] ^ (crc >> 8);
   2162 		dat[i] ^= state[(state[x] + state[y]) % RC4STATE];
   2163 	}
   2164 	crc = ~crc;
   2165 	dat += len;
   2166 
   2167 	/* append little-endian crc32 and encrypt */
   2168 	dat[0] = crc;
   2169 	dat[1] = crc >> 8;
   2170 	dat[2] = crc >> 16;
   2171 	dat[3] = crc >> 24;
   2172 	for (i = 0; i < IEEE80211_WEP_CRCLEN; i++) {
   2173 		x = (x + 1) % RC4STATE;
   2174 		y = (state[x] + y) % RC4STATE;
   2175 		RC4SWAP(x, y);
   2176 		dat[i] ^= state[(state[x] + state[y]) % RC4STATE];
   2177 	}
   2178 }
   2179 
   2180 static void
   2181 wi_start(ifp)
   2182 	struct ifnet		*ifp;
   2183 {
   2184 	struct wi_softc		*sc;
   2185 	struct mbuf		*m0;
   2186 	struct wi_frame		tx_frame;
   2187 	struct ether_header	*eh;
   2188 	int			id;
   2189 
   2190 	sc = ifp->if_softc;
   2191 
   2192 	if (ifp->if_flags & IFF_OACTIVE)
   2193 		return;
   2194 
   2195  nextpkt:
   2196 	IFQ_DEQUEUE(&ifp->if_snd, m0);
   2197 	if (m0 == NULL)
   2198 		return;
   2199 
   2200 	memset((char *)&tx_frame, 0, sizeof(tx_frame));
   2201 	tx_frame.wi_frame_ctl = htole16(WI_FTYPE_DATA);
   2202 	id = sc->wi_tx_data_id;
   2203 	eh = mtod(m0, struct ether_header *);
   2204 
   2205 	if (sc->wi_ptype == WI_PORTTYPE_HOSTAP) {
   2206 		if (wihap_check_tx(&sc->wi_hostap_info, eh->ether_dhost,
   2207 				   &tx_frame.wi_tx_rate) == 0 &&
   2208 		    (ifp->if_flags & IFF_PROMISC) == 0) {
   2209 			if (ifp->if_flags & IFF_DEBUG)
   2210 				printf("%s: Host-AP: dropping unassoc "
   2211 				    "dst %s\n", sc->sc_dev.dv_xname,
   2212 				    ether_sprintf(eh->ether_dhost));
   2213 			m_freem(m0);
   2214 			goto nextpkt;
   2215 		}
   2216 	}
   2217 
   2218 	/*
   2219 	 * Use RFC1042 encoding for IP and ARP datagrams,
   2220 	 * 802.3 for anything else.
   2221 	 */
   2222 	if (eh->ether_type == htons(ETHERTYPE_IP) ||
   2223 	    eh->ether_type == htons(ETHERTYPE_ARP) ||
   2224 	    eh->ether_type == htons(ETHERTYPE_REVARP) ||
   2225 	    eh->ether_type == htons(ETHERTYPE_IPV6)) {
   2226 		memcpy((char *)&tx_frame.wi_addr1, (char *)&eh->ether_dhost,
   2227 		    ETHER_ADDR_LEN);
   2228 		if (sc->wi_ptype == WI_PORTTYPE_HOSTAP) {
   2229 			tx_frame.wi_tx_ctl |= htole16(WI_ENC_TX_MGMT);/* XXX */
   2230 			tx_frame.wi_frame_ctl |= htole16(WI_FCTL_FROMDS);
   2231 			if (sc->wi_use_wep)
   2232 				tx_frame.wi_frame_ctl |= htole16(WI_FCTL_WEP);
   2233 			memcpy((char *)&tx_frame.wi_addr2,
   2234 			    (char *)LLADDR(ifp->if_sadl), ETHER_ADDR_LEN);
   2235 			memcpy((char *)&tx_frame.wi_addr3,
   2236 			    (char *)&eh->ether_shost, ETHER_ADDR_LEN);
   2237 		} else
   2238 			memcpy((char *)&tx_frame.wi_addr2,
   2239 			    (char *)&eh->ether_shost, ETHER_ADDR_LEN);
   2240 		memcpy((char *)&tx_frame.wi_dst_addr, (char *)&eh->ether_dhost,
   2241 		    ETHER_ADDR_LEN);
   2242 		memcpy((char *)&tx_frame.wi_src_addr, (char *)&eh->ether_shost,
   2243 		    ETHER_ADDR_LEN);
   2244 
   2245 		tx_frame.wi_dat_len = m0->m_pkthdr.len - WI_SNAPHDR_LEN;
   2246 		tx_frame.wi_dat[0] = htons(WI_SNAP_WORD0);
   2247 		tx_frame.wi_dat[1] = htons(WI_SNAP_WORD1);
   2248 		tx_frame.wi_len = htons(m0->m_pkthdr.len - WI_SNAPHDR_LEN);
   2249 		tx_frame.wi_type = eh->ether_type;
   2250 
   2251 		if (sc->wi_ptype == WI_PORTTYPE_HOSTAP && sc->wi_use_wep) {
   2252 			/* Do host encryption. */
   2253 			memcpy(&sc->wi_txbuf[4], &tx_frame.wi_dat[0], 8);
   2254 
   2255 			m_copydata(m0, sizeof(struct ether_header),
   2256 			    m0->m_pkthdr.len - sizeof(struct ether_header),
   2257 			    (caddr_t)&sc->wi_txbuf[12]);
   2258 
   2259 			wi_do_hostencrypt(sc, (caddr_t)&sc->wi_txbuf,
   2260 			    tx_frame.wi_dat_len);
   2261 
   2262 			tx_frame.wi_dat_len += IEEE80211_WEP_IVLEN +
   2263 			    IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN;
   2264 
   2265 			tx_frame.wi_dat_len = htole16(tx_frame.wi_dat_len);
   2266 
   2267 			wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
   2268 			    sizeof(struct wi_frame));
   2269 			wi_write_data(sc, id, WI_802_11_OFFSET_RAW,
   2270 			    (caddr_t)&sc->wi_txbuf,
   2271 			    (m0->m_pkthdr.len -
   2272 			     sizeof(struct ether_header)) + 18);
   2273 		} else {
   2274 			m_copydata(m0, sizeof(struct ether_header),
   2275 			    m0->m_pkthdr.len - sizeof(struct ether_header),
   2276 			    (caddr_t)&sc->wi_txbuf);
   2277 
   2278 			tx_frame.wi_dat_len = htole16(tx_frame.wi_dat_len);
   2279 
   2280 			wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
   2281 			    sizeof(struct wi_frame));
   2282 			wi_write_data(sc, id, WI_802_11_OFFSET,
   2283 			    (caddr_t)&sc->wi_txbuf,
   2284 			    (m0->m_pkthdr.len -
   2285 			     sizeof(struct ether_header)) + 2);
   2286 		}
   2287 	} else {
   2288 		tx_frame.wi_dat_len = htole16(m0->m_pkthdr.len);
   2289 
   2290 		if (sc->wi_ptype == WI_PORTTYPE_HOSTAP && sc->wi_use_wep) {
   2291 			/* Do host encryption.  (XXX - not implemented) */
   2292 			printf("%s: host encryption not implemented "
   2293 			    "for 802.3\n", sc->sc_dev.dv_xname);
   2294 		} else {
   2295 			m_copydata(m0, 0, m0->m_pkthdr.len,
   2296 			    (caddr_t)&sc->wi_txbuf);
   2297 
   2298 			wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
   2299 			    sizeof(struct wi_frame));
   2300 			wi_write_data(sc, id, WI_802_3_OFFSET,
   2301 			    (caddr_t)&sc->wi_txbuf, m0->m_pkthdr.len + 2);
   2302 		}
   2303 	}
   2304 
   2305 #if NBPFILTER > 0
   2306 	/*
   2307 	 * If there's a BPF listener, bounce a copy of
   2308 	 * this frame to him.
   2309 	 */
   2310 	if (ifp->if_bpf)
   2311 		bpf_mtap(ifp->if_bpf, m0);
   2312 #endif
   2313 
   2314 	m_freem(m0);
   2315 
   2316 	if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id, 0, 0))
   2317 		printf("%s: xmit failed\n", sc->sc_dev.dv_xname);
   2318 
   2319 	ifp->if_flags |= IFF_OACTIVE;
   2320 
   2321 	/*
   2322 	 * Set a timeout in case the chip goes out to lunch.
   2323 	 */
   2324 	ifp->if_timer = 5;
   2325 
   2326 	return;
   2327 }
   2328 
   2329 int
   2330 wi_mgmt_xmit(sc, data, len)
   2331 	struct wi_softc		*sc;
   2332 	caddr_t			data;
   2333 	int			len;
   2334 {
   2335 	struct wi_frame		tx_frame;
   2336 	int			id;
   2337 	struct wi_80211_hdr	*hdr;
   2338 	caddr_t			dptr;
   2339 
   2340 	hdr = (struct wi_80211_hdr *)data;
   2341 	dptr = data + sizeof(struct wi_80211_hdr);
   2342 
   2343 	memset((char *)&tx_frame, 0, sizeof(tx_frame));
   2344 	id = sc->wi_tx_mgmt_id;
   2345 
   2346 	memcpy((char *)&tx_frame.wi_frame_ctl, (char *)hdr,
   2347 	   sizeof(struct wi_80211_hdr));
   2348 
   2349 	tx_frame.wi_tx_ctl = htole16(WI_ENC_TX_MGMT);
   2350 	tx_frame.wi_dat_len = len - sizeof(struct wi_80211_hdr);
   2351 	tx_frame.wi_len = htole16(tx_frame.wi_dat_len);
   2352 
   2353 	tx_frame.wi_dat_len = htole16(tx_frame.wi_dat_len);
   2354 
   2355 	wi_write_data(sc, id, 0, (caddr_t)&tx_frame, sizeof(struct wi_frame));
   2356 	wi_write_data(sc, id, WI_802_11_OFFSET_RAW, dptr,
   2357 	    (len - sizeof(struct wi_80211_hdr)) + 2);
   2358 
   2359 	if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id, 0, 0)) {
   2360 		printf("%s: xmit failed\n", sc->sc_dev.dv_xname);
   2361 		return(EIO);
   2362 	}
   2363 
   2364 	return(0);
   2365 }
   2366 
   2367 static void
   2368 wi_stop(ifp, disable)
   2369 	struct ifnet *ifp;
   2370 {
   2371 	struct wi_softc	*sc = ifp->if_softc;
   2372 
   2373 	wihap_shutdown(sc);
   2374 
   2375 	CSR_WRITE_2(sc, WI_INT_EN, 0);
   2376 	wi_cmd(sc, WI_CMD_DISABLE|sc->wi_portnum, 0, 0, 0);
   2377 
   2378 	callout_stop(&sc->wi_inquire_ch);
   2379 	callout_stop(&sc->wi_scan_sh);
   2380 
   2381 	if (disable) {
   2382 		if (sc->sc_enabled) {
   2383 			if (sc->sc_disable)
   2384 				(*sc->sc_disable)(sc);
   2385 			sc->sc_enabled = 0;
   2386 		}
   2387 	}
   2388 
   2389 	ifp->if_flags &= ~(IFF_OACTIVE | IFF_RUNNING);
   2390 	ifp->if_timer = 0;
   2391 }
   2392 
   2393 static void
   2394 wi_watchdog(ifp)
   2395 	struct ifnet		*ifp;
   2396 {
   2397 	struct wi_softc		*sc;
   2398 
   2399 	sc = ifp->if_softc;
   2400 
   2401 	printf("%s: device timeout\n", sc->sc_dev.dv_xname);
   2402 
   2403 	wi_init(ifp);
   2404 
   2405 	ifp->if_oerrors++;
   2406 
   2407 	return;
   2408 }
   2409 
   2410 void
   2411 wi_shutdown(sc)
   2412 	struct wi_softc *sc;
   2413 {
   2414 	int s;
   2415 
   2416 	s = splnet();
   2417 	if (sc->sc_enabled) {
   2418 		if (sc->sc_disable)
   2419 			(*sc->sc_disable)(sc);
   2420 		sc->sc_enabled = 0;
   2421 	}
   2422 	splx(s);
   2423 }
   2424 
   2425 int
   2426 wi_activate(self, act)
   2427 	struct device *self;
   2428 	enum devact act;
   2429 {
   2430 	struct wi_softc *sc = (struct wi_softc *)self;
   2431 	int rv = 0, s;
   2432 
   2433 	s = splnet();
   2434 	switch (act) {
   2435 	case DVACT_ACTIVATE:
   2436 		rv = EOPNOTSUPP;
   2437 		break;
   2438 
   2439 	case DVACT_DEACTIVATE:
   2440 		if_deactivate(&sc->sc_ethercom.ec_if);
   2441 		break;
   2442 	}
   2443 	splx(s);
   2444 	return (rv);
   2445 }
   2446 
   2447 static void
   2448 wi_get_id(sc)
   2449 	struct wi_softc *sc;
   2450 {
   2451 	struct wi_ltv_ver       ver;
   2452 	struct wi_card_ident	*id;
   2453 
   2454 	/* getting chip identity */
   2455 	memset(&ver, 0, sizeof(ver));
   2456 	ver.wi_type = WI_RID_CARD_ID;
   2457 	ver.wi_len = 5;
   2458 	wi_read_record(sc, (struct wi_ltv_gen *)&ver);
   2459 	printf("%s: using ", sc->sc_dev.dv_xname);
   2460 
   2461 	sc->sc_firmware_type = WI_NOTYPE;
   2462 	for (id = wi_card_ident; id->card_name != NULL; id++) {
   2463 		if (le16toh(ver.wi_ver[0]) == id->card_id) {
   2464 			printf("%s", id->card_name);
   2465 			sc->sc_firmware_type = id->firm_type;
   2466 			break;
   2467 		}
   2468 	}
   2469 	if (sc->sc_firmware_type == WI_NOTYPE) {
   2470 		if (le16toh(ver.wi_ver[0]) & 0x8000) {
   2471 			printf("Unknown PRISM2 chip");
   2472 			sc->sc_firmware_type = WI_INTERSIL;
   2473 		} else {
   2474 			printf("Unknown Lucent chip");
   2475 			sc->sc_firmware_type = WI_LUCENT;
   2476 		}
   2477 	}
   2478 
   2479 	/* get primary firmware version (Only Prism chips) */
   2480 	if (sc->sc_firmware_type != WI_LUCENT) {
   2481 		memset(&ver, 0, sizeof(ver));
   2482 		ver.wi_type = WI_RID_PRI_IDENTITY;
   2483 		ver.wi_len = 5;
   2484 		wi_read_record(sc, (struct wi_ltv_gen *)&ver);
   2485 		LE16TOH(ver.wi_ver[1]);
   2486 		LE16TOH(ver.wi_ver[2]);
   2487 		LE16TOH(ver.wi_ver[3]);
   2488 		sc->sc_pri_firmware_ver = ver.wi_ver[2] * 10000 +
   2489 		    ver.wi_ver[3] * 100 + ver.wi_ver[1];
   2490 	}
   2491 
   2492 	/* get station firmware version */
   2493 	memset(&ver, 0, sizeof(ver));
   2494 	ver.wi_type = WI_RID_STA_IDENTITY;
   2495 	ver.wi_len = 5;
   2496 	wi_read_record(sc, (struct wi_ltv_gen *)&ver);
   2497 	LE16TOH(ver.wi_ver[1]);
   2498 	LE16TOH(ver.wi_ver[2]);
   2499 	LE16TOH(ver.wi_ver[3]);
   2500 	sc->sc_sta_firmware_ver = ver.wi_ver[2] * 10000 +
   2501 	    ver.wi_ver[3] * 100 + ver.wi_ver[1];
   2502 	if (sc->sc_firmware_type == WI_INTERSIL &&
   2503 	    (sc->sc_sta_firmware_ver == 10102 || sc->sc_sta_firmware_ver == 20102)) {
   2504 		struct wi_ltv_str sver;
   2505 		char *p;
   2506 
   2507 		memset(&sver, 0, sizeof(sver));
   2508 		sver.wi_type = WI_RID_SYMBOL_IDENTITY;
   2509 		sver.wi_len = 7;
   2510 		/* value should be the format like "V2.00-11" */
   2511 		if (wi_read_record(sc, (struct wi_ltv_gen *)&sver) == 0 &&
   2512 		    *(p = (char *)sver.wi_str) >= 'A' &&
   2513 		    p[2] == '.' && p[5] == '-' && p[8] == '\0') {
   2514 			sc->sc_firmware_type = WI_SYMBOL;
   2515 			sc->sc_sta_firmware_ver = (p[1] - '0') * 10000 +
   2516 			    (p[3] - '0') * 1000 + (p[4] - '0') * 100 +
   2517 			    (p[6] - '0') * 10 + (p[7] - '0');
   2518 		}
   2519 	}
   2520 
   2521 	printf("\n%s: %s Firmware: ", sc->sc_dev.dv_xname,
   2522 	     sc->sc_firmware_type == WI_LUCENT ? "Lucent" :
   2523 	    (sc->sc_firmware_type == WI_SYMBOL ? "Symbol" : "Intersil"));
   2524 	if (sc->sc_firmware_type != WI_LUCENT)	/* XXX */
   2525 	    printf("Primary (%u.%u.%u), ", sc->sc_pri_firmware_ver / 10000,
   2526 		    (sc->sc_pri_firmware_ver % 10000) / 100,
   2527 		    sc->sc_pri_firmware_ver % 100);
   2528 	printf("Station (%u.%u.%u)\n",
   2529 	    sc->sc_sta_firmware_ver / 10000, (sc->sc_sta_firmware_ver % 10000) / 100,
   2530 	    sc->sc_sta_firmware_ver % 100);
   2531 
   2532 	return;
   2533 }
   2534 
   2535 int
   2536 wi_detach(sc)
   2537 	struct wi_softc *sc;
   2538 {
   2539 	struct ifnet *ifp = sc->sc_ifp;
   2540 	int s;
   2541 
   2542 	if (!sc->sc_attached)
   2543 		return (0);
   2544 
   2545 	s = splnet();
   2546 	callout_stop(&sc->wi_inquire_ch);
   2547 
   2548 	/* Delete all remaining media. */
   2549 	ifmedia_delete_instance(&sc->sc_media, IFM_INST_ANY);
   2550 
   2551 	ether_ifdetach(ifp);
   2552 	if_detach(ifp);
   2553 	if (sc->sc_enabled) {
   2554 		if (sc->sc_disable)
   2555 			(*sc->sc_disable)(sc);
   2556 		sc->sc_enabled = 0;
   2557 	}
   2558 	splx(s);
   2559 	return (0);
   2560 }
   2561 
   2562 void
   2563 wi_power(sc, why)
   2564 	struct wi_softc *sc;
   2565 	int why;
   2566 {
   2567 	int s;
   2568 
   2569 	if (!sc->sc_enabled)
   2570 		return;
   2571 
   2572 	s = splnet();
   2573 	switch (why) {
   2574 	case PWR_SUSPEND:
   2575 	case PWR_STANDBY:
   2576 		wi_stop(sc->sc_ifp, 0);
   2577 		if (sc->sc_enabled) {
   2578 			if (sc->sc_disable)
   2579 				(*sc->sc_disable)(sc);
   2580 		}
   2581 		break;
   2582 	case PWR_RESUME:
   2583 		sc->sc_enabled = 0;
   2584 		wi_init(sc->sc_ifp);
   2585 		(void)wi_intr(sc);
   2586 		break;
   2587 	case PWR_SOFTSUSPEND:
   2588 	case PWR_SOFTSTANDBY:
   2589 	case PWR_SOFTRESUME:
   2590 		break;
   2591 	}
   2592 	splx(s);
   2593 }
   2594 
   2595 static int
   2596 wi_set_ssid(ws, id, len)
   2597 	struct ieee80211_nwid *ws;
   2598 	u_int8_t *id;
   2599 	int len;
   2600 {
   2601 
   2602 	if (len > IEEE80211_NWID_LEN)
   2603 		return (EINVAL);
   2604 	ws->i_len = len;
   2605 	memcpy(ws->i_nwid, id, len);
   2606 	return (0);
   2607 }
   2608 
   2609 static void
   2610 wi_request_fill_ssid(wreq, ws)
   2611 	struct wi_req *wreq;
   2612 	struct ieee80211_nwid *ws;
   2613 {
   2614 	int len = ws->i_len;
   2615 
   2616 	memset(&wreq->wi_val[0], 0, sizeof(wreq->wi_val));
   2617 	wreq->wi_val[0] = htole16(len);
   2618 	wreq->wi_len = roundup(len, 2) / 2 + 2;
   2619 	memcpy(&wreq->wi_val[1], ws->i_nwid, len);
   2620 }
   2621 
   2622 static int
   2623 wi_write_ssid(sc, type, wreq, ws)
   2624 	struct wi_softc *sc;
   2625 	int type;
   2626 	struct wi_req *wreq;
   2627 	struct ieee80211_nwid *ws;
   2628 {
   2629 
   2630 	wreq->wi_type = type;
   2631 	wi_request_fill_ssid(wreq, ws);
   2632 	return (wi_write_record(sc, (struct wi_ltv_gen *)wreq));
   2633 }
   2634 
   2635 static int
   2636 wi_sync_media(sc, ptype, txrate)
   2637 	struct wi_softc *sc;
   2638 	int ptype;
   2639 	int txrate;
   2640 {
   2641 	int media = sc->sc_media.ifm_cur->ifm_media;
   2642 	int options = IFM_OPTIONS(media);
   2643 	int subtype;
   2644 
   2645 	switch (txrate) {
   2646 	case 1:
   2647 		subtype = IFM_IEEE80211_DS1;
   2648 		break;
   2649 	case 2:
   2650 		subtype = IFM_IEEE80211_DS2;
   2651 		break;
   2652 	case 3:
   2653 		subtype = IFM_AUTO;
   2654 		break;
   2655 	case 5:
   2656 		subtype = IFM_IEEE80211_DS5;
   2657 		break;
   2658 	case 11:
   2659 		subtype = IFM_IEEE80211_DS11;
   2660 		break;
   2661 	default:
   2662 		subtype = IFM_MANUAL;		/* Unable to represent */
   2663 		break;
   2664 	}
   2665 
   2666 	options &= ~IFM_OMASK;
   2667 	switch (ptype) {
   2668 	case WI_PORTTYPE_BSS:
   2669 		/* default port type */
   2670 		break;
   2671 	case WI_PORTTYPE_ADHOC:
   2672 		options |= IFM_IEEE80211_ADHOC;
   2673 		break;
   2674 	case WI_PORTTYPE_IBSS:
   2675 		if (sc->wi_create_ibss)
   2676 			options |= IFM_IEEE80211_IBSSMASTER;
   2677 		else
   2678 			options |= IFM_IEEE80211_IBSS;
   2679 		break;
   2680 	default:
   2681 		subtype = IFM_MANUAL;		/* Unable to represent */
   2682 		break;
   2683 	}
   2684 	media = IFM_MAKEWORD(IFM_TYPE(media), subtype, options,
   2685 	    IFM_INST(media));
   2686 	if (ifmedia_match(&sc->sc_media, media, sc->sc_media.ifm_mask) == NULL)
   2687 		return (EINVAL);
   2688 	ifmedia_set(&sc->sc_media, media);
   2689 	sc->wi_ptype = ptype;
   2690 	sc->wi_tx_rate = txrate;
   2691 	return (0);
   2692 }
   2693 
   2694 static int
   2695 wi_media_change(ifp)
   2696 	struct ifnet *ifp;
   2697 {
   2698 	struct wi_softc *sc = ifp->if_softc;
   2699 	int otype = sc->wi_ptype;
   2700 	int orate = sc->wi_tx_rate;
   2701 	int ocreate_ibss = sc->wi_create_ibss;
   2702 
   2703 	sc->wi_create_ibss = 0;
   2704 
   2705 	switch (sc->sc_media.ifm_cur->ifm_media & IFM_OMASK) {
   2706 	case 0:
   2707 		sc->wi_ptype = WI_PORTTYPE_BSS;
   2708 		break;
   2709 	case IFM_IEEE80211_ADHOC:
   2710 		sc->wi_ptype = WI_PORTTYPE_ADHOC;
   2711 		break;
   2712 	case IFM_IEEE80211_HOSTAP:
   2713 		sc->wi_ptype = WI_PORTTYPE_HOSTAP;
   2714 		break;
   2715 	case IFM_IEEE80211_IBSSMASTER:
   2716 	case IFM_IEEE80211_IBSSMASTER|IFM_IEEE80211_IBSS:
   2717 		if ((sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS) == 0)
   2718 			return (EINVAL);
   2719 		sc->wi_create_ibss = 1;
   2720 		/* FALLTHROUGH */
   2721 	case IFM_IEEE80211_IBSS:
   2722 		sc->wi_ptype = WI_PORTTYPE_IBSS;
   2723 		break;
   2724 	default:
   2725 		/* Invalid combination. */
   2726 		sc->wi_create_ibss = ocreate_ibss;
   2727 		return (EINVAL);
   2728 	}
   2729 
   2730 	switch (IFM_SUBTYPE(sc->sc_media.ifm_cur->ifm_media)) {
   2731 	case IFM_IEEE80211_DS1:
   2732 		sc->wi_tx_rate = 1;
   2733 		break;
   2734 	case IFM_IEEE80211_DS2:
   2735 		sc->wi_tx_rate = 2;
   2736 		break;
   2737 	case IFM_AUTO:
   2738 		sc->wi_tx_rate = 3;
   2739 		break;
   2740 	case IFM_IEEE80211_DS5:
   2741 		sc->wi_tx_rate = 5;
   2742 		break;
   2743 	case IFM_IEEE80211_DS11:
   2744 		sc->wi_tx_rate = 11;
   2745 		break;
   2746 	}
   2747 
   2748 	if (sc->sc_enabled != 0) {
   2749 		if (otype != sc->wi_ptype ||
   2750 		    orate != sc->wi_tx_rate ||
   2751 		    ocreate_ibss != sc->wi_create_ibss)
   2752 			wi_init(ifp);
   2753 	}
   2754 
   2755 	ifp->if_baudrate = ifmedia_baudrate(sc->sc_media.ifm_cur->ifm_media);
   2756 
   2757 	return (0);
   2758 }
   2759 
   2760 static void
   2761 wi_media_status(ifp, imr)
   2762 	struct ifnet *ifp;
   2763 	struct ifmediareq *imr;
   2764 {
   2765 	struct wi_softc *sc = ifp->if_softc;
   2766 
   2767 	if (sc->sc_enabled == 0) {
   2768 		imr->ifm_active = IFM_IEEE80211|IFM_NONE;
   2769 		imr->ifm_status = 0;
   2770 		return;
   2771 	}
   2772 
   2773 	imr->ifm_active = sc->sc_media.ifm_cur->ifm_media;
   2774 	imr->ifm_status = IFM_AVALID|IFM_ACTIVE;
   2775 }
   2776 
   2777 static int
   2778 wi_set_nwkey(sc, nwkey)
   2779 	struct wi_softc *sc;
   2780 	struct ieee80211_nwkey *nwkey;
   2781 {
   2782 	int i, error;
   2783 	size_t len;
   2784 	struct wi_req wreq;
   2785 	struct wi_ltv_keys *wk = (struct wi_ltv_keys *)&wreq;
   2786 
   2787 	if ((sc->wi_flags & WI_FLAGS_HAS_WEP) == 0)
   2788 		return ENODEV;
   2789 	if (nwkey->i_defkid <= 0 ||
   2790 	    nwkey->i_defkid > IEEE80211_WEP_NKID)
   2791 		return EINVAL;
   2792 	memcpy(wk, &sc->wi_keys, sizeof(*wk));
   2793 	for (i = 0; i < IEEE80211_WEP_NKID; i++) {
   2794 		if (nwkey->i_key[i].i_keydat == NULL)
   2795 			continue;
   2796 		len = nwkey->i_key[i].i_keylen;
   2797 		if (len > sizeof(wk->wi_keys[i].wi_keydat))
   2798 			return EINVAL;
   2799 		error = copyin(nwkey->i_key[i].i_keydat,
   2800 		    wk->wi_keys[i].wi_keydat, len);
   2801 		if (error)
   2802 			return error;
   2803 		wk->wi_keys[i].wi_keylen = htole16(len);
   2804 	}
   2805 
   2806 	wk->wi_len = (sizeof(*wk) / 2) + 1;
   2807 	wk->wi_type = WI_RID_DEFLT_CRYPT_KEYS;
   2808 	if (sc->sc_enabled != 0) {
   2809 		error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
   2810 		if (error)
   2811 			return error;
   2812 	}
   2813 	error = wi_setdef(sc, &wreq);
   2814 	if (error)
   2815 		return error;
   2816 
   2817 	wreq.wi_len = 2;
   2818 	wreq.wi_type = WI_RID_TX_CRYPT_KEY;
   2819 	wreq.wi_val[0] = htole16(nwkey->i_defkid - 1);
   2820 	if (sc->sc_enabled != 0) {
   2821 		error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
   2822 		if (error)
   2823 			return error;
   2824 	}
   2825 	error = wi_setdef(sc, &wreq);
   2826 	if (error)
   2827 		return error;
   2828 
   2829 	wreq.wi_type = WI_RID_ENCRYPTION;
   2830 	wreq.wi_val[0] = htole16(nwkey->i_wepon);
   2831 	if (sc->sc_enabled != 0) {
   2832 		error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
   2833 		if (error)
   2834 			return error;
   2835 	}
   2836 	error = wi_setdef(sc, &wreq);
   2837 	if (error)
   2838 		return error;
   2839 
   2840 	if (sc->sc_enabled != 0)
   2841 		wi_init(&sc->sc_ethercom.ec_if);
   2842 	return 0;
   2843 }
   2844 
   2845 static int
   2846 wi_get_nwkey(sc, nwkey)
   2847 	struct wi_softc *sc;
   2848 	struct ieee80211_nwkey *nwkey;
   2849 {
   2850 	int i, len, error;
   2851 	struct wi_ltv_keys *wk = &sc->wi_keys;
   2852 
   2853 	if ((sc->wi_flags & WI_FLAGS_HAS_WEP) == 0)
   2854 		return ENODEV;
   2855 	nwkey->i_wepon = sc->wi_use_wep;
   2856 	nwkey->i_defkid = sc->wi_tx_key + 1;
   2857 
   2858 	/* do not show any keys to non-root user */
   2859 	error = suser(curproc->p_ucred, &curproc->p_acflag);
   2860 	for (i = 0; i < IEEE80211_WEP_NKID; i++) {
   2861 		if (nwkey->i_key[i].i_keydat == NULL)
   2862 			continue;
   2863 		/* error holds results of suser() for the first time */
   2864 		if (error)
   2865 			return error;
   2866 		len = le16toh(wk->wi_keys[i].wi_keylen);
   2867 		if (nwkey->i_key[i].i_keylen < len)
   2868 			return ENOSPC;
   2869 		nwkey->i_key[i].i_keylen = len;
   2870 		error = copyout(wk->wi_keys[i].wi_keydat,
   2871 		    nwkey->i_key[i].i_keydat, len);
   2872 		if (error)
   2873 			return error;
   2874 	}
   2875 	return 0;
   2876 }
   2877 
   2878 static int
   2879 wi_set_pm(struct wi_softc *sc, struct ieee80211_power *power)
   2880 {
   2881 
   2882 	sc->wi_pm_enabled = power->i_enabled;
   2883 	sc->wi_max_sleep = power->i_maxsleep;
   2884 
   2885 	if (sc->sc_enabled)
   2886 		return (wi_init(&sc->sc_ethercom.ec_if));
   2887 
   2888 	return (0);
   2889 }
   2890 
   2891 static int
   2892 wi_get_pm(struct wi_softc *sc, struct ieee80211_power *power)
   2893 {
   2894 
   2895 	power->i_enabled = sc->wi_pm_enabled;
   2896 	power->i_maxsleep = sc->wi_max_sleep;
   2897 
   2898 	return (0);
   2899 }
   2900