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