xref: /openbsd-src/sys/dev/ic/if_wi.c (revision d13be5d47e4149db2549a9828e244d59dbc43f15)
1 /*	$OpenBSD: if_wi.c,v 1.150 2011/06/21 16:52:45 tedu 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(&mac.wi_mac_addr, &ic->ic_myaddr, IEEE80211_ADDR_LEN);
230 
231 	wi_get_id(sc);
232 	printf("address %s", ether_sprintf(ic->ic_myaddr));
233 
234 	bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
235 	ifp->if_softc = sc;
236 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
237 	ifp->if_ioctl = funcs->f_ioctl;
238 	ifp->if_start = funcs->f_start;
239 	ifp->if_watchdog = funcs->f_watchdog;
240 	ifp->if_baudrate = 10000000;
241 	IFQ_SET_READY(&ifp->if_snd);
242 
243 	(void)wi_set_ssid(&sc->wi_node_name, WI_DEFAULT_NODENAME,
244 	    sizeof(WI_DEFAULT_NODENAME) - 1);
245 	(void)wi_set_ssid(&sc->wi_net_name, WI_DEFAULT_NETNAME,
246 	    sizeof(WI_DEFAULT_NETNAME) - 1);
247 	(void)wi_set_ssid(&sc->wi_ibss_name, WI_DEFAULT_IBSS,
248 	    sizeof(WI_DEFAULT_IBSS) - 1);
249 
250 	sc->wi_portnum = WI_DEFAULT_PORT;
251 	sc->wi_ptype = WI_PORTTYPE_BSS;
252 	sc->wi_ap_density = WI_DEFAULT_AP_DENSITY;
253 	sc->wi_rts_thresh = WI_DEFAULT_RTS_THRESH;
254 	sc->wi_tx_rate = WI_DEFAULT_TX_RATE;
255 	sc->wi_max_data_len = WI_DEFAULT_DATALEN;
256 	sc->wi_create_ibss = WI_DEFAULT_CREATE_IBSS;
257 	sc->wi_pm_enabled = WI_DEFAULT_PM_ENABLED;
258 	sc->wi_max_sleep = WI_DEFAULT_MAX_SLEEP;
259 	sc->wi_roaming = WI_DEFAULT_ROAMING;
260 	sc->wi_authtype = WI_DEFAULT_AUTHTYPE;
261 	sc->wi_diversity = WI_DEFAULT_DIVERSITY;
262 	sc->wi_crypto_algorithm = WI_CRYPTO_FIRMWARE_WEP;
263 
264 	/*
265 	 * Read the default channel from the NIC. This may vary
266 	 * depending on the country where the NIC was purchased, so
267 	 * we can't hard-code a default and expect it to work for
268 	 * everyone.
269 	 */
270 	gen.wi_type = WI_RID_OWN_CHNL;
271 	gen.wi_len = 2;
272 	if (wi_read_record(sc, &gen) == 0)
273 		sc->wi_channel = letoh16(gen.wi_val);
274 	else
275 		sc->wi_channel = 3;
276 
277 	/*
278 	 * Set flags based on firmware version.
279 	 */
280 	switch (sc->sc_firmware_type) {
281 	case WI_LUCENT:
282 		sc->wi_flags |= WI_FLAGS_HAS_ROAMING;
283 		if (sc->sc_sta_firmware_ver >= 60000)
284 			sc->wi_flags |= WI_FLAGS_HAS_MOR;
285 		if (sc->sc_sta_firmware_ver >= 60006) {
286 			sc->wi_flags |= WI_FLAGS_HAS_IBSS;
287 			sc->wi_flags |= WI_FLAGS_HAS_CREATE_IBSS;
288 		}
289 		sc->wi_ibss_port = htole16(1);
290 		break;
291 	case WI_INTERSIL:
292 		sc->wi_flags |= WI_FLAGS_HAS_ROAMING;
293 		/* older prism firmware is slow so crank the count */
294 		if (sc->sc_sta_firmware_ver < 10000)
295 			sc->wi_cmd_count = 5000;
296 		else
297 			sc->wi_cmd_count = 2000;
298 		if (sc->sc_sta_firmware_ver >= 800) {
299 #ifndef SMALL_KERNEL
300 			/*
301 			 * USB hostap is more pain than it is worth
302 			 * for now, things would have to be overhauled
303 			 */
304 			if ((sc->sc_sta_firmware_ver != 10402) &&
305 			    (!(sc->wi_flags & WI_FLAGS_BUS_USB)))
306 				sc->wi_flags |= WI_FLAGS_HAS_HOSTAP;
307 #endif
308 			sc->wi_flags |= WI_FLAGS_HAS_IBSS;
309 			sc->wi_flags |= WI_FLAGS_HAS_CREATE_IBSS;
310 		}
311 		if (sc->sc_sta_firmware_ver >= 10603)
312 			sc->wi_flags |= WI_FLAGS_HAS_ENH_SECURITY;
313 		sc->wi_ibss_port = htole16(0);
314 		break;
315 	case WI_SYMBOL:
316 		sc->wi_flags |= WI_FLAGS_HAS_DIVERSITY;
317 		if (sc->sc_sta_firmware_ver >= 20000)
318 			sc->wi_flags |= WI_FLAGS_HAS_IBSS;
319 		if (sc->sc_sta_firmware_ver >= 25000)
320 			sc->wi_flags |= WI_FLAGS_HAS_CREATE_IBSS;
321 		sc->wi_ibss_port = htole16(4);
322 		break;
323 	}
324 
325 	/*
326 	 * Find out if we support WEP on this card.
327 	 */
328 	gen.wi_type = WI_RID_WEP_AVAIL;
329 	gen.wi_len = 2;
330 	if (wi_read_record(sc, &gen) == 0 && gen.wi_val != htole16(0))
331 		sc->wi_flags |= WI_FLAGS_HAS_WEP;
332 	timeout_set(&sc->sc_timo, funcs->f_inquire, sc);
333 
334 	bzero(&sc->wi_stats, sizeof(sc->wi_stats));
335 
336 	/* Find supported rates. */
337 	rates.wi_type = WI_RID_DATA_RATES;
338 	rates.wi_len = sizeof(rates.wi_rates);
339 	if (wi_read_record(sc, (struct wi_ltv_gen *)&rates) == 0) {
340 		int i, nrates;
341 
342 		nrates = letoh16(*(u_int16_t *)rates.wi_rates);
343 		if (nrates > sizeof(rates.wi_rates) - 2)
344 			nrates = sizeof(rates.wi_rates) - 2;
345 
346 		sc->wi_supprates = 0;
347 		for (i = 0; i < nrates; i++)
348 			sc->wi_supprates |= rates.wi_rates[2 + i];
349 	} else
350 		sc->wi_supprates = WI_SUPPRATES_1M | WI_SUPPRATES_2M |
351 		    WI_SUPPRATES_5M | WI_SUPPRATES_11M;
352 
353 	ifmedia_init(&sc->sc_media, 0, wi_media_change, wi_media_status);
354 #define	ADD(m, c)	ifmedia_add(&sc->sc_media, (m), (c), NULL)
355 	ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 0, 0), 0);
356 	ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, IFM_IEEE80211_ADHOC, 0), 0);
357 	if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
358 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, IFM_IEEE80211_IBSS,
359 		    0), 0);
360 	if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
361 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO,
362 		    IFM_IEEE80211_IBSSMASTER, 0), 0);
363 	if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)
364 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO,
365 		    IFM_IEEE80211_HOSTAP, 0), 0);
366 	if (sc->wi_supprates & WI_SUPPRATES_1M) {
367 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1, 0, 0), 0);
368 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
369 		    IFM_IEEE80211_ADHOC, 0), 0);
370 		if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
371 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
372 			    IFM_IEEE80211_IBSS, 0), 0);
373 		if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
374 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
375 			    IFM_IEEE80211_IBSSMASTER, 0), 0);
376 		if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)
377 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
378 			    IFM_IEEE80211_HOSTAP, 0), 0);
379 	}
380 	if (sc->wi_supprates & WI_SUPPRATES_2M) {
381 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2, 0, 0), 0);
382 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
383 		    IFM_IEEE80211_ADHOC, 0), 0);
384 		if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
385 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
386 			    IFM_IEEE80211_IBSS, 0), 0);
387 		if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
388 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
389 			    IFM_IEEE80211_IBSSMASTER, 0), 0);
390 		if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)
391 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
392 			    IFM_IEEE80211_HOSTAP, 0), 0);
393 	}
394 	if (sc->wi_supprates & WI_SUPPRATES_5M) {
395 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5, 0, 0), 0);
396 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
397 		    IFM_IEEE80211_ADHOC, 0), 0);
398 		if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
399 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
400 			    IFM_IEEE80211_IBSS, 0), 0);
401 		if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
402 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
403 			    IFM_IEEE80211_IBSSMASTER, 0), 0);
404 		if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)
405 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
406 			    IFM_IEEE80211_HOSTAP, 0), 0);
407 	}
408 	if (sc->wi_supprates & WI_SUPPRATES_11M) {
409 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11, 0, 0), 0);
410 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
411 		    IFM_IEEE80211_ADHOC, 0), 0);
412 		if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
413 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
414 			    IFM_IEEE80211_IBSS, 0), 0);
415 		if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
416 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
417 			    IFM_IEEE80211_IBSSMASTER, 0), 0);
418 		if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)
419 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
420 			    IFM_IEEE80211_HOSTAP, 0), 0);
421 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_MANUAL, 0, 0), 0);
422 	}
423 #undef ADD
424 	ifmedia_set(&sc->sc_media,
425 	    IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 0, 0));
426 
427 	/*
428 	 * Call MI attach routines.
429 	 */
430 	if_attach(ifp);
431 	memcpy(((struct arpcom *)ifp)->ac_enaddr, ic->ic_myaddr,
432 	    ETHER_ADDR_LEN);
433 	ether_ifattach(ifp);
434 	printf("\n");
435 
436 	sc->wi_flags |= WI_FLAGS_ATTACHED;
437 
438 #if NBPFILTER > 0
439 	BPFATTACH(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
440 #endif
441 
442 	if_addgroup(ifp, "wlan");
443 	ifp->if_priority = IF_WIRELESS_DEFAULT_PRIORITY;
444 
445 	wi_init(sc);
446 	wi_stop(sc);
447 
448 	return (0);
449 }
450 
451 STATIC void
452 wi_intr_enable(struct wi_softc *sc, int mode)
453 {
454 	if (!(sc->wi_flags & WI_FLAGS_BUS_USB))
455 		CSR_WRITE_2(sc, WI_INT_EN, mode);
456 }
457 
458 STATIC void
459 wi_intr_ack(struct wi_softc *sc, int mode)
460 {
461 	if (!(sc->wi_flags & WI_FLAGS_BUS_USB))
462 		CSR_WRITE_2(sc, WI_EVENT_ACK, mode);
463 }
464 
465 int
466 wi_intr(void *vsc)
467 {
468 	struct wi_softc		*sc = vsc;
469 	struct ifnet		*ifp;
470 	u_int16_t		status;
471 
472 	DPRINTF(WID_INTR, ("wi_intr: sc %p\n", sc));
473 
474 	ifp = &sc->sc_ic.ic_if;
475 
476 	if (!(sc->wi_flags & WI_FLAGS_ATTACHED) || !(ifp->if_flags & IFF_UP)) {
477 		CSR_WRITE_2(sc, WI_INT_EN, 0);
478 		CSR_WRITE_2(sc, WI_EVENT_ACK, 0xffff);
479 		return (0);
480 	}
481 
482 	/* Disable interrupts. */
483 	CSR_WRITE_2(sc, WI_INT_EN, 0);
484 
485 	status = CSR_READ_2(sc, WI_EVENT_STAT);
486 	CSR_WRITE_2(sc, WI_EVENT_ACK, ~WI_INTRS);
487 
488 	if (status & WI_EV_RX) {
489 		wi_rxeof(sc);
490 		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
491 	}
492 
493 	if (status & WI_EV_TX) {
494 		wi_txeof(sc, status);
495 		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX);
496 	}
497 
498 	if (status & WI_EV_ALLOC) {
499 		int			id;
500 		id = CSR_READ_2(sc, WI_ALLOC_FID);
501 		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
502 		if (id == sc->wi_tx_data_id)
503 			wi_txeof(sc, status);
504 	}
505 
506 	if (status & WI_EV_INFO) {
507 		wi_update_stats(sc);
508 		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO);
509 	}
510 
511 	if (status & WI_EV_TX_EXC) {
512 		wi_txeof(sc, status);
513 		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX_EXC);
514 	}
515 
516 	if (status & WI_EV_INFO_DROP) {
517 		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO_DROP);
518 	}
519 
520 	/* Re-enable interrupts. */
521 	CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
522 
523 	if (!IFQ_IS_EMPTY(&ifp->if_snd))
524 		wi_start(ifp);
525 
526 	return (1);
527 }
528 
529 STATIC int
530 wi_get_fid_io(struct wi_softc *sc, int fid)
531 {
532 	return CSR_READ_2(sc, fid);
533 }
534 
535 
536 void
537 wi_rxeof(struct wi_softc *sc)
538 {
539 	struct ifnet		*ifp;
540 	struct ether_header	*eh;
541 	struct mbuf		*m;
542 	caddr_t			olddata;
543 	u_int16_t		ftype;
544 	int			maxlen;
545 	int			id;
546 
547 	ifp = &sc->sc_ic.ic_if;
548 
549 	id = wi_get_fid(sc, WI_RX_FID);
550 
551 	if (sc->wi_procframe || sc->wi_debug.wi_monitor) {
552 		struct wi_frame	*rx_frame;
553 		int		datlen, hdrlen;
554 
555 		MGETHDR(m, M_DONTWAIT, MT_DATA);
556 		if (m == NULL) {
557 			ifp->if_ierrors++;
558 			return;
559 		}
560 		MCLGET(m, M_DONTWAIT);
561 		if (!(m->m_flags & M_EXT)) {
562 			m_freem(m);
563 			ifp->if_ierrors++;
564 			return;
565 		}
566 
567 		m->m_pkthdr.rcvif = ifp;
568 
569 		if (wi_read_data(sc, id, 0, mtod(m, caddr_t),
570 		    sizeof(struct wi_frame))) {
571 			m_freem(m);
572 			ifp->if_ierrors++;
573 			return;
574 		}
575 
576 		rx_frame = mtod(m, struct wi_frame *);
577 
578 		if (rx_frame->wi_status & htole16(WI_STAT_BADCRC)) {
579 			m_freem(m);
580 			ifp->if_ierrors++;
581 			return;
582 		}
583 
584 		switch ((letoh16(rx_frame->wi_status) & WI_STAT_MAC_PORT)
585 		    >> 8) {
586 		case 7:
587 			switch (letoh16(rx_frame->wi_frame_ctl) &
588 			    WI_FCTL_FTYPE) {
589 			case WI_FTYPE_DATA:
590 				hdrlen = WI_DATA_HDRLEN;
591 				datlen = letoh16(rx_frame->wi_dat_len);
592 				break;
593 			case WI_FTYPE_MGMT:
594 				hdrlen = WI_MGMT_HDRLEN;
595 				datlen = letoh16(rx_frame->wi_dat_len);
596 				break;
597 			case WI_FTYPE_CTL:
598 				hdrlen = WI_CTL_HDRLEN;
599 				datlen = 0;
600 				break;
601 			default:
602 				printf(WI_PRT_FMT ": received packet of "
603 				    "unknown type on port 7\n", WI_PRT_ARG(sc));
604 				m_freem(m);
605 				ifp->if_ierrors++;
606 				return;
607 			}
608 			break;
609 		case 0:
610 			hdrlen = WI_DATA_HDRLEN;
611 			datlen = letoh16(rx_frame->wi_dat_len);
612 			break;
613 		default:
614 			printf(WI_PRT_FMT ": received packet on invalid port "
615 			    "(wi_status=0x%x)\n", WI_PRT_ARG(sc),
616 			    letoh16(rx_frame->wi_status));
617 			m_freem(m);
618 			ifp->if_ierrors++;
619 			return;
620 		}
621 
622 		if ((hdrlen + datlen + 2) > MCLBYTES) {
623 			m_freem(m);
624 			ifp->if_ierrors++;
625 			return;
626 		}
627 
628 		if (wi_read_data(sc, id, hdrlen, mtod(m, caddr_t) + hdrlen,
629 		    datlen + 2)) {
630 			m_freem(m);
631 			ifp->if_ierrors++;
632 			return;
633 		}
634 
635 		m->m_pkthdr.len = m->m_len = hdrlen + datlen;
636 	} else {
637 		struct wi_frame rx_frame;
638 
639 		/* First read in the frame header */
640 		if (wi_read_data(sc, id, 0, (caddr_t)&rx_frame,
641 		    sizeof(rx_frame))) {
642 			ifp->if_ierrors++;
643 			return;
644 		}
645 
646 		/* Drop undecryptable or packets with receive errors here */
647 		if (rx_frame.wi_status & htole16(WI_STAT_ERRSTAT)) {
648 			ifp->if_ierrors++;
649 			return;
650 		}
651 
652 		/* Stash frame type in host byte order for later use */
653 		ftype = letoh16(rx_frame.wi_frame_ctl) & WI_FCTL_FTYPE;
654 
655 		MGETHDR(m, M_DONTWAIT, MT_DATA);
656 		if (m == NULL) {
657 			ifp->if_ierrors++;
658 			return;
659 		}
660 		MCLGET(m, M_DONTWAIT);
661 		if (!(m->m_flags & M_EXT)) {
662 			m_freem(m);
663 			ifp->if_ierrors++;
664 			return;
665 		}
666 
667 		olddata = m->m_data;
668 		/* Align the data after the ethernet header */
669 		m->m_data = (caddr_t)ALIGN(m->m_data +
670 		    sizeof(struct ether_header)) - sizeof(struct ether_header);
671 
672 		eh = mtod(m, struct ether_header *);
673 		maxlen = MCLBYTES - (m->m_data - olddata);
674 		m->m_pkthdr.rcvif = ifp;
675 
676 		if (ftype == WI_FTYPE_MGMT &&
677 		    sc->wi_ptype == WI_PORTTYPE_HOSTAP) {
678 
679 			u_int16_t rxlen = letoh16(rx_frame.wi_dat_len);
680 
681 			if ((WI_802_11_OFFSET_RAW + rxlen + 2) > maxlen) {
682 				printf("%s: oversized mgmt packet received in "
683 				    "hostap mode (wi_dat_len=%d, "
684 				    "wi_status=0x%x)\n", sc->sc_dev.dv_xname,
685 				    rxlen, letoh16(rx_frame.wi_status));
686 				m_freem(m);
687 				ifp->if_ierrors++;
688 				return;
689 			}
690 
691 			/* Put the whole header in there. */
692 			bcopy(&rx_frame, mtod(m, void *),
693 			    sizeof(struct wi_frame));
694 			if (wi_read_data(sc, id, WI_802_11_OFFSET_RAW,
695 			    mtod(m, caddr_t) + WI_802_11_OFFSET_RAW,
696 			    rxlen + 2)) {
697 				m_freem(m);
698 				if (sc->sc_ic.ic_if.if_flags & IFF_DEBUG)
699 					printf("wihap: failed to copy header\n");
700 				ifp->if_ierrors++;
701 				return;
702 			}
703 
704 			m->m_pkthdr.len = m->m_len =
705 			    WI_802_11_OFFSET_RAW + rxlen;
706 
707 			/* XXX: consider giving packet to bhp? */
708 
709 			wihap_mgmt_input(sc, &rx_frame, m);
710 
711 			return;
712 		}
713 
714 		switch (letoh16(rx_frame.wi_status) & WI_RXSTAT_MSG_TYPE) {
715 		case WI_STAT_1042:
716 		case WI_STAT_TUNNEL:
717 		case WI_STAT_WMP_MSG:
718 			if ((letoh16(rx_frame.wi_dat_len) + WI_SNAPHDR_LEN) >
719 			    maxlen) {
720 				printf(WI_PRT_FMT ": oversized packet received "
721 				    "(wi_dat_len=%d, wi_status=0x%x)\n",
722 				    WI_PRT_ARG(sc),
723 				    letoh16(rx_frame.wi_dat_len),
724 				    letoh16(rx_frame.wi_status));
725 				m_freem(m);
726 				ifp->if_ierrors++;
727 				return;
728 			}
729 			m->m_pkthdr.len = m->m_len =
730 			    letoh16(rx_frame.wi_dat_len) + WI_SNAPHDR_LEN;
731 
732 			bcopy(&rx_frame.wi_dst_addr,
733 			    &eh->ether_dhost, ETHER_ADDR_LEN);
734 			bcopy(&rx_frame.wi_src_addr,
735 			    &eh->ether_shost, ETHER_ADDR_LEN);
736 			bcopy(&rx_frame.wi_type,
737 			    &eh->ether_type, ETHER_TYPE_LEN);
738 
739 			if (wi_read_data(sc, id, WI_802_11_OFFSET,
740 			    mtod(m, caddr_t) + sizeof(struct ether_header),
741 			    m->m_len + 2)) {
742 				ifp->if_ierrors++;
743 				m_freem(m);
744 				return;
745 			}
746 			break;
747 		default:
748 			if ((letoh16(rx_frame.wi_dat_len) +
749 			    sizeof(struct ether_header)) > maxlen) {
750 				printf(WI_PRT_FMT ": oversized packet received "
751 				    "(wi_dat_len=%d, wi_status=0x%x)\n",
752 				    WI_PRT_ARG(sc),
753 				    letoh16(rx_frame.wi_dat_len),
754 				    letoh16(rx_frame.wi_status));
755 				m_freem(m);
756 				ifp->if_ierrors++;
757 				return;
758 			}
759 			m->m_pkthdr.len = m->m_len =
760 			    letoh16(rx_frame.wi_dat_len) +
761 			    sizeof(struct ether_header);
762 
763 			if (wi_read_data(sc, id, WI_802_3_OFFSET,
764 			    mtod(m, caddr_t), m->m_len + 2)) {
765 				m_freem(m);
766 				ifp->if_ierrors++;
767 				return;
768 			}
769 			break;
770 		}
771 
772 		ifp->if_ipackets++;
773 
774 		if (sc->wi_use_wep &&
775 		    rx_frame.wi_frame_ctl & htole16(WI_FCTL_WEP)) {
776 			int len;
777 
778 			switch (sc->wi_crypto_algorithm) {
779 			case WI_CRYPTO_FIRMWARE_WEP:
780 				break;
781 			case WI_CRYPTO_SOFTWARE_WEP:
782 				m_copydata(m, 0, m->m_pkthdr.len,
783 				    (caddr_t)sc->wi_rxbuf);
784 				len = m->m_pkthdr.len -
785 				    sizeof(struct ether_header);
786 				if (wi_do_hostdecrypt(sc, sc->wi_rxbuf +
787 				    sizeof(struct ether_header), len)) {
788 					if (sc->sc_ic.ic_if.if_flags & IFF_DEBUG)
789 						printf(WI_PRT_FMT ": Error decrypting incoming packet.\n", WI_PRT_ARG(sc));
790 					m_freem(m);
791 					ifp->if_ierrors++;
792 					return;
793 				}
794 				len -= IEEE80211_WEP_IVLEN +
795 				    IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN;
796 				/*
797 				 * copy data back to mbufs:
798 				 * we need to ditch the IV & most LLC/SNAP stuff
799 				 * (except SNAP type, we're going use that to
800 				 * overwrite the ethertype in the ether_header)
801 				 */
802 				m_copyback(m, sizeof(struct ether_header) -
803 				    WI_ETHERTYPE_LEN, WI_ETHERTYPE_LEN +
804 				    (len - WI_SNAPHDR_LEN),
805 				    sc->wi_rxbuf + sizeof(struct ether_header) +
806 				    IEEE80211_WEP_IVLEN +
807 				    IEEE80211_WEP_KIDLEN + WI_SNAPHDR_LEN,
808 				    M_NOWAIT);
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(&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(&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, &mcast.wi_mcast[i], ETHER_ADDR_LEN);
1427 		i++;
1428 		ETHER_NEXT_MULTI(step, enm);
1429 	}
1430 
1431 	mcast.wi_len = (i * 3) + 1;
1432 	wi_write_record(sc, (struct wi_ltv_gen *)&mcast);
1433 
1434 	return;
1435 }
1436 
1437 STATIC int
1438 wi_setdef(struct wi_softc *sc, struct wi_req *wreq)
1439 {
1440 	struct ifnet		*ifp;
1441 	int error = 0;
1442 
1443 	ifp = &sc->sc_ic.ic_if;
1444 
1445 	switch(wreq->wi_type) {
1446 	case WI_RID_MAC_NODE:
1447 		bcopy(&wreq->wi_val, LLADDR(ifp->if_sadl), ETHER_ADDR_LEN);
1448 		bcopy(&wreq->wi_val, &sc->sc_ic.ic_myaddr, ETHER_ADDR_LEN);
1449 		break;
1450 	case WI_RID_PORTTYPE:
1451 		error = wi_sync_media(sc, letoh16(wreq->wi_val[0]),
1452 		    sc->wi_tx_rate);
1453 		break;
1454 	case WI_RID_TX_RATE:
1455 		error = wi_sync_media(sc, sc->wi_ptype,
1456 		    letoh16(wreq->wi_val[0]));
1457 		break;
1458 	case WI_RID_MAX_DATALEN:
1459 		sc->wi_max_data_len = letoh16(wreq->wi_val[0]);
1460 		break;
1461 	case WI_RID_RTS_THRESH:
1462 		sc->wi_rts_thresh = letoh16(wreq->wi_val[0]);
1463 		break;
1464 	case WI_RID_SYSTEM_SCALE:
1465 		sc->wi_ap_density = letoh16(wreq->wi_val[0]);
1466 		break;
1467 	case WI_RID_CREATE_IBSS:
1468 		sc->wi_create_ibss = letoh16(wreq->wi_val[0]);
1469 		error = wi_sync_media(sc, sc->wi_ptype, sc->wi_tx_rate);
1470 		break;
1471 	case WI_RID_OWN_CHNL:
1472 		sc->wi_channel = letoh16(wreq->wi_val[0]);
1473 		break;
1474 	case WI_RID_NODENAME:
1475 		error = wi_set_ssid(&sc->wi_node_name,
1476 		    (u_int8_t *)&wreq->wi_val[1], letoh16(wreq->wi_val[0]));
1477 		break;
1478 	case WI_RID_DESIRED_SSID:
1479 		error = wi_set_ssid(&sc->wi_net_name,
1480 		    (u_int8_t *)&wreq->wi_val[1], letoh16(wreq->wi_val[0]));
1481 		break;
1482 	case WI_RID_OWN_SSID:
1483 		error = wi_set_ssid(&sc->wi_ibss_name,
1484 		    (u_int8_t *)&wreq->wi_val[1], letoh16(wreq->wi_val[0]));
1485 		break;
1486 	case WI_RID_PM_ENABLED:
1487 		sc->wi_pm_enabled = letoh16(wreq->wi_val[0]);
1488 		break;
1489 	case WI_RID_MICROWAVE_OVEN:
1490 		sc->wi_mor_enabled = letoh16(wreq->wi_val[0]);
1491 		break;
1492 	case WI_RID_MAX_SLEEP:
1493 		sc->wi_max_sleep = letoh16(wreq->wi_val[0]);
1494 		break;
1495 	case WI_RID_CNFAUTHMODE:
1496 		sc->wi_authtype = letoh16(wreq->wi_val[0]);
1497 		break;
1498 	case WI_RID_ROAMING_MODE:
1499 		sc->wi_roaming = letoh16(wreq->wi_val[0]);
1500 		break;
1501 	case WI_RID_SYMBOL_DIVERSITY:
1502 		sc->wi_diversity = letoh16(wreq->wi_val[0]);
1503 		break;
1504 	case WI_RID_ENH_SECURITY:
1505 		sc->wi_enh_security = letoh16(wreq->wi_val[0]);
1506 		break;
1507 	case WI_RID_ENCRYPTION:
1508 		sc->wi_use_wep = letoh16(wreq->wi_val[0]);
1509 		break;
1510 	case WI_RID_TX_CRYPT_KEY:
1511 		sc->wi_tx_key = letoh16(wreq->wi_val[0]);
1512 		break;
1513 	case WI_RID_DEFLT_CRYPT_KEYS:
1514 		bcopy(wreq, &sc->wi_keys, sizeof(struct wi_ltv_keys));
1515 		break;
1516 	case WI_FRID_CRYPTO_ALG:
1517 		switch (letoh16(wreq->wi_val[0])) {
1518 		case WI_CRYPTO_FIRMWARE_WEP:
1519 			sc->wi_crypto_algorithm = WI_CRYPTO_FIRMWARE_WEP;
1520 			break;
1521 		case WI_CRYPTO_SOFTWARE_WEP:
1522 			sc->wi_crypto_algorithm = WI_CRYPTO_SOFTWARE_WEP;
1523 			break;
1524 		default:
1525 			printf(WI_PRT_FMT ": unsupported crypto algorithm %d\n",
1526 			    WI_PRT_ARG(sc), letoh16(wreq->wi_val[0]));
1527 			error = EINVAL;
1528 		}
1529 		break;
1530 	default:
1531 		error = EINVAL;
1532 		break;
1533 	}
1534 
1535 	return (error);
1536 }
1537 
1538 STATIC int
1539 wi_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
1540 {
1541 	int			s, error = 0, i, j, len;
1542 	struct wi_softc		*sc = ifp->if_softc;
1543 	struct ifreq		*ifr = (struct ifreq *)data;
1544 	struct proc		*p = curproc;
1545 	struct ifaddr		*ifa = (struct ifaddr *)data;
1546 	struct wi_scan_res	*res;
1547 	struct wi_scan_p2_hdr	*p2;
1548 	struct wi_req		*wreq = NULL;
1549 	u_int32_t		flags;
1550 	struct ieee80211_nwid		*nwidp = NULL;
1551 	struct ieee80211_nodereq_all	*na;
1552 	struct ieee80211_bssid		*bssid;
1553 
1554 	s = splnet();
1555 	if (!(sc->wi_flags & WI_FLAGS_ATTACHED)) {
1556 		error = ENODEV;
1557 		goto fail;
1558 	}
1559 
1560 	/*
1561 	 * Prevent processes from entering this function while another
1562 	 * process is tsleep'ing in it.
1563 	 */
1564 	while ((sc->wi_flags & WI_FLAGS_BUSY) && error == 0)
1565 		error = tsleep(&sc->wi_flags, PCATCH, "wiioc", 0);
1566 	if (error != 0) {
1567 		splx(s);
1568 		return error;
1569 	}
1570 	sc->wi_flags |= WI_FLAGS_BUSY;
1571 
1572 
1573 	DPRINTF (WID_IOCTL, ("wi_ioctl: command %lu data %p\n",
1574 	    command, data));
1575 
1576 	switch(command) {
1577 	case SIOCSIFADDR:
1578 		ifp->if_flags |= IFF_UP;
1579 		switch (ifa->ifa_addr->sa_family) {
1580 #ifdef INET
1581 		case AF_INET:
1582 			wi_init(sc);
1583 			arp_ifinit(&sc->sc_ic.ic_ac, ifa);
1584 			break;
1585 #endif	/* INET */
1586 		default:
1587 			wi_init(sc);
1588 			break;
1589 		}
1590 		break;
1591 	case SIOCSIFFLAGS:
1592 		if (ifp->if_flags & IFF_UP) {
1593 			if (ifp->if_flags & IFF_RUNNING &&
1594 			    ifp->if_flags & IFF_PROMISC &&
1595 			    !(sc->wi_if_flags & IFF_PROMISC)) {
1596 				if (sc->wi_ptype != WI_PORTTYPE_HOSTAP)
1597 					WI_SETVAL(WI_RID_PROMISC, 1);
1598 			} else if (ifp->if_flags & IFF_RUNNING &&
1599 			    !(ifp->if_flags & IFF_PROMISC) &&
1600 			    sc->wi_if_flags & IFF_PROMISC) {
1601 				if (sc->wi_ptype != WI_PORTTYPE_HOSTAP)
1602 					WI_SETVAL(WI_RID_PROMISC, 0);
1603 			} else
1604 				wi_init(sc);
1605 		} else if (ifp->if_flags & IFF_RUNNING)
1606 			wi_stop(sc);
1607 		sc->wi_if_flags = ifp->if_flags;
1608 		error = 0;
1609 		break;
1610 	case SIOCSIFMEDIA:
1611 	case SIOCGIFMEDIA:
1612 		error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, command);
1613 		break;
1614 	case SIOCGWAVELAN:
1615 		wreq = malloc(sizeof *wreq, M_DEVBUF, M_WAITOK | M_ZERO);
1616 		error = copyin(ifr->ifr_data, wreq, sizeof(*wreq));
1617 		if (error)
1618 			break;
1619 		if (wreq->wi_len > WI_MAX_DATALEN) {
1620 			error = EINVAL;
1621 			break;
1622 		}
1623 		switch (wreq->wi_type) {
1624 		case WI_RID_IFACE_STATS:
1625 			/* XXX native byte order */
1626 			bcopy(&sc->wi_stats, &wreq->wi_val,
1627 			    sizeof(sc->wi_stats));
1628 			wreq->wi_len = (sizeof(sc->wi_stats) / 2) + 1;
1629 			break;
1630 		case WI_RID_DEFLT_CRYPT_KEYS:
1631 			/* For non-root user, return all-zeroes keys */
1632 			if (suser(p, 0))
1633 				bzero(wreq, sizeof(struct wi_ltv_keys));
1634 			else
1635 				bcopy(&sc->wi_keys, wreq,
1636 					sizeof(struct wi_ltv_keys));
1637 			break;
1638 		case WI_RID_PROCFRAME:
1639 			wreq->wi_len = 2;
1640 			wreq->wi_val[0] = htole16(sc->wi_procframe);
1641 			break;
1642 		case WI_RID_PRISM2:
1643 			wreq->wi_len = 2;
1644 			wreq->wi_val[0] = htole16(sc->sc_firmware_type ==
1645 			    WI_LUCENT ? 0 : 1);
1646 			break;
1647 		case WI_FRID_CRYPTO_ALG:
1648 			wreq->wi_val[0] =
1649 			    htole16((u_int16_t)sc->wi_crypto_algorithm);
1650 			wreq->wi_len = 1;
1651 			break;
1652 		case WI_RID_SCAN_RES:
1653 			if (sc->sc_firmware_type == WI_LUCENT) {
1654 				memcpy((char *)wreq->wi_val,
1655 				    (char *)sc->wi_scanbuf,
1656 				    sc->wi_scanbuf_len * 2);
1657 				wreq->wi_len = sc->wi_scanbuf_len;
1658 				break;
1659 			}
1660 			/* FALLTHROUGH */
1661 		default:
1662 			if (wi_read_record(sc, (struct wi_ltv_gen *)wreq)) {
1663 				error = EINVAL;
1664 			}
1665 			break;
1666 		}
1667 		error = copyout(wreq, ifr->ifr_data, sizeof(*wreq));
1668 		break;
1669 	case SIOCSWAVELAN:
1670 		if ((error = suser(curproc, 0)) != 0)
1671 			break;
1672 		wreq = malloc(sizeof *wreq, M_DEVBUF, M_WAITOK | M_ZERO);
1673 		error = copyin(ifr->ifr_data, wreq, sizeof(*wreq));
1674 		if (error)
1675 			break;
1676 		error = EINVAL;
1677 		if (wreq->wi_len > WI_MAX_DATALEN)
1678 			break;
1679 		switch (wreq->wi_type) {
1680 		case WI_RID_IFACE_STATS:
1681 			break;
1682 		case WI_RID_MGMT_XMIT:
1683 			error = wi_mgmt_xmit(sc, (caddr_t)&wreq->wi_val,
1684 			    wreq->wi_len);
1685 			break;
1686 		case WI_RID_PROCFRAME:
1687 			sc->wi_procframe = letoh16(wreq->wi_val[0]);
1688 			error = 0;
1689 			break;
1690 		case WI_RID_SCAN_REQ:
1691 			error = 0;
1692 			if (sc->sc_firmware_type == WI_LUCENT)
1693 				wi_cmd(sc, WI_CMD_INQUIRE,
1694 				    WI_INFO_SCAN_RESULTS, 0, 0);
1695 			else
1696 				error = wi_write_record(sc,
1697 				    (struct wi_ltv_gen *)wreq);
1698 			break;
1699 		case WI_FRID_CRYPTO_ALG:
1700 			if (sc->sc_firmware_type != WI_LUCENT) {
1701 				error = wi_setdef(sc, wreq);
1702 				if (!error && (ifp->if_flags & IFF_UP))
1703 					wi_init(sc);
1704 			}
1705 			break;
1706 		case WI_RID_SYMBOL_DIVERSITY:
1707 		case WI_RID_ROAMING_MODE:
1708 		case WI_RID_CREATE_IBSS:
1709 		case WI_RID_MICROWAVE_OVEN:
1710 		case WI_RID_OWN_SSID:
1711 		case WI_RID_ENH_SECURITY:
1712 			/*
1713 			 * Check for features that may not be supported
1714 			 * (must be just before default case).
1715 			 */
1716 			if ((wreq->wi_type == WI_RID_SYMBOL_DIVERSITY &&
1717 			    !(sc->wi_flags & WI_FLAGS_HAS_DIVERSITY)) ||
1718 			    (wreq->wi_type == WI_RID_ROAMING_MODE &&
1719 			    !(sc->wi_flags & WI_FLAGS_HAS_ROAMING)) ||
1720 			    (wreq->wi_type == WI_RID_CREATE_IBSS &&
1721 			    !(sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)) ||
1722 			    (wreq->wi_type == WI_RID_MICROWAVE_OVEN &&
1723 			    !(sc->wi_flags & WI_FLAGS_HAS_MOR)) ||
1724 			    (wreq->wi_type == WI_RID_ENH_SECURITY &&
1725 			    !(sc->wi_flags & WI_FLAGS_HAS_ENH_SECURITY)) ||
1726 			    (wreq->wi_type == WI_RID_OWN_SSID &&
1727 			    wreq->wi_len != 0))
1728 				break;
1729 			/* FALLTHROUGH */
1730 		default:
1731 			error = wi_write_record(sc, (struct wi_ltv_gen *)wreq);
1732 			if (!error)
1733 				error = wi_setdef(sc, wreq);
1734 			if (!error && (ifp->if_flags & IFF_UP))
1735 				wi_init(sc);
1736 		}
1737 		break;
1738 	case SIOCGPRISM2DEBUG:
1739 		wreq = malloc(sizeof *wreq, M_DEVBUF, M_WAITOK | M_ZERO);
1740 		error = copyin(ifr->ifr_data, wreq, sizeof(*wreq));
1741 		if (error)
1742 			break;
1743 		if (!(ifp->if_flags & IFF_RUNNING) ||
1744 		    sc->sc_firmware_type == WI_LUCENT) {
1745 			error = EIO;
1746 			break;
1747 		}
1748 		error = wi_get_debug(sc, wreq);
1749 		if (error == 0)
1750 			error = copyout(wreq, ifr->ifr_data, sizeof(*wreq));
1751 		break;
1752 	case SIOCSPRISM2DEBUG:
1753 		if ((error = suser(curproc, 0)) != 0)
1754 			break;
1755 		wreq = malloc(sizeof *wreq, M_DEVBUF, M_WAITOK | M_ZERO);
1756 		error = copyin(ifr->ifr_data, wreq, sizeof(*wreq));
1757 		if (error)
1758 			break;
1759 		error = wi_set_debug(sc, wreq);
1760 		break;
1761 	case SIOCG80211NWID:
1762 		if ((ifp->if_flags & IFF_UP) && sc->wi_net_name.i_len > 0) {
1763 			/* Return the desired ID */
1764 			error = copyout(&sc->wi_net_name, ifr->ifr_data,
1765 			    sizeof(sc->wi_net_name));
1766 		} else {
1767 			wreq = malloc(sizeof *wreq, M_DEVBUF, M_WAITOK|M_ZERO);
1768 			wreq->wi_type = WI_RID_CURRENT_SSID;
1769 			wreq->wi_len = WI_MAX_DATALEN;
1770 			if (wi_read_record(sc, (struct wi_ltv_gen *)wreq) ||
1771 			    letoh16(wreq->wi_val[0]) > IEEE80211_NWID_LEN)
1772 				error = EINVAL;
1773 			else {
1774 				nwidp = malloc(sizeof *nwidp, M_DEVBUF,
1775 				    M_WAITOK | M_ZERO);
1776 				wi_set_ssid(nwidp, (u_int8_t *)&wreq->wi_val[1],
1777 				    letoh16(wreq->wi_val[0]));
1778 				error = copyout(nwidp, ifr->ifr_data,
1779 				    sizeof(*nwidp));
1780 			}
1781 		}
1782 		break;
1783 	case SIOCS80211NWID:
1784 		if ((error = suser(curproc, 0)) != 0)
1785 			break;
1786 		nwidp = malloc(sizeof *nwidp, M_DEVBUF, M_WAITOK);
1787 		error = copyin(ifr->ifr_data, nwidp, sizeof(*nwidp));
1788 		if (error)
1789 			break;
1790 		if (nwidp->i_len > IEEE80211_NWID_LEN) {
1791 			error = EINVAL;
1792 			break;
1793 		}
1794 		if (sc->wi_net_name.i_len == nwidp->i_len &&
1795 		    memcmp(sc->wi_net_name.i_nwid, nwidp->i_nwid, nwidp->i_len) == 0)
1796 			break;
1797 		wi_set_ssid(&sc->wi_net_name, nwidp->i_nwid, nwidp->i_len);
1798 		WI_SETSTR(WI_RID_DESIRED_SSID, sc->wi_net_name);
1799 		if (ifp->if_flags & IFF_UP)
1800 			/* Reinitialize WaveLAN. */
1801 			wi_init(sc);
1802 		break;
1803 	case SIOCS80211NWKEY:
1804 		if ((error = suser(curproc, 0)) != 0)
1805 			break;
1806 		error = wi_set_nwkey(sc, (struct ieee80211_nwkey *)data);
1807 		break;
1808 	case SIOCG80211NWKEY:
1809 		error = wi_get_nwkey(sc, (struct ieee80211_nwkey *)data);
1810 		break;
1811 	case SIOCS80211POWER:
1812 		if ((error = suser(curproc, 0)) != 0)
1813 			break;
1814 		error = wi_set_pm(sc, (struct ieee80211_power *)data);
1815 		break;
1816 	case SIOCG80211POWER:
1817 		error = wi_get_pm(sc, (struct ieee80211_power *)data);
1818 		break;
1819 	case SIOCS80211TXPOWER:
1820 		if ((error = suser(curproc, 0)) != 0)
1821 			break;
1822 		error = wi_set_txpower(sc, (struct ieee80211_txpower *)data);
1823 		break;
1824 	case SIOCG80211TXPOWER:
1825 		error = wi_get_txpower(sc, (struct ieee80211_txpower *)data);
1826 		break;
1827 	case SIOCS80211CHANNEL:
1828 		if ((error = suser(curproc, 0)) != 0)
1829 			break;
1830 		if (((struct ieee80211chanreq *)data)->i_channel > 14) {
1831 			error = EINVAL;
1832 			break;
1833 		}
1834 		wreq = malloc(sizeof *wreq, M_DEVBUF, M_WAITOK | M_ZERO);
1835 		wreq->wi_type = WI_RID_OWN_CHNL;
1836 		wreq->wi_val[0] =
1837 		    htole16(((struct ieee80211chanreq *)data)->i_channel);
1838 		error = wi_setdef(sc, wreq);
1839 		if (!error && (ifp->if_flags & IFF_UP))
1840 			wi_init(sc);
1841 		break;
1842 	case SIOCG80211CHANNEL:
1843 		wreq = malloc(sizeof *wreq, M_DEVBUF, M_WAITOK | M_ZERO);
1844 		wreq->wi_type = WI_RID_CURRENT_CHAN;
1845 		wreq->wi_len = WI_MAX_DATALEN;
1846 		if (wi_read_record(sc, (struct wi_ltv_gen *)wreq)) {
1847 			error = EINVAL;
1848 			break;
1849 		}
1850 		((struct ieee80211chanreq *)data)->i_channel =
1851 		    letoh16(wreq->wi_val[0]);
1852 		break;
1853 	case SIOCG80211BSSID:
1854 		bssid = (struct ieee80211_bssid *)data;
1855 		wreq = malloc(sizeof *wreq, M_DEVBUF, M_WAITOK | M_ZERO);
1856 		wreq->wi_type = WI_RID_CURRENT_BSSID;
1857 		wreq->wi_len = WI_MAX_DATALEN;
1858 		if (wi_read_record(sc, (struct wi_ltv_gen *)wreq)) {
1859 			error = EINVAL;
1860 			break;
1861 		}
1862 		IEEE80211_ADDR_COPY(bssid->i_bssid, wreq->wi_val);
1863 		break;
1864 	case SIOCS80211SCAN:
1865 		if ((error = suser(curproc, 0)) != 0)
1866 			break;
1867 		if (sc->wi_ptype == WI_PORTTYPE_HOSTAP)
1868 			break;
1869 		if ((ifp->if_flags & IFF_UP) == 0) {
1870 			error = ENETDOWN;
1871 			break;
1872 		}
1873 		if (sc->sc_firmware_type == WI_LUCENT) {
1874 			wi_cmd(sc, WI_CMD_INQUIRE,
1875 			    WI_INFO_SCAN_RESULTS, 0, 0);
1876 		} else {
1877 			wreq = malloc(sizeof *wreq, M_DEVBUF, M_WAITOK|M_ZERO);
1878 			wreq->wi_len = 3;
1879 			wreq->wi_type = WI_RID_SCAN_REQ;
1880 			wreq->wi_val[0] = 0x3FFF;
1881 			wreq->wi_val[1] = 0x000F;
1882 
1883 			error = wi_write_record(sc,
1884 			    (struct wi_ltv_gen *)wreq);
1885 			if (error)
1886 				break;
1887 		}
1888 		sc->wi_scan_lock = 0;
1889 		timeout_set(&sc->wi_scan_timeout, wi_scan_timeout, sc);
1890 		len = WI_WAVELAN_RES_TIMEOUT;
1891 		if (sc->wi_flags & WI_FLAGS_BUS_USB) {
1892 			/* Use a longer timeout for wi@usb */
1893 			len = WI_WAVELAN_RES_TIMEOUT * 4;
1894 		}
1895 		timeout_add(&sc->wi_scan_timeout, len);
1896 
1897 		/* Let the userspace process wait for completion */
1898 		error = tsleep(&sc->wi_scan_lock, PCATCH, "wiscan",
1899 		    hz * IEEE80211_SCAN_TIMEOUT);
1900 		break;
1901 	case SIOCG80211ALLNODES:
1902 	    {
1903 		struct ieee80211_nodereq	*nr = NULL;
1904 
1905 		if ((error = suser(curproc, 0)) != 0)
1906 			break;
1907 		na = (struct ieee80211_nodereq_all *)data;
1908 		if (sc->wi_ptype == WI_PORTTYPE_HOSTAP) {
1909 			/* List all associated stations */
1910 			error = wihap_ioctl(sc, command, data);
1911 			break;
1912 		}
1913 		wreq = malloc(sizeof *wreq, M_DEVBUF, M_WAITOK | M_ZERO);
1914 		wreq->wi_len = WI_MAX_DATALEN;
1915 		wreq->wi_type = WI_RID_SCAN_RES;
1916 		if (sc->sc_firmware_type == WI_LUCENT) {
1917 			bcopy(sc->wi_scanbuf, wreq->wi_val,
1918 			    sc->wi_scanbuf_len * 2);
1919 			wreq->wi_len = sc->wi_scanbuf_len;
1920 			i = 0;
1921 			len = WI_WAVELAN_RES_SIZE;
1922 		} else {
1923 			if (wi_read_record(sc, (struct wi_ltv_gen *)wreq)) {
1924 				error = EINVAL;
1925 				break;
1926 			}
1927 			p2 = (struct wi_scan_p2_hdr *)wreq->wi_val;
1928 			if (p2->wi_reason == 0)
1929 				break;
1930 			i = sizeof(*p2);
1931 			len = WI_PRISM2_RES_SIZE;
1932 		}
1933 
1934 		for (na->na_nodes = j = 0; (i < (wreq->wi_len * 2) - len) &&
1935 		    (na->na_size >= j + sizeof(struct ieee80211_nodereq));
1936 		    i += len) {
1937 
1938 			if (nr == NULL)
1939 				nr = malloc(sizeof *nr, M_DEVBUF, M_WAITOK);
1940 			res = (struct wi_scan_res *)((char *)wreq->wi_val + i);
1941 			if (res == NULL)
1942 				break;
1943 
1944 			bzero(nr, sizeof(*nr));
1945 			IEEE80211_ADDR_COPY(nr->nr_macaddr, res->wi_bssid);
1946 			IEEE80211_ADDR_COPY(nr->nr_bssid, res->wi_bssid);
1947 			nr->nr_channel = letoh16(res->wi_chan);
1948 			nr->nr_chan_flags = IEEE80211_CHAN_B;
1949 			nr->nr_rssi = letoh16(res->wi_signal);
1950 			nr->nr_max_rssi = 0; /* XXX */
1951 			nr->nr_nwid_len = letoh16(res->wi_ssid_len);
1952 			bcopy(res->wi_ssid, nr->nr_nwid, nr->nr_nwid_len);
1953 			nr->nr_intval = letoh16(res->wi_interval);
1954 			nr->nr_capinfo = letoh16(res->wi_capinfo);
1955 			nr->nr_txrate = res->wi_rate == WI_WAVELAN_RES_1M ? 2 :
1956 			    (res->wi_rate == WI_WAVELAN_RES_2M ? 4 :
1957 			    (res->wi_rate == WI_WAVELAN_RES_5M ? 11 :
1958 			    (res->wi_rate == WI_WAVELAN_RES_11M ? 22 : 0)));
1959 			nr->nr_nrates = 0;
1960 			while (res->wi_srates[nr->nr_nrates] != 0) {
1961 				nr->nr_rates[nr->nr_nrates] =
1962 				    res->wi_srates[nr->nr_nrates] &
1963 				    WI_VAR_SRATES_MASK;
1964 				nr->nr_nrates++;
1965 			}
1966 			nr->nr_flags = 0;
1967 			if (bcmp(nr->nr_macaddr, nr->nr_bssid,
1968 			    IEEE80211_ADDR_LEN) == 0)
1969 				nr->nr_flags |= IEEE80211_NODEREQ_AP;
1970 
1971 			error = copyout(nr, (caddr_t)na->na_node + j,
1972 			    sizeof(struct ieee80211_nodereq));
1973 			if (error)
1974 				break;
1975 			j += sizeof(struct ieee80211_nodereq);
1976 			na->na_nodes++;
1977 		}
1978 		if (nr)
1979 			free(nr, M_DEVBUF);
1980 		break;
1981 	    }
1982 	case SIOCG80211FLAGS:
1983 		if (sc->wi_ptype != WI_PORTTYPE_HOSTAP)
1984 			break;
1985 		ifr->ifr_flags = 0;
1986 		if (sc->wi_flags & WI_FLAGS_HAS_ENH_SECURITY) {
1987 			wreq = malloc(sizeof *wreq, M_DEVBUF, M_WAITOK|M_ZERO);
1988 			wreq->wi_len = WI_MAX_DATALEN;
1989 			wreq->wi_type = WI_RID_ENH_SECURITY;
1990 			if (wi_read_record(sc, (struct wi_ltv_gen *)wreq)) {
1991 				error = EINVAL;
1992 				break;
1993 			}
1994 			sc->wi_enh_security = letoh16(wreq->wi_val[0]);
1995 			if (sc->wi_enh_security == WI_HIDESSID_IGNPROBES)
1996 				ifr->ifr_flags |= IEEE80211_F_HIDENWID >>
1997 				    IEEE80211_F_USERSHIFT;
1998 		}
1999 		break;
2000 	case SIOCS80211FLAGS:
2001 		if ((error = suser(curproc, 0)) != 0)
2002 			break;
2003 		if (sc->wi_ptype != WI_PORTTYPE_HOSTAP) {
2004 			error = EINVAL;
2005 			break;
2006 		}
2007 		flags = (u_int32_t)ifr->ifr_flags << IEEE80211_F_USERSHIFT;
2008 		if (sc->wi_flags & WI_FLAGS_HAS_ENH_SECURITY) {
2009 			sc->wi_enh_security = (flags & IEEE80211_F_HIDENWID) ?
2010 			    WI_HIDESSID_IGNPROBES : 0;
2011 			WI_SETVAL(WI_RID_ENH_SECURITY, sc->wi_enh_security);
2012 		}
2013 		break;
2014 	case SIOCHOSTAP_ADD:
2015 	case SIOCHOSTAP_DEL:
2016 	case SIOCHOSTAP_GET:
2017 	case SIOCHOSTAP_GETALL:
2018 	case SIOCHOSTAP_GFLAGS:
2019 	case SIOCHOSTAP_SFLAGS:
2020 		/* Send all Host AP specific ioctl's to Host AP code. */
2021 		error = wihap_ioctl(sc, command, data);
2022 		break;
2023 	default:
2024 		error = ether_ioctl(ifp, &sc->sc_ic.ic_ac, command, data);
2025 	}
2026 
2027 	if (error == ENETRESET) {
2028 		if (ifp->if_flags & IFF_RUNNING)
2029 			wi_setmulti(sc);
2030 		error = 0;
2031 	}
2032 
2033 	if (wreq)
2034 		free(wreq, M_DEVBUF);
2035 	if (nwidp)
2036 		free(nwidp, M_DEVBUF);
2037 
2038 fail:
2039 	sc->wi_flags &= ~WI_FLAGS_BUSY;
2040 	wakeup(&sc->wi_flags);
2041 	splx(s);
2042 	return(error);
2043 }
2044 
2045 void
2046 wi_scan_timeout(void *arg)
2047 {
2048 	struct wi_softc		*sc = (struct wi_softc *)arg;
2049 	struct wi_req		wreq;
2050 
2051 	if (sc->wi_scan_lock++ < WI_WAVELAN_RES_TRIES &&
2052 	    sc->sc_firmware_type != WI_LUCENT &&
2053 	    (sc->wi_flags & WI_FLAGS_BUS_USB) == 0) {
2054 		/*
2055 		 * The Prism2/2.5/3 chipsets will set an extra field in the
2056 		 * scan result if the scan request has been completed by the
2057 		 * firmware. This allows to poll for completion and to
2058 		 * wait for some more time if the scan is still in progress.
2059 		 *
2060 		 * XXX This doesn't work with wi@usb because it isn't safe
2061 		 * to call wi_read_record_usb() while beeing in the timeout
2062 		 * handler.
2063 		 */
2064 		wreq.wi_len = WI_MAX_DATALEN;
2065 		wreq.wi_type = WI_RID_SCAN_RES;
2066 
2067 		if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq) == 0 &&
2068 		    ((struct wi_scan_p2_hdr *)wreq.wi_val)->wi_reason == 0) {
2069 			/* Wait some more time for scan completion */
2070 			timeout_add(&sc->wi_scan_timeout, WI_WAVELAN_RES_TIMEOUT);
2071 			return;
2072 		}
2073 	}
2074 
2075 	if (sc->sc_ic.ic_if.if_flags & IFF_DEBUG)
2076 		printf(WI_PRT_FMT ": wi_scan_timeout: %d tries\n",
2077 		    WI_PRT_ARG(sc), sc->wi_scan_lock);
2078 
2079 	/* Wakeup the userland */
2080 	wakeup(&sc->wi_scan_lock);
2081 	sc->wi_scan_lock = 0;
2082 }
2083 
2084 STATIC void
2085 wi_init_io(struct wi_softc *sc)
2086 {
2087 	struct ifnet		*ifp = &sc->sc_ic.ic_ac.ac_if;
2088 	int			s;
2089 	struct wi_ltv_macaddr	mac;
2090 	int			id = 0;
2091 
2092 	if (!(sc->wi_flags & WI_FLAGS_ATTACHED))
2093 		return;
2094 
2095 	DPRINTF(WID_INIT, ("wi_init: sc %p\n", sc));
2096 
2097 	s = splnet();
2098 
2099 	if (ifp->if_flags & IFF_RUNNING)
2100 		wi_stop(sc);
2101 
2102 	wi_reset(sc);
2103 
2104 	/* Program max data length. */
2105 	WI_SETVAL(WI_RID_MAX_DATALEN, sc->wi_max_data_len);
2106 
2107 	/* Set the port type. */
2108 	WI_SETVAL(WI_RID_PORTTYPE, sc->wi_ptype);
2109 
2110 	/* Enable/disable IBSS creation. */
2111 	WI_SETVAL(WI_RID_CREATE_IBSS, sc->wi_create_ibss);
2112 
2113 	/* Program the RTS/CTS threshold. */
2114 	WI_SETVAL(WI_RID_RTS_THRESH, sc->wi_rts_thresh);
2115 
2116 	/* Program the TX rate */
2117 	WI_SETVAL(WI_RID_TX_RATE, sc->wi_tx_rate);
2118 
2119 	/* Access point density */
2120 	WI_SETVAL(WI_RID_SYSTEM_SCALE, sc->wi_ap_density);
2121 
2122 	/* Power Management Enabled */
2123 	WI_SETVAL(WI_RID_PM_ENABLED, sc->wi_pm_enabled);
2124 
2125 	/* Power Management Max Sleep */
2126 	WI_SETVAL(WI_RID_MAX_SLEEP, sc->wi_max_sleep);
2127 
2128 	/* Set Enhanced Security if supported. */
2129 	if (sc->wi_flags & WI_FLAGS_HAS_ENH_SECURITY)
2130 		WI_SETVAL(WI_RID_ENH_SECURITY, sc->wi_enh_security);
2131 
2132 	/* Set Roaming Mode unless this is a Symbol card. */
2133 	if (sc->wi_flags & WI_FLAGS_HAS_ROAMING)
2134 		WI_SETVAL(WI_RID_ROAMING_MODE, sc->wi_roaming);
2135 
2136 	/* Set Antenna Diversity if this is a Symbol card. */
2137 	if (sc->wi_flags & WI_FLAGS_HAS_DIVERSITY)
2138 		WI_SETVAL(WI_RID_SYMBOL_DIVERSITY, sc->wi_diversity);
2139 
2140 	/* Specify the network name */
2141 	WI_SETSTR(WI_RID_DESIRED_SSID, sc->wi_net_name);
2142 
2143 	/* Specify the IBSS name */
2144 	if (sc->wi_net_name.i_len != 0 && (sc->wi_ptype == WI_PORTTYPE_HOSTAP ||
2145 	    (sc->wi_create_ibss && sc->wi_ptype == WI_PORTTYPE_IBSS)))
2146 		WI_SETSTR(WI_RID_OWN_SSID, sc->wi_net_name);
2147 	else
2148 		WI_SETSTR(WI_RID_OWN_SSID, sc->wi_ibss_name);
2149 
2150 	/* Specify the frequency to use */
2151 	WI_SETVAL(WI_RID_OWN_CHNL, sc->wi_channel);
2152 
2153 	/* Program the nodename. */
2154 	WI_SETSTR(WI_RID_NODENAME, sc->wi_node_name);
2155 
2156 	/* Set our MAC address. */
2157 	mac.wi_len = 4;
2158 	mac.wi_type = WI_RID_MAC_NODE;
2159 	bcopy(LLADDR(ifp->if_sadl), &sc->sc_ic.ic_myaddr, ETHER_ADDR_LEN);
2160 	bcopy(&sc->sc_ic.ic_myaddr, &mac.wi_mac_addr, ETHER_ADDR_LEN);
2161 	wi_write_record(sc, (struct wi_ltv_gen *)&mac);
2162 
2163 	/*
2164 	 * Initialize promisc mode.
2165 	 *	Being in the Host-AP mode causes
2166 	 *	great deal of pain if promisc mode is set.
2167 	 *	Therefore we avoid confusing the firmware
2168 	 *	and always reset promisc mode in Host-AP regime,
2169 	 *	it shows us all the packets anyway.
2170 	 */
2171 	if (sc->wi_ptype != WI_PORTTYPE_HOSTAP && ifp->if_flags & IFF_PROMISC)
2172 		WI_SETVAL(WI_RID_PROMISC, 1);
2173 	else
2174 		WI_SETVAL(WI_RID_PROMISC, 0);
2175 
2176 	/* Configure WEP. */
2177 	if (sc->wi_flags & WI_FLAGS_HAS_WEP) {
2178 		WI_SETVAL(WI_RID_ENCRYPTION, sc->wi_use_wep);
2179 		WI_SETVAL(WI_RID_TX_CRYPT_KEY, sc->wi_tx_key);
2180 		sc->wi_keys.wi_len = (sizeof(struct wi_ltv_keys) / 2) + 1;
2181 		sc->wi_keys.wi_type = WI_RID_DEFLT_CRYPT_KEYS;
2182 		wi_write_record(sc, (struct wi_ltv_gen *)&sc->wi_keys);
2183 		if (sc->sc_firmware_type != WI_LUCENT && sc->wi_use_wep) {
2184 			/*
2185 			 * HWB3163 EVAL-CARD Firmware version less than 0.8.2.
2186 			 *
2187 			 * If promiscuous mode is disabled, the Prism2 chip
2188 			 * does not work with WEP .
2189 			 * I'm currently investigating the details of this.
2190 			 * (ichiro@netbsd.org)
2191 			 */
2192 			 if (sc->sc_firmware_type == WI_INTERSIL &&
2193 			    sc->sc_sta_firmware_ver < 802 ) {
2194 				/* firm ver < 0.8.2 */
2195 				WI_SETVAL(WI_RID_PROMISC, 1);
2196 			 }
2197 			 WI_SETVAL(WI_RID_CNFAUTHMODE, sc->wi_authtype);
2198 		}
2199 	}
2200 
2201 	/* Set multicast filter. */
2202 	wi_setmulti(sc);
2203 
2204 	/* Enable desired port */
2205 	wi_cmd(sc, WI_CMD_ENABLE | sc->wi_portnum, 0, 0, 0);
2206 
2207 	if (wi_alloc_nicmem(sc, ETHER_MAX_LEN + sizeof(struct wi_frame) + 8, &id))
2208 		printf(WI_PRT_FMT ": tx buffer allocation failed\n",
2209 		    WI_PRT_ARG(sc));
2210 	sc->wi_tx_data_id = id;
2211 
2212 	if (wi_alloc_nicmem(sc, ETHER_MAX_LEN + sizeof(struct wi_frame) + 8, &id))
2213 		printf(WI_PRT_FMT ": mgmt. buffer allocation failed\n",
2214 		    WI_PRT_ARG(sc));
2215 	sc->wi_tx_mgmt_id = id;
2216 
2217 	/* Set txpower */
2218 	if (sc->wi_flags & WI_FLAGS_TXPOWER)
2219 		wi_set_txpower(sc, NULL);
2220 
2221 	/* enable interrupts */
2222 	wi_intr_enable(sc, WI_INTRS);
2223 
2224         wihap_init(sc);
2225 
2226 	splx(s);
2227 
2228 	ifp->if_flags |= IFF_RUNNING;
2229 	ifp->if_flags &= ~IFF_OACTIVE;
2230 
2231 	timeout_add_sec(&sc->sc_timo, 60);
2232 
2233 	return;
2234 }
2235 
2236 STATIC void
2237 wi_do_hostencrypt(struct wi_softc *sc, caddr_t buf, int len)
2238 {
2239 	u_int32_t crc, klen;
2240 	u_int8_t key[RC4KEYLEN];
2241 	u_int8_t *dat;
2242 	struct rc4_ctx ctx;
2243 
2244 	if (!sc->wi_icv_flag) {
2245 		sc->wi_icv = arc4random();
2246 		sc->wi_icv_flag++;
2247         } else
2248 		sc->wi_icv++;
2249 	/*
2250 	 * Skip 'bad' IVs from Fluhrer/Mantin/Shamir:
2251 	 * (B, 255, N) with 3 <= B < 8
2252 	 */
2253 	if (sc->wi_icv >= 0x03ff00 &&
2254             (sc->wi_icv & 0xf8ff00) == 0x00ff00)
2255                 sc->wi_icv += 0x000100;
2256 
2257 	/* prepend 24bit IV to tx key, byte order does not matter */
2258 	bzero(key, sizeof(key));
2259 	key[0] = sc->wi_icv >> 16;
2260 	key[1] = sc->wi_icv >> 8;
2261 	key[2] = sc->wi_icv;
2262 
2263 	klen = letoh16(sc->wi_keys.wi_keys[sc->wi_tx_key].wi_keylen);
2264 	bcopy(&sc->wi_keys.wi_keys[sc->wi_tx_key].wi_keydat,
2265 	    key + IEEE80211_WEP_IVLEN, klen);
2266 	klen = (klen > IEEE80211_WEP_KEYLEN) ? RC4KEYLEN : RC4KEYLEN / 2;
2267 
2268 	/* rc4 keysetup */
2269 	rc4_keysetup(&ctx, key, klen);
2270 
2271 	/* output: IV, tx keyid, rc4(data), rc4(crc32(data)) */
2272 	dat = buf;
2273 	dat[0] = key[0];
2274 	dat[1] = key[1];
2275 	dat[2] = key[2];
2276 	dat[3] = sc->wi_tx_key << 6;		/* pad and keyid */
2277 	dat += 4;
2278 
2279 	/* compute crc32 over data and encrypt */
2280 	crc = ~ether_crc32_le(dat, len);
2281 	rc4_crypt(&ctx, dat, dat, len);
2282 	dat += len;
2283 
2284 	/* append little-endian crc32 and encrypt */
2285 	dat[0] = crc;
2286 	dat[1] = crc >> 8;
2287 	dat[2] = crc >> 16;
2288 	dat[3] = crc >> 24;
2289 	rc4_crypt(&ctx, dat, dat, IEEE80211_WEP_CRCLEN);
2290 }
2291 
2292 STATIC int
2293 wi_do_hostdecrypt(struct wi_softc *sc, caddr_t buf, int len)
2294 {
2295 	u_int32_t crc, klen, kid;
2296 	u_int8_t key[RC4KEYLEN];
2297 	u_int8_t *dat;
2298 	struct rc4_ctx ctx;
2299 
2300 	if (len < IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN +
2301 	    IEEE80211_WEP_CRCLEN)
2302 		return -1;
2303 	len -= (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN +
2304 	    IEEE80211_WEP_CRCLEN);
2305 
2306 	dat = buf;
2307 
2308 	bzero(key, sizeof(key));
2309 	key[0] = dat[0];
2310 	key[1] = dat[1];
2311 	key[2] = dat[2];
2312 	kid = (dat[3] >> 6) % 4;
2313 	dat += 4;
2314 
2315 	klen = letoh16(sc->wi_keys.wi_keys[kid].wi_keylen);
2316 	bcopy(&sc->wi_keys.wi_keys[kid].wi_keydat,
2317 	    key + IEEE80211_WEP_IVLEN, klen);
2318 	klen = (klen > IEEE80211_WEP_KEYLEN) ? RC4KEYLEN : RC4KEYLEN / 2;
2319 
2320 	/* rc4 keysetup */
2321 	rc4_keysetup(&ctx, key, klen);
2322 
2323 	/* decrypt and compute crc32 over data */
2324 	rc4_crypt(&ctx, dat, dat, len);
2325 	crc = ~ether_crc32_le(dat, len);
2326 	dat += len;
2327 
2328 	/* decrypt little-endian crc32 and verify */
2329 	rc4_crypt(&ctx, dat, dat, IEEE80211_WEP_CRCLEN);
2330 
2331 	if ((dat[0] != crc) && (dat[1] != crc >> 8) &&
2332 	    (dat[2] != crc >> 16) && (dat[3] != crc >> 24)) {
2333 		if (sc->sc_ic.ic_if.if_flags & IFF_DEBUG)
2334 			printf(WI_PRT_FMT ": wi_do_hostdecrypt: iv mismatch: "
2335 			    "0x%02x%02x%02x%02x vs. 0x%x\n", WI_PRT_ARG(sc),
2336 			    dat[3], dat[2], dat[1], dat[0], crc);
2337 		return -1;
2338 	}
2339 
2340 	return 0;
2341 }
2342 
2343 void
2344 wi_start(struct ifnet *ifp)
2345 {
2346 	struct wi_softc		*sc;
2347 	struct mbuf		*m0;
2348 	struct wi_frame		tx_frame;
2349 	struct ether_header	*eh;
2350 	int			id, hostencrypt = 0;
2351 
2352 	sc = ifp->if_softc;
2353 
2354 	DPRINTF(WID_START, ("wi_start: ifp %p sc %p\n", ifp, sc));
2355 
2356 	if (!(sc->wi_flags & WI_FLAGS_ATTACHED))
2357 		return;
2358 
2359 	if (ifp->if_flags & IFF_OACTIVE)
2360 		return;
2361 
2362 nextpkt:
2363 	IFQ_DEQUEUE(&ifp->if_snd, m0);
2364 	if (m0 == NULL)
2365 		return;
2366 
2367 	bzero(&tx_frame, sizeof(tx_frame));
2368 	tx_frame.wi_frame_ctl = htole16(WI_FTYPE_DATA | WI_STYPE_DATA);
2369 	id = sc->wi_tx_data_id;
2370 	eh = mtod(m0, struct ether_header *);
2371 
2372 	if (sc->wi_ptype == WI_PORTTYPE_HOSTAP) {
2373 		if (!wihap_check_tx(&sc->wi_hostap_info, eh->ether_dhost,
2374 		    &tx_frame.wi_tx_rate) && !(ifp->if_flags & IFF_PROMISC)) {
2375 			if (ifp->if_flags & IFF_DEBUG)
2376 				printf(WI_PRT_FMT
2377 				    ": wi_start: dropping unassoc dst %s\n",
2378 				    WI_PRT_ARG(sc),
2379 				    ether_sprintf(eh->ether_dhost));
2380 			m_freem(m0);
2381 			goto nextpkt;
2382 		}
2383 	}
2384 
2385 	/*
2386 	 * Use RFC1042 encoding for IP and ARP datagrams,
2387 	 * 802.3 for anything else.
2388 	 */
2389 	if (eh->ether_type == htons(ETHERTYPE_IP) ||
2390 	    eh->ether_type == htons(ETHERTYPE_ARP) ||
2391 	    eh->ether_type == htons(ETHERTYPE_REVARP) ||
2392 	    eh->ether_type == htons(ETHERTYPE_IPV6)) {
2393 		bcopy(&eh->ether_dhost,
2394 		    &tx_frame.wi_addr1, ETHER_ADDR_LEN);
2395 		if (sc->wi_ptype == WI_PORTTYPE_HOSTAP) {
2396 			tx_frame.wi_tx_ctl = htole16(WI_ENC_TX_MGMT); /* XXX */
2397 			tx_frame.wi_frame_ctl |= htole16(WI_FCTL_FROMDS);
2398 			bcopy(&sc->sc_ic.ic_myaddr,
2399 			    &tx_frame.wi_addr2, ETHER_ADDR_LEN);
2400 			bcopy(&eh->ether_shost,
2401 			    &tx_frame.wi_addr3, ETHER_ADDR_LEN);
2402 			if (sc->wi_use_wep)
2403 				hostencrypt = 1;
2404 		} else if (sc->wi_ptype == WI_PORTTYPE_BSS && sc->wi_use_wep &&
2405 		    sc->wi_crypto_algorithm != WI_CRYPTO_FIRMWARE_WEP) {
2406 			tx_frame.wi_tx_ctl = htole16(WI_ENC_TX_MGMT); /* XXX */
2407 			tx_frame.wi_frame_ctl |= htole16(WI_FCTL_TODS);
2408 			bcopy(&sc->sc_ic.ic_myaddr,
2409 			    &tx_frame.wi_addr2, ETHER_ADDR_LEN);
2410 			bcopy(&eh->ether_dhost,
2411 			    &tx_frame.wi_addr3, ETHER_ADDR_LEN);
2412 			hostencrypt = 1;
2413 		} else
2414 			bcopy(&eh->ether_shost,
2415 			    &tx_frame.wi_addr2, ETHER_ADDR_LEN);
2416 		bcopy(&eh->ether_dhost, &tx_frame.wi_dst_addr, ETHER_ADDR_LEN);
2417 		bcopy(&eh->ether_shost, &tx_frame.wi_src_addr, ETHER_ADDR_LEN);
2418 
2419 		tx_frame.wi_dat_len = m0->m_pkthdr.len - WI_SNAPHDR_LEN;
2420 		tx_frame.wi_dat[0] = htons(WI_SNAP_WORD0);
2421 		tx_frame.wi_dat[1] = htons(WI_SNAP_WORD1);
2422 		tx_frame.wi_len = htons(m0->m_pkthdr.len - WI_SNAPHDR_LEN);
2423 		tx_frame.wi_type = eh->ether_type;
2424 
2425 		if (hostencrypt) {
2426 
2427 			/* Do host encryption. */
2428 			tx_frame.wi_frame_ctl |= htole16(WI_FCTL_WEP);
2429 			bcopy(&tx_frame.wi_dat[0], &sc->wi_txbuf[4], 6);
2430 			bcopy(&tx_frame.wi_type, &sc->wi_txbuf[10], 2);
2431 
2432 			m_copydata(m0, sizeof(struct ether_header),
2433 			    m0->m_pkthdr.len - sizeof(struct ether_header),
2434 			    (caddr_t)&sc->wi_txbuf[12]);
2435 
2436 			wi_do_hostencrypt(sc, (caddr_t)&sc->wi_txbuf,
2437 			    tx_frame.wi_dat_len);
2438 
2439 			tx_frame.wi_dat_len += IEEE80211_WEP_IVLEN +
2440 			    IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN;
2441 
2442 			tx_frame.wi_dat_len = htole16(tx_frame.wi_dat_len);
2443 			wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
2444 			    sizeof(struct wi_frame));
2445 			wi_write_data(sc, id, WI_802_11_OFFSET_RAW,
2446 			    (caddr_t)&sc->wi_txbuf,
2447 			    (m0->m_pkthdr.len -
2448 			     sizeof(struct ether_header)) + 18);
2449 		} else {
2450 			m_copydata(m0, sizeof(struct ether_header),
2451 			    m0->m_pkthdr.len - sizeof(struct ether_header),
2452 			    (caddr_t)&sc->wi_txbuf);
2453 
2454 			tx_frame.wi_dat_len = htole16(tx_frame.wi_dat_len);
2455 			wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
2456 			    sizeof(struct wi_frame));
2457 			wi_write_data(sc, id, WI_802_11_OFFSET,
2458 			    (caddr_t)&sc->wi_txbuf,
2459 			    (m0->m_pkthdr.len -
2460 			     sizeof(struct ether_header)) + 2);
2461 		}
2462 	} else {
2463 		tx_frame.wi_dat_len = htole16(m0->m_pkthdr.len);
2464 
2465 		if (sc->wi_ptype == WI_PORTTYPE_HOSTAP && sc->wi_use_wep) {
2466 
2467 			/* Do host encryption. (XXX - not implemented) */
2468 			printf(WI_PRT_FMT
2469 			    ": host encrypt not implemented for 802.3\n",
2470 			    WI_PRT_ARG(sc));
2471 		} else {
2472 			m_copydata(m0, 0, m0->m_pkthdr.len,
2473 			    (caddr_t)&sc->wi_txbuf);
2474 
2475 			wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
2476 			    sizeof(struct wi_frame));
2477 			wi_write_data(sc, id, WI_802_3_OFFSET,
2478 			    (caddr_t)&sc->wi_txbuf, m0->m_pkthdr.len + 2);
2479 		}
2480 	}
2481 
2482 #if NBPFILTER > 0
2483 	/*
2484 	 * If there's a BPF listener, bounce a copy of
2485 	 * this frame to him.
2486 	 */
2487 	if (ifp->if_bpf)
2488 		bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT);
2489 #endif
2490 
2491 	m_freem(m0);
2492 
2493 	ifp->if_flags |= IFF_OACTIVE;
2494 
2495 	/*
2496 	 * Set a timeout in case the chip goes out to lunch.
2497 	 */
2498 	ifp->if_timer = 5;
2499 
2500 	if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id, 0, 0))
2501 		printf(WI_PRT_FMT ": wi_start: xmit failed\n", WI_PRT_ARG(sc));
2502 
2503 	return;
2504 }
2505 
2506 STATIC int
2507 wi_mgmt_xmit(struct wi_softc *sc, caddr_t data, int len)
2508 {
2509 	struct wi_frame		tx_frame;
2510 	int			id;
2511 	struct wi_80211_hdr	*hdr;
2512 	caddr_t			dptr;
2513 
2514 	if (!(sc->wi_flags & WI_FLAGS_ATTACHED))
2515 		return(ENODEV);
2516 
2517 	hdr = (struct wi_80211_hdr *)data;
2518 	dptr = data + sizeof(struct wi_80211_hdr);
2519 
2520 	bzero(&tx_frame, sizeof(tx_frame));
2521 	id = sc->wi_tx_mgmt_id;
2522 
2523 	bcopy(hdr, &tx_frame.wi_frame_ctl, sizeof(struct wi_80211_hdr));
2524 
2525 	tx_frame.wi_tx_ctl = htole16(WI_ENC_TX_MGMT);
2526 	tx_frame.wi_dat_len = len - sizeof(struct wi_80211_hdr);
2527 	tx_frame.wi_len = htole16(tx_frame.wi_dat_len);
2528 
2529 	tx_frame.wi_dat_len = htole16(tx_frame.wi_dat_len);
2530 	wi_write_data(sc, id, 0, (caddr_t)&tx_frame, sizeof(struct wi_frame));
2531 	wi_write_data(sc, id, WI_802_11_OFFSET_RAW, dptr,
2532 	    (len - sizeof(struct wi_80211_hdr)) + 2);
2533 
2534 	if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id, 0, 0)) {
2535 		printf(WI_PRT_FMT ": wi_mgmt_xmit: xmit failed\n",
2536 		    WI_PRT_ARG(sc));
2537 		/*
2538 		 * Hostile stations or corrupt frames may crash the card
2539 		 * and cause the kernel to get stuck printing complaints.
2540 		 * Reset the card and hope the problem goes away.
2541 		 */
2542 		wi_reset(sc);
2543 		return(EIO);
2544 	}
2545 
2546 	return(0);
2547 }
2548 
2549 void
2550 wi_stop(struct wi_softc *sc)
2551 {
2552 	struct ifnet		*ifp;
2553 
2554 	wihap_shutdown(sc);
2555 
2556 	if (!(sc->wi_flags & WI_FLAGS_ATTACHED))
2557 		return;
2558 
2559 	DPRINTF(WID_STOP, ("wi_stop: sc %p\n", sc));
2560 
2561 	timeout_del(&sc->sc_timo);
2562 
2563 	ifp = &sc->sc_ic.ic_if;
2564 
2565 	wi_intr_enable(sc, 0);
2566 	wi_cmd(sc, WI_CMD_DISABLE|sc->wi_portnum, 0, 0, 0);
2567 
2568 	ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE);
2569 	ifp->if_timer = 0;
2570 
2571 	return;
2572 }
2573 
2574 
2575 void
2576 wi_watchdog(struct ifnet *ifp)
2577 {
2578 	struct wi_softc		*sc;
2579 
2580 	sc = ifp->if_softc;
2581 
2582 	printf(WI_PRT_FMT ": device timeout\n", WI_PRT_ARG(sc));
2583 
2584 	wi_cor_reset(sc);
2585 	wi_init(sc);
2586 
2587 	ifp->if_oerrors++;
2588 
2589 	return;
2590 }
2591 
2592 void
2593 wi_detach(struct wi_softc *sc)
2594 {
2595 	struct ifnet *ifp;
2596 	ifp = &sc->sc_ic.ic_if;
2597 
2598 	if (ifp->if_flags & IFF_RUNNING)
2599 		wi_stop(sc);
2600 
2601 	if (sc->wi_flags & WI_FLAGS_ATTACHED) {
2602 		sc->wi_flags &= ~WI_FLAGS_ATTACHED;
2603 	}
2604 }
2605 
2606 STATIC void
2607 wi_get_id(struct wi_softc *sc)
2608 {
2609 	struct wi_ltv_ver		ver;
2610 	const struct wi_card_ident	*id;
2611 	u_int16_t			pri_fw_ver[3];
2612 	const char			*card_name;
2613 	u_int16_t			card_id;
2614 
2615 	/* get chip identity */
2616 	bzero(&ver, sizeof(ver));
2617 	ver.wi_type = WI_RID_CARD_ID;
2618 	ver.wi_len = 5;
2619 	wi_read_record(sc, (struct wi_ltv_gen *)&ver);
2620 	card_id = letoh16(ver.wi_ver[0]);
2621 	for (id = wi_card_ident; id->firm_type != WI_NOTYPE; id++) {
2622 		if (card_id == id->card_id)
2623 			break;
2624 	}
2625 	if (id->firm_type != WI_NOTYPE) {
2626 		sc->sc_firmware_type = id->firm_type;
2627 		card_name = id->card_name;
2628 	} else if (ver.wi_ver[0] & htole16(0x8000)) {
2629 		sc->sc_firmware_type = WI_INTERSIL;
2630 		card_name = "Unknown PRISM2 chip";
2631 	} else {
2632 		sc->sc_firmware_type = WI_LUCENT;
2633 	}
2634 
2635 	/* get primary firmware version (XXX - how to do Lucent?) */
2636 	if (sc->sc_firmware_type != WI_LUCENT) {
2637 		bzero(&ver, sizeof(ver));
2638 		ver.wi_type = WI_RID_PRI_IDENTITY;
2639 		ver.wi_len = 5;
2640 		wi_read_record(sc, (struct wi_ltv_gen *)&ver);
2641 		pri_fw_ver[0] = letoh16(ver.wi_ver[2]);
2642 		pri_fw_ver[1] = letoh16(ver.wi_ver[3]);
2643 		pri_fw_ver[2] = letoh16(ver.wi_ver[1]);
2644 	}
2645 
2646 	/* get station firmware version */
2647 	bzero(&ver, sizeof(ver));
2648 	ver.wi_type = WI_RID_STA_IDENTITY;
2649 	ver.wi_len = 5;
2650 	wi_read_record(sc, (struct wi_ltv_gen *)&ver);
2651 	ver.wi_ver[1] = letoh16(ver.wi_ver[1]);
2652 	ver.wi_ver[2] = letoh16(ver.wi_ver[2]);
2653 	ver.wi_ver[3] = letoh16(ver.wi_ver[3]);
2654 	sc->sc_sta_firmware_ver = ver.wi_ver[2] * 10000 +
2655 	    ver.wi_ver[3] * 100 + ver.wi_ver[1];
2656 
2657 	if (sc->sc_firmware_type == WI_INTERSIL &&
2658 	    (sc->sc_sta_firmware_ver == 10102 || sc->sc_sta_firmware_ver == 20102)) {
2659 		struct wi_ltv_str sver;
2660 		char *p;
2661 
2662 		bzero(&sver, sizeof(sver));
2663 		sver.wi_type = WI_RID_SYMBOL_IDENTITY;
2664 		sver.wi_len = 7;
2665 		/* value should be something like "V2.00-11" */
2666 		if (wi_read_record(sc, (struct wi_ltv_gen *)&sver) == 0 &&
2667 		    *(p = (char *)sver.wi_str) >= 'A' &&
2668 		    p[2] == '.' && p[5] == '-' && p[8] == '\0') {
2669 			sc->sc_firmware_type = WI_SYMBOL;
2670 			sc->sc_sta_firmware_ver = (p[1] - '0') * 10000 +
2671 			    (p[3] - '0') * 1000 + (p[4] - '0') * 100 +
2672 			    (p[6] - '0') * 10 + (p[7] - '0');
2673 		}
2674 	}
2675 
2676 	if (sc->sc_firmware_type == WI_LUCENT) {
2677 		printf("%s: Firmware %d.%02d variant %d, ", WI_PRT_ARG(sc),
2678 		    ver.wi_ver[2], ver.wi_ver[3], ver.wi_ver[1]);
2679 	} else {
2680 		printf("%s: %s%s (0x%04x), Firmware %d.%d.%d (primary), %d.%d.%d (station), ",
2681 		    WI_PRT_ARG(sc),
2682 		    sc->sc_firmware_type == WI_SYMBOL ? "Symbol " : "",
2683 		    card_name, card_id, pri_fw_ver[0], pri_fw_ver[1],
2684 		    pri_fw_ver[2], sc->sc_sta_firmware_ver / 10000,
2685 		    (sc->sc_sta_firmware_ver % 10000) / 100,
2686 		    sc->sc_sta_firmware_ver % 100);
2687 	}
2688 }
2689 
2690 STATIC int
2691 wi_sync_media(struct wi_softc *sc, int ptype, int txrate)
2692 {
2693 	int media = sc->sc_media.ifm_cur->ifm_media;
2694 	int options = IFM_OPTIONS(media);
2695 	int subtype;
2696 
2697 	switch (txrate) {
2698 	case 1:
2699 		subtype = IFM_IEEE80211_DS1;
2700 		break;
2701 	case 2:
2702 		subtype = IFM_IEEE80211_DS2;
2703 		break;
2704 	case 3:
2705 		subtype = IFM_AUTO;
2706 		break;
2707 	case 5:
2708 		subtype = IFM_IEEE80211_DS5;
2709 		break;
2710 	case 11:
2711 		subtype = IFM_IEEE80211_DS11;
2712 		break;
2713 	default:
2714 		subtype = IFM_MANUAL;		/* Unable to represent */
2715 		break;
2716 	}
2717 
2718 	options &= ~IFM_OMASK;
2719 	switch (ptype) {
2720 	case WI_PORTTYPE_BSS:
2721 		/* default port type */
2722 		break;
2723 	case WI_PORTTYPE_ADHOC:
2724 		options |= IFM_IEEE80211_ADHOC;
2725 		break;
2726 	case WI_PORTTYPE_HOSTAP:
2727 		options |= IFM_IEEE80211_HOSTAP;
2728 		break;
2729 	case WI_PORTTYPE_IBSS:
2730 		if (sc->wi_create_ibss)
2731 			options |= IFM_IEEE80211_IBSSMASTER;
2732 		else
2733 			options |= IFM_IEEE80211_IBSS;
2734 		break;
2735 	default:
2736 		subtype = IFM_MANUAL;		/* Unable to represent */
2737 		break;
2738 	}
2739 	media = IFM_MAKEWORD(IFM_TYPE(media), subtype, options,
2740 	IFM_INST(media));
2741 	if (ifmedia_match(&sc->sc_media, media, sc->sc_media.ifm_mask) == NULL)
2742 		return (EINVAL);
2743 	ifmedia_set(&sc->sc_media, media);
2744 	sc->wi_ptype = ptype;
2745 	sc->wi_tx_rate = txrate;
2746 	return (0);
2747 }
2748 
2749 STATIC int
2750 wi_media_change(struct ifnet *ifp)
2751 {
2752 	struct wi_softc *sc = ifp->if_softc;
2753 	int otype = sc->wi_ptype;
2754 	int orate = sc->wi_tx_rate;
2755 	int ocreate_ibss = sc->wi_create_ibss;
2756 
2757 	if ((sc->sc_media.ifm_cur->ifm_media & IFM_IEEE80211_HOSTAP) &&
2758 	    sc->sc_firmware_type != WI_INTERSIL)
2759 		return (EINVAL);
2760 
2761 	sc->wi_create_ibss = 0;
2762 
2763 	switch (sc->sc_media.ifm_cur->ifm_media & IFM_OMASK) {
2764 	case 0:
2765 		sc->wi_ptype = WI_PORTTYPE_BSS;
2766 		break;
2767 	case IFM_IEEE80211_ADHOC:
2768 		sc->wi_ptype = WI_PORTTYPE_ADHOC;
2769 		break;
2770 	case IFM_IEEE80211_HOSTAP:
2771 		sc->wi_ptype = WI_PORTTYPE_HOSTAP;
2772 		break;
2773 	case IFM_IEEE80211_IBSSMASTER:
2774 	case IFM_IEEE80211_IBSSMASTER|IFM_IEEE80211_IBSS:
2775 		if (!(sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS))
2776 			return (EINVAL);
2777 		sc->wi_create_ibss = 1;
2778 		/* FALLTHROUGH */
2779 	case IFM_IEEE80211_IBSS:
2780 		sc->wi_ptype = WI_PORTTYPE_IBSS;
2781 		break;
2782 	default:
2783 		/* Invalid combination. */
2784 		return (EINVAL);
2785 	}
2786 
2787 	switch (IFM_SUBTYPE(sc->sc_media.ifm_cur->ifm_media)) {
2788 	case IFM_IEEE80211_DS1:
2789 		sc->wi_tx_rate = 1;
2790 		break;
2791 	case IFM_IEEE80211_DS2:
2792 		sc->wi_tx_rate = 2;
2793 		break;
2794 	case IFM_AUTO:
2795 		sc->wi_tx_rate = 3;
2796 		break;
2797 	case IFM_IEEE80211_DS5:
2798 		sc->wi_tx_rate = 5;
2799 		break;
2800 	case IFM_IEEE80211_DS11:
2801 		sc->wi_tx_rate = 11;
2802 		break;
2803 	}
2804 
2805 	if (sc->sc_ic.ic_if.if_flags & IFF_UP) {
2806 		if (otype != sc->wi_ptype || orate != sc->wi_tx_rate ||
2807 		    ocreate_ibss != sc->wi_create_ibss)
2808 			wi_init(sc);
2809 	}
2810 
2811 	ifp->if_baudrate = ifmedia_baudrate(sc->sc_media.ifm_cur->ifm_media);
2812 
2813 	return (0);
2814 }
2815 
2816 STATIC void
2817 wi_media_status(struct ifnet *ifp, struct ifmediareq *imr)
2818 {
2819 	struct wi_softc *sc = ifp->if_softc;
2820 	struct wi_req wreq;
2821 
2822 	if (!(sc->sc_ic.ic_if.if_flags & IFF_UP)) {
2823 		imr->ifm_active = IFM_IEEE80211|IFM_NONE;
2824 		imr->ifm_status = 0;
2825 		return;
2826 	}
2827 
2828 	if (sc->wi_tx_rate == 3) {
2829 		imr->ifm_active = IFM_IEEE80211|IFM_AUTO;
2830 
2831 		wreq.wi_type = WI_RID_CUR_TX_RATE;
2832 		wreq.wi_len = WI_MAX_DATALEN;
2833 		if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq) == 0) {
2834 			switch (letoh16(wreq.wi_val[0])) {
2835 			case 1:
2836 				imr->ifm_active |= IFM_IEEE80211_DS1;
2837 				break;
2838 			case 2:
2839 				imr->ifm_active |= IFM_IEEE80211_DS2;
2840 				break;
2841 			case 6:
2842 				imr->ifm_active |= IFM_IEEE80211_DS5;
2843 				break;
2844 			case 11:
2845 				imr->ifm_active |= IFM_IEEE80211_DS11;
2846 				break;
2847 			}
2848 		}
2849 	} else {
2850 		imr->ifm_active = sc->sc_media.ifm_cur->ifm_media;
2851 	}
2852 
2853 	imr->ifm_status = IFM_AVALID;
2854 	switch (sc->wi_ptype) {
2855 	case WI_PORTTYPE_ADHOC:
2856 	case WI_PORTTYPE_IBSS:
2857 		/*
2858 		 * XXX: It would be nice if we could give some actually
2859 		 * useful status like whether we joined another IBSS or
2860 		 * created one ourselves.
2861 		 */
2862 		/* FALLTHROUGH */
2863 	case WI_PORTTYPE_HOSTAP:
2864 		imr->ifm_status |= IFM_ACTIVE;
2865 		break;
2866 	default:
2867 		wreq.wi_type = WI_RID_COMMQUAL;
2868 		wreq.wi_len = WI_MAX_DATALEN;
2869 		if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq) == 0 &&
2870 		    letoh16(wreq.wi_val[0]) != 0)
2871 			imr->ifm_status |= IFM_ACTIVE;
2872 	}
2873 }
2874 
2875 STATIC int
2876 wi_set_nwkey(struct wi_softc *sc, struct ieee80211_nwkey *nwkey)
2877 {
2878 	int i, len, error;
2879 	struct wi_req wreq;
2880 	struct wi_ltv_keys *wk = (struct wi_ltv_keys *)&wreq;
2881 
2882 	if (!(sc->wi_flags & WI_FLAGS_HAS_WEP))
2883 		return ENODEV;
2884 	if (nwkey->i_defkid <= 0 || nwkey->i_defkid > IEEE80211_WEP_NKID)
2885 		return EINVAL;
2886 	memcpy(wk, &sc->wi_keys, sizeof(*wk));
2887 	for (i = 0; i < IEEE80211_WEP_NKID; i++) {
2888 		if (nwkey->i_key[i].i_keydat == NULL)
2889 			continue;
2890 		len = nwkey->i_key[i].i_keylen;
2891 		if (len > sizeof(wk->wi_keys[i].wi_keydat))
2892 			return EINVAL;
2893 		error = copyin(nwkey->i_key[i].i_keydat,
2894 		    wk->wi_keys[i].wi_keydat, len);
2895 		if (error)
2896 			return error;
2897 		wk->wi_keys[i].wi_keylen = htole16(len);
2898 	}
2899 
2900 	wk->wi_len = (sizeof(*wk) / 2) + 1;
2901 	wk->wi_type = WI_RID_DEFLT_CRYPT_KEYS;
2902 	if (sc->sc_ic.ic_if.if_flags & IFF_UP) {
2903 		error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
2904 		if (error)
2905 			return error;
2906 	}
2907 	if ((error = wi_setdef(sc, &wreq)))
2908 		return (error);
2909 
2910 	wreq.wi_len = 2;
2911 	wreq.wi_type = WI_RID_TX_CRYPT_KEY;
2912 	wreq.wi_val[0] = htole16(nwkey->i_defkid - 1);
2913 	if (sc->sc_ic.ic_if.if_flags & IFF_UP) {
2914 		error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
2915 		if (error)
2916 			return error;
2917 	}
2918 	if ((error = wi_setdef(sc, &wreq)))
2919 		return (error);
2920 
2921 	wreq.wi_type = WI_RID_ENCRYPTION;
2922 	wreq.wi_val[0] = htole16(nwkey->i_wepon);
2923 	if (sc->sc_ic.ic_if.if_flags & IFF_UP) {
2924 		error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
2925 		if (error)
2926 			return error;
2927 	}
2928 	if ((error = wi_setdef(sc, &wreq)))
2929 		return (error);
2930 
2931 	if (sc->sc_ic.ic_if.if_flags & IFF_UP)
2932 		wi_init(sc);
2933 	return 0;
2934 }
2935 
2936 STATIC int
2937 wi_get_nwkey(struct wi_softc *sc, struct ieee80211_nwkey *nwkey)
2938 {
2939 	int i, len, error;
2940 	struct wi_ltv_keys *wk = &sc->wi_keys;
2941 
2942 	if (!(sc->wi_flags & WI_FLAGS_HAS_WEP))
2943 		return ENODEV;
2944 	nwkey->i_wepon = sc->wi_use_wep;
2945 	nwkey->i_defkid = sc->wi_tx_key + 1;
2946 
2947 	/* do not show any keys to non-root user */
2948 	error = suser(curproc, 0);
2949 	for (i = 0; i < IEEE80211_WEP_NKID; i++) {
2950 		if (nwkey->i_key[i].i_keydat == NULL)
2951 			continue;
2952 		/* error holds results of suser() for the first time */
2953 		if (error)
2954 			return error;
2955 		len = letoh16(wk->wi_keys[i].wi_keylen);
2956 		if (nwkey->i_key[i].i_keylen < len)
2957 			return ENOSPC;
2958 		nwkey->i_key[i].i_keylen = len;
2959 		error = copyout(wk->wi_keys[i].wi_keydat,
2960 		    nwkey->i_key[i].i_keydat, len);
2961 		if (error)
2962 			return error;
2963 	}
2964 	return 0;
2965 }
2966 
2967 STATIC int
2968 wi_set_pm(struct wi_softc *sc, struct ieee80211_power *power)
2969 {
2970 
2971 	sc->wi_pm_enabled = power->i_enabled;
2972 	sc->wi_max_sleep = power->i_maxsleep;
2973 
2974 	if (sc->sc_ic.ic_if.if_flags & IFF_UP)
2975 		wi_init(sc);
2976 
2977 	return (0);
2978 }
2979 
2980 STATIC int
2981 wi_get_pm(struct wi_softc *sc, struct ieee80211_power *power)
2982 {
2983 
2984 	power->i_enabled = sc->wi_pm_enabled;
2985 	power->i_maxsleep = sc->wi_max_sleep;
2986 
2987 	return (0);
2988 }
2989 
2990 STATIC int
2991 wi_set_txpower(struct wi_softc *sc, struct ieee80211_txpower *txpower)
2992 {
2993 	u_int16_t	cmd;
2994 	u_int16_t	power;
2995 	int8_t		tmp;
2996 	int		error;
2997 	int		alc;
2998 
2999 	if (txpower == NULL) {
3000 		if (!(sc->wi_flags & WI_FLAGS_TXPOWER))
3001 			return (EINVAL);
3002 		alc = 0;		/* disable ALC */
3003 	} else {
3004 		if (txpower->i_mode == IEEE80211_TXPOWER_MODE_AUTO) {
3005 			alc = 1;	/* enable ALC */
3006 			sc->wi_flags &= ~WI_FLAGS_TXPOWER;
3007 		} else {
3008 			alc = 0;	/* disable ALC */
3009 			sc->wi_flags |= WI_FLAGS_TXPOWER;
3010 			sc->wi_txpower = txpower->i_val;
3011 		}
3012 	}
3013 
3014 	/* Set ALC */
3015 	cmd = WI_CMD_DEBUG | (WI_DEBUG_CONFBITS << 8);
3016 	if ((error = wi_cmd(sc, cmd, alc, 0x8, 0)) != 0)
3017 		return (error);
3018 
3019 	/* No need to set the TX power value if ALC is enabled */
3020 	if (alc)
3021 		return (0);
3022 
3023 	/* Convert dBM to internal TX power value */
3024 	if (sc->wi_txpower > 20)
3025 		power = 128;
3026 	else if (sc->wi_txpower < -43)
3027 		power = 127;
3028 	else {
3029 		tmp = sc->wi_txpower;
3030 		tmp = -12 - tmp;
3031 		tmp <<= 2;
3032 
3033 		power = (u_int16_t)tmp;
3034 	}
3035 
3036 	/* Set manual TX power */
3037 	cmd = WI_CMD_WRITE_MIF;
3038 	if ((error = wi_cmd(sc, cmd,
3039 		 WI_HFA384X_CR_MANUAL_TX_POWER, power, 0)) != 0)
3040 		return (error);
3041 
3042 	if (sc->sc_ic.ic_if.if_flags & IFF_DEBUG)
3043 		printf("%s: %u (%d dBm)\n", sc->sc_dev.dv_xname, power,
3044 		    sc->wi_txpower);
3045 
3046 	return (0);
3047 }
3048 
3049 STATIC int
3050 wi_get_txpower(struct wi_softc *sc, struct ieee80211_txpower *txpower)
3051 {
3052 	u_int16_t	cmd;
3053 	u_int16_t	power;
3054 	int8_t		tmp;
3055 	int		error;
3056 
3057 	if (sc->wi_flags & WI_FLAGS_BUS_USB)
3058 		return (EOPNOTSUPP);
3059 
3060 	/* Get manual TX power */
3061 	cmd = WI_CMD_READ_MIF;
3062 	if ((error = wi_cmd(sc, cmd,
3063 		 WI_HFA384X_CR_MANUAL_TX_POWER, 0, 0)) != 0)
3064 		return (error);
3065 
3066 	power = CSR_READ_2(sc, WI_RESP0);
3067 
3068 	/* Convert internal TX power value to dBM */
3069 	if (power > 255)
3070 		txpower->i_val = 255;
3071 	else {
3072 		tmp = power;
3073 		tmp >>= 2;
3074 		txpower->i_val = (u_int16_t)(-12 - tmp);
3075 	}
3076 
3077 	if (sc->wi_flags & WI_FLAGS_TXPOWER)
3078 		txpower->i_mode = IEEE80211_TXPOWER_MODE_FIXED;
3079 	else
3080 		txpower->i_mode = IEEE80211_TXPOWER_MODE_AUTO;
3081 
3082 	return (0);
3083 }
3084 
3085 STATIC int
3086 wi_set_ssid(struct ieee80211_nwid *ws, u_int8_t *id, int len)
3087 {
3088 
3089 	if (len > IEEE80211_NWID_LEN)
3090 		return (EINVAL);
3091 	ws->i_len = len;
3092 	memcpy(ws->i_nwid, id, len);
3093 	return (0);
3094 }
3095 
3096 STATIC int
3097 wi_get_debug(struct wi_softc *sc, struct wi_req *wreq)
3098 {
3099 	int			error = 0;
3100 
3101 	wreq->wi_len = 1;
3102 
3103 	switch (wreq->wi_type) {
3104 	case WI_DEBUG_SLEEP:
3105 		wreq->wi_len++;
3106 		wreq->wi_val[0] = htole16(sc->wi_debug.wi_sleep);
3107 		break;
3108 	case WI_DEBUG_DELAYSUPP:
3109 		wreq->wi_len++;
3110 		wreq->wi_val[0] = htole16(sc->wi_debug.wi_delaysupp);
3111 		break;
3112 	case WI_DEBUG_TXSUPP:
3113 		wreq->wi_len++;
3114 		wreq->wi_val[0] = htole16(sc->wi_debug.wi_txsupp);
3115 		break;
3116 	case WI_DEBUG_MONITOR:
3117 		wreq->wi_len++;
3118 		wreq->wi_val[0] = htole16(sc->wi_debug.wi_monitor);
3119 		break;
3120 	case WI_DEBUG_LEDTEST:
3121 		wreq->wi_len += 3;
3122 		wreq->wi_val[0] = htole16(sc->wi_debug.wi_ledtest);
3123 		wreq->wi_val[1] = htole16(sc->wi_debug.wi_ledtest_param0);
3124 		wreq->wi_val[2] = htole16(sc->wi_debug.wi_ledtest_param1);
3125 		break;
3126 	case WI_DEBUG_CONTTX:
3127 		wreq->wi_len += 2;
3128 		wreq->wi_val[0] = htole16(sc->wi_debug.wi_conttx);
3129 		wreq->wi_val[1] = htole16(sc->wi_debug.wi_conttx_param0);
3130 		break;
3131 	case WI_DEBUG_CONTRX:
3132 		wreq->wi_len++;
3133 		wreq->wi_val[0] = htole16(sc->wi_debug.wi_contrx);
3134 		break;
3135 	case WI_DEBUG_SIGSTATE:
3136 		wreq->wi_len += 2;
3137 		wreq->wi_val[0] = htole16(sc->wi_debug.wi_sigstate);
3138 		wreq->wi_val[1] = htole16(sc->wi_debug.wi_sigstate_param0);
3139 		break;
3140 	case WI_DEBUG_CONFBITS:
3141 		wreq->wi_len += 2;
3142 		wreq->wi_val[0] = htole16(sc->wi_debug.wi_confbits);
3143 		wreq->wi_val[1] = htole16(sc->wi_debug.wi_confbits_param0);
3144 		break;
3145 	default:
3146 		error = EIO;
3147 		break;
3148 	}
3149 
3150 	return (error);
3151 }
3152 
3153 STATIC int
3154 wi_set_debug(struct wi_softc *sc, struct wi_req *wreq)
3155 {
3156 	int				error = 0;
3157 	u_int16_t			cmd, param0 = 0, param1 = 0;
3158 
3159 	switch (wreq->wi_type) {
3160 	case WI_DEBUG_RESET:
3161 	case WI_DEBUG_INIT:
3162 	case WI_DEBUG_CALENABLE:
3163 		break;
3164 	case WI_DEBUG_SLEEP:
3165 		sc->wi_debug.wi_sleep = 1;
3166 		break;
3167 	case WI_DEBUG_WAKE:
3168 		sc->wi_debug.wi_sleep = 0;
3169 		break;
3170 	case WI_DEBUG_CHAN:
3171 		param0 = letoh16(wreq->wi_val[0]);
3172 		break;
3173 	case WI_DEBUG_DELAYSUPP:
3174 		sc->wi_debug.wi_delaysupp = 1;
3175 		break;
3176 	case WI_DEBUG_TXSUPP:
3177 		sc->wi_debug.wi_txsupp = 1;
3178 		break;
3179 	case WI_DEBUG_MONITOR:
3180 		sc->wi_debug.wi_monitor = 1;
3181 		break;
3182 	case WI_DEBUG_LEDTEST:
3183 		param0 = letoh16(wreq->wi_val[0]);
3184 		param1 = letoh16(wreq->wi_val[1]);
3185 		sc->wi_debug.wi_ledtest = 1;
3186 		sc->wi_debug.wi_ledtest_param0 = param0;
3187 		sc->wi_debug.wi_ledtest_param1 = param1;
3188 		break;
3189 	case WI_DEBUG_CONTTX:
3190 		param0 = letoh16(wreq->wi_val[0]);
3191 		sc->wi_debug.wi_conttx = 1;
3192 		sc->wi_debug.wi_conttx_param0 = param0;
3193 		break;
3194 	case WI_DEBUG_STOPTEST:
3195 		sc->wi_debug.wi_delaysupp = 0;
3196 		sc->wi_debug.wi_txsupp = 0;
3197 		sc->wi_debug.wi_monitor = 0;
3198 		sc->wi_debug.wi_ledtest = 0;
3199 		sc->wi_debug.wi_ledtest_param0 = 0;
3200 		sc->wi_debug.wi_ledtest_param1 = 0;
3201 		sc->wi_debug.wi_conttx = 0;
3202 		sc->wi_debug.wi_conttx_param0 = 0;
3203 		sc->wi_debug.wi_contrx = 0;
3204 		sc->wi_debug.wi_sigstate = 0;
3205 		sc->wi_debug.wi_sigstate_param0 = 0;
3206 		break;
3207 	case WI_DEBUG_CONTRX:
3208 		sc->wi_debug.wi_contrx = 1;
3209 		break;
3210 	case WI_DEBUG_SIGSTATE:
3211 		param0 = letoh16(wreq->wi_val[0]);
3212 		sc->wi_debug.wi_sigstate = 1;
3213 		sc->wi_debug.wi_sigstate_param0 = param0;
3214 		break;
3215 	case WI_DEBUG_CONFBITS:
3216 		param0 = letoh16(wreq->wi_val[0]);
3217 		param1 = letoh16(wreq->wi_val[1]);
3218 		sc->wi_debug.wi_confbits = param0;
3219 		sc->wi_debug.wi_confbits_param0 = param1;
3220 		break;
3221 	default:
3222 		error = EIO;
3223 		break;
3224 	}
3225 
3226 	if (error)
3227 		return (error);
3228 
3229 	cmd = WI_CMD_DEBUG | (wreq->wi_type << 8);
3230 	error = wi_cmd(sc, cmd, param0, param1, 0);
3231 
3232 	return (error);
3233 }
3234