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