xref: /openbsd/sys/dev/ic/if_wi.c (revision 8529ddd3)
1 /*	$OpenBSD: if_wi.c,v 1.160 2015/03/14 03:38:47 jsg Exp $	*/
2 
3 /*
4  * Copyright (c) 1997, 1998, 1999
5  *	Bill Paul <wpaul@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  *	From: if_wi.c,v 1.7 1999/07/04 14:40:22 wpaul Exp $
35  */
36 
37 /*
38  * Lucent WaveLAN/IEEE 802.11 driver for OpenBSD.
39  *
40  * Originally written by Bill Paul <wpaul@ctr.columbia.edu>
41  * Electrical Engineering Department
42  * Columbia University, New York City
43  */
44 
45 /*
46  * The WaveLAN/IEEE adapter is the second generation of the WaveLAN
47  * from Lucent. Unlike the older cards, the new ones are programmed
48  * entirely via a firmware-driven controller called the Hermes.
49  * Unfortunately, Lucent will not release the Hermes programming manual
50  * without an NDA (if at all). What they do release is an API library
51  * called the HCF (Hardware Control Functions) which is supposed to
52  * do the device-specific operations of a device driver for you. The
53  * publicly available version of the HCF library (the 'HCF Light') is
54  * a) extremely gross, b) lacks certain features, particularly support
55  * for 802.11 frames, and c) is contaminated by the GNU Public License.
56  *
57  * This driver does not use the HCF or HCF Light at all. Instead, it
58  * programs the Hermes controller directly, using information gleaned
59  * from the HCF Light code and corresponding documentation.
60  */
61 
62 #define WI_HERMES_AUTOINC_WAR	/* Work around data write autoinc bug. */
63 #define WI_HERMES_STATS_WAR	/* Work around stats counter bug. */
64 
65 #include "bpfilter.h"
66 
67 #include <sys/param.h>
68 #include <sys/systm.h>
69 #include <sys/sockio.h>
70 #include <sys/mbuf.h>
71 #include <sys/malloc.h>
72 #include <sys/kernel.h>
73 #include <sys/socket.h>
74 #include <sys/device.h>
75 
76 #include <net/if.h>
77 #include <net/if_dl.h>
78 #include <net/if_media.h>
79 
80 #include <netinet/in.h>
81 #include <netinet/if_ether.h>
82 
83 #include <net80211/ieee80211_var.h>
84 #include <net80211/ieee80211_ioctl.h>
85 
86 #if NBPFILTER > 0
87 #include <net/bpf.h>
88 #endif
89 
90 #include <machine/bus.h>
91 
92 #include <dev/ic/if_wireg.h>
93 #include <dev/ic/if_wi_ieee.h>
94 #include <dev/ic/if_wivar.h>
95 
96 #include <crypto/arc4.h>
97 
98 #define BPFATTACH(if_bpf,if,dlt,sz)
99 #define STATIC
100 
101 #ifdef WIDEBUG
102 
103 u_int32_t	widebug = WIDEBUG;
104 
105 #define WID_INTR	0x01
106 #define WID_START	0x02
107 #define WID_IOCTL	0x04
108 #define WID_INIT	0x08
109 #define WID_STOP	0x10
110 #define WID_RESET	0x20
111 
112 #define DPRINTF(mask,args) if (widebug & (mask)) printf args;
113 
114 #else	/* !WIDEBUG */
115 #define DPRINTF(mask,args)
116 #endif	/* WIDEBUG */
117 
118 #ifdef foo
119 static u_int8_t	wi_mcast_addr[6] = { 0x01, 0x60, 0x1D, 0x00, 0x01, 0x00 };
120 #endif
121 
122 STATIC void wi_reset(struct wi_softc *);
123 STATIC int wi_ioctl(struct ifnet *, u_long, caddr_t);
124 STATIC void wi_init_io(struct wi_softc *);
125 STATIC void wi_start(struct ifnet *);
126 STATIC void wi_watchdog(struct ifnet *);
127 STATIC void wi_rxeof(struct wi_softc *);
128 STATIC void wi_txeof(struct wi_softc *, int);
129 STATIC void wi_update_stats(struct wi_softc *);
130 STATIC void wi_setmulti(struct wi_softc *);
131 
132 STATIC int wi_cmd_io(struct wi_softc *, int, int, int, int);
133 STATIC int wi_read_record_io(struct wi_softc *, struct wi_ltv_gen *);
134 STATIC int wi_write_record_io(struct wi_softc *, struct wi_ltv_gen *);
135 STATIC int wi_read_data_io(struct wi_softc *, int,
136 					int, caddr_t, int);
137 STATIC int wi_write_data_io(struct wi_softc *, int,
138 					int, caddr_t, int);
139 STATIC int wi_seek(struct wi_softc *, int, int, int);
140 
141 STATIC void wi_inquire(void *);
142 STATIC int wi_setdef(struct wi_softc *, struct wi_req *);
143 STATIC void wi_get_id(struct wi_softc *);
144 
145 STATIC int wi_media_change(struct ifnet *);
146 STATIC void wi_media_status(struct ifnet *, struct ifmediareq *);
147 
148 STATIC int wi_set_ssid(struct ieee80211_nwid *, u_int8_t *, int);
149 STATIC int wi_set_nwkey(struct wi_softc *, struct ieee80211_nwkey *);
150 STATIC int wi_get_nwkey(struct wi_softc *, struct ieee80211_nwkey *);
151 STATIC int wi_sync_media(struct wi_softc *, int, int);
152 STATIC int wi_set_pm(struct wi_softc *, struct ieee80211_power *);
153 STATIC int wi_get_pm(struct wi_softc *, struct ieee80211_power *);
154 STATIC int wi_set_txpower(struct wi_softc *, struct ieee80211_txpower *);
155 STATIC int wi_get_txpower(struct wi_softc *, struct ieee80211_txpower *);
156 
157 STATIC int wi_get_debug(struct wi_softc *, struct wi_req *);
158 STATIC int wi_set_debug(struct wi_softc *, struct wi_req *);
159 
160 STATIC void wi_do_hostencrypt(struct wi_softc *, caddr_t, int);
161 STATIC int wi_do_hostdecrypt(struct wi_softc *, caddr_t, int);
162 
163 STATIC int wi_alloc_nicmem_io(struct wi_softc *, int, int *);
164 STATIC int wi_get_fid_io(struct wi_softc *sc, int fid);
165 STATIC void wi_intr_enable(struct wi_softc *sc, int mode);
166 STATIC void wi_intr_ack(struct wi_softc *sc, int mode);
167 void	 wi_scan_timeout(void *);
168 
169 /* Autoconfig definition of driver back-end */
170 struct cfdriver wi_cd = {
171 	NULL, "wi", DV_IFNET
172 };
173 
174 const struct wi_card_ident wi_card_ident[] = {
175 	WI_CARD_IDS
176 };
177 
178 struct wi_funcs wi_func_io = {
179         wi_cmd_io,
180         wi_read_record_io,
181         wi_write_record_io,
182         wi_alloc_nicmem_io,
183         wi_read_data_io,
184         wi_write_data_io,
185         wi_get_fid_io,
186         wi_init_io,
187 
188         wi_start,
189         wi_ioctl,
190         wi_watchdog,
191         wi_inquire,
192 };
193 
194 int
195 wi_attach(struct wi_softc *sc, struct wi_funcs *funcs)
196 {
197 	struct ieee80211com	*ic;
198 	struct ifnet		*ifp;
199 	struct wi_ltv_macaddr	mac;
200 	struct wi_ltv_rates	rates;
201 	struct wi_ltv_gen	gen;
202 	int			error;
203 
204 	ic = &sc->sc_ic;
205 	ifp = &ic->ic_if;
206 
207 	sc->sc_funcs = funcs;
208 	sc->wi_cmd_count = 500;
209 
210 	wi_reset(sc);
211 
212 	/* Read the station address. */
213 	mac.wi_type = WI_RID_MAC_NODE;
214 	mac.wi_len = 4;
215 	error = wi_read_record(sc, (struct wi_ltv_gen *)&mac);
216 	if (error) {
217 		printf(": unable to read station address\n");
218 		return (error);
219 	}
220 	bcopy(&mac.wi_mac_addr, &ic->ic_myaddr, IEEE80211_ADDR_LEN);
221 
222 	wi_get_id(sc);
223 	printf("address %s", ether_sprintf(ic->ic_myaddr));
224 
225 	bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
226 	ifp->if_softc = sc;
227 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
228 	ifp->if_ioctl = funcs->f_ioctl;
229 	ifp->if_start = funcs->f_start;
230 	ifp->if_watchdog = funcs->f_watchdog;
231 	IFQ_SET_READY(&ifp->if_snd);
232 
233 	(void)wi_set_ssid(&sc->wi_node_name, WI_DEFAULT_NODENAME,
234 	    sizeof(WI_DEFAULT_NODENAME) - 1);
235 	(void)wi_set_ssid(&sc->wi_net_name, WI_DEFAULT_NETNAME,
236 	    sizeof(WI_DEFAULT_NETNAME) - 1);
237 	(void)wi_set_ssid(&sc->wi_ibss_name, WI_DEFAULT_IBSS,
238 	    sizeof(WI_DEFAULT_IBSS) - 1);
239 
240 	sc->wi_portnum = WI_DEFAULT_PORT;
241 	sc->wi_ptype = WI_PORTTYPE_BSS;
242 	sc->wi_ap_density = WI_DEFAULT_AP_DENSITY;
243 	sc->wi_rts_thresh = WI_DEFAULT_RTS_THRESH;
244 	sc->wi_tx_rate = WI_DEFAULT_TX_RATE;
245 	sc->wi_max_data_len = WI_DEFAULT_DATALEN;
246 	sc->wi_create_ibss = WI_DEFAULT_CREATE_IBSS;
247 	sc->wi_pm_enabled = WI_DEFAULT_PM_ENABLED;
248 	sc->wi_max_sleep = WI_DEFAULT_MAX_SLEEP;
249 	sc->wi_roaming = WI_DEFAULT_ROAMING;
250 	sc->wi_authtype = WI_DEFAULT_AUTHTYPE;
251 	sc->wi_diversity = WI_DEFAULT_DIVERSITY;
252 	sc->wi_crypto_algorithm = WI_CRYPTO_FIRMWARE_WEP;
253 
254 	/*
255 	 * Read the default channel from the NIC. This may vary
256 	 * depending on the country where the NIC was purchased, so
257 	 * we can't hard-code a default and expect it to work for
258 	 * everyone.
259 	 */
260 	gen.wi_type = WI_RID_OWN_CHNL;
261 	gen.wi_len = 2;
262 	if (wi_read_record(sc, &gen) == 0)
263 		sc->wi_channel = letoh16(gen.wi_val);
264 	else
265 		sc->wi_channel = 3;
266 
267 	/*
268 	 * Set flags based on firmware version.
269 	 */
270 	switch (sc->sc_firmware_type) {
271 	case WI_LUCENT:
272 		sc->wi_flags |= WI_FLAGS_HAS_ROAMING;
273 		if (sc->sc_sta_firmware_ver >= 60000)
274 			sc->wi_flags |= WI_FLAGS_HAS_MOR;
275 		if (sc->sc_sta_firmware_ver >= 60006) {
276 			sc->wi_flags |= WI_FLAGS_HAS_IBSS;
277 			sc->wi_flags |= WI_FLAGS_HAS_CREATE_IBSS;
278 		}
279 		sc->wi_ibss_port = htole16(1);
280 		break;
281 	case WI_INTERSIL:
282 		sc->wi_flags |= WI_FLAGS_HAS_ROAMING;
283 		/* older prism firmware is slow so crank the count */
284 		if (sc->sc_sta_firmware_ver < 10000)
285 			sc->wi_cmd_count = 5000;
286 		else
287 			sc->wi_cmd_count = 2000;
288 		if (sc->sc_sta_firmware_ver >= 800) {
289 #ifndef SMALL_KERNEL
290 			/*
291 			 * USB hostap is more pain than it is worth
292 			 * for now, things would have to be overhauled
293 			 */
294 			if ((sc->sc_sta_firmware_ver != 10402) &&
295 			    (!(sc->wi_flags & WI_FLAGS_BUS_USB)))
296 				sc->wi_flags |= WI_FLAGS_HAS_HOSTAP;
297 #endif
298 			sc->wi_flags |= WI_FLAGS_HAS_IBSS;
299 			sc->wi_flags |= WI_FLAGS_HAS_CREATE_IBSS;
300 		}
301 		if (sc->sc_sta_firmware_ver >= 10603)
302 			sc->wi_flags |= WI_FLAGS_HAS_ENH_SECURITY;
303 		sc->wi_ibss_port = htole16(0);
304 		break;
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 && gen.wi_val != htole16(0))
321 		sc->wi_flags |= WI_FLAGS_HAS_WEP;
322 	timeout_set(&sc->sc_timo, funcs->f_inquire, sc);
323 
324 	bzero(&sc->wi_stats, sizeof(sc->wi_stats));
325 
326 	/* Find supported rates. */
327 	rates.wi_type = WI_RID_DATA_RATES;
328 	rates.wi_len = sizeof(rates.wi_rates);
329 	if (wi_read_record(sc, (struct wi_ltv_gen *)&rates) == 0) {
330 		int i, nrates;
331 
332 		nrates = letoh16(*(u_int16_t *)rates.wi_rates);
333 		if (nrates > sizeof(rates.wi_rates) - 2)
334 			nrates = sizeof(rates.wi_rates) - 2;
335 
336 		sc->wi_supprates = 0;
337 		for (i = 0; i < nrates; i++)
338 			sc->wi_supprates |= rates.wi_rates[2 + i];
339 	} else
340 		sc->wi_supprates = WI_SUPPRATES_1M | WI_SUPPRATES_2M |
341 		    WI_SUPPRATES_5M | WI_SUPPRATES_11M;
342 
343 	ifmedia_init(&sc->sc_media, 0, wi_media_change, wi_media_status);
344 #define	ADD(m, c)	ifmedia_add(&sc->sc_media, (m), (c), NULL)
345 	ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 0, 0), 0);
346 	ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, IFM_IEEE80211_ADHOC, 0), 0);
347 	if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
348 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, IFM_IEEE80211_IBSS,
349 		    0), 0);
350 	if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
351 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO,
352 		    IFM_IEEE80211_IBSSMASTER, 0), 0);
353 	if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)
354 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO,
355 		    IFM_IEEE80211_HOSTAP, 0), 0);
356 	if (sc->wi_supprates & WI_SUPPRATES_1M) {
357 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1, 0, 0), 0);
358 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
359 		    IFM_IEEE80211_ADHOC, 0), 0);
360 		if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
361 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
362 			    IFM_IEEE80211_IBSS, 0), 0);
363 		if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
364 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
365 			    IFM_IEEE80211_IBSSMASTER, 0), 0);
366 		if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)
367 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
368 			    IFM_IEEE80211_HOSTAP, 0), 0);
369 	}
370 	if (sc->wi_supprates & WI_SUPPRATES_2M) {
371 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2, 0, 0), 0);
372 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
373 		    IFM_IEEE80211_ADHOC, 0), 0);
374 		if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
375 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
376 			    IFM_IEEE80211_IBSS, 0), 0);
377 		if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
378 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
379 			    IFM_IEEE80211_IBSSMASTER, 0), 0);
380 		if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)
381 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
382 			    IFM_IEEE80211_HOSTAP, 0), 0);
383 	}
384 	if (sc->wi_supprates & WI_SUPPRATES_5M) {
385 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5, 0, 0), 0);
386 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
387 		    IFM_IEEE80211_ADHOC, 0), 0);
388 		if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
389 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
390 			    IFM_IEEE80211_IBSS, 0), 0);
391 		if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
392 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
393 			    IFM_IEEE80211_IBSSMASTER, 0), 0);
394 		if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)
395 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
396 			    IFM_IEEE80211_HOSTAP, 0), 0);
397 	}
398 	if (sc->wi_supprates & WI_SUPPRATES_11M) {
399 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11, 0, 0), 0);
400 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
401 		    IFM_IEEE80211_ADHOC, 0), 0);
402 		if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
403 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
404 			    IFM_IEEE80211_IBSS, 0), 0);
405 		if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
406 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
407 			    IFM_IEEE80211_IBSSMASTER, 0), 0);
408 		if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)
409 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
410 			    IFM_IEEE80211_HOSTAP, 0), 0);
411 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_MANUAL, 0, 0), 0);
412 	}
413 #undef ADD
414 	ifmedia_set(&sc->sc_media,
415 	    IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 0, 0));
416 
417 	/*
418 	 * Call MI attach routines.
419 	 */
420 	if_attach(ifp);
421 	memcpy(((struct arpcom *)ifp)->ac_enaddr, ic->ic_myaddr,
422 	    ETHER_ADDR_LEN);
423 	ether_ifattach(ifp);
424 	printf("\n");
425 
426 	sc->wi_flags |= WI_FLAGS_ATTACHED;
427 
428 #if NBPFILTER > 0
429 	BPFATTACH(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
430 #endif
431 
432 	if_addgroup(ifp, "wlan");
433 	ifp->if_priority = IF_WIRELESS_DEFAULT_PRIORITY;
434 
435 	wi_init(sc);
436 	wi_stop(sc);
437 
438 	return (0);
439 }
440 
441 STATIC void
442 wi_intr_enable(struct wi_softc *sc, int mode)
443 {
444 	if (!(sc->wi_flags & WI_FLAGS_BUS_USB))
445 		CSR_WRITE_2(sc, WI_INT_EN, mode);
446 }
447 
448 STATIC void
449 wi_intr_ack(struct wi_softc *sc, int mode)
450 {
451 	if (!(sc->wi_flags & WI_FLAGS_BUS_USB))
452 		CSR_WRITE_2(sc, WI_EVENT_ACK, mode);
453 }
454 
455 int
456 wi_intr(void *vsc)
457 {
458 	struct wi_softc		*sc = vsc;
459 	struct ifnet		*ifp;
460 	u_int16_t		status;
461 
462 	DPRINTF(WID_INTR, ("wi_intr: sc %p\n", sc));
463 
464 	ifp = &sc->sc_ic.ic_if;
465 
466 	if (!(sc->wi_flags & WI_FLAGS_ATTACHED) || !(ifp->if_flags & IFF_UP)) {
467 		CSR_WRITE_2(sc, WI_INT_EN, 0);
468 		CSR_WRITE_2(sc, WI_EVENT_ACK, 0xffff);
469 		return (0);
470 	}
471 
472 	/* Disable interrupts. */
473 	CSR_WRITE_2(sc, WI_INT_EN, 0);
474 
475 	status = CSR_READ_2(sc, WI_EVENT_STAT);
476 	CSR_WRITE_2(sc, WI_EVENT_ACK, ~WI_INTRS);
477 
478 	if (status & WI_EV_RX) {
479 		wi_rxeof(sc);
480 		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
481 	}
482 
483 	if (status & WI_EV_TX) {
484 		wi_txeof(sc, status);
485 		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX);
486 	}
487 
488 	if (status & WI_EV_ALLOC) {
489 		int			id;
490 		id = CSR_READ_2(sc, WI_ALLOC_FID);
491 		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
492 		if (id == sc->wi_tx_data_id)
493 			wi_txeof(sc, status);
494 	}
495 
496 	if (status & WI_EV_INFO) {
497 		wi_update_stats(sc);
498 		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO);
499 	}
500 
501 	if (status & WI_EV_TX_EXC) {
502 		wi_txeof(sc, status);
503 		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX_EXC);
504 	}
505 
506 	if (status & WI_EV_INFO_DROP) {
507 		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO_DROP);
508 	}
509 
510 	/* Re-enable interrupts. */
511 	CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
512 
513 	if (status == 0)
514 		return (0);
515 
516 	if (!IFQ_IS_EMPTY(&ifp->if_snd))
517 		wi_start(ifp);
518 
519 	return (1);
520 }
521 
522 STATIC int
523 wi_get_fid_io(struct wi_softc *sc, int fid)
524 {
525 	return CSR_READ_2(sc, fid);
526 }
527 
528 
529 void
530 wi_rxeof(struct wi_softc *sc)
531 {
532 	struct ifnet		*ifp;
533 	struct ether_header	*eh;
534 	struct mbuf		*m;
535 	caddr_t			olddata;
536 	u_int16_t		ftype;
537 	int			maxlen;
538 	int			id;
539 
540 	ifp = &sc->sc_ic.ic_if;
541 
542 	id = wi_get_fid(sc, WI_RX_FID);
543 
544 	if (sc->wi_procframe || sc->wi_debug.wi_monitor) {
545 		struct wi_frame	*rx_frame;
546 		int		datlen, hdrlen;
547 
548 		MGETHDR(m, M_DONTWAIT, MT_DATA);
549 		if (m == NULL) {
550 			ifp->if_ierrors++;
551 			return;
552 		}
553 		MCLGET(m, M_DONTWAIT);
554 		if (!(m->m_flags & M_EXT)) {
555 			m_freem(m);
556 			ifp->if_ierrors++;
557 			return;
558 		}
559 
560 		m->m_pkthdr.rcvif = ifp;
561 
562 		if (wi_read_data(sc, id, 0, mtod(m, caddr_t),
563 		    sizeof(struct wi_frame))) {
564 			m_freem(m);
565 			ifp->if_ierrors++;
566 			return;
567 		}
568 
569 		rx_frame = mtod(m, struct wi_frame *);
570 
571 		if (rx_frame->wi_status & htole16(WI_STAT_BADCRC)) {
572 			m_freem(m);
573 			ifp->if_ierrors++;
574 			return;
575 		}
576 
577 		switch ((letoh16(rx_frame->wi_status) & WI_STAT_MAC_PORT)
578 		    >> 8) {
579 		case 7:
580 			switch (letoh16(rx_frame->wi_frame_ctl) &
581 			    WI_FCTL_FTYPE) {
582 			case WI_FTYPE_DATA:
583 				hdrlen = WI_DATA_HDRLEN;
584 				datlen = letoh16(rx_frame->wi_dat_len);
585 				break;
586 			case WI_FTYPE_MGMT:
587 				hdrlen = WI_MGMT_HDRLEN;
588 				datlen = letoh16(rx_frame->wi_dat_len);
589 				break;
590 			case WI_FTYPE_CTL:
591 				hdrlen = WI_CTL_HDRLEN;
592 				datlen = 0;
593 				break;
594 			default:
595 				printf(WI_PRT_FMT ": received packet of "
596 				    "unknown type on port 7\n", WI_PRT_ARG(sc));
597 				m_freem(m);
598 				ifp->if_ierrors++;
599 				return;
600 			}
601 			break;
602 		case 0:
603 			hdrlen = WI_DATA_HDRLEN;
604 			datlen = letoh16(rx_frame->wi_dat_len);
605 			break;
606 		default:
607 			printf(WI_PRT_FMT ": received packet on invalid port "
608 			    "(wi_status=0x%x)\n", WI_PRT_ARG(sc),
609 			    letoh16(rx_frame->wi_status));
610 			m_freem(m);
611 			ifp->if_ierrors++;
612 			return;
613 		}
614 
615 		if ((hdrlen + datlen + 2) > MCLBYTES) {
616 			m_freem(m);
617 			ifp->if_ierrors++;
618 			return;
619 		}
620 
621 		if (wi_read_data(sc, id, hdrlen, mtod(m, caddr_t) + hdrlen,
622 		    datlen + 2)) {
623 			m_freem(m);
624 			ifp->if_ierrors++;
625 			return;
626 		}
627 
628 		m->m_pkthdr.len = m->m_len = hdrlen + datlen;
629 	} else {
630 		struct wi_frame rx_frame;
631 
632 		/* First read in the frame header */
633 		if (wi_read_data(sc, id, 0, (caddr_t)&rx_frame,
634 		    sizeof(rx_frame))) {
635 			ifp->if_ierrors++;
636 			return;
637 		}
638 
639 		/* Drop undecryptable or packets with receive errors here */
640 		if (rx_frame.wi_status & htole16(WI_STAT_ERRSTAT)) {
641 			ifp->if_ierrors++;
642 			return;
643 		}
644 
645 		/* Stash frame type in host byte order for later use */
646 		ftype = letoh16(rx_frame.wi_frame_ctl) & WI_FCTL_FTYPE;
647 
648 		MGETHDR(m, M_DONTWAIT, MT_DATA);
649 		if (m == NULL) {
650 			ifp->if_ierrors++;
651 			return;
652 		}
653 		MCLGET(m, M_DONTWAIT);
654 		if (!(m->m_flags & M_EXT)) {
655 			m_freem(m);
656 			ifp->if_ierrors++;
657 			return;
658 		}
659 
660 		olddata = m->m_data;
661 		/* Align the data after the ethernet header */
662 		m->m_data = (caddr_t)ALIGN(m->m_data +
663 		    sizeof(struct ether_header)) - sizeof(struct ether_header);
664 
665 		eh = mtod(m, struct ether_header *);
666 		maxlen = MCLBYTES - (m->m_data - olddata);
667 		m->m_pkthdr.rcvif = ifp;
668 
669 		if (ftype == WI_FTYPE_MGMT &&
670 		    sc->wi_ptype == WI_PORTTYPE_HOSTAP) {
671 
672 			u_int16_t rxlen = letoh16(rx_frame.wi_dat_len);
673 
674 			if ((WI_802_11_OFFSET_RAW + rxlen + 2) > maxlen) {
675 				printf("%s: oversized mgmt packet received in "
676 				    "hostap mode (wi_dat_len=%d, "
677 				    "wi_status=0x%x)\n", sc->sc_dev.dv_xname,
678 				    rxlen, letoh16(rx_frame.wi_status));
679 				m_freem(m);
680 				ifp->if_ierrors++;
681 				return;
682 			}
683 
684 			/* Put the whole header in there. */
685 			bcopy(&rx_frame, mtod(m, void *),
686 			    sizeof(struct wi_frame));
687 			if (wi_read_data(sc, id, WI_802_11_OFFSET_RAW,
688 			    mtod(m, caddr_t) + WI_802_11_OFFSET_RAW,
689 			    rxlen + 2)) {
690 				m_freem(m);
691 				if (sc->sc_ic.ic_if.if_flags & IFF_DEBUG)
692 					printf("wihap: failed to copy header\n");
693 				ifp->if_ierrors++;
694 				return;
695 			}
696 
697 			m->m_pkthdr.len = m->m_len =
698 			    WI_802_11_OFFSET_RAW + rxlen;
699 
700 			/* XXX: consider giving packet to bhp? */
701 
702 			wihap_mgmt_input(sc, &rx_frame, m);
703 
704 			return;
705 		}
706 
707 		switch (letoh16(rx_frame.wi_status) & WI_RXSTAT_MSG_TYPE) {
708 		case WI_STAT_1042:
709 		case WI_STAT_TUNNEL:
710 		case WI_STAT_WMP_MSG:
711 			if ((letoh16(rx_frame.wi_dat_len) + WI_SNAPHDR_LEN) >
712 			    maxlen) {
713 				printf(WI_PRT_FMT ": oversized packet received "
714 				    "(wi_dat_len=%d, wi_status=0x%x)\n",
715 				    WI_PRT_ARG(sc),
716 				    letoh16(rx_frame.wi_dat_len),
717 				    letoh16(rx_frame.wi_status));
718 				m_freem(m);
719 				ifp->if_ierrors++;
720 				return;
721 			}
722 			m->m_pkthdr.len = m->m_len =
723 			    letoh16(rx_frame.wi_dat_len) + WI_SNAPHDR_LEN;
724 
725 			bcopy(&rx_frame.wi_dst_addr,
726 			    &eh->ether_dhost, ETHER_ADDR_LEN);
727 			bcopy(&rx_frame.wi_src_addr,
728 			    &eh->ether_shost, ETHER_ADDR_LEN);
729 			bcopy(&rx_frame.wi_type,
730 			    &eh->ether_type, ETHER_TYPE_LEN);
731 
732 			if (wi_read_data(sc, id, WI_802_11_OFFSET,
733 			    mtod(m, caddr_t) + sizeof(struct ether_header),
734 			    m->m_len + 2)) {
735 				ifp->if_ierrors++;
736 				m_freem(m);
737 				return;
738 			}
739 			break;
740 		default:
741 			if ((letoh16(rx_frame.wi_dat_len) +
742 			    sizeof(struct ether_header)) > maxlen) {
743 				printf(WI_PRT_FMT ": oversized packet received "
744 				    "(wi_dat_len=%d, wi_status=0x%x)\n",
745 				    WI_PRT_ARG(sc),
746 				    letoh16(rx_frame.wi_dat_len),
747 				    letoh16(rx_frame.wi_status));
748 				m_freem(m);
749 				ifp->if_ierrors++;
750 				return;
751 			}
752 			m->m_pkthdr.len = m->m_len =
753 			    letoh16(rx_frame.wi_dat_len) +
754 			    sizeof(struct ether_header);
755 
756 			if (wi_read_data(sc, id, WI_802_3_OFFSET,
757 			    mtod(m, caddr_t), m->m_len + 2)) {
758 				m_freem(m);
759 				ifp->if_ierrors++;
760 				return;
761 			}
762 			break;
763 		}
764 
765 		ifp->if_ipackets++;
766 
767 		if (sc->wi_use_wep &&
768 		    rx_frame.wi_frame_ctl & htole16(WI_FCTL_WEP)) {
769 			int len;
770 
771 			switch (sc->wi_crypto_algorithm) {
772 			case WI_CRYPTO_FIRMWARE_WEP:
773 				break;
774 			case WI_CRYPTO_SOFTWARE_WEP:
775 				m_copydata(m, 0, m->m_pkthdr.len,
776 				    (caddr_t)sc->wi_rxbuf);
777 				len = m->m_pkthdr.len -
778 				    sizeof(struct ether_header);
779 				if (wi_do_hostdecrypt(sc, sc->wi_rxbuf +
780 				    sizeof(struct ether_header), len)) {
781 					if (sc->sc_ic.ic_if.if_flags & IFF_DEBUG)
782 						printf(WI_PRT_FMT ": Error decrypting incoming packet.\n", WI_PRT_ARG(sc));
783 					m_freem(m);
784 					ifp->if_ierrors++;
785 					return;
786 				}
787 				len -= IEEE80211_WEP_IVLEN +
788 				    IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN;
789 				/*
790 				 * copy data back to mbufs:
791 				 * we need to ditch the IV & most LLC/SNAP stuff
792 				 * (except SNAP type, we're going use that to
793 				 * overwrite the ethertype in the ether_header)
794 				 */
795 				m_copyback(m, sizeof(struct ether_header) -
796 				    WI_ETHERTYPE_LEN, WI_ETHERTYPE_LEN +
797 				    (len - WI_SNAPHDR_LEN),
798 				    sc->wi_rxbuf + sizeof(struct ether_header) +
799 				    IEEE80211_WEP_IVLEN +
800 				    IEEE80211_WEP_KIDLEN + WI_SNAPHDR_LEN,
801 				    M_NOWAIT);
802 				m_adj(m, -(WI_ETHERTYPE_LEN +
803 				    IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN +
804 				    WI_SNAPHDR_LEN));
805 				break;
806 			}
807 		}
808 
809 		if (sc->wi_ptype == WI_PORTTYPE_HOSTAP) {
810 			/*
811 			 * Give host AP code first crack at data packets.
812 			 * If it decides to handle it (or drop it), it will
813 			 * return a non-zero.  Otherwise, it is destined for
814 			 * this host.
815 			 */
816 			if (wihap_data_input(sc, &rx_frame, m))
817 				return;
818 		}
819 	}
820 
821 #if NBPFILTER > 0
822 	/* Handle BPF listeners. */
823 	if (ifp->if_bpf)
824 		bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
825 #endif
826 
827 	/* Receive packet unless in procframe or monitor mode. */
828 	if (sc->wi_procframe || sc->wi_debug.wi_monitor)
829 		m_freem(m);
830 	else
831 		ether_input_mbuf(ifp, m);
832 
833 	return;
834 }
835 
836 void
837 wi_txeof(struct wi_softc *sc, int status)
838 {
839 	struct ifnet		*ifp;
840 
841 	ifp = &sc->sc_ic.ic_if;
842 
843 	ifp->if_timer = 0;
844 	ifp->if_flags &= ~IFF_OACTIVE;
845 
846 	if (status & WI_EV_TX_EXC)
847 		ifp->if_oerrors++;
848 	else
849 		ifp->if_opackets++;
850 
851 	return;
852 }
853 
854 void
855 wi_inquire(void *xsc)
856 {
857 	struct wi_softc		*sc;
858 	struct ifnet		*ifp;
859 	int s, rv;
860 
861 	sc = xsc;
862 	ifp = &sc->sc_ic.ic_if;
863 
864 	timeout_add_sec(&sc->sc_timo, 60);
865 
866 	/* Don't do this while we're transmitting */
867 	if (ifp->if_flags & IFF_OACTIVE)
868 		return;
869 
870 	s = splnet();
871 	rv = wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_COUNTERS, 0, 0);
872 	splx(s);
873 	if (rv)
874 		printf(WI_PRT_FMT ": wi_cmd failed with %d\n", WI_PRT_ARG(sc),
875 		    rv);
876 
877 	return;
878 }
879 
880 void
881 wi_update_stats(struct wi_softc *sc)
882 {
883 	struct wi_ltv_gen	gen;
884 	u_int16_t		id;
885 	struct ifnet		*ifp;
886 	u_int32_t		*ptr;
887 	int			len, i;
888 	u_int16_t		t;
889 
890 	ifp = &sc->sc_ic.ic_if;
891 
892 	id = wi_get_fid(sc, WI_INFO_FID);
893 
894 	wi_read_data(sc, id, 0, (char *)&gen, 4);
895 
896 	if (gen.wi_type == htole16(WI_INFO_SCAN_RESULTS)) {
897 		sc->wi_scanbuf_len = letoh16(gen.wi_len);
898 		wi_read_data(sc, id, 4, (caddr_t)sc->wi_scanbuf,
899 		    sc->wi_scanbuf_len * 2);
900 		return;
901 	} else if (gen.wi_type != htole16(WI_INFO_COUNTERS))
902 		return;
903 
904 	/* Some card versions have a larger stats structure */
905 	len = (letoh16(gen.wi_len) - 1 < sizeof(sc->wi_stats) / 4) ?
906 	    letoh16(gen.wi_len) - 1 : sizeof(sc->wi_stats) / 4;
907 
908 	ptr = (u_int32_t *)&sc->wi_stats;
909 
910 	for (i = 0; i < len; i++) {
911 		if (sc->wi_flags & WI_FLAGS_BUS_USB) {
912 			wi_read_data(sc, id, 4 + i*2, (char *)&t, 2);
913 			t = letoh16(t);
914 		} else
915 			t = CSR_READ_2(sc, WI_DATA1);
916 #ifdef WI_HERMES_STATS_WAR
917 		if (t > 0xF000)
918 			t = ~t & 0xFFFF;
919 #endif
920 		ptr[i] += t;
921 	}
922 
923 	ifp->if_collisions = sc->wi_stats.wi_tx_single_retries +
924 	    sc->wi_stats.wi_tx_multi_retries +
925 	    sc->wi_stats.wi_tx_retry_limit;
926 
927 	return;
928 }
929 
930 STATIC int
931 wi_cmd_io(struct wi_softc *sc, int cmd, int val0, int val1, int val2)
932 {
933 	int			i, s = 0;
934 
935 	/* Wait for the busy bit to clear. */
936 	for (i = sc->wi_cmd_count; i--; DELAY(1000)) {
937 		if (!(CSR_READ_2(sc, WI_COMMAND) & WI_CMD_BUSY))
938 			break;
939 	}
940 	if (i < 0) {
941 		if (sc->sc_ic.ic_if.if_flags & IFF_DEBUG)
942 			printf(WI_PRT_FMT ": wi_cmd_io: busy bit won't clear\n",
943 			    WI_PRT_ARG(sc));
944 		return(ETIMEDOUT);
945 	}
946 
947 	CSR_WRITE_2(sc, WI_PARAM0, val0);
948 	CSR_WRITE_2(sc, WI_PARAM1, val1);
949 	CSR_WRITE_2(sc, WI_PARAM2, val2);
950 	CSR_WRITE_2(sc, WI_COMMAND, cmd);
951 
952 	for (i = WI_TIMEOUT; i--; DELAY(WI_DELAY)) {
953 		/*
954 		 * Wait for 'command complete' bit to be
955 		 * set in the event status register.
956 		 */
957 		s = CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_CMD;
958 		if (s) {
959 			/* Ack the event and read result code. */
960 			s = CSR_READ_2(sc, WI_STATUS);
961 			CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_CMD);
962 			if (s & WI_STAT_CMD_RESULT)
963 				return(EIO);
964 			break;
965 		}
966 	}
967 
968 	if (i < 0) {
969 		if (sc->sc_ic.ic_if.if_flags & IFF_DEBUG)
970 			printf(WI_PRT_FMT
971 			    ": timeout in wi_cmd 0x%04x; event status 0x%04x\n",
972 			    WI_PRT_ARG(sc), cmd, s);
973 		return(ETIMEDOUT);
974 	}
975 
976 	return(0);
977 }
978 
979 STATIC void
980 wi_reset(struct wi_softc *sc)
981 {
982 	int error, tries = 3;
983 
984 	DPRINTF(WID_RESET, ("wi_reset: sc %p\n", sc));
985 
986 	/* Symbol firmware cannot be initialized more than once. */
987 	if (sc->sc_firmware_type == WI_SYMBOL) {
988 		if (sc->wi_flags & WI_FLAGS_INITIALIZED)
989 			return;
990 		tries = 1;
991 	}
992 
993 	for (; tries--; DELAY(WI_DELAY * 1000)) {
994 		if ((error = wi_cmd(sc, WI_CMD_INI, 0, 0, 0)) == 0)
995 			break;
996 	}
997 	if (tries < 0) {
998 		printf(WI_PRT_FMT ": init failed\n", WI_PRT_ARG(sc));
999 		return;
1000 	}
1001 	sc->wi_flags |= WI_FLAGS_INITIALIZED;
1002 
1003 	wi_intr_enable(sc, 0);
1004 	wi_intr_ack(sc, 0xffff);
1005 
1006 	/* Calibrate timer. */
1007 	WI_SETVAL(WI_RID_TICK_TIME, 8);
1008 
1009 	return;
1010 }
1011 
1012 STATIC void
1013 wi_cor_reset(struct wi_softc *sc)
1014 {
1015 	u_int8_t cor_value;
1016 
1017 	DPRINTF(WID_RESET, ("wi_cor_reset: sc %p\n", sc));
1018 
1019 	/*
1020 	 * Do a soft reset of the card; this is required for Symbol cards.
1021 	 * This shouldn't hurt other cards but there have been reports
1022 	 * of the COR reset messing up old Lucent firmware revisions so
1023 	 * we avoid soft reset on Lucent cards for now.
1024 	 */
1025 	if (sc->sc_firmware_type != WI_LUCENT) {
1026 		cor_value = bus_space_read_1(sc->wi_ltag, sc->wi_lhandle,
1027 		    sc->wi_cor_offset);
1028 		bus_space_write_1(sc->wi_ltag, sc->wi_lhandle,
1029 		    sc->wi_cor_offset, (cor_value | WI_COR_SOFT_RESET));
1030 		DELAY(1000);
1031 		bus_space_write_1(sc->wi_ltag, sc->wi_lhandle,
1032 		    sc->wi_cor_offset, (cor_value & ~WI_COR_SOFT_RESET));
1033 		DELAY(1000);
1034 	}
1035 
1036 	return;
1037 }
1038 
1039 /*
1040  * Read an LTV record from the NIC.
1041  */
1042 STATIC int
1043 wi_read_record_io(struct wi_softc *sc, struct wi_ltv_gen *ltv)
1044 {
1045 	u_int8_t		*ptr;
1046 	int			len, code;
1047 	struct wi_ltv_gen	*oltv, p2ltv;
1048 
1049 	if (sc->sc_firmware_type != WI_LUCENT) {
1050 		oltv = ltv;
1051 		switch (ltv->wi_type) {
1052 		case WI_RID_ENCRYPTION:
1053 			p2ltv.wi_type = WI_RID_P2_ENCRYPTION;
1054 			p2ltv.wi_len = 2;
1055 			ltv = &p2ltv;
1056 			break;
1057 		case WI_RID_TX_CRYPT_KEY:
1058 			if (ltv->wi_val > WI_NLTV_KEYS)
1059 				return (EINVAL);
1060 			p2ltv.wi_type = WI_RID_P2_TX_CRYPT_KEY;
1061 			p2ltv.wi_len = 2;
1062 			ltv = &p2ltv;
1063 			break;
1064 		}
1065 	}
1066 
1067 	/* Tell the NIC to enter record read mode. */
1068 	if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_READ, ltv->wi_type, 0, 0))
1069 		return(EIO);
1070 
1071 	/* Seek to the record. */
1072 	if (wi_seek(sc, ltv->wi_type, 0, WI_BAP1))
1073 		return(EIO);
1074 
1075 	/*
1076 	 * Read the length and record type and make sure they
1077 	 * match what we expect (this verifies that we have enough
1078 	 * room to hold all of the returned data).
1079 	 */
1080 	len = CSR_READ_2(sc, WI_DATA1);
1081 	if (len > ltv->wi_len)
1082 		return(ENOSPC);
1083 	code = CSR_READ_2(sc, WI_DATA1);
1084 	if (code != ltv->wi_type)
1085 		return(EIO);
1086 
1087 	ltv->wi_len = len;
1088 	ltv->wi_type = code;
1089 
1090 	/* Now read the data. */
1091 	ptr = (u_int8_t *)&ltv->wi_val;
1092 	if (ltv->wi_len > 1)
1093 		CSR_READ_RAW_2(sc, WI_DATA1, ptr, (ltv->wi_len-1)*2);
1094 
1095 	if (ltv->wi_type == WI_RID_PORTTYPE && sc->wi_ptype == WI_PORTTYPE_IBSS
1096 	    && ltv->wi_val == sc->wi_ibss_port) {
1097 		/*
1098 		 * Convert vendor IBSS port type to WI_PORTTYPE_IBSS.
1099 		 * Since Lucent uses port type 1 for BSS *and* IBSS we
1100 		 * have to rely on wi_ptype to distinguish this for us.
1101 		 */
1102 		ltv->wi_val = htole16(WI_PORTTYPE_IBSS);
1103 	} else if (sc->sc_firmware_type != WI_LUCENT) {
1104 		int v;
1105 
1106 		switch (oltv->wi_type) {
1107 		case WI_RID_TX_RATE:
1108 		case WI_RID_CUR_TX_RATE:
1109 			switch (letoh16(ltv->wi_val)) {
1110 			case 1: v = 1; break;
1111 			case 2: v = 2; break;
1112 			case 3:	v = 6; break;
1113 			case 4: v = 5; break;
1114 			case 7: v = 7; break;
1115 			case 8: v = 11; break;
1116 			case 15: v = 3; break;
1117 			default: v = 0x100 + letoh16(ltv->wi_val); break;
1118 			}
1119 			oltv->wi_val = htole16(v);
1120 			break;
1121 		case WI_RID_ENCRYPTION:
1122 			oltv->wi_len = 2;
1123 			if (ltv->wi_val & htole16(0x01))
1124 				oltv->wi_val = htole16(1);
1125 			else
1126 				oltv->wi_val = htole16(0);
1127 			break;
1128 		case WI_RID_TX_CRYPT_KEY:
1129 		case WI_RID_CNFAUTHMODE:
1130 			oltv->wi_len = 2;
1131 			oltv->wi_val = ltv->wi_val;
1132 			break;
1133 		}
1134 	}
1135 
1136 	return(0);
1137 }
1138 
1139 /*
1140  * Same as read, except we inject data instead of reading it.
1141  */
1142 STATIC int
1143 wi_write_record_io(struct wi_softc *sc, struct wi_ltv_gen *ltv)
1144 {
1145 	u_int8_t		*ptr;
1146 	u_int16_t		val = 0;
1147 	int			i;
1148 	struct wi_ltv_gen	p2ltv;
1149 
1150 	if (ltv->wi_type == WI_RID_PORTTYPE &&
1151 	    letoh16(ltv->wi_val) == WI_PORTTYPE_IBSS) {
1152 		/* Convert WI_PORTTYPE_IBSS to vendor IBSS port type. */
1153 		p2ltv.wi_type = WI_RID_PORTTYPE;
1154 		p2ltv.wi_len = 2;
1155 		p2ltv.wi_val = sc->wi_ibss_port;
1156 		ltv = &p2ltv;
1157 	} else if (sc->sc_firmware_type != WI_LUCENT) {
1158 		int v;
1159 
1160 		switch (ltv->wi_type) {
1161 		case WI_RID_TX_RATE:
1162 			p2ltv.wi_type = WI_RID_TX_RATE;
1163 			p2ltv.wi_len = 2;
1164 			switch (letoh16(ltv->wi_val)) {
1165 			case 1: v = 1; break;
1166 			case 2: v = 2; break;
1167 			case 3:	v = 15; break;
1168 			case 5: v = 4; break;
1169 			case 6: v = 3; break;
1170 			case 7: v = 7; break;
1171 			case 11: v = 8; break;
1172 			default: return EINVAL;
1173 			}
1174 			p2ltv.wi_val = htole16(v);
1175 			ltv = &p2ltv;
1176 			break;
1177 		case WI_RID_ENCRYPTION:
1178 			p2ltv.wi_type = WI_RID_P2_ENCRYPTION;
1179 			p2ltv.wi_len = 2;
1180 			if (ltv->wi_val & htole16(0x01)) {
1181 				val = PRIVACY_INVOKED;
1182 				/*
1183 				 * If using shared key WEP we must set the
1184 				 * EXCLUDE_UNENCRYPTED bit.  Symbol cards
1185 				 * need this bit set even when not using
1186 				 * shared key. We can't just test for
1187 				 * IEEE80211_AUTH_SHARED since Symbol cards
1188 				 * have 2 shared key modes.
1189 				 */
1190 				if (sc->wi_authtype != IEEE80211_AUTH_OPEN ||
1191 				    sc->sc_firmware_type == WI_SYMBOL)
1192 					val |= EXCLUDE_UNENCRYPTED;
1193 
1194 				switch (sc->wi_crypto_algorithm) {
1195 				case WI_CRYPTO_FIRMWARE_WEP:
1196 					/*
1197 					 * TX encryption is broken in
1198 					 * Host AP mode.
1199 					 */
1200 					if (sc->wi_ptype == WI_PORTTYPE_HOSTAP)
1201 						val |= HOST_ENCRYPT;
1202 					break;
1203 				case WI_CRYPTO_SOFTWARE_WEP:
1204 					val |= HOST_ENCRYPT|HOST_DECRYPT;
1205 					break;
1206 				}
1207 				p2ltv.wi_val = htole16(val);
1208 			} else
1209 				p2ltv.wi_val = htole16(HOST_ENCRYPT | HOST_DECRYPT);
1210 			ltv = &p2ltv;
1211 			break;
1212 		case WI_RID_TX_CRYPT_KEY:
1213 			if (ltv->wi_val > WI_NLTV_KEYS)
1214 				return (EINVAL);
1215 			p2ltv.wi_type = WI_RID_P2_TX_CRYPT_KEY;
1216 			p2ltv.wi_len = 2;
1217 			p2ltv.wi_val = ltv->wi_val;
1218 			ltv = &p2ltv;
1219 			break;
1220 		case WI_RID_DEFLT_CRYPT_KEYS: {
1221 				int error;
1222 				int keylen;
1223 				struct wi_ltv_str ws;
1224 				struct wi_ltv_keys *wk = (struct wi_ltv_keys *)ltv;
1225 
1226 				keylen = wk->wi_keys[sc->wi_tx_key].wi_keylen;
1227 				keylen = letoh16(keylen);
1228 
1229 				for (i = 0; i < 4; i++) {
1230 					bzero(&ws, sizeof(ws));
1231 					ws.wi_len = (keylen > 5) ? 8 : 4;
1232 					ws.wi_type = WI_RID_P2_CRYPT_KEY0 + i;
1233 					bcopy(&wk->wi_keys[i].wi_keydat,
1234 					    ws.wi_str, keylen);
1235 					error = wi_write_record(sc,
1236 					    (struct wi_ltv_gen *)&ws);
1237 					if (error)
1238 						return (error);
1239 				}
1240 			}
1241 			return (0);
1242 		}
1243 	}
1244 
1245 	if (wi_seek(sc, ltv->wi_type, 0, WI_BAP1))
1246 		return(EIO);
1247 
1248 	CSR_WRITE_2(sc, WI_DATA1, ltv->wi_len);
1249 	CSR_WRITE_2(sc, WI_DATA1, ltv->wi_type);
1250 
1251 	ptr = (u_int8_t *)&ltv->wi_val;
1252 	if (ltv->wi_len > 1)
1253 		CSR_WRITE_RAW_2(sc, WI_DATA1, ptr, (ltv->wi_len-1) *2);
1254 
1255 	if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_WRITE, ltv->wi_type, 0, 0))
1256 		return(EIO);
1257 
1258 	return(0);
1259 }
1260 
1261 STATIC int
1262 wi_seek(struct wi_softc *sc, int id, int off, int chan)
1263 {
1264 	int			i;
1265 	int			selreg, offreg;
1266 
1267 	switch (chan) {
1268 	case WI_BAP0:
1269 		selreg = WI_SEL0;
1270 		offreg = WI_OFF0;
1271 		break;
1272 	case WI_BAP1:
1273 		selreg = WI_SEL1;
1274 		offreg = WI_OFF1;
1275 		break;
1276 	default:
1277 		printf(WI_PRT_FMT ": invalid data path: %x\n", WI_PRT_ARG(sc),
1278 		    chan);
1279 		return(EIO);
1280 	}
1281 
1282 	CSR_WRITE_2(sc, selreg, id);
1283 	CSR_WRITE_2(sc, offreg, off);
1284 
1285 	for (i = WI_TIMEOUT; i--; DELAY(1))
1286 		if (!(CSR_READ_2(sc, offreg) & (WI_OFF_BUSY|WI_OFF_ERR)))
1287 			break;
1288 
1289 	if (i < 0)
1290 		return(ETIMEDOUT);
1291 
1292 	return(0);
1293 }
1294 
1295 STATIC int
1296 wi_read_data_io(struct wi_softc *sc, int id, int off, caddr_t buf, int len)
1297 {
1298 	u_int8_t		*ptr;
1299 
1300 	if (wi_seek(sc, id, off, WI_BAP1))
1301 		return(EIO);
1302 
1303 	ptr = (u_int8_t *)buf;
1304 	CSR_READ_RAW_2(sc, WI_DATA1, ptr, len);
1305 
1306 	return(0);
1307 }
1308 
1309 /*
1310  * According to the comments in the HCF Light code, there is a bug in
1311  * the Hermes (or possibly in certain Hermes firmware revisions) where
1312  * the chip's internal autoincrement counter gets thrown off during
1313  * data writes: the autoincrement is missed, causing one data word to
1314  * be overwritten and subsequent words to be written to the wrong memory
1315  * locations. The end result is that we could end up transmitting bogus
1316  * frames without realizing it. The workaround for this is to write a
1317  * couple of extra guard words after the end of the transfer, then
1318  * attempt to read then back. If we fail to locate the guard words where
1319  * we expect them, we preform the transfer over again.
1320  */
1321 STATIC int
1322 wi_write_data_io(struct wi_softc *sc, int id, int off, caddr_t buf, int len)
1323 {
1324 	u_int8_t		*ptr;
1325 
1326 #ifdef WI_HERMES_AUTOINC_WAR
1327 again:
1328 #endif
1329 
1330 	if (wi_seek(sc, id, off, WI_BAP0))
1331 		return(EIO);
1332 
1333 	ptr = (u_int8_t *)buf;
1334 	CSR_WRITE_RAW_2(sc, WI_DATA0, ptr, len);
1335 
1336 #ifdef WI_HERMES_AUTOINC_WAR
1337 	CSR_WRITE_2(sc, WI_DATA0, 0x1234);
1338 	CSR_WRITE_2(sc, WI_DATA0, 0x5678);
1339 
1340 	if (wi_seek(sc, id, off + len, WI_BAP0))
1341 		return(EIO);
1342 
1343 	if (CSR_READ_2(sc, WI_DATA0) != 0x1234 ||
1344 	    CSR_READ_2(sc, WI_DATA0) != 0x5678)
1345 		goto again;
1346 #endif
1347 
1348 	return(0);
1349 }
1350 
1351 /*
1352  * Allocate a region of memory inside the NIC and zero
1353  * it out.
1354  */
1355 STATIC int
1356 wi_alloc_nicmem_io(struct wi_softc *sc, int len, int *id)
1357 {
1358 	int			i;
1359 
1360 	if (wi_cmd(sc, WI_CMD_ALLOC_MEM, len, 0, 0)) {
1361 		printf(WI_PRT_FMT ": failed to allocate %d bytes on NIC\n",
1362 		    WI_PRT_ARG(sc), len);
1363 		return(ENOMEM);
1364 	}
1365 
1366 	for (i = WI_TIMEOUT; i--; DELAY(1)) {
1367 		if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_ALLOC)
1368 			break;
1369 	}
1370 
1371 	if (i < 0)
1372 		return(ETIMEDOUT);
1373 
1374 	*id = CSR_READ_2(sc, WI_ALLOC_FID);
1375 	CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
1376 
1377 	if (wi_seek(sc, *id, 0, WI_BAP0))
1378 		return(EIO);
1379 
1380 	for (i = 0; i < len / 2; i++)
1381 		CSR_WRITE_2(sc, WI_DATA0, 0);
1382 
1383 	return(0);
1384 }
1385 
1386 STATIC void
1387 wi_setmulti(struct wi_softc *sc)
1388 {
1389 	struct arpcom		*ac = &sc->sc_ic.ic_ac;
1390 	struct ifnet		*ifp;
1391 	int			i = 0;
1392 	struct wi_ltv_mcast	mcast;
1393 	struct ether_multistep	step;
1394 	struct ether_multi	*enm;
1395 
1396 	ifp = &sc->sc_ic.ic_if;
1397 
1398 	bzero(&mcast, sizeof(mcast));
1399 
1400 	mcast.wi_type = WI_RID_MCAST_LIST;
1401 	mcast.wi_len = ((ETHER_ADDR_LEN / 2) * 16) + 1;
1402 
1403 	if (ac->ac_multirangecnt > 0)
1404 		ifp->if_flags |= IFF_ALLMULTI;
1405 
1406 	if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
1407 		wi_write_record(sc, (struct wi_ltv_gen *)&mcast);
1408 		return;
1409 	}
1410 
1411 	ETHER_FIRST_MULTI(step, &sc->sc_ic.ic_ac, enm);
1412 	while (enm != NULL) {
1413 		if (i >= 16) {
1414 			bzero(&mcast, sizeof(mcast));
1415 			break;
1416 		}
1417 
1418 		bcopy(enm->enm_addrlo, &mcast.wi_mcast[i], ETHER_ADDR_LEN);
1419 		i++;
1420 		ETHER_NEXT_MULTI(step, enm);
1421 	}
1422 
1423 	mcast.wi_len = (i * 3) + 1;
1424 	wi_write_record(sc, (struct wi_ltv_gen *)&mcast);
1425 
1426 	return;
1427 }
1428 
1429 STATIC int
1430 wi_setdef(struct wi_softc *sc, struct wi_req *wreq)
1431 {
1432 	struct ifnet		*ifp;
1433 	int error = 0;
1434 
1435 	ifp = &sc->sc_ic.ic_if;
1436 
1437 	switch(wreq->wi_type) {
1438 	case WI_RID_MAC_NODE:
1439 		bcopy(&wreq->wi_val, LLADDR(ifp->if_sadl), ETHER_ADDR_LEN);
1440 		bcopy(&wreq->wi_val, &sc->sc_ic.ic_myaddr, ETHER_ADDR_LEN);
1441 		break;
1442 	case WI_RID_PORTTYPE:
1443 		error = wi_sync_media(sc, letoh16(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 		    letoh16(wreq->wi_val[0]));
1449 		break;
1450 	case WI_RID_MAX_DATALEN:
1451 		sc->wi_max_data_len = letoh16(wreq->wi_val[0]);
1452 		break;
1453 	case WI_RID_RTS_THRESH:
1454 		sc->wi_rts_thresh = letoh16(wreq->wi_val[0]);
1455 		break;
1456 	case WI_RID_SYSTEM_SCALE:
1457 		sc->wi_ap_density = letoh16(wreq->wi_val[0]);
1458 		break;
1459 	case WI_RID_CREATE_IBSS:
1460 		sc->wi_create_ibss = letoh16(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 = letoh16(wreq->wi_val[0]);
1465 		break;
1466 	case WI_RID_NODENAME:
1467 		error = wi_set_ssid(&sc->wi_node_name,
1468 		    (u_int8_t *)&wreq->wi_val[1], letoh16(wreq->wi_val[0]));
1469 		break;
1470 	case WI_RID_DESIRED_SSID:
1471 		error = wi_set_ssid(&sc->wi_net_name,
1472 		    (u_int8_t *)&wreq->wi_val[1], letoh16(wreq->wi_val[0]));
1473 		break;
1474 	case WI_RID_OWN_SSID:
1475 		error = wi_set_ssid(&sc->wi_ibss_name,
1476 		    (u_int8_t *)&wreq->wi_val[1], letoh16(wreq->wi_val[0]));
1477 		break;
1478 	case WI_RID_PM_ENABLED:
1479 		sc->wi_pm_enabled = letoh16(wreq->wi_val[0]);
1480 		break;
1481 	case WI_RID_MICROWAVE_OVEN:
1482 		sc->wi_mor_enabled = letoh16(wreq->wi_val[0]);
1483 		break;
1484 	case WI_RID_MAX_SLEEP:
1485 		sc->wi_max_sleep = letoh16(wreq->wi_val[0]);
1486 		break;
1487 	case WI_RID_CNFAUTHMODE:
1488 		sc->wi_authtype = letoh16(wreq->wi_val[0]);
1489 		break;
1490 	case WI_RID_ROAMING_MODE:
1491 		sc->wi_roaming = letoh16(wreq->wi_val[0]);
1492 		break;
1493 	case WI_RID_SYMBOL_DIVERSITY:
1494 		sc->wi_diversity = letoh16(wreq->wi_val[0]);
1495 		break;
1496 	case WI_RID_ENH_SECURITY:
1497 		sc->wi_enh_security = letoh16(wreq->wi_val[0]);
1498 		break;
1499 	case WI_RID_ENCRYPTION:
1500 		sc->wi_use_wep = letoh16(wreq->wi_val[0]);
1501 		break;
1502 	case WI_RID_TX_CRYPT_KEY:
1503 		sc->wi_tx_key = letoh16(wreq->wi_val[0]);
1504 		break;
1505 	case WI_RID_DEFLT_CRYPT_KEYS:
1506 		bcopy(wreq, &sc->wi_keys, sizeof(struct wi_ltv_keys));
1507 		break;
1508 	case WI_FRID_CRYPTO_ALG:
1509 		switch (letoh16(wreq->wi_val[0])) {
1510 		case WI_CRYPTO_FIRMWARE_WEP:
1511 			sc->wi_crypto_algorithm = WI_CRYPTO_FIRMWARE_WEP;
1512 			break;
1513 		case WI_CRYPTO_SOFTWARE_WEP:
1514 			sc->wi_crypto_algorithm = WI_CRYPTO_SOFTWARE_WEP;
1515 			break;
1516 		default:
1517 			printf(WI_PRT_FMT ": unsupported crypto algorithm %d\n",
1518 			    WI_PRT_ARG(sc), letoh16(wreq->wi_val[0]));
1519 			error = EINVAL;
1520 		}
1521 		break;
1522 	default:
1523 		error = EINVAL;
1524 		break;
1525 	}
1526 
1527 	return (error);
1528 }
1529 
1530 STATIC int
1531 wi_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
1532 {
1533 	int			s, error = 0, i, j, len;
1534 	struct wi_softc		*sc = ifp->if_softc;
1535 	struct ifreq		*ifr = (struct ifreq *)data;
1536 	struct proc		*p = curproc;
1537 	struct ifaddr		*ifa = (struct ifaddr *)data;
1538 	struct wi_scan_res	*res;
1539 	struct wi_scan_p2_hdr	*p2;
1540 	struct wi_req		*wreq = NULL;
1541 	u_int32_t		flags;
1542 	struct ieee80211_nwid		*nwidp = NULL;
1543 	struct ieee80211_nodereq_all	*na;
1544 	struct ieee80211_bssid		*bssid;
1545 
1546 	s = splnet();
1547 	if (!(sc->wi_flags & WI_FLAGS_ATTACHED)) {
1548 		error = ENODEV;
1549 		goto fail;
1550 	}
1551 
1552 	/*
1553 	 * Prevent processes from entering this function while another
1554 	 * process is tsleep'ing in it.
1555 	 */
1556 	while ((sc->wi_flags & WI_FLAGS_BUSY) && error == 0)
1557 		error = tsleep(&sc->wi_flags, PCATCH, "wiioc", 0);
1558 	if (error != 0) {
1559 		splx(s);
1560 		return error;
1561 	}
1562 	sc->wi_flags |= WI_FLAGS_BUSY;
1563 
1564 
1565 	DPRINTF (WID_IOCTL, ("wi_ioctl: command %lu data %p\n",
1566 	    command, data));
1567 
1568 	switch(command) {
1569 	case SIOCSIFADDR:
1570 		ifp->if_flags |= IFF_UP;
1571 		switch (ifa->ifa_addr->sa_family) {
1572 		case AF_INET:
1573 			wi_init(sc);
1574 			arp_ifinit(&sc->sc_ic.ic_ac, ifa);
1575 			break;
1576 		default:
1577 			wi_init(sc);
1578 			break;
1579 		}
1580 		break;
1581 	case SIOCSIFFLAGS:
1582 		if (ifp->if_flags & IFF_UP) {
1583 			if (ifp->if_flags & IFF_RUNNING &&
1584 			    ifp->if_flags & IFF_PROMISC &&
1585 			    !(sc->wi_if_flags & IFF_PROMISC)) {
1586 				if (sc->wi_ptype != WI_PORTTYPE_HOSTAP)
1587 					WI_SETVAL(WI_RID_PROMISC, 1);
1588 			} else if (ifp->if_flags & IFF_RUNNING &&
1589 			    !(ifp->if_flags & IFF_PROMISC) &&
1590 			    sc->wi_if_flags & IFF_PROMISC) {
1591 				if (sc->wi_ptype != WI_PORTTYPE_HOSTAP)
1592 					WI_SETVAL(WI_RID_PROMISC, 0);
1593 			} else
1594 				wi_init(sc);
1595 		} else if (ifp->if_flags & IFF_RUNNING)
1596 			wi_stop(sc);
1597 		sc->wi_if_flags = ifp->if_flags;
1598 		error = 0;
1599 		break;
1600 	case SIOCSIFMEDIA:
1601 	case SIOCGIFMEDIA:
1602 		error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, command);
1603 		break;
1604 	case SIOCGWAVELAN:
1605 		wreq = malloc(sizeof *wreq, M_DEVBUF, M_WAITOK | M_ZERO);
1606 		error = copyin(ifr->ifr_data, wreq, sizeof(*wreq));
1607 		if (error)
1608 			break;
1609 		if (wreq->wi_len > WI_MAX_DATALEN) {
1610 			error = EINVAL;
1611 			break;
1612 		}
1613 		switch (wreq->wi_type) {
1614 		case WI_RID_IFACE_STATS:
1615 			/* XXX native byte order */
1616 			bcopy(&sc->wi_stats, &wreq->wi_val,
1617 			    sizeof(sc->wi_stats));
1618 			wreq->wi_len = (sizeof(sc->wi_stats) / 2) + 1;
1619 			break;
1620 		case WI_RID_DEFLT_CRYPT_KEYS:
1621 			/* For non-root user, return all-zeroes keys */
1622 			if (suser(p, 0))
1623 				bzero(wreq, sizeof(struct wi_ltv_keys));
1624 			else
1625 				bcopy(&sc->wi_keys, wreq,
1626 					sizeof(struct wi_ltv_keys));
1627 			break;
1628 		case WI_RID_PROCFRAME:
1629 			wreq->wi_len = 2;
1630 			wreq->wi_val[0] = htole16(sc->wi_procframe);
1631 			break;
1632 		case WI_RID_PRISM2:
1633 			wreq->wi_len = 2;
1634 			wreq->wi_val[0] = htole16(sc->sc_firmware_type ==
1635 			    WI_LUCENT ? 0 : 1);
1636 			break;
1637 		case WI_FRID_CRYPTO_ALG:
1638 			wreq->wi_val[0] =
1639 			    htole16((u_int16_t)sc->wi_crypto_algorithm);
1640 			wreq->wi_len = 1;
1641 			break;
1642 		case WI_RID_SCAN_RES:
1643 			if (sc->sc_firmware_type == WI_LUCENT) {
1644 				memcpy((char *)wreq->wi_val,
1645 				    (char *)sc->wi_scanbuf,
1646 				    sc->wi_scanbuf_len * 2);
1647 				wreq->wi_len = sc->wi_scanbuf_len;
1648 				break;
1649 			}
1650 			/* FALLTHROUGH */
1651 		default:
1652 			if (wi_read_record(sc, (struct wi_ltv_gen *)wreq)) {
1653 				error = EINVAL;
1654 			}
1655 			break;
1656 		}
1657 		error = copyout(wreq, ifr->ifr_data, sizeof(*wreq));
1658 		break;
1659 	case SIOCSWAVELAN:
1660 		if ((error = suser(curproc, 0)) != 0)
1661 			break;
1662 		wreq = malloc(sizeof *wreq, M_DEVBUF, M_WAITOK | M_ZERO);
1663 		error = copyin(ifr->ifr_data, wreq, sizeof(*wreq));
1664 		if (error)
1665 			break;
1666 		error = EINVAL;
1667 		if (wreq->wi_len > WI_MAX_DATALEN)
1668 			break;
1669 		switch (wreq->wi_type) {
1670 		case WI_RID_IFACE_STATS:
1671 			break;
1672 		case WI_RID_MGMT_XMIT:
1673 			error = wi_mgmt_xmit(sc, (caddr_t)&wreq->wi_val,
1674 			    wreq->wi_len);
1675 			break;
1676 		case WI_RID_PROCFRAME:
1677 			sc->wi_procframe = letoh16(wreq->wi_val[0]);
1678 			error = 0;
1679 			break;
1680 		case WI_RID_SCAN_REQ:
1681 			error = 0;
1682 			if (sc->sc_firmware_type == WI_LUCENT)
1683 				wi_cmd(sc, WI_CMD_INQUIRE,
1684 				    WI_INFO_SCAN_RESULTS, 0, 0);
1685 			else
1686 				error = wi_write_record(sc,
1687 				    (struct wi_ltv_gen *)wreq);
1688 			break;
1689 		case WI_FRID_CRYPTO_ALG:
1690 			if (sc->sc_firmware_type != WI_LUCENT) {
1691 				error = wi_setdef(sc, wreq);
1692 				if (!error && (ifp->if_flags & IFF_UP))
1693 					wi_init(sc);
1694 			}
1695 			break;
1696 		case WI_RID_SYMBOL_DIVERSITY:
1697 		case WI_RID_ROAMING_MODE:
1698 		case WI_RID_CREATE_IBSS:
1699 		case WI_RID_MICROWAVE_OVEN:
1700 		case WI_RID_OWN_SSID:
1701 		case WI_RID_ENH_SECURITY:
1702 			/*
1703 			 * Check for features that may not be supported
1704 			 * (must be just before default case).
1705 			 */
1706 			if ((wreq->wi_type == WI_RID_SYMBOL_DIVERSITY &&
1707 			    !(sc->wi_flags & WI_FLAGS_HAS_DIVERSITY)) ||
1708 			    (wreq->wi_type == WI_RID_ROAMING_MODE &&
1709 			    !(sc->wi_flags & WI_FLAGS_HAS_ROAMING)) ||
1710 			    (wreq->wi_type == WI_RID_CREATE_IBSS &&
1711 			    !(sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)) ||
1712 			    (wreq->wi_type == WI_RID_MICROWAVE_OVEN &&
1713 			    !(sc->wi_flags & WI_FLAGS_HAS_MOR)) ||
1714 			    (wreq->wi_type == WI_RID_ENH_SECURITY &&
1715 			    !(sc->wi_flags & WI_FLAGS_HAS_ENH_SECURITY)) ||
1716 			    (wreq->wi_type == WI_RID_OWN_SSID &&
1717 			    wreq->wi_len != 0))
1718 				break;
1719 			/* FALLTHROUGH */
1720 		default:
1721 			error = wi_write_record(sc, (struct wi_ltv_gen *)wreq);
1722 			if (!error)
1723 				error = wi_setdef(sc, wreq);
1724 			if (!error && (ifp->if_flags & IFF_UP))
1725 				wi_init(sc);
1726 		}
1727 		break;
1728 	case SIOCGPRISM2DEBUG:
1729 		wreq = malloc(sizeof *wreq, M_DEVBUF, M_WAITOK | M_ZERO);
1730 		error = copyin(ifr->ifr_data, wreq, sizeof(*wreq));
1731 		if (error)
1732 			break;
1733 		if (!(ifp->if_flags & IFF_RUNNING) ||
1734 		    sc->sc_firmware_type == WI_LUCENT) {
1735 			error = EIO;
1736 			break;
1737 		}
1738 		error = wi_get_debug(sc, wreq);
1739 		if (error == 0)
1740 			error = copyout(wreq, ifr->ifr_data, sizeof(*wreq));
1741 		break;
1742 	case SIOCSPRISM2DEBUG:
1743 		if ((error = suser(curproc, 0)) != 0)
1744 			break;
1745 		wreq = malloc(sizeof *wreq, M_DEVBUF, M_WAITOK | M_ZERO);
1746 		error = copyin(ifr->ifr_data, wreq, sizeof(*wreq));
1747 		if (error)
1748 			break;
1749 		error = wi_set_debug(sc, wreq);
1750 		break;
1751 	case SIOCG80211NWID:
1752 		if ((ifp->if_flags & IFF_UP) && sc->wi_net_name.i_len > 0) {
1753 			/* Return the desired ID */
1754 			error = copyout(&sc->wi_net_name, ifr->ifr_data,
1755 			    sizeof(sc->wi_net_name));
1756 		} else {
1757 			wreq = malloc(sizeof *wreq, M_DEVBUF, M_WAITOK|M_ZERO);
1758 			wreq->wi_type = WI_RID_CURRENT_SSID;
1759 			wreq->wi_len = WI_MAX_DATALEN;
1760 			if (wi_read_record(sc, (struct wi_ltv_gen *)wreq) ||
1761 			    letoh16(wreq->wi_val[0]) > IEEE80211_NWID_LEN)
1762 				error = EINVAL;
1763 			else {
1764 				nwidp = malloc(sizeof *nwidp, M_DEVBUF,
1765 				    M_WAITOK | M_ZERO);
1766 				wi_set_ssid(nwidp, (u_int8_t *)&wreq->wi_val[1],
1767 				    letoh16(wreq->wi_val[0]));
1768 				error = copyout(nwidp, ifr->ifr_data,
1769 				    sizeof(*nwidp));
1770 			}
1771 		}
1772 		break;
1773 	case SIOCS80211NWID:
1774 		if ((error = suser(curproc, 0)) != 0)
1775 			break;
1776 		nwidp = malloc(sizeof *nwidp, M_DEVBUF, M_WAITOK);
1777 		error = copyin(ifr->ifr_data, nwidp, sizeof(*nwidp));
1778 		if (error)
1779 			break;
1780 		if (nwidp->i_len > IEEE80211_NWID_LEN) {
1781 			error = EINVAL;
1782 			break;
1783 		}
1784 		if (sc->wi_net_name.i_len == nwidp->i_len &&
1785 		    memcmp(sc->wi_net_name.i_nwid, nwidp->i_nwid, nwidp->i_len) == 0)
1786 			break;
1787 		wi_set_ssid(&sc->wi_net_name, nwidp->i_nwid, nwidp->i_len);
1788 		WI_SETSTR(WI_RID_DESIRED_SSID, sc->wi_net_name);
1789 		if (ifp->if_flags & IFF_UP)
1790 			/* Reinitialize WaveLAN. */
1791 			wi_init(sc);
1792 		break;
1793 	case SIOCS80211NWKEY:
1794 		if ((error = suser(curproc, 0)) != 0)
1795 			break;
1796 		error = wi_set_nwkey(sc, (struct ieee80211_nwkey *)data);
1797 		break;
1798 	case SIOCG80211NWKEY:
1799 		error = wi_get_nwkey(sc, (struct ieee80211_nwkey *)data);
1800 		break;
1801 	case SIOCS80211POWER:
1802 		if ((error = suser(curproc, 0)) != 0)
1803 			break;
1804 		error = wi_set_pm(sc, (struct ieee80211_power *)data);
1805 		break;
1806 	case SIOCG80211POWER:
1807 		error = wi_get_pm(sc, (struct ieee80211_power *)data);
1808 		break;
1809 	case SIOCS80211TXPOWER:
1810 		if ((error = suser(curproc, 0)) != 0)
1811 			break;
1812 		error = wi_set_txpower(sc, (struct ieee80211_txpower *)data);
1813 		break;
1814 	case SIOCG80211TXPOWER:
1815 		error = wi_get_txpower(sc, (struct ieee80211_txpower *)data);
1816 		break;
1817 	case SIOCS80211CHANNEL:
1818 		if ((error = suser(curproc, 0)) != 0)
1819 			break;
1820 		if (((struct ieee80211chanreq *)data)->i_channel > 14) {
1821 			error = EINVAL;
1822 			break;
1823 		}
1824 		wreq = malloc(sizeof *wreq, M_DEVBUF, M_WAITOK | M_ZERO);
1825 		wreq->wi_type = WI_RID_OWN_CHNL;
1826 		wreq->wi_val[0] =
1827 		    htole16(((struct ieee80211chanreq *)data)->i_channel);
1828 		error = wi_setdef(sc, wreq);
1829 		if (!error && (ifp->if_flags & IFF_UP))
1830 			wi_init(sc);
1831 		break;
1832 	case SIOCG80211CHANNEL:
1833 		wreq = malloc(sizeof *wreq, M_DEVBUF, M_WAITOK | M_ZERO);
1834 		wreq->wi_type = WI_RID_CURRENT_CHAN;
1835 		wreq->wi_len = WI_MAX_DATALEN;
1836 		if (wi_read_record(sc, (struct wi_ltv_gen *)wreq)) {
1837 			error = EINVAL;
1838 			break;
1839 		}
1840 		((struct ieee80211chanreq *)data)->i_channel =
1841 		    letoh16(wreq->wi_val[0]);
1842 		break;
1843 	case SIOCG80211BSSID:
1844 		bssid = (struct ieee80211_bssid *)data;
1845 		wreq = malloc(sizeof *wreq, M_DEVBUF, M_WAITOK | M_ZERO);
1846 		wreq->wi_type = WI_RID_CURRENT_BSSID;
1847 		wreq->wi_len = WI_MAX_DATALEN;
1848 		if (wi_read_record(sc, (struct wi_ltv_gen *)wreq)) {
1849 			error = EINVAL;
1850 			break;
1851 		}
1852 		IEEE80211_ADDR_COPY(bssid->i_bssid, wreq->wi_val);
1853 		break;
1854 	case SIOCS80211SCAN:
1855 		if ((error = suser(curproc, 0)) != 0)
1856 			break;
1857 		if (sc->wi_ptype == WI_PORTTYPE_HOSTAP)
1858 			break;
1859 		if ((ifp->if_flags & IFF_UP) == 0) {
1860 			error = ENETDOWN;
1861 			break;
1862 		}
1863 		if (sc->sc_firmware_type == WI_LUCENT) {
1864 			wi_cmd(sc, WI_CMD_INQUIRE,
1865 			    WI_INFO_SCAN_RESULTS, 0, 0);
1866 		} else {
1867 			wreq = malloc(sizeof *wreq, M_DEVBUF, M_WAITOK|M_ZERO);
1868 			wreq->wi_len = 3;
1869 			wreq->wi_type = WI_RID_SCAN_REQ;
1870 			wreq->wi_val[0] = 0x3FFF;
1871 			wreq->wi_val[1] = 0x000F;
1872 
1873 			error = wi_write_record(sc,
1874 			    (struct wi_ltv_gen *)wreq);
1875 			if (error)
1876 				break;
1877 		}
1878 		sc->wi_scan_lock = 0;
1879 		timeout_set(&sc->wi_scan_timeout, wi_scan_timeout, sc);
1880 		len = WI_WAVELAN_RES_TIMEOUT;
1881 		if (sc->wi_flags & WI_FLAGS_BUS_USB) {
1882 			/* Use a longer timeout for wi@usb */
1883 			len = WI_WAVELAN_RES_TIMEOUT * 4;
1884 		}
1885 		timeout_add(&sc->wi_scan_timeout, len);
1886 
1887 		/* Let the userspace process wait for completion */
1888 		error = tsleep(&sc->wi_scan_lock, PCATCH, "wiscan",
1889 		    hz * IEEE80211_SCAN_TIMEOUT);
1890 		break;
1891 	case SIOCG80211ALLNODES:
1892 	    {
1893 		struct ieee80211_nodereq	*nr = NULL;
1894 
1895 		if ((error = suser(curproc, 0)) != 0)
1896 			break;
1897 		na = (struct ieee80211_nodereq_all *)data;
1898 		if (sc->wi_ptype == WI_PORTTYPE_HOSTAP) {
1899 			/* List all associated stations */
1900 			error = wihap_ioctl(sc, command, data);
1901 			break;
1902 		}
1903 		wreq = malloc(sizeof *wreq, M_DEVBUF, M_WAITOK | M_ZERO);
1904 		wreq->wi_len = WI_MAX_DATALEN;
1905 		wreq->wi_type = WI_RID_SCAN_RES;
1906 		if (sc->sc_firmware_type == WI_LUCENT) {
1907 			bcopy(sc->wi_scanbuf, wreq->wi_val,
1908 			    sc->wi_scanbuf_len * 2);
1909 			wreq->wi_len = sc->wi_scanbuf_len;
1910 			i = 0;
1911 			len = WI_WAVELAN_RES_SIZE;
1912 		} else {
1913 			if (wi_read_record(sc, (struct wi_ltv_gen *)wreq)) {
1914 				error = EINVAL;
1915 				break;
1916 			}
1917 			p2 = (struct wi_scan_p2_hdr *)wreq->wi_val;
1918 			if (p2->wi_reason == 0)
1919 				break;
1920 			i = sizeof(*p2);
1921 			len = WI_PRISM2_RES_SIZE;
1922 		}
1923 
1924 		for (na->na_nodes = j = 0; (i < (wreq->wi_len * 2) - len) &&
1925 		    (na->na_size >= j + sizeof(struct ieee80211_nodereq));
1926 		    i += len) {
1927 
1928 			if (nr == NULL)
1929 				nr = malloc(sizeof *nr, M_DEVBUF, M_WAITOK);
1930 			res = (struct wi_scan_res *)((char *)wreq->wi_val + i);
1931 			if (res == NULL)
1932 				break;
1933 
1934 			bzero(nr, sizeof(*nr));
1935 			IEEE80211_ADDR_COPY(nr->nr_macaddr, res->wi_bssid);
1936 			IEEE80211_ADDR_COPY(nr->nr_bssid, res->wi_bssid);
1937 			nr->nr_channel = letoh16(res->wi_chan);
1938 			nr->nr_chan_flags = IEEE80211_CHAN_B;
1939 			nr->nr_rssi = letoh16(res->wi_signal);
1940 			nr->nr_max_rssi = 0; /* XXX */
1941 			nr->nr_nwid_len = letoh16(res->wi_ssid_len);
1942 			bcopy(res->wi_ssid, nr->nr_nwid, nr->nr_nwid_len);
1943 			nr->nr_intval = letoh16(res->wi_interval);
1944 			nr->nr_capinfo = letoh16(res->wi_capinfo);
1945 			nr->nr_txrate = res->wi_rate == WI_WAVELAN_RES_1M ? 2 :
1946 			    (res->wi_rate == WI_WAVELAN_RES_2M ? 4 :
1947 			    (res->wi_rate == WI_WAVELAN_RES_5M ? 11 :
1948 			    (res->wi_rate == WI_WAVELAN_RES_11M ? 22 : 0)));
1949 			nr->nr_nrates = 0;
1950 			while (res->wi_srates[nr->nr_nrates] != 0) {
1951 				nr->nr_rates[nr->nr_nrates] =
1952 				    res->wi_srates[nr->nr_nrates] &
1953 				    WI_VAR_SRATES_MASK;
1954 				nr->nr_nrates++;
1955 			}
1956 			nr->nr_flags = 0;
1957 			if (bcmp(nr->nr_macaddr, nr->nr_bssid,
1958 			    IEEE80211_ADDR_LEN) == 0)
1959 				nr->nr_flags |= IEEE80211_NODEREQ_AP;
1960 
1961 			error = copyout(nr, (caddr_t)na->na_node + j,
1962 			    sizeof(struct ieee80211_nodereq));
1963 			if (error)
1964 				break;
1965 			j += sizeof(struct ieee80211_nodereq);
1966 			na->na_nodes++;
1967 		}
1968 		if (nr)
1969 			free(nr, M_DEVBUF, 0);
1970 		break;
1971 	    }
1972 	case SIOCG80211FLAGS:
1973 		if (sc->wi_ptype != WI_PORTTYPE_HOSTAP)
1974 			break;
1975 		ifr->ifr_flags = 0;
1976 		if (sc->wi_flags & WI_FLAGS_HAS_ENH_SECURITY) {
1977 			wreq = malloc(sizeof *wreq, M_DEVBUF, M_WAITOK|M_ZERO);
1978 			wreq->wi_len = WI_MAX_DATALEN;
1979 			wreq->wi_type = WI_RID_ENH_SECURITY;
1980 			if (wi_read_record(sc, (struct wi_ltv_gen *)wreq)) {
1981 				error = EINVAL;
1982 				break;
1983 			}
1984 			sc->wi_enh_security = letoh16(wreq->wi_val[0]);
1985 			if (sc->wi_enh_security == WI_HIDESSID_IGNPROBES)
1986 				ifr->ifr_flags |= IEEE80211_F_HIDENWID >>
1987 				    IEEE80211_F_USERSHIFT;
1988 		}
1989 		break;
1990 	case SIOCS80211FLAGS:
1991 		if ((error = suser(curproc, 0)) != 0)
1992 			break;
1993 		if (sc->wi_ptype != WI_PORTTYPE_HOSTAP) {
1994 			error = EINVAL;
1995 			break;
1996 		}
1997 		flags = (u_int32_t)ifr->ifr_flags << IEEE80211_F_USERSHIFT;
1998 		if (sc->wi_flags & WI_FLAGS_HAS_ENH_SECURITY) {
1999 			sc->wi_enh_security = (flags & IEEE80211_F_HIDENWID) ?
2000 			    WI_HIDESSID_IGNPROBES : 0;
2001 			WI_SETVAL(WI_RID_ENH_SECURITY, sc->wi_enh_security);
2002 		}
2003 		break;
2004 	case SIOCHOSTAP_ADD:
2005 	case SIOCHOSTAP_DEL:
2006 	case SIOCHOSTAP_GET:
2007 	case SIOCHOSTAP_GETALL:
2008 	case SIOCHOSTAP_GFLAGS:
2009 	case SIOCHOSTAP_SFLAGS:
2010 		/* Send all Host AP specific ioctl's to Host AP code. */
2011 		error = wihap_ioctl(sc, command, data);
2012 		break;
2013 	default:
2014 		error = ether_ioctl(ifp, &sc->sc_ic.ic_ac, command, data);
2015 	}
2016 
2017 	if (error == ENETRESET) {
2018 		if (ifp->if_flags & IFF_RUNNING)
2019 			wi_setmulti(sc);
2020 		error = 0;
2021 	}
2022 
2023 	if (wreq)
2024 		free(wreq, M_DEVBUF, 0);
2025 	if (nwidp)
2026 		free(nwidp, M_DEVBUF, 0);
2027 
2028 fail:
2029 	sc->wi_flags &= ~WI_FLAGS_BUSY;
2030 	wakeup(&sc->wi_flags);
2031 	splx(s);
2032 	return(error);
2033 }
2034 
2035 void
2036 wi_scan_timeout(void *arg)
2037 {
2038 	struct wi_softc		*sc = (struct wi_softc *)arg;
2039 	struct wi_req		wreq;
2040 
2041 	if (sc->wi_scan_lock++ < WI_WAVELAN_RES_TRIES &&
2042 	    sc->sc_firmware_type != WI_LUCENT &&
2043 	    (sc->wi_flags & WI_FLAGS_BUS_USB) == 0) {
2044 		/*
2045 		 * The Prism2/2.5/3 chipsets will set an extra field in the
2046 		 * scan result if the scan request has been completed by the
2047 		 * firmware. This allows to poll for completion and to
2048 		 * wait for some more time if the scan is still in progress.
2049 		 *
2050 		 * XXX This doesn't work with wi@usb because it isn't safe
2051 		 * to call wi_read_record_usb() while beeing in the timeout
2052 		 * handler.
2053 		 */
2054 		wreq.wi_len = WI_MAX_DATALEN;
2055 		wreq.wi_type = WI_RID_SCAN_RES;
2056 
2057 		if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq) == 0 &&
2058 		    ((struct wi_scan_p2_hdr *)wreq.wi_val)->wi_reason == 0) {
2059 			/* Wait some more time for scan completion */
2060 			timeout_add(&sc->wi_scan_timeout, WI_WAVELAN_RES_TIMEOUT);
2061 			return;
2062 		}
2063 	}
2064 
2065 	if (sc->sc_ic.ic_if.if_flags & IFF_DEBUG)
2066 		printf(WI_PRT_FMT ": wi_scan_timeout: %d tries\n",
2067 		    WI_PRT_ARG(sc), sc->wi_scan_lock);
2068 
2069 	/* Wakeup the userland */
2070 	wakeup(&sc->wi_scan_lock);
2071 	sc->wi_scan_lock = 0;
2072 }
2073 
2074 STATIC void
2075 wi_init_io(struct wi_softc *sc)
2076 {
2077 	struct ifnet		*ifp = &sc->sc_ic.ic_ac.ac_if;
2078 	int			s;
2079 	struct wi_ltv_macaddr	mac;
2080 	int			id = 0;
2081 
2082 	if (!(sc->wi_flags & WI_FLAGS_ATTACHED))
2083 		return;
2084 
2085 	DPRINTF(WID_INIT, ("wi_init: sc %p\n", sc));
2086 
2087 	s = splnet();
2088 
2089 	if (ifp->if_flags & IFF_RUNNING)
2090 		wi_stop(sc);
2091 
2092 	wi_reset(sc);
2093 
2094 	/* Program max data length. */
2095 	WI_SETVAL(WI_RID_MAX_DATALEN, sc->wi_max_data_len);
2096 
2097 	/* Set the port type. */
2098 	WI_SETVAL(WI_RID_PORTTYPE, sc->wi_ptype);
2099 
2100 	/* Enable/disable IBSS creation. */
2101 	WI_SETVAL(WI_RID_CREATE_IBSS, sc->wi_create_ibss);
2102 
2103 	/* Program the RTS/CTS threshold. */
2104 	WI_SETVAL(WI_RID_RTS_THRESH, sc->wi_rts_thresh);
2105 
2106 	/* Program the TX rate */
2107 	WI_SETVAL(WI_RID_TX_RATE, sc->wi_tx_rate);
2108 
2109 	/* Access point density */
2110 	WI_SETVAL(WI_RID_SYSTEM_SCALE, sc->wi_ap_density);
2111 
2112 	/* Power Management Enabled */
2113 	WI_SETVAL(WI_RID_PM_ENABLED, sc->wi_pm_enabled);
2114 
2115 	/* Power Management Max Sleep */
2116 	WI_SETVAL(WI_RID_MAX_SLEEP, sc->wi_max_sleep);
2117 
2118 	/* Set Enhanced Security if supported. */
2119 	if (sc->wi_flags & WI_FLAGS_HAS_ENH_SECURITY)
2120 		WI_SETVAL(WI_RID_ENH_SECURITY, sc->wi_enh_security);
2121 
2122 	/* Set Roaming Mode unless this is a Symbol card. */
2123 	if (sc->wi_flags & WI_FLAGS_HAS_ROAMING)
2124 		WI_SETVAL(WI_RID_ROAMING_MODE, sc->wi_roaming);
2125 
2126 	/* Set Antenna Diversity if this is a Symbol card. */
2127 	if (sc->wi_flags & WI_FLAGS_HAS_DIVERSITY)
2128 		WI_SETVAL(WI_RID_SYMBOL_DIVERSITY, sc->wi_diversity);
2129 
2130 	/* Specify the network name */
2131 	WI_SETSTR(WI_RID_DESIRED_SSID, sc->wi_net_name);
2132 
2133 	/* Specify the IBSS name */
2134 	if (sc->wi_net_name.i_len != 0 && (sc->wi_ptype == WI_PORTTYPE_HOSTAP ||
2135 	    (sc->wi_create_ibss && sc->wi_ptype == WI_PORTTYPE_IBSS)))
2136 		WI_SETSTR(WI_RID_OWN_SSID, sc->wi_net_name);
2137 	else
2138 		WI_SETSTR(WI_RID_OWN_SSID, sc->wi_ibss_name);
2139 
2140 	/* Specify the frequency to use */
2141 	WI_SETVAL(WI_RID_OWN_CHNL, sc->wi_channel);
2142 
2143 	/* Program the nodename. */
2144 	WI_SETSTR(WI_RID_NODENAME, sc->wi_node_name);
2145 
2146 	/* Set our MAC address. */
2147 	mac.wi_len = 4;
2148 	mac.wi_type = WI_RID_MAC_NODE;
2149 	bcopy(LLADDR(ifp->if_sadl), &sc->sc_ic.ic_myaddr, ETHER_ADDR_LEN);
2150 	bcopy(&sc->sc_ic.ic_myaddr, &mac.wi_mac_addr, ETHER_ADDR_LEN);
2151 	wi_write_record(sc, (struct wi_ltv_gen *)&mac);
2152 
2153 	/*
2154 	 * Initialize promisc mode.
2155 	 *	Being in the Host-AP mode causes
2156 	 *	great deal of pain if promisc mode is set.
2157 	 *	Therefore we avoid confusing the firmware
2158 	 *	and always reset promisc mode in Host-AP regime,
2159 	 *	it shows us all the packets anyway.
2160 	 */
2161 	if (sc->wi_ptype != WI_PORTTYPE_HOSTAP && ifp->if_flags & IFF_PROMISC)
2162 		WI_SETVAL(WI_RID_PROMISC, 1);
2163 	else
2164 		WI_SETVAL(WI_RID_PROMISC, 0);
2165 
2166 	/* Configure WEP. */
2167 	if (sc->wi_flags & WI_FLAGS_HAS_WEP) {
2168 		WI_SETVAL(WI_RID_ENCRYPTION, sc->wi_use_wep);
2169 		WI_SETVAL(WI_RID_TX_CRYPT_KEY, sc->wi_tx_key);
2170 		sc->wi_keys.wi_len = (sizeof(struct wi_ltv_keys) / 2) + 1;
2171 		sc->wi_keys.wi_type = WI_RID_DEFLT_CRYPT_KEYS;
2172 		wi_write_record(sc, (struct wi_ltv_gen *)&sc->wi_keys);
2173 		if (sc->sc_firmware_type != WI_LUCENT && sc->wi_use_wep) {
2174 			/*
2175 			 * HWB3163 EVAL-CARD Firmware version less than 0.8.2.
2176 			 *
2177 			 * If promiscuous mode is disabled, the Prism2 chip
2178 			 * does not work with WEP .
2179 			 * I'm currently investigating the details of this.
2180 			 * (ichiro@netbsd.org)
2181 			 */
2182 			 if (sc->sc_firmware_type == WI_INTERSIL &&
2183 			    sc->sc_sta_firmware_ver < 802 ) {
2184 				/* firm ver < 0.8.2 */
2185 				WI_SETVAL(WI_RID_PROMISC, 1);
2186 			 }
2187 			 WI_SETVAL(WI_RID_CNFAUTHMODE, sc->wi_authtype);
2188 		}
2189 	}
2190 
2191 	/* Set multicast filter. */
2192 	wi_setmulti(sc);
2193 
2194 	/* Enable desired port */
2195 	wi_cmd(sc, WI_CMD_ENABLE | sc->wi_portnum, 0, 0, 0);
2196 
2197 	if (wi_alloc_nicmem(sc, ETHER_MAX_LEN + sizeof(struct wi_frame) + 8, &id))
2198 		printf(WI_PRT_FMT ": tx buffer allocation failed\n",
2199 		    WI_PRT_ARG(sc));
2200 	sc->wi_tx_data_id = id;
2201 
2202 	if (wi_alloc_nicmem(sc, ETHER_MAX_LEN + sizeof(struct wi_frame) + 8, &id))
2203 		printf(WI_PRT_FMT ": mgmt. buffer allocation failed\n",
2204 		    WI_PRT_ARG(sc));
2205 	sc->wi_tx_mgmt_id = id;
2206 
2207 	/* Set txpower */
2208 	if (sc->wi_flags & WI_FLAGS_TXPOWER)
2209 		wi_set_txpower(sc, NULL);
2210 
2211 	/* enable interrupts */
2212 	wi_intr_enable(sc, WI_INTRS);
2213 
2214         wihap_init(sc);
2215 
2216 	splx(s);
2217 
2218 	ifp->if_flags |= IFF_RUNNING;
2219 	ifp->if_flags &= ~IFF_OACTIVE;
2220 
2221 	timeout_add_sec(&sc->sc_timo, 60);
2222 
2223 	return;
2224 }
2225 
2226 STATIC void
2227 wi_do_hostencrypt(struct wi_softc *sc, caddr_t buf, int len)
2228 {
2229 	u_int32_t crc, klen;
2230 	u_int8_t key[RC4KEYLEN];
2231 	u_int8_t *dat;
2232 	struct rc4_ctx ctx;
2233 
2234 	if (!sc->wi_icv_flag) {
2235 		sc->wi_icv = arc4random();
2236 		sc->wi_icv_flag++;
2237         } else
2238 		sc->wi_icv++;
2239 	/*
2240 	 * Skip 'bad' IVs from Fluhrer/Mantin/Shamir:
2241 	 * (B, 255, N) with 3 <= B < 8
2242 	 */
2243 	if (sc->wi_icv >= 0x03ff00 &&
2244             (sc->wi_icv & 0xf8ff00) == 0x00ff00)
2245                 sc->wi_icv += 0x000100;
2246 
2247 	/* prepend 24bit IV to tx key, byte order does not matter */
2248 	bzero(key, sizeof(key));
2249 	key[0] = sc->wi_icv >> 16;
2250 	key[1] = sc->wi_icv >> 8;
2251 	key[2] = sc->wi_icv;
2252 
2253 	klen = letoh16(sc->wi_keys.wi_keys[sc->wi_tx_key].wi_keylen);
2254 	bcopy(&sc->wi_keys.wi_keys[sc->wi_tx_key].wi_keydat,
2255 	    key + IEEE80211_WEP_IVLEN, klen);
2256 	klen = (klen > IEEE80211_WEP_KEYLEN) ? RC4KEYLEN : RC4KEYLEN / 2;
2257 
2258 	/* rc4 keysetup */
2259 	rc4_keysetup(&ctx, key, klen);
2260 
2261 	/* output: IV, tx keyid, rc4(data), rc4(crc32(data)) */
2262 	dat = buf;
2263 	dat[0] = key[0];
2264 	dat[1] = key[1];
2265 	dat[2] = key[2];
2266 	dat[3] = sc->wi_tx_key << 6;		/* pad and keyid */
2267 	dat += 4;
2268 
2269 	/* compute crc32 over data and encrypt */
2270 	crc = ~ether_crc32_le(dat, len);
2271 	rc4_crypt(&ctx, dat, dat, len);
2272 	dat += len;
2273 
2274 	/* append little-endian crc32 and encrypt */
2275 	dat[0] = crc;
2276 	dat[1] = crc >> 8;
2277 	dat[2] = crc >> 16;
2278 	dat[3] = crc >> 24;
2279 	rc4_crypt(&ctx, dat, dat, IEEE80211_WEP_CRCLEN);
2280 }
2281 
2282 STATIC int
2283 wi_do_hostdecrypt(struct wi_softc *sc, caddr_t buf, int len)
2284 {
2285 	u_int32_t crc, klen, kid;
2286 	u_int8_t key[RC4KEYLEN];
2287 	u_int8_t *dat;
2288 	struct rc4_ctx ctx;
2289 
2290 	if (len < IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN +
2291 	    IEEE80211_WEP_CRCLEN)
2292 		return -1;
2293 	len -= (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN +
2294 	    IEEE80211_WEP_CRCLEN);
2295 
2296 	dat = buf;
2297 
2298 	bzero(key, sizeof(key));
2299 	key[0] = dat[0];
2300 	key[1] = dat[1];
2301 	key[2] = dat[2];
2302 	kid = (dat[3] >> 6) % 4;
2303 	dat += 4;
2304 
2305 	klen = letoh16(sc->wi_keys.wi_keys[kid].wi_keylen);
2306 	bcopy(&sc->wi_keys.wi_keys[kid].wi_keydat,
2307 	    key + IEEE80211_WEP_IVLEN, klen);
2308 	klen = (klen > IEEE80211_WEP_KEYLEN) ? RC4KEYLEN : RC4KEYLEN / 2;
2309 
2310 	/* rc4 keysetup */
2311 	rc4_keysetup(&ctx, key, klen);
2312 
2313 	/* decrypt and compute crc32 over data */
2314 	rc4_crypt(&ctx, dat, dat, len);
2315 	crc = ~ether_crc32_le(dat, len);
2316 	dat += len;
2317 
2318 	/* decrypt little-endian crc32 and verify */
2319 	rc4_crypt(&ctx, dat, dat, IEEE80211_WEP_CRCLEN);
2320 
2321 	if ((dat[0] != crc) && (dat[1] != crc >> 8) &&
2322 	    (dat[2] != crc >> 16) && (dat[3] != crc >> 24)) {
2323 		if (sc->sc_ic.ic_if.if_flags & IFF_DEBUG)
2324 			printf(WI_PRT_FMT ": wi_do_hostdecrypt: iv mismatch: "
2325 			    "0x%02x%02x%02x%02x vs. 0x%x\n", WI_PRT_ARG(sc),
2326 			    dat[3], dat[2], dat[1], dat[0], crc);
2327 		return -1;
2328 	}
2329 
2330 	return 0;
2331 }
2332 
2333 void
2334 wi_start(struct ifnet *ifp)
2335 {
2336 	struct wi_softc		*sc;
2337 	struct mbuf		*m0;
2338 	struct wi_frame		tx_frame;
2339 	struct ether_header	*eh;
2340 	int			id, hostencrypt = 0;
2341 
2342 	sc = ifp->if_softc;
2343 
2344 	DPRINTF(WID_START, ("wi_start: ifp %p sc %p\n", ifp, sc));
2345 
2346 	if (!(sc->wi_flags & WI_FLAGS_ATTACHED))
2347 		return;
2348 
2349 	if (ifp->if_flags & IFF_OACTIVE)
2350 		return;
2351 
2352 nextpkt:
2353 	IFQ_DEQUEUE(&ifp->if_snd, m0);
2354 	if (m0 == NULL)
2355 		return;
2356 
2357 	bzero(&tx_frame, sizeof(tx_frame));
2358 	tx_frame.wi_frame_ctl = htole16(WI_FTYPE_DATA | WI_STYPE_DATA);
2359 	id = sc->wi_tx_data_id;
2360 	eh = mtod(m0, struct ether_header *);
2361 
2362 	if (sc->wi_ptype == WI_PORTTYPE_HOSTAP) {
2363 		if (!wihap_check_tx(&sc->wi_hostap_info, eh->ether_dhost,
2364 		    &tx_frame.wi_tx_rate) && !(ifp->if_flags & IFF_PROMISC)) {
2365 			if (ifp->if_flags & IFF_DEBUG)
2366 				printf(WI_PRT_FMT
2367 				    ": wi_start: dropping unassoc dst %s\n",
2368 				    WI_PRT_ARG(sc),
2369 				    ether_sprintf(eh->ether_dhost));
2370 			m_freem(m0);
2371 			goto nextpkt;
2372 		}
2373 	}
2374 
2375 	/*
2376 	 * Use RFC1042 encoding for IP and ARP datagrams,
2377 	 * 802.3 for anything else.
2378 	 */
2379 	if (eh->ether_type == htons(ETHERTYPE_IP) ||
2380 	    eh->ether_type == htons(ETHERTYPE_ARP) ||
2381 	    eh->ether_type == htons(ETHERTYPE_REVARP) ||
2382 	    eh->ether_type == htons(ETHERTYPE_IPV6)) {
2383 		bcopy(&eh->ether_dhost,
2384 		    &tx_frame.wi_addr1, ETHER_ADDR_LEN);
2385 		if (sc->wi_ptype == WI_PORTTYPE_HOSTAP) {
2386 			tx_frame.wi_tx_ctl = htole16(WI_ENC_TX_MGMT); /* XXX */
2387 			tx_frame.wi_frame_ctl |= htole16(WI_FCTL_FROMDS);
2388 			bcopy(&sc->sc_ic.ic_myaddr,
2389 			    &tx_frame.wi_addr2, ETHER_ADDR_LEN);
2390 			bcopy(&eh->ether_shost,
2391 			    &tx_frame.wi_addr3, ETHER_ADDR_LEN);
2392 			if (sc->wi_use_wep)
2393 				hostencrypt = 1;
2394 		} else if (sc->wi_ptype == WI_PORTTYPE_BSS && sc->wi_use_wep &&
2395 		    sc->wi_crypto_algorithm != WI_CRYPTO_FIRMWARE_WEP) {
2396 			tx_frame.wi_tx_ctl = htole16(WI_ENC_TX_MGMT); /* XXX */
2397 			tx_frame.wi_frame_ctl |= htole16(WI_FCTL_TODS);
2398 			bcopy(&sc->sc_ic.ic_myaddr,
2399 			    &tx_frame.wi_addr2, ETHER_ADDR_LEN);
2400 			bcopy(&eh->ether_dhost,
2401 			    &tx_frame.wi_addr3, ETHER_ADDR_LEN);
2402 			hostencrypt = 1;
2403 		} else
2404 			bcopy(&eh->ether_shost,
2405 			    &tx_frame.wi_addr2, ETHER_ADDR_LEN);
2406 		bcopy(&eh->ether_dhost, &tx_frame.wi_dst_addr, ETHER_ADDR_LEN);
2407 		bcopy(&eh->ether_shost, &tx_frame.wi_src_addr, ETHER_ADDR_LEN);
2408 
2409 		tx_frame.wi_dat_len = m0->m_pkthdr.len - WI_SNAPHDR_LEN;
2410 		tx_frame.wi_dat[0] = htons(WI_SNAP_WORD0);
2411 		tx_frame.wi_dat[1] = htons(WI_SNAP_WORD1);
2412 		tx_frame.wi_len = htons(m0->m_pkthdr.len - WI_SNAPHDR_LEN);
2413 		tx_frame.wi_type = eh->ether_type;
2414 
2415 		if (hostencrypt) {
2416 
2417 			/* Do host encryption. */
2418 			tx_frame.wi_frame_ctl |= htole16(WI_FCTL_WEP);
2419 			bcopy(&tx_frame.wi_dat[0], &sc->wi_txbuf[4], 6);
2420 			bcopy(&tx_frame.wi_type, &sc->wi_txbuf[10], 2);
2421 
2422 			m_copydata(m0, sizeof(struct ether_header),
2423 			    m0->m_pkthdr.len - sizeof(struct ether_header),
2424 			    (caddr_t)&sc->wi_txbuf[12]);
2425 
2426 			wi_do_hostencrypt(sc, (caddr_t)&sc->wi_txbuf,
2427 			    tx_frame.wi_dat_len);
2428 
2429 			tx_frame.wi_dat_len += IEEE80211_WEP_IVLEN +
2430 			    IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN;
2431 
2432 			tx_frame.wi_dat_len = htole16(tx_frame.wi_dat_len);
2433 			wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
2434 			    sizeof(struct wi_frame));
2435 			wi_write_data(sc, id, WI_802_11_OFFSET_RAW,
2436 			    (caddr_t)&sc->wi_txbuf,
2437 			    (m0->m_pkthdr.len -
2438 			     sizeof(struct ether_header)) + 18);
2439 		} else {
2440 			m_copydata(m0, sizeof(struct ether_header),
2441 			    m0->m_pkthdr.len - sizeof(struct ether_header),
2442 			    (caddr_t)&sc->wi_txbuf);
2443 
2444 			tx_frame.wi_dat_len = htole16(tx_frame.wi_dat_len);
2445 			wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
2446 			    sizeof(struct wi_frame));
2447 			wi_write_data(sc, id, WI_802_11_OFFSET,
2448 			    (caddr_t)&sc->wi_txbuf,
2449 			    (m0->m_pkthdr.len -
2450 			     sizeof(struct ether_header)) + 2);
2451 		}
2452 	} else {
2453 		tx_frame.wi_dat_len = htole16(m0->m_pkthdr.len);
2454 
2455 		if (sc->wi_ptype == WI_PORTTYPE_HOSTAP && sc->wi_use_wep) {
2456 
2457 			/* Do host encryption. (XXX - not implemented) */
2458 			printf(WI_PRT_FMT
2459 			    ": host encrypt not implemented for 802.3\n",
2460 			    WI_PRT_ARG(sc));
2461 		} else {
2462 			m_copydata(m0, 0, m0->m_pkthdr.len,
2463 			    (caddr_t)&sc->wi_txbuf);
2464 
2465 			wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
2466 			    sizeof(struct wi_frame));
2467 			wi_write_data(sc, id, WI_802_3_OFFSET,
2468 			    (caddr_t)&sc->wi_txbuf, m0->m_pkthdr.len + 2);
2469 		}
2470 	}
2471 
2472 #if NBPFILTER > 0
2473 	/*
2474 	 * If there's a BPF listener, bounce a copy of
2475 	 * this frame to him.
2476 	 */
2477 	if (ifp->if_bpf)
2478 		bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT);
2479 #endif
2480 
2481 	m_freem(m0);
2482 
2483 	ifp->if_flags |= IFF_OACTIVE;
2484 
2485 	/*
2486 	 * Set a timeout in case the chip goes out to lunch.
2487 	 */
2488 	ifp->if_timer = 5;
2489 
2490 	if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id, 0, 0))
2491 		printf(WI_PRT_FMT ": wi_start: xmit failed\n", WI_PRT_ARG(sc));
2492 
2493 	return;
2494 }
2495 
2496 STATIC int
2497 wi_mgmt_xmit(struct wi_softc *sc, caddr_t data, int len)
2498 {
2499 	struct wi_frame		tx_frame;
2500 	int			id;
2501 	struct wi_80211_hdr	*hdr;
2502 	caddr_t			dptr;
2503 
2504 	if (!(sc->wi_flags & WI_FLAGS_ATTACHED))
2505 		return(ENODEV);
2506 
2507 	hdr = (struct wi_80211_hdr *)data;
2508 	dptr = data + sizeof(struct wi_80211_hdr);
2509 
2510 	bzero(&tx_frame, sizeof(tx_frame));
2511 	id = sc->wi_tx_mgmt_id;
2512 
2513 	bcopy(hdr, &tx_frame.wi_frame_ctl, sizeof(struct wi_80211_hdr));
2514 
2515 	tx_frame.wi_tx_ctl = htole16(WI_ENC_TX_MGMT);
2516 	tx_frame.wi_dat_len = len - sizeof(struct wi_80211_hdr);
2517 	tx_frame.wi_len = htole16(tx_frame.wi_dat_len);
2518 
2519 	tx_frame.wi_dat_len = htole16(tx_frame.wi_dat_len);
2520 	wi_write_data(sc, id, 0, (caddr_t)&tx_frame, sizeof(struct wi_frame));
2521 	wi_write_data(sc, id, WI_802_11_OFFSET_RAW, dptr,
2522 	    (len - sizeof(struct wi_80211_hdr)) + 2);
2523 
2524 	if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id, 0, 0)) {
2525 		printf(WI_PRT_FMT ": wi_mgmt_xmit: xmit failed\n",
2526 		    WI_PRT_ARG(sc));
2527 		/*
2528 		 * Hostile stations or corrupt frames may crash the card
2529 		 * and cause the kernel to get stuck printing complaints.
2530 		 * Reset the card and hope the problem goes away.
2531 		 */
2532 		wi_reset(sc);
2533 		return(EIO);
2534 	}
2535 
2536 	return(0);
2537 }
2538 
2539 void
2540 wi_stop(struct wi_softc *sc)
2541 {
2542 	struct ifnet		*ifp;
2543 
2544 	wihap_shutdown(sc);
2545 
2546 	if (!(sc->wi_flags & WI_FLAGS_ATTACHED))
2547 		return;
2548 
2549 	DPRINTF(WID_STOP, ("wi_stop: sc %p\n", sc));
2550 
2551 	timeout_del(&sc->sc_timo);
2552 
2553 	ifp = &sc->sc_ic.ic_if;
2554 
2555 	wi_intr_enable(sc, 0);
2556 	wi_cmd(sc, WI_CMD_DISABLE|sc->wi_portnum, 0, 0, 0);
2557 
2558 	ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE);
2559 	ifp->if_timer = 0;
2560 
2561 	return;
2562 }
2563 
2564 
2565 void
2566 wi_watchdog(struct ifnet *ifp)
2567 {
2568 	struct wi_softc		*sc;
2569 
2570 	sc = ifp->if_softc;
2571 
2572 	printf(WI_PRT_FMT ": device timeout\n", WI_PRT_ARG(sc));
2573 
2574 	wi_cor_reset(sc);
2575 	wi_init(sc);
2576 
2577 	ifp->if_oerrors++;
2578 
2579 	return;
2580 }
2581 
2582 void
2583 wi_detach(struct wi_softc *sc)
2584 {
2585 	struct ifnet *ifp;
2586 	ifp = &sc->sc_ic.ic_if;
2587 
2588 	if (ifp->if_flags & IFF_RUNNING)
2589 		wi_stop(sc);
2590 
2591 	if (sc->wi_flags & WI_FLAGS_ATTACHED) {
2592 		sc->wi_flags &= ~WI_FLAGS_ATTACHED;
2593 	}
2594 }
2595 
2596 STATIC void
2597 wi_get_id(struct wi_softc *sc)
2598 {
2599 	struct wi_ltv_ver		ver;
2600 	const struct wi_card_ident	*id;
2601 	u_int16_t			pri_fw_ver[3];
2602 	const char			*card_name;
2603 	u_int16_t			card_id;
2604 
2605 	/* get chip identity */
2606 	bzero(&ver, sizeof(ver));
2607 	ver.wi_type = WI_RID_CARD_ID;
2608 	ver.wi_len = 5;
2609 	wi_read_record(sc, (struct wi_ltv_gen *)&ver);
2610 	card_id = letoh16(ver.wi_ver[0]);
2611 	for (id = wi_card_ident; id->firm_type != WI_NOTYPE; id++) {
2612 		if (card_id == id->card_id)
2613 			break;
2614 	}
2615 	if (id->firm_type != WI_NOTYPE) {
2616 		sc->sc_firmware_type = id->firm_type;
2617 		card_name = id->card_name;
2618 	} else if (ver.wi_ver[0] & htole16(0x8000)) {
2619 		sc->sc_firmware_type = WI_INTERSIL;
2620 		card_name = "Unknown PRISM2 chip";
2621 	} else {
2622 		sc->sc_firmware_type = WI_LUCENT;
2623 	}
2624 
2625 	/* get primary firmware version (XXX - how to do Lucent?) */
2626 	if (sc->sc_firmware_type != WI_LUCENT) {
2627 		bzero(&ver, sizeof(ver));
2628 		ver.wi_type = WI_RID_PRI_IDENTITY;
2629 		ver.wi_len = 5;
2630 		wi_read_record(sc, (struct wi_ltv_gen *)&ver);
2631 		pri_fw_ver[0] = letoh16(ver.wi_ver[2]);
2632 		pri_fw_ver[1] = letoh16(ver.wi_ver[3]);
2633 		pri_fw_ver[2] = letoh16(ver.wi_ver[1]);
2634 	}
2635 
2636 	/* get station firmware version */
2637 	bzero(&ver, sizeof(ver));
2638 	ver.wi_type = WI_RID_STA_IDENTITY;
2639 	ver.wi_len = 5;
2640 	wi_read_record(sc, (struct wi_ltv_gen *)&ver);
2641 	ver.wi_ver[1] = letoh16(ver.wi_ver[1]);
2642 	ver.wi_ver[2] = letoh16(ver.wi_ver[2]);
2643 	ver.wi_ver[3] = letoh16(ver.wi_ver[3]);
2644 	sc->sc_sta_firmware_ver = ver.wi_ver[2] * 10000 +
2645 	    ver.wi_ver[3] * 100 + ver.wi_ver[1];
2646 
2647 	if (sc->sc_firmware_type == WI_INTERSIL &&
2648 	    (sc->sc_sta_firmware_ver == 10102 || sc->sc_sta_firmware_ver == 20102)) {
2649 		struct wi_ltv_str sver;
2650 		char *p;
2651 
2652 		bzero(&sver, sizeof(sver));
2653 		sver.wi_type = WI_RID_SYMBOL_IDENTITY;
2654 		sver.wi_len = 7;
2655 		/* value should be something like "V2.00-11" */
2656 		if (wi_read_record(sc, (struct wi_ltv_gen *)&sver) == 0 &&
2657 		    *(p = (char *)sver.wi_str) >= 'A' &&
2658 		    p[2] == '.' && p[5] == '-' && p[8] == '\0') {
2659 			sc->sc_firmware_type = WI_SYMBOL;
2660 			sc->sc_sta_firmware_ver = (p[1] - '0') * 10000 +
2661 			    (p[3] - '0') * 1000 + (p[4] - '0') * 100 +
2662 			    (p[6] - '0') * 10 + (p[7] - '0');
2663 		}
2664 	}
2665 
2666 	if (sc->sc_firmware_type == WI_LUCENT) {
2667 		printf("%s: Firmware %d.%02d variant %d, ", WI_PRT_ARG(sc),
2668 		    ver.wi_ver[2], ver.wi_ver[3], ver.wi_ver[1]);
2669 	} else {
2670 		printf("%s: %s%s (0x%04x), Firmware %d.%d.%d (primary), %d.%d.%d (station), ",
2671 		    WI_PRT_ARG(sc),
2672 		    sc->sc_firmware_type == WI_SYMBOL ? "Symbol " : "",
2673 		    card_name, card_id, pri_fw_ver[0], pri_fw_ver[1],
2674 		    pri_fw_ver[2], sc->sc_sta_firmware_ver / 10000,
2675 		    (sc->sc_sta_firmware_ver % 10000) / 100,
2676 		    sc->sc_sta_firmware_ver % 100);
2677 	}
2678 }
2679 
2680 STATIC int
2681 wi_sync_media(struct wi_softc *sc, int ptype, int txrate)
2682 {
2683 	int media = sc->sc_media.ifm_cur->ifm_media;
2684 	int options = IFM_OPTIONS(media);
2685 	int subtype;
2686 
2687 	switch (txrate) {
2688 	case 1:
2689 		subtype = IFM_IEEE80211_DS1;
2690 		break;
2691 	case 2:
2692 		subtype = IFM_IEEE80211_DS2;
2693 		break;
2694 	case 3:
2695 		subtype = IFM_AUTO;
2696 		break;
2697 	case 5:
2698 		subtype = IFM_IEEE80211_DS5;
2699 		break;
2700 	case 11:
2701 		subtype = IFM_IEEE80211_DS11;
2702 		break;
2703 	default:
2704 		subtype = IFM_MANUAL;		/* Unable to represent */
2705 		break;
2706 	}
2707 
2708 	options &= ~IFM_OMASK;
2709 	switch (ptype) {
2710 	case WI_PORTTYPE_BSS:
2711 		/* default port type */
2712 		break;
2713 	case WI_PORTTYPE_ADHOC:
2714 		options |= IFM_IEEE80211_ADHOC;
2715 		break;
2716 	case WI_PORTTYPE_HOSTAP:
2717 		options |= IFM_IEEE80211_HOSTAP;
2718 		break;
2719 	case WI_PORTTYPE_IBSS:
2720 		if (sc->wi_create_ibss)
2721 			options |= IFM_IEEE80211_IBSSMASTER;
2722 		else
2723 			options |= IFM_IEEE80211_IBSS;
2724 		break;
2725 	default:
2726 		subtype = IFM_MANUAL;		/* Unable to represent */
2727 		break;
2728 	}
2729 	media = IFM_MAKEWORD(IFM_TYPE(media), subtype, options,
2730 	IFM_INST(media));
2731 	if (ifmedia_match(&sc->sc_media, media, sc->sc_media.ifm_mask) == NULL)
2732 		return (EINVAL);
2733 	ifmedia_set(&sc->sc_media, media);
2734 	sc->wi_ptype = ptype;
2735 	sc->wi_tx_rate = txrate;
2736 	return (0);
2737 }
2738 
2739 STATIC int
2740 wi_media_change(struct ifnet *ifp)
2741 {
2742 	struct wi_softc *sc = ifp->if_softc;
2743 	int otype = sc->wi_ptype;
2744 	int orate = sc->wi_tx_rate;
2745 	int ocreate_ibss = sc->wi_create_ibss;
2746 
2747 	if ((sc->sc_media.ifm_cur->ifm_media & IFM_IEEE80211_HOSTAP) &&
2748 	    sc->sc_firmware_type != WI_INTERSIL)
2749 		return (EINVAL);
2750 
2751 	sc->wi_create_ibss = 0;
2752 
2753 	switch (sc->sc_media.ifm_cur->ifm_media & IFM_OMASK) {
2754 	case 0:
2755 		sc->wi_ptype = WI_PORTTYPE_BSS;
2756 		break;
2757 	case IFM_IEEE80211_ADHOC:
2758 		sc->wi_ptype = WI_PORTTYPE_ADHOC;
2759 		break;
2760 	case IFM_IEEE80211_HOSTAP:
2761 		sc->wi_ptype = WI_PORTTYPE_HOSTAP;
2762 		break;
2763 	case IFM_IEEE80211_IBSSMASTER:
2764 	case IFM_IEEE80211_IBSSMASTER|IFM_IEEE80211_IBSS:
2765 		if (!(sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS))
2766 			return (EINVAL);
2767 		sc->wi_create_ibss = 1;
2768 		/* FALLTHROUGH */
2769 	case IFM_IEEE80211_IBSS:
2770 		sc->wi_ptype = WI_PORTTYPE_IBSS;
2771 		break;
2772 	default:
2773 		/* Invalid combination. */
2774 		return (EINVAL);
2775 	}
2776 
2777 	switch (IFM_SUBTYPE(sc->sc_media.ifm_cur->ifm_media)) {
2778 	case IFM_IEEE80211_DS1:
2779 		sc->wi_tx_rate = 1;
2780 		break;
2781 	case IFM_IEEE80211_DS2:
2782 		sc->wi_tx_rate = 2;
2783 		break;
2784 	case IFM_AUTO:
2785 		sc->wi_tx_rate = 3;
2786 		break;
2787 	case IFM_IEEE80211_DS5:
2788 		sc->wi_tx_rate = 5;
2789 		break;
2790 	case IFM_IEEE80211_DS11:
2791 		sc->wi_tx_rate = 11;
2792 		break;
2793 	}
2794 
2795 	if (sc->sc_ic.ic_if.if_flags & IFF_UP) {
2796 		if (otype != sc->wi_ptype || orate != sc->wi_tx_rate ||
2797 		    ocreate_ibss != sc->wi_create_ibss)
2798 			wi_init(sc);
2799 	}
2800 
2801 	ifp->if_baudrate = ifmedia_baudrate(sc->sc_media.ifm_cur->ifm_media);
2802 
2803 	return (0);
2804 }
2805 
2806 STATIC void
2807 wi_media_status(struct ifnet *ifp, struct ifmediareq *imr)
2808 {
2809 	struct wi_softc *sc = ifp->if_softc;
2810 	struct wi_req wreq;
2811 
2812 	if (!(sc->sc_ic.ic_if.if_flags & IFF_UP)) {
2813 		imr->ifm_active = IFM_IEEE80211|IFM_NONE;
2814 		imr->ifm_status = 0;
2815 		return;
2816 	}
2817 
2818 	if (sc->wi_tx_rate == 3) {
2819 		imr->ifm_active = IFM_IEEE80211|IFM_AUTO;
2820 
2821 		wreq.wi_type = WI_RID_CUR_TX_RATE;
2822 		wreq.wi_len = WI_MAX_DATALEN;
2823 		if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq) == 0) {
2824 			switch (letoh16(wreq.wi_val[0])) {
2825 			case 1:
2826 				imr->ifm_active |= IFM_IEEE80211_DS1;
2827 				break;
2828 			case 2:
2829 				imr->ifm_active |= IFM_IEEE80211_DS2;
2830 				break;
2831 			case 6:
2832 				imr->ifm_active |= IFM_IEEE80211_DS5;
2833 				break;
2834 			case 11:
2835 				imr->ifm_active |= IFM_IEEE80211_DS11;
2836 				break;
2837 			}
2838 		}
2839 	} else {
2840 		imr->ifm_active = sc->sc_media.ifm_cur->ifm_media;
2841 	}
2842 
2843 	imr->ifm_status = IFM_AVALID;
2844 	switch (sc->wi_ptype) {
2845 	case WI_PORTTYPE_ADHOC:
2846 	case WI_PORTTYPE_IBSS:
2847 		/*
2848 		 * XXX: It would be nice if we could give some actually
2849 		 * useful status like whether we joined another IBSS or
2850 		 * created one ourselves.
2851 		 */
2852 		/* FALLTHROUGH */
2853 	case WI_PORTTYPE_HOSTAP:
2854 		imr->ifm_status |= IFM_ACTIVE;
2855 		break;
2856 	default:
2857 		wreq.wi_type = WI_RID_COMMQUAL;
2858 		wreq.wi_len = WI_MAX_DATALEN;
2859 		if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq) == 0 &&
2860 		    letoh16(wreq.wi_val[0]) != 0)
2861 			imr->ifm_status |= IFM_ACTIVE;
2862 	}
2863 }
2864 
2865 STATIC int
2866 wi_set_nwkey(struct wi_softc *sc, struct ieee80211_nwkey *nwkey)
2867 {
2868 	int i, len, error;
2869 	struct wi_req wreq;
2870 	struct wi_ltv_keys *wk = (struct wi_ltv_keys *)&wreq;
2871 
2872 	if (!(sc->wi_flags & WI_FLAGS_HAS_WEP))
2873 		return ENODEV;
2874 	if (nwkey->i_defkid <= 0 || nwkey->i_defkid > IEEE80211_WEP_NKID)
2875 		return EINVAL;
2876 	memcpy(wk, &sc->wi_keys, sizeof(*wk));
2877 	for (i = 0; i < IEEE80211_WEP_NKID; i++) {
2878 		if (nwkey->i_key[i].i_keydat == NULL)
2879 			continue;
2880 		len = nwkey->i_key[i].i_keylen;
2881 		if (len > sizeof(wk->wi_keys[i].wi_keydat))
2882 			return EINVAL;
2883 		error = copyin(nwkey->i_key[i].i_keydat,
2884 		    wk->wi_keys[i].wi_keydat, len);
2885 		if (error)
2886 			return error;
2887 		wk->wi_keys[i].wi_keylen = htole16(len);
2888 	}
2889 
2890 	wk->wi_len = (sizeof(*wk) / 2) + 1;
2891 	wk->wi_type = WI_RID_DEFLT_CRYPT_KEYS;
2892 	if (sc->sc_ic.ic_if.if_flags & IFF_UP) {
2893 		error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
2894 		if (error)
2895 			return error;
2896 	}
2897 	if ((error = wi_setdef(sc, &wreq)))
2898 		return (error);
2899 
2900 	wreq.wi_len = 2;
2901 	wreq.wi_type = WI_RID_TX_CRYPT_KEY;
2902 	wreq.wi_val[0] = htole16(nwkey->i_defkid - 1);
2903 	if (sc->sc_ic.ic_if.if_flags & IFF_UP) {
2904 		error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
2905 		if (error)
2906 			return error;
2907 	}
2908 	if ((error = wi_setdef(sc, &wreq)))
2909 		return (error);
2910 
2911 	wreq.wi_type = WI_RID_ENCRYPTION;
2912 	wreq.wi_val[0] = htole16(nwkey->i_wepon);
2913 	if (sc->sc_ic.ic_if.if_flags & IFF_UP) {
2914 		error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
2915 		if (error)
2916 			return error;
2917 	}
2918 	if ((error = wi_setdef(sc, &wreq)))
2919 		return (error);
2920 
2921 	if (sc->sc_ic.ic_if.if_flags & IFF_UP)
2922 		wi_init(sc);
2923 	return 0;
2924 }
2925 
2926 STATIC int
2927 wi_get_nwkey(struct wi_softc *sc, struct ieee80211_nwkey *nwkey)
2928 {
2929 	int i, len, error;
2930 	struct wi_ltv_keys *wk = &sc->wi_keys;
2931 
2932 	if (!(sc->wi_flags & WI_FLAGS_HAS_WEP))
2933 		return ENODEV;
2934 	nwkey->i_wepon = sc->wi_use_wep;
2935 	nwkey->i_defkid = sc->wi_tx_key + 1;
2936 
2937 	/* do not show any keys to non-root user */
2938 	error = suser(curproc, 0);
2939 	for (i = 0; i < IEEE80211_WEP_NKID; i++) {
2940 		if (nwkey->i_key[i].i_keydat == NULL)
2941 			continue;
2942 		/* error holds results of suser() for the first time */
2943 		if (error)
2944 			return error;
2945 		len = letoh16(wk->wi_keys[i].wi_keylen);
2946 		if (nwkey->i_key[i].i_keylen < len)
2947 			return ENOSPC;
2948 		nwkey->i_key[i].i_keylen = len;
2949 		error = copyout(wk->wi_keys[i].wi_keydat,
2950 		    nwkey->i_key[i].i_keydat, len);
2951 		if (error)
2952 			return error;
2953 	}
2954 	return 0;
2955 }
2956 
2957 STATIC int
2958 wi_set_pm(struct wi_softc *sc, struct ieee80211_power *power)
2959 {
2960 
2961 	sc->wi_pm_enabled = power->i_enabled;
2962 	sc->wi_max_sleep = power->i_maxsleep;
2963 
2964 	if (sc->sc_ic.ic_if.if_flags & IFF_UP)
2965 		wi_init(sc);
2966 
2967 	return (0);
2968 }
2969 
2970 STATIC int
2971 wi_get_pm(struct wi_softc *sc, struct ieee80211_power *power)
2972 {
2973 
2974 	power->i_enabled = sc->wi_pm_enabled;
2975 	power->i_maxsleep = sc->wi_max_sleep;
2976 
2977 	return (0);
2978 }
2979 
2980 STATIC int
2981 wi_set_txpower(struct wi_softc *sc, struct ieee80211_txpower *txpower)
2982 {
2983 	u_int16_t	cmd;
2984 	u_int16_t	power;
2985 	int8_t		tmp;
2986 	int		error;
2987 	int		alc;
2988 
2989 	if (txpower == NULL) {
2990 		if (!(sc->wi_flags & WI_FLAGS_TXPOWER))
2991 			return (EINVAL);
2992 		alc = 0;		/* disable ALC */
2993 	} else {
2994 		if (txpower->i_mode == IEEE80211_TXPOWER_MODE_AUTO) {
2995 			alc = 1;	/* enable ALC */
2996 			sc->wi_flags &= ~WI_FLAGS_TXPOWER;
2997 		} else {
2998 			alc = 0;	/* disable ALC */
2999 			sc->wi_flags |= WI_FLAGS_TXPOWER;
3000 			sc->wi_txpower = txpower->i_val;
3001 		}
3002 	}
3003 
3004 	/* Set ALC */
3005 	cmd = WI_CMD_DEBUG | (WI_DEBUG_CONFBITS << 8);
3006 	if ((error = wi_cmd(sc, cmd, alc, 0x8, 0)) != 0)
3007 		return (error);
3008 
3009 	/* No need to set the TX power value if ALC is enabled */
3010 	if (alc)
3011 		return (0);
3012 
3013 	/* Convert dBM to internal TX power value */
3014 	if (sc->wi_txpower > 20)
3015 		power = 128;
3016 	else if (sc->wi_txpower < -43)
3017 		power = 127;
3018 	else {
3019 		tmp = sc->wi_txpower;
3020 		tmp = -12 - tmp;
3021 		tmp <<= 2;
3022 
3023 		power = (u_int16_t)tmp;
3024 	}
3025 
3026 	/* Set manual TX power */
3027 	cmd = WI_CMD_WRITE_MIF;
3028 	if ((error = wi_cmd(sc, cmd,
3029 		 WI_HFA384X_CR_MANUAL_TX_POWER, power, 0)) != 0)
3030 		return (error);
3031 
3032 	if (sc->sc_ic.ic_if.if_flags & IFF_DEBUG)
3033 		printf("%s: %u (%d dBm)\n", sc->sc_dev.dv_xname, power,
3034 		    sc->wi_txpower);
3035 
3036 	return (0);
3037 }
3038 
3039 STATIC int
3040 wi_get_txpower(struct wi_softc *sc, struct ieee80211_txpower *txpower)
3041 {
3042 	u_int16_t	cmd;
3043 	u_int16_t	power;
3044 	int8_t		tmp;
3045 	int		error;
3046 
3047 	if (sc->wi_flags & WI_FLAGS_BUS_USB)
3048 		return (EOPNOTSUPP);
3049 
3050 	/* Get manual TX power */
3051 	cmd = WI_CMD_READ_MIF;
3052 	if ((error = wi_cmd(sc, cmd,
3053 		 WI_HFA384X_CR_MANUAL_TX_POWER, 0, 0)) != 0)
3054 		return (error);
3055 
3056 	power = CSR_READ_2(sc, WI_RESP0);
3057 
3058 	/* Convert internal TX power value to dBM */
3059 	if (power > 255)
3060 		txpower->i_val = 255;
3061 	else {
3062 		tmp = power;
3063 		tmp >>= 2;
3064 		txpower->i_val = (u_int16_t)(-12 - tmp);
3065 	}
3066 
3067 	if (sc->wi_flags & WI_FLAGS_TXPOWER)
3068 		txpower->i_mode = IEEE80211_TXPOWER_MODE_FIXED;
3069 	else
3070 		txpower->i_mode = IEEE80211_TXPOWER_MODE_AUTO;
3071 
3072 	return (0);
3073 }
3074 
3075 STATIC int
3076 wi_set_ssid(struct ieee80211_nwid *ws, u_int8_t *id, int len)
3077 {
3078 
3079 	if (len > IEEE80211_NWID_LEN)
3080 		return (EINVAL);
3081 	ws->i_len = len;
3082 	memcpy(ws->i_nwid, id, len);
3083 	return (0);
3084 }
3085 
3086 STATIC int
3087 wi_get_debug(struct wi_softc *sc, struct wi_req *wreq)
3088 {
3089 	int			error = 0;
3090 
3091 	wreq->wi_len = 1;
3092 
3093 	switch (wreq->wi_type) {
3094 	case WI_DEBUG_SLEEP:
3095 		wreq->wi_len++;
3096 		wreq->wi_val[0] = htole16(sc->wi_debug.wi_sleep);
3097 		break;
3098 	case WI_DEBUG_DELAYSUPP:
3099 		wreq->wi_len++;
3100 		wreq->wi_val[0] = htole16(sc->wi_debug.wi_delaysupp);
3101 		break;
3102 	case WI_DEBUG_TXSUPP:
3103 		wreq->wi_len++;
3104 		wreq->wi_val[0] = htole16(sc->wi_debug.wi_txsupp);
3105 		break;
3106 	case WI_DEBUG_MONITOR:
3107 		wreq->wi_len++;
3108 		wreq->wi_val[0] = htole16(sc->wi_debug.wi_monitor);
3109 		break;
3110 	case WI_DEBUG_LEDTEST:
3111 		wreq->wi_len += 3;
3112 		wreq->wi_val[0] = htole16(sc->wi_debug.wi_ledtest);
3113 		wreq->wi_val[1] = htole16(sc->wi_debug.wi_ledtest_param0);
3114 		wreq->wi_val[2] = htole16(sc->wi_debug.wi_ledtest_param1);
3115 		break;
3116 	case WI_DEBUG_CONTTX:
3117 		wreq->wi_len += 2;
3118 		wreq->wi_val[0] = htole16(sc->wi_debug.wi_conttx);
3119 		wreq->wi_val[1] = htole16(sc->wi_debug.wi_conttx_param0);
3120 		break;
3121 	case WI_DEBUG_CONTRX:
3122 		wreq->wi_len++;
3123 		wreq->wi_val[0] = htole16(sc->wi_debug.wi_contrx);
3124 		break;
3125 	case WI_DEBUG_SIGSTATE:
3126 		wreq->wi_len += 2;
3127 		wreq->wi_val[0] = htole16(sc->wi_debug.wi_sigstate);
3128 		wreq->wi_val[1] = htole16(sc->wi_debug.wi_sigstate_param0);
3129 		break;
3130 	case WI_DEBUG_CONFBITS:
3131 		wreq->wi_len += 2;
3132 		wreq->wi_val[0] = htole16(sc->wi_debug.wi_confbits);
3133 		wreq->wi_val[1] = htole16(sc->wi_debug.wi_confbits_param0);
3134 		break;
3135 	default:
3136 		error = EIO;
3137 		break;
3138 	}
3139 
3140 	return (error);
3141 }
3142 
3143 STATIC int
3144 wi_set_debug(struct wi_softc *sc, struct wi_req *wreq)
3145 {
3146 	int				error = 0;
3147 	u_int16_t			cmd, param0 = 0, param1 = 0;
3148 
3149 	switch (wreq->wi_type) {
3150 	case WI_DEBUG_RESET:
3151 	case WI_DEBUG_INIT:
3152 	case WI_DEBUG_CALENABLE:
3153 		break;
3154 	case WI_DEBUG_SLEEP:
3155 		sc->wi_debug.wi_sleep = 1;
3156 		break;
3157 	case WI_DEBUG_WAKE:
3158 		sc->wi_debug.wi_sleep = 0;
3159 		break;
3160 	case WI_DEBUG_CHAN:
3161 		param0 = letoh16(wreq->wi_val[0]);
3162 		break;
3163 	case WI_DEBUG_DELAYSUPP:
3164 		sc->wi_debug.wi_delaysupp = 1;
3165 		break;
3166 	case WI_DEBUG_TXSUPP:
3167 		sc->wi_debug.wi_txsupp = 1;
3168 		break;
3169 	case WI_DEBUG_MONITOR:
3170 		sc->wi_debug.wi_monitor = 1;
3171 		break;
3172 	case WI_DEBUG_LEDTEST:
3173 		param0 = letoh16(wreq->wi_val[0]);
3174 		param1 = letoh16(wreq->wi_val[1]);
3175 		sc->wi_debug.wi_ledtest = 1;
3176 		sc->wi_debug.wi_ledtest_param0 = param0;
3177 		sc->wi_debug.wi_ledtest_param1 = param1;
3178 		break;
3179 	case WI_DEBUG_CONTTX:
3180 		param0 = letoh16(wreq->wi_val[0]);
3181 		sc->wi_debug.wi_conttx = 1;
3182 		sc->wi_debug.wi_conttx_param0 = param0;
3183 		break;
3184 	case WI_DEBUG_STOPTEST:
3185 		sc->wi_debug.wi_delaysupp = 0;
3186 		sc->wi_debug.wi_txsupp = 0;
3187 		sc->wi_debug.wi_monitor = 0;
3188 		sc->wi_debug.wi_ledtest = 0;
3189 		sc->wi_debug.wi_ledtest_param0 = 0;
3190 		sc->wi_debug.wi_ledtest_param1 = 0;
3191 		sc->wi_debug.wi_conttx = 0;
3192 		sc->wi_debug.wi_conttx_param0 = 0;
3193 		sc->wi_debug.wi_contrx = 0;
3194 		sc->wi_debug.wi_sigstate = 0;
3195 		sc->wi_debug.wi_sigstate_param0 = 0;
3196 		break;
3197 	case WI_DEBUG_CONTRX:
3198 		sc->wi_debug.wi_contrx = 1;
3199 		break;
3200 	case WI_DEBUG_SIGSTATE:
3201 		param0 = letoh16(wreq->wi_val[0]);
3202 		sc->wi_debug.wi_sigstate = 1;
3203 		sc->wi_debug.wi_sigstate_param0 = param0;
3204 		break;
3205 	case WI_DEBUG_CONFBITS:
3206 		param0 = letoh16(wreq->wi_val[0]);
3207 		param1 = letoh16(wreq->wi_val[1]);
3208 		sc->wi_debug.wi_confbits = param0;
3209 		sc->wi_debug.wi_confbits_param0 = param1;
3210 		break;
3211 	default:
3212 		error = EIO;
3213 		break;
3214 	}
3215 
3216 	if (error)
3217 		return (error);
3218 
3219 	cmd = WI_CMD_DEBUG | (wreq->wi_type << 8);
3220 	error = wi_cmd(sc, cmd, param0, param1, 0);
3221 
3222 	return (error);
3223 }
3224