1 /*	$OpenBSD: if_wi.c,v 1.108 2004/03/18 16:16:10 millert 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 <net/if_ieee80211.h>
91 
92 #if NBPFILTER > 0
93 #include <net/bpf.h>
94 #endif
95 
96 #include <machine/bus.h>
97 
98 #include <dev/rndvar.h>
99 
100 #include <dev/ic/if_wireg.h>
101 #include <dev/ic/if_wi_ieee.h>
102 #include <dev/ic/if_wivar.h>
103 
104 #include <crypto/arc4.h>
105 
106 #define BPF_MTAP(if,mbuf) bpf_mtap((if)->if_bpf, (mbuf))
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 #if !defined(lint) && !defined(__OpenBSD__)
128 static const char rcsid[] =
129 	"$OpenBSD: if_wi.c,v 1.108 2004/03/18 16:16:10 millert Exp $";
130 #endif	/* lint */
131 
132 #ifdef foo
133 static u_int8_t	wi_mcast_addr[6] = { 0x01, 0x60, 0x1D, 0x00, 0x01, 0x00 };
134 #endif
135 
136 STATIC void wi_reset(struct wi_softc *);
137 STATIC int wi_ioctl(struct ifnet *, u_long, caddr_t);
138 STATIC void wi_init_io(struct wi_softc *);
139 STATIC void wi_start(struct ifnet *);
140 STATIC void wi_watchdog(struct ifnet *);
141 STATIC void wi_shutdown(void *);
142 STATIC void wi_rxeof(struct wi_softc *);
143 STATIC void wi_txeof(struct wi_softc *, int);
144 STATIC void wi_update_stats(struct wi_softc *);
145 STATIC void wi_setmulti(struct wi_softc *);
146 
147 STATIC int wi_cmd_io(struct wi_softc *, int, int, int, int);
148 STATIC int wi_read_record_io(struct wi_softc *, struct wi_ltv_gen *);
149 STATIC int wi_write_record_io(struct wi_softc *, struct wi_ltv_gen *);
150 STATIC int wi_read_data_io(struct wi_softc *, int,
151 					int, caddr_t, int);
152 STATIC int wi_write_data_io(struct wi_softc *, int,
153 					int, caddr_t, int);
154 STATIC int wi_seek(struct wi_softc *, int, int, int);
155 
156 STATIC void wi_inquire(void *);
157 STATIC int wi_setdef(struct wi_softc *, struct wi_req *);
158 STATIC void wi_get_id(struct wi_softc *);
159 
160 STATIC int wi_media_change(struct ifnet *);
161 STATIC void wi_media_status(struct ifnet *, struct ifmediareq *);
162 
163 STATIC int wi_set_ssid(struct ieee80211_nwid *, u_int8_t *, int);
164 STATIC int wi_set_nwkey(struct wi_softc *, struct ieee80211_nwkey *);
165 STATIC int wi_get_nwkey(struct wi_softc *, struct ieee80211_nwkey *);
166 STATIC int wi_sync_media(struct wi_softc *, int, int);
167 STATIC int wi_set_pm(struct wi_softc *, struct ieee80211_power *);
168 STATIC int wi_get_pm(struct wi_softc *, struct ieee80211_power *);
169 
170 STATIC int wi_get_debug(struct wi_softc *, struct wi_req *);
171 STATIC int wi_set_debug(struct wi_softc *, struct wi_req *);
172 
173 STATIC void wi_do_hostencrypt(struct wi_softc *, caddr_t, int);
174 STATIC int wi_do_hostdecrypt(struct wi_softc *, caddr_t, int);
175 
176 STATIC int wi_alloc_nicmem_io(struct wi_softc *, int, int *);
177 STATIC int wi_get_fid_io(struct wi_softc *sc, int fid);
178 STATIC void wi_intr_enable(struct wi_softc *sc, int mode);
179 STATIC void wi_intr_ack(struct wi_softc *sc, int mode);
180 
181 /* Autoconfig definition of driver back-end */
182 struct cfdriver wi_cd = {
183 	NULL, "wi", DV_IFNET
184 };
185 
186 const struct wi_card_ident wi_card_ident[] = {
187 	WI_CARD_IDS
188 };
189 
190 struct wi_funcs wi_func_io = {
191         wi_cmd_io,
192         wi_read_record_io,
193         wi_write_record_io,
194         wi_alloc_nicmem_io,
195         wi_read_data_io,
196         wi_write_data_io,
197         wi_get_fid_io,
198         wi_init_io,
199 
200         wi_start,
201         wi_ioctl,
202         wi_watchdog,
203         wi_inquire,
204 };
205 
206 int
wi_attach(struct wi_softc * sc,struct wi_funcs * funcs)207 wi_attach(struct wi_softc *sc, struct wi_funcs *funcs)
208 {
209 	struct wi_ltv_macaddr	mac;
210 	struct wi_ltv_gen	gen;
211 	struct ifnet		*ifp;
212 	int			error;
213 
214 	sc->sc_funcs = funcs;
215 	sc->wi_cmd_count = 500;
216 
217 	wi_reset(sc);
218 
219 	/* Read the station address. */
220 	mac.wi_type = WI_RID_MAC_NODE;
221 	mac.wi_len = 4;
222 	error = wi_read_record(sc, (struct wi_ltv_gen *)&mac);
223 	if (error) {
224 		printf(": unable to read station address\n");
225 		return (error);
226 	}
227 	bcopy((char *)&mac.wi_mac_addr, (char *)&sc->sc_arpcom.ac_enaddr,
228 	    ETHER_ADDR_LEN);
229 
230 	wi_get_id(sc);
231 	printf("address %s", ether_sprintf(sc->sc_arpcom.ac_enaddr));
232 
233 	ifp = &sc->sc_arpcom.ac_if;
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 			if (sc->sc_sta_firmware_ver != 10402)
301 				sc->wi_flags |= WI_FLAGS_HAS_HOSTAP;
302 #endif
303 			sc->wi_flags |= WI_FLAGS_HAS_IBSS;
304 			sc->wi_flags |= WI_FLAGS_HAS_CREATE_IBSS;
305 		}
306 		if (sc->sc_sta_firmware_ver >= 10603)
307 			sc->wi_flags |= WI_FLAGS_HAS_ENH_SECURITY;
308 		sc->wi_ibss_port = htole16(0);
309 		break;
310 	case WI_SYMBOL:
311 		sc->wi_flags |= WI_FLAGS_HAS_DIVERSITY;
312 		if (sc->sc_sta_firmware_ver >= 20000)
313 			sc->wi_flags |= WI_FLAGS_HAS_IBSS;
314 		if (sc->sc_sta_firmware_ver >= 25000)
315 			sc->wi_flags |= WI_FLAGS_HAS_CREATE_IBSS;
316 		sc->wi_ibss_port = htole16(4);
317 		break;
318 	}
319 
320 	/*
321 	 * Find out if we support WEP on this card.
322 	 */
323 	gen.wi_type = WI_RID_WEP_AVAIL;
324 	gen.wi_len = 2;
325 	if (wi_read_record(sc, &gen) == 0 && gen.wi_val != htole16(0))
326 		sc->wi_flags |= WI_FLAGS_HAS_WEP;
327 	timeout_set(&sc->sc_timo, funcs->f_inquire, sc);
328 
329 	bzero((char *)&sc->wi_stats, sizeof(sc->wi_stats));
330 
331 	/* Find supported rates. */
332 	gen.wi_type = WI_RID_DATA_RATES;
333 	gen.wi_len = 2;
334 	if (wi_read_record(sc, &gen))
335 		sc->wi_supprates = WI_SUPPRATES_1M | WI_SUPPRATES_2M |
336 		    WI_SUPPRATES_5M | WI_SUPPRATES_11M;
337 	else
338 		sc->wi_supprates = gen.wi_val;
339 
340 	ifmedia_init(&sc->sc_media, 0, wi_media_change, wi_media_status);
341 #define	ADD(m, c)	ifmedia_add(&sc->sc_media, (m), (c), NULL)
342 	ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 0, 0), 0);
343 	ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, IFM_IEEE80211_ADHOC, 0), 0);
344 	if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
345 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, IFM_IEEE80211_IBSS,
346 		    0), 0);
347 	if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
348 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO,
349 		    IFM_IEEE80211_IBSSMASTER, 0), 0);
350 	if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)
351 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO,
352 		    IFM_IEEE80211_HOSTAP, 0), 0);
353 	if (sc->wi_supprates & WI_SUPPRATES_1M) {
354 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1, 0, 0), 0);
355 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
356 		    IFM_IEEE80211_ADHOC, 0), 0);
357 		if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
358 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
359 			    IFM_IEEE80211_IBSS, 0), 0);
360 		if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
361 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
362 			    IFM_IEEE80211_IBSSMASTER, 0), 0);
363 		if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)
364 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
365 			    IFM_IEEE80211_HOSTAP, 0), 0);
366 	}
367 	if (sc->wi_supprates & WI_SUPPRATES_2M) {
368 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2, 0, 0), 0);
369 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
370 		    IFM_IEEE80211_ADHOC, 0), 0);
371 		if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
372 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
373 			    IFM_IEEE80211_IBSS, 0), 0);
374 		if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
375 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
376 			    IFM_IEEE80211_IBSSMASTER, 0), 0);
377 		if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)
378 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
379 			    IFM_IEEE80211_HOSTAP, 0), 0);
380 	}
381 	if (sc->wi_supprates & WI_SUPPRATES_5M) {
382 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5, 0, 0), 0);
383 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
384 		    IFM_IEEE80211_ADHOC, 0), 0);
385 		if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
386 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
387 			    IFM_IEEE80211_IBSS, 0), 0);
388 		if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
389 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
390 			    IFM_IEEE80211_IBSSMASTER, 0), 0);
391 		if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)
392 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
393 			    IFM_IEEE80211_HOSTAP, 0), 0);
394 	}
395 	if (sc->wi_supprates & WI_SUPPRATES_11M) {
396 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11, 0, 0), 0);
397 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
398 		    IFM_IEEE80211_ADHOC, 0), 0);
399 		if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
400 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
401 			    IFM_IEEE80211_IBSS, 0), 0);
402 		if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
403 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
404 			    IFM_IEEE80211_IBSSMASTER, 0), 0);
405 		if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)
406 			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
407 			    IFM_IEEE80211_HOSTAP, 0), 0);
408 		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_MANUAL, 0, 0), 0);
409 	}
410 #undef ADD
411 	ifmedia_set(&sc->sc_media,
412 	    IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 0, 0));
413 
414 	/*
415 	 * Call MI attach routines.
416 	 */
417 	if_attach(ifp);
418 	ether_ifattach(ifp);
419 	printf("\n");
420 
421 	sc->wi_flags |= WI_FLAGS_ATTACHED;
422 
423 #if NBPFILTER > 0
424 	BPFATTACH(&sc->sc_arpcom.ac_if.if_bpf, ifp, DLT_EN10MB,
425 	    sizeof(struct ether_header));
426 #endif
427 
428 	sc->sc_sdhook = shutdownhook_establish(wi_shutdown, sc);
429 
430 	wi_init(sc);
431 	wi_stop(sc);
432 
433 	return (0);
434 }
435 
436 STATIC void
wi_intr_enable(struct wi_softc * sc,int mode)437 wi_intr_enable(struct wi_softc *sc, int mode)
438 {
439 	if (!(sc->wi_flags & WI_FLAGS_BUS_USB))
440 		CSR_WRITE_2(sc, WI_INT_EN, mode);
441 }
442 
443 STATIC void
wi_intr_ack(struct wi_softc * sc,int mode)444 wi_intr_ack(struct wi_softc *sc, int mode)
445 {
446 	if (!(sc->wi_flags & WI_FLAGS_BUS_USB))
447 		CSR_WRITE_2(sc, WI_EVENT_ACK, mode);
448 }
449 
450 int
wi_intr(vsc)451 wi_intr(vsc)
452 	void			*vsc;
453 {
454 	struct wi_softc		*sc = vsc;
455 	struct ifnet		*ifp;
456 	u_int16_t		status;
457 
458 	DPRINTF(WID_INTR, ("wi_intr: sc %p\n", sc));
459 
460 	ifp = &sc->sc_arpcom.ac_if;
461 
462 	if (!(sc->wi_flags & WI_FLAGS_ATTACHED) || !(ifp->if_flags & IFF_UP)) {
463 		CSR_WRITE_2(sc, WI_INT_EN, 0);
464 		CSR_WRITE_2(sc, WI_EVENT_ACK, 0xffff);
465 		return (0);
466 	}
467 
468 	/* Disable interrupts. */
469 	CSR_WRITE_2(sc, WI_INT_EN, 0);
470 
471 	status = CSR_READ_2(sc, WI_EVENT_STAT);
472 	CSR_WRITE_2(sc, WI_EVENT_ACK, ~WI_INTRS);
473 
474 	if (status & WI_EV_RX) {
475 		wi_rxeof(sc);
476 		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
477 	}
478 
479 	if (status & WI_EV_TX) {
480 		wi_txeof(sc, status);
481 		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX);
482 	}
483 
484 	if (status & WI_EV_ALLOC) {
485 		int			id;
486 		id = CSR_READ_2(sc, WI_ALLOC_FID);
487 		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
488 		if (id == sc->wi_tx_data_id)
489 			wi_txeof(sc, status);
490 	}
491 
492 	if (status & WI_EV_INFO) {
493 		wi_update_stats(sc);
494 		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO);
495 	}
496 
497 	if (status & WI_EV_TX_EXC) {
498 		wi_txeof(sc, status);
499 		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX_EXC);
500 	}
501 
502 	if (status & WI_EV_INFO_DROP) {
503 		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO_DROP);
504 	}
505 
506 	/* Re-enable interrupts. */
507 	CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
508 
509 	if (!IFQ_IS_EMPTY(&ifp->if_snd))
510 		wi_start(ifp);
511 
512 	return (1);
513 }
514 
515 STATIC int
wi_get_fid_io(struct wi_softc * sc,int fid)516 wi_get_fid_io(struct wi_softc *sc, int fid)
517 {
518 	return CSR_READ_2(sc, fid);
519 }
520 
521 
522 void
wi_rxeof(sc)523 wi_rxeof(sc)
524 	struct wi_softc		*sc;
525 {
526 	struct ifnet		*ifp;
527 	struct ether_header	*eh;
528 	struct mbuf		*m;
529 	caddr_t			olddata;
530 	u_int16_t		ftype;
531 	int			maxlen;
532 	int			id;
533 
534 	ifp = &sc->sc_arpcom.ac_if;
535 
536 	id = wi_get_fid(sc, WI_RX_FID);
537 
538 	if (sc->wi_procframe || sc->wi_debug.wi_monitor) {
539 		struct wi_frame	*rx_frame;
540 		int		datlen, hdrlen;
541 
542 		MGETHDR(m, M_DONTWAIT, MT_DATA);
543 		if (m == NULL) {
544 			ifp->if_ierrors++;
545 			return;
546 		}
547 		MCLGET(m, M_DONTWAIT);
548 		if (!(m->m_flags & M_EXT)) {
549 			m_freem(m);
550 			ifp->if_ierrors++;
551 			return;
552 		}
553 
554 		m->m_pkthdr.rcvif = ifp;
555 
556 		if (wi_read_data(sc, id, 0, mtod(m, caddr_t),
557 		    sizeof(struct wi_frame))) {
558 			m_freem(m);
559 			ifp->if_ierrors++;
560 			return;
561 		}
562 
563 		rx_frame = mtod(m, struct wi_frame *);
564 
565 		if (rx_frame->wi_status & htole16(WI_STAT_BADCRC)) {
566 			m_freem(m);
567 			ifp->if_ierrors++;
568 			return;
569 		}
570 
571 		switch ((letoh16(rx_frame->wi_status) & WI_STAT_MAC_PORT)
572 		    >> 8) {
573 		case 7:
574 			switch (letoh16(rx_frame->wi_frame_ctl) &
575 			    WI_FCTL_FTYPE) {
576 			case WI_FTYPE_DATA:
577 				hdrlen = WI_DATA_HDRLEN;
578 				datlen = letoh16(rx_frame->wi_dat_len);
579 				break;
580 			case WI_FTYPE_MGMT:
581 				hdrlen = WI_MGMT_HDRLEN;
582 				datlen = letoh16(rx_frame->wi_dat_len);
583 				break;
584 			case WI_FTYPE_CTL:
585 				hdrlen = WI_CTL_HDRLEN;
586 				datlen = 0;
587 				break;
588 			default:
589 				printf(WI_PRT_FMT ": received packet of "
590 				    "unknown type on port 7\n", WI_PRT_ARG(sc));
591 				m_freem(m);
592 				ifp->if_ierrors++;
593 				return;
594 			}
595 			break;
596 		case 0:
597 			hdrlen = WI_DATA_HDRLEN;
598 			datlen = letoh16(rx_frame->wi_dat_len);
599 			break;
600 		default:
601 			printf(WI_PRT_FMT ": received packet on invalid port "
602 			    "(wi_status=0x%x)\n", WI_PRT_ARG(sc),
603 			    letoh16(rx_frame->wi_status));
604 			m_freem(m);
605 			ifp->if_ierrors++;
606 			return;
607 		}
608 
609 		if ((hdrlen + datlen + 2) > MCLBYTES) {
610 			m_freem(m);
611 			ifp->if_ierrors++;
612 			return;
613 		}
614 
615 		if (wi_read_data(sc, id, hdrlen, mtod(m, caddr_t) + hdrlen,
616 		    datlen + 2)) {
617 			m_freem(m);
618 			ifp->if_ierrors++;
619 			return;
620 		}
621 
622 		m->m_pkthdr.len = m->m_len = hdrlen + datlen;
623 	} else {
624 		struct wi_frame rx_frame;
625 
626 		/* First read in the frame header */
627 		if (wi_read_data(sc, id, 0, (caddr_t)&rx_frame,
628 		    sizeof(rx_frame))) {
629 			ifp->if_ierrors++;
630 			return;
631 		}
632 
633 		/* Drop undecryptable or packets with receive errors here */
634 		if (rx_frame.wi_status & htole16(WI_STAT_ERRSTAT)) {
635 			ifp->if_ierrors++;
636 			return;
637 		}
638 
639 		/* Stash frame type in host byte order for later use */
640 		ftype = letoh16(rx_frame.wi_frame_ctl) & WI_FCTL_FTYPE;
641 
642 		MGETHDR(m, M_DONTWAIT, MT_DATA);
643 		if (m == NULL) {
644 			ifp->if_ierrors++;
645 			return;
646 		}
647 		MCLGET(m, M_DONTWAIT);
648 		if (!(m->m_flags & M_EXT)) {
649 			m_freem(m);
650 			ifp->if_ierrors++;
651 			return;
652 		}
653 
654 		olddata = m->m_data;
655 		/* Align the data after the ethernet header */
656 		m->m_data = (caddr_t)ALIGN(m->m_data +
657 		    sizeof(struct ether_header)) - sizeof(struct ether_header);
658 
659 		eh = mtod(m, struct ether_header *);
660 		maxlen = MCLBYTES - (m->m_data - olddata);
661 		m->m_pkthdr.rcvif = ifp;
662 
663 		if (ftype == WI_FTYPE_MGMT &&
664 		    sc->wi_ptype == WI_PORTTYPE_HOSTAP) {
665 
666 			u_int16_t rxlen = letoh16(rx_frame.wi_dat_len);
667 
668 			if ((WI_802_11_OFFSET_RAW + rxlen + 2) > maxlen) {
669 				printf("%s: oversized mgmt packet received in "
670 				    "hostap mode (wi_dat_len=%d, "
671 				    "wi_status=0x%x)\n", sc->sc_dev.dv_xname,
672 				    rxlen, letoh16(rx_frame.wi_status));
673 				m_freem(m);
674 				ifp->if_ierrors++;
675 				return;
676 			}
677 
678 			/* Put the whole header in there. */
679 			bcopy(&rx_frame, mtod(m, void *),
680 			    sizeof(struct wi_frame));
681 			if (wi_read_data(sc, id, WI_802_11_OFFSET_RAW,
682 			    mtod(m, caddr_t) + WI_802_11_OFFSET_RAW,
683 			    rxlen + 2)) {
684 				m_freem(m);
685 				if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG)
686 					printf("wihap: failed to copy header\n");
687 				ifp->if_ierrors++;
688 				return;
689 			}
690 
691 			m->m_pkthdr.len = m->m_len =
692 			    WI_802_11_OFFSET_RAW + rxlen;
693 
694 			/* XXX: consider giving packet to bhp? */
695 
696 			wihap_mgmt_input(sc, &rx_frame, m);
697 
698 			return;
699 		}
700 
701 		switch (letoh16(rx_frame.wi_status) & WI_RXSTAT_MSG_TYPE) {
702 		case WI_STAT_1042:
703 		case WI_STAT_TUNNEL:
704 		case WI_STAT_WMP_MSG:
705 			if ((letoh16(rx_frame.wi_dat_len) + WI_SNAPHDR_LEN) >
706 			    maxlen) {
707 				printf(WI_PRT_FMT ": oversized packet received "
708 				    "(wi_dat_len=%d, wi_status=0x%x)\n",
709 				    WI_PRT_ARG(sc),
710 				    letoh16(rx_frame.wi_dat_len),
711 				    letoh16(rx_frame.wi_status));
712 				m_freem(m);
713 				ifp->if_ierrors++;
714 				return;
715 			}
716 			m->m_pkthdr.len = m->m_len =
717 			    letoh16(rx_frame.wi_dat_len) + WI_SNAPHDR_LEN;
718 
719 			bcopy((char *)&rx_frame.wi_dst_addr,
720 			    (char *)&eh->ether_dhost, ETHER_ADDR_LEN);
721 			bcopy((char *)&rx_frame.wi_src_addr,
722 			    (char *)&eh->ether_shost, ETHER_ADDR_LEN);
723 			bcopy((char *)&rx_frame.wi_type,
724 			    (char *)&eh->ether_type, ETHER_TYPE_LEN);
725 
726 			if (wi_read_data(sc, id, WI_802_11_OFFSET,
727 			    mtod(m, caddr_t) + sizeof(struct ether_header),
728 			    m->m_len + 2)) {
729 				ifp->if_ierrors++;
730 				m_freem(m);
731 				return;
732 			}
733 			break;
734 		default:
735 			if ((letoh16(rx_frame.wi_dat_len) +
736 			    sizeof(struct ether_header)) > maxlen) {
737 				printf(WI_PRT_FMT ": oversized packet received "
738 				    "(wi_dat_len=%d, wi_status=0x%x)\n",
739 				    WI_PRT_ARG(sc),
740 				    letoh16(rx_frame.wi_dat_len),
741 				    letoh16(rx_frame.wi_status));
742 				m_freem(m);
743 				ifp->if_ierrors++;
744 				return;
745 			}
746 			m->m_pkthdr.len = m->m_len =
747 			    letoh16(rx_frame.wi_dat_len) +
748 			    sizeof(struct ether_header);
749 
750 			if (wi_read_data(sc, id, WI_802_3_OFFSET,
751 			    mtod(m, caddr_t), m->m_len + 2)) {
752 				m_freem(m);
753 				ifp->if_ierrors++;
754 				return;
755 			}
756 			break;
757 		}
758 
759 		ifp->if_ipackets++;
760 
761 		if (sc->wi_use_wep &&
762 		    rx_frame.wi_frame_ctl & htole16(WI_FCTL_WEP)) {
763 			int len;
764 			u_int8_t rx_buf[1596];
765 
766 			switch (sc->wi_crypto_algorithm) {
767 			case WI_CRYPTO_FIRMWARE_WEP:
768 				break;
769 			case WI_CRYPTO_SOFTWARE_WEP:
770 				m_copydata(m, 0, m->m_pkthdr.len,
771 				    (caddr_t)rx_buf);
772 				len = m->m_pkthdr.len -
773 				    sizeof(struct ether_header);
774 				if (wi_do_hostdecrypt(sc, rx_buf +
775 				    sizeof(struct ether_header), len)) {
776 					if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG)
777 						printf(WI_PRT_FMT ": Error decrypting incoming packet.\n", WI_PRT_ARG(sc));
778 					m_freem(m);
779 					ifp->if_ierrors++;
780 					return;
781 				}
782 				len -= IEEE80211_WEP_IVLEN +
783 				    IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN;
784 				/*
785 				 * copy data back to mbufs:
786 				 * we need to ditch the IV & most LLC/SNAP stuff
787 				 * (except SNAP type, we're going use that to
788 				 * overwrite the ethertype in the ether_header)
789 				 */
790 				m_copyback(m, sizeof(struct ether_header) -
791 				    WI_ETHERTYPE_LEN, WI_ETHERTYPE_LEN +
792 				    (len - WI_SNAPHDR_LEN),
793 				    rx_buf + sizeof(struct ether_header) +
794 				    IEEE80211_WEP_IVLEN +
795 				    IEEE80211_WEP_KIDLEN + WI_SNAPHDR_LEN);
796 				m_adj(m, -(WI_ETHERTYPE_LEN +
797 				    IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN +
798 				    WI_SNAPHDR_LEN));
799 				break;
800 			}
801 		}
802 
803 		if (sc->wi_ptype == WI_PORTTYPE_HOSTAP) {
804 			/*
805 			 * Give host AP code first crack at data packets.
806 			 * If it decides to handle it (or drop it), it will
807 			 * return a non-zero.  Otherwise, it is destined for
808 			 * this host.
809 			 */
810 			if (wihap_data_input(sc, &rx_frame, m))
811 				return;
812 		}
813 	}
814 
815 #if NBPFILTER > 0
816 	/* Handle BPF listeners. */
817 	if (ifp->if_bpf)
818 		BPF_MTAP(ifp, m);
819 #endif
820 
821 	/* Receive packet unless in procframe or monitor mode. */
822 	if (sc->wi_procframe || sc->wi_debug.wi_monitor)
823 		m_freem(m);
824 	else
825 		ether_input_mbuf(ifp, m);
826 
827 	return;
828 }
829 
830 void
wi_txeof(sc,status)831 wi_txeof(sc, status)
832 	struct wi_softc		*sc;
833 	int			status;
834 {
835 	struct ifnet		*ifp;
836 
837 	ifp = &sc->sc_arpcom.ac_if;
838 
839 	ifp->if_timer = 0;
840 	ifp->if_flags &= ~IFF_OACTIVE;
841 
842 	if (status & WI_EV_TX_EXC)
843 		ifp->if_oerrors++;
844 	else
845 		ifp->if_opackets++;
846 
847 	return;
848 }
849 
850 void
wi_inquire(xsc)851 wi_inquire(xsc)
852 	void			*xsc;
853 {
854 	struct wi_softc		*sc;
855 	struct ifnet		*ifp;
856 	int s, rv;
857 
858 	sc = xsc;
859 	ifp = &sc->sc_arpcom.ac_if;
860 
861 	timeout_add(&sc->sc_timo, hz * 60);
862 
863 	/* Don't do this while we're transmitting */
864 	if (ifp->if_flags & IFF_OACTIVE)
865 		return;
866 
867 	s = splimp();
868 	rv = wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_COUNTERS, 0, 0);
869 	splx(s);
870 	if (rv)
871 		printf(WI_PRT_FMT ": wi_cmd failed with %d\n", WI_PRT_ARG(sc),
872 		    rv);
873 
874 	return;
875 }
876 
877 void
wi_update_stats(sc)878 wi_update_stats(sc)
879 	struct wi_softc		*sc;
880 {
881 	struct wi_ltv_gen	gen;
882 	u_int16_t		id;
883 	struct ifnet		*ifp;
884 	u_int32_t		*ptr;
885 	int			len, i;
886 	u_int16_t		t;
887 
888 	ifp = &sc->sc_arpcom.ac_if;
889 
890 	id = wi_get_fid(sc, WI_INFO_FID);
891 
892 	wi_read_data(sc, id, 0, (char *)&gen, 4);
893 
894 	if (gen.wi_type == htole16(WI_INFO_SCAN_RESULTS)) {
895 		sc->wi_scanbuf_len = letoh16(gen.wi_len);
896 		wi_read_data(sc, id, 4, (caddr_t)sc->wi_scanbuf,
897 		    sc->wi_scanbuf_len * 2);
898 		return;
899 	} else if (gen.wi_type != htole16(WI_INFO_COUNTERS))
900 		return;
901 
902 	/* Some card versions have a larger stats structure */
903 	len = (letoh16(gen.wi_len) - 1 < sizeof(sc->wi_stats) / 4) ?
904 	    letoh16(gen.wi_len) - 1 : sizeof(sc->wi_stats) / 4;
905 
906 	ptr = (u_int32_t *)&sc->wi_stats;
907 
908 	for (i = 0; i < len; i++) {
909 		if (sc->wi_flags & WI_FLAGS_BUS_USB) {
910 			wi_read_data(sc, id, 4 + i*2, (char *)&t, 2);
911 			t = letoh16(t);
912 		} else
913 			t = CSR_READ_2(sc, WI_DATA1);
914 #ifdef WI_HERMES_STATS_WAR
915 		if (t > 0xF000)
916 			t = ~t & 0xFFFF;
917 #endif
918 		ptr[i] += t;
919 	}
920 
921 	ifp->if_collisions = sc->wi_stats.wi_tx_single_retries +
922 	    sc->wi_stats.wi_tx_multi_retries +
923 	    sc->wi_stats.wi_tx_retry_limit;
924 
925 	return;
926 }
927 
928 STATIC int
wi_cmd_io(sc,cmd,val0,val1,val2)929 wi_cmd_io(sc, cmd, val0, val1, val2)
930 	struct wi_softc		*sc;
931 	int			cmd;
932 	int			val0;
933 	int			val1;
934 	int			val2;
935 {
936 	int			i, s = 0;
937 
938 	/* Wait for the busy bit to clear. */
939 	for (i = sc->wi_cmd_count; i--; DELAY(1000)) {
940 		if (!(CSR_READ_2(sc, WI_COMMAND) & WI_CMD_BUSY))
941 			break;
942 	}
943 	if (i < 0) {
944 		if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG)
945 			printf(WI_PRT_FMT ": wi_cmd_io: busy bit won't clear\n",
946 			    WI_PRT_ARG(sc));
947 		return(ETIMEDOUT);
948 	}
949 
950 	CSR_WRITE_2(sc, WI_PARAM0, val0);
951 	CSR_WRITE_2(sc, WI_PARAM1, val1);
952 	CSR_WRITE_2(sc, WI_PARAM2, val2);
953 	CSR_WRITE_2(sc, WI_COMMAND, cmd);
954 
955 	for (i = WI_TIMEOUT; i--; DELAY(WI_DELAY)) {
956 		/*
957 		 * Wait for 'command complete' bit to be
958 		 * set in the event status register.
959 		 */
960 		s = CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_CMD;
961 		if (s) {
962 			/* Ack the event and read result code. */
963 			s = CSR_READ_2(sc, WI_STATUS);
964 			CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_CMD);
965 			if (s & WI_STAT_CMD_RESULT)
966 				return(EIO);
967 			break;
968 		}
969 	}
970 
971 	if (i < 0) {
972 		if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG)
973 			printf(WI_PRT_FMT
974 			    ": timeout in wi_cmd 0x%04x; event status 0x%04x\n",
975 			    WI_PRT_ARG(sc), cmd, s);
976 		return(ETIMEDOUT);
977 	}
978 
979 	return(0);
980 }
981 
982 STATIC void
wi_reset(sc)983 wi_reset(sc)
984 	struct wi_softc		*sc;
985 {
986 	int error, tries = 3;
987 
988 	DPRINTF(WID_RESET, ("wi_reset: sc %p\n", sc));
989 
990 	/* Symbol firmware cannot be initialized more than once. */
991 	if (sc->sc_firmware_type == WI_SYMBOL) {
992 		if (sc->wi_flags & WI_FLAGS_INITIALIZED)
993 			return;
994 		tries = 1;
995 	}
996 
997 	for (; tries--; DELAY(WI_DELAY * 1000)) {
998 		if ((error = wi_cmd(sc, WI_CMD_INI, 0, 0, 0)) == 0)
999 			break;
1000 	}
1001 	if (tries < 0) {
1002 		printf(WI_PRT_FMT ": init failed\n", WI_PRT_ARG(sc));
1003 		return;
1004 	}
1005 	sc->wi_flags |= WI_FLAGS_INITIALIZED;
1006 
1007 	wi_intr_enable(sc, 0);
1008 	wi_intr_ack(sc, 0xffff);
1009 
1010 	/* Calibrate timer. */
1011 	WI_SETVAL(WI_RID_TICK_TIME, 8);
1012 
1013 	return;
1014 }
1015 
1016 STATIC void
wi_cor_reset(sc)1017 wi_cor_reset(sc)
1018 	struct wi_softc		*sc;
1019 {
1020 	u_int8_t cor_value;
1021 
1022 	DPRINTF(WID_RESET, ("wi_cor_reset: sc %p\n", sc));
1023 
1024 	/*
1025 	 * Do a soft reset of the card; this is required for Symbol cards.
1026 	 * This shouldn't hurt other cards but there have been reports
1027 	 * of the COR reset messing up old Lucent firmware revisions so
1028 	 * we avoid soft reset Lucent cards for now.
1029 	 */
1030 	if (sc->sc_firmware_type != WI_LUCENT) {
1031 		cor_value = bus_space_read_1(sc->wi_ltag, sc->wi_lhandle,
1032 		    sc->wi_cor_offset);
1033 		bus_space_write_1(sc->wi_ltag, sc->wi_lhandle,
1034 		    sc->wi_cor_offset, (cor_value | WI_COR_SOFT_RESET));
1035 		DELAY(1000);
1036 		bus_space_write_1(sc->wi_ltag, sc->wi_lhandle,
1037 		    sc->wi_cor_offset, (cor_value & ~WI_COR_SOFT_RESET));
1038 		DELAY(1000);
1039 	}
1040 
1041 	return;
1042 }
1043 
1044 /*
1045  * Read an LTV record from the NIC.
1046  */
1047 STATIC int
wi_read_record_io(sc,ltv)1048 wi_read_record_io(sc, ltv)
1049 	struct wi_softc		*sc;
1050 	struct wi_ltv_gen	*ltv;
1051 {
1052 	u_int8_t		*ptr;
1053 	int			len, code;
1054 	struct wi_ltv_gen	*oltv = NULL, 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
wi_write_record_io(sc,ltv)1150 wi_write_record_io(sc, ltv)
1151 	struct wi_softc		*sc;
1152 	struct wi_ltv_gen	*ltv;
1153 {
1154 	u_int8_t		*ptr;
1155 	u_int16_t		val = 0;
1156 	int			i;
1157 	struct wi_ltv_gen	p2ltv;
1158 
1159 	if (ltv->wi_type == WI_RID_PORTTYPE &&
1160 	    letoh16(ltv->wi_val) == WI_PORTTYPE_IBSS) {
1161 		/* Convert WI_PORTTYPE_IBSS to vendor IBSS port type. */
1162 		p2ltv.wi_type = WI_RID_PORTTYPE;
1163 		p2ltv.wi_len = 2;
1164 		p2ltv.wi_val = sc->wi_ibss_port;
1165 		ltv = &p2ltv;
1166 	} else if (sc->sc_firmware_type != WI_LUCENT) {
1167 		int v;
1168 
1169 		switch (ltv->wi_type) {
1170 		case WI_RID_TX_RATE:
1171 			p2ltv.wi_type = WI_RID_TX_RATE;
1172 			p2ltv.wi_len = 2;
1173 			switch (letoh16(ltv->wi_val)) {
1174 			case 1: v = 1; break;
1175 			case 2: v = 2; break;
1176 			case 3:	v = 15; break;
1177 			case 5: v = 4; break;
1178 			case 6: v = 3; break;
1179 			case 7: v = 7; break;
1180 			case 11: v = 8; break;
1181 			default: return EINVAL;
1182 			}
1183 			p2ltv.wi_val = htole16(v);
1184 			ltv = &p2ltv;
1185 			break;
1186 		case WI_RID_ENCRYPTION:
1187 			p2ltv.wi_type = WI_RID_P2_ENCRYPTION;
1188 			p2ltv.wi_len = 2;
1189 			if (ltv->wi_val & htole16(0x01)) {
1190 				val = PRIVACY_INVOKED;
1191 				/*
1192 				 * If using shared key WEP we must set the
1193 				 * EXCLUDE_UNENCRYPTED bit.  Symbol cards
1194 				 * need this bit set even when not using
1195 				 * shared key. We can't just test for
1196 				 * IEEE80211_AUTH_SHARED since Symbol cards
1197 				 * have 2 shared key modes.
1198 				 */
1199 				if (sc->wi_authtype != IEEE80211_AUTH_OPEN ||
1200 				    sc->sc_firmware_type == WI_SYMBOL)
1201 					val |= EXCLUDE_UNENCRYPTED;
1202 
1203 				switch (sc->wi_crypto_algorithm) {
1204 				case WI_CRYPTO_FIRMWARE_WEP:
1205 					/*
1206 					 * TX encryption is broken in
1207 					 * Host AP mode.
1208 					 */
1209 					if (sc->wi_ptype == WI_PORTTYPE_HOSTAP)
1210 						val |= HOST_ENCRYPT;
1211 					break;
1212 				case WI_CRYPTO_SOFTWARE_WEP:
1213 					val |= HOST_ENCRYPT|HOST_DECRYPT;
1214 					break;
1215 				}
1216 				p2ltv.wi_val = htole16(val);
1217 			} else
1218 				p2ltv.wi_val = htole16(HOST_ENCRYPT | HOST_DECRYPT);
1219 			ltv = &p2ltv;
1220 			break;
1221 		case WI_RID_TX_CRYPT_KEY:
1222 			if (ltv->wi_val > WI_NLTV_KEYS)
1223 				return (EINVAL);
1224 			p2ltv.wi_type = WI_RID_P2_TX_CRYPT_KEY;
1225 			p2ltv.wi_len = 2;
1226 			p2ltv.wi_val = ltv->wi_val;
1227 			ltv = &p2ltv;
1228 			break;
1229 		case WI_RID_DEFLT_CRYPT_KEYS: {
1230 				int error;
1231 				int keylen;
1232 				struct wi_ltv_str ws;
1233 				struct wi_ltv_keys *wk = (struct wi_ltv_keys *)ltv;
1234 				keylen = wk->wi_keys[sc->wi_tx_key].wi_keylen;
1235 				keylen = letoh16(keylen);
1236 
1237 				for (i = 0; i < 4; i++) {
1238 					bzero(&ws, sizeof(ws));
1239 					ws.wi_len = (keylen > 5) ? 8 : 4;
1240 					ws.wi_type = WI_RID_P2_CRYPT_KEY0 + i;
1241 					bcopy(&wk->wi_keys[i].wi_keydat,
1242 					    ws.wi_str, keylen);
1243 					error = wi_write_record(sc,
1244 					    (struct wi_ltv_gen *)&ws);
1245 					if (error)
1246 						return (error);
1247 				}
1248 			}
1249 			return (0);
1250 		}
1251 	}
1252 
1253 	if (wi_seek(sc, ltv->wi_type, 0, WI_BAP1))
1254 		return(EIO);
1255 
1256 	CSR_WRITE_2(sc, WI_DATA1, ltv->wi_len);
1257 	CSR_WRITE_2(sc, WI_DATA1, ltv->wi_type);
1258 
1259 	ptr = (u_int8_t *)&ltv->wi_val;
1260 	if (ltv->wi_len > 1)
1261 		CSR_WRITE_RAW_2(sc, WI_DATA1, ptr, (ltv->wi_len-1) *2);
1262 
1263 	if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_WRITE, ltv->wi_type, 0, 0))
1264 		return(EIO);
1265 
1266 	return(0);
1267 }
1268 
1269 STATIC int
wi_seek(sc,id,off,chan)1270 wi_seek(sc, id, off, chan)
1271 	struct wi_softc		*sc;
1272 	int			id, off, chan;
1273 {
1274 	int			i;
1275 	int			selreg, offreg;
1276 
1277 	switch (chan) {
1278 	case WI_BAP0:
1279 		selreg = WI_SEL0;
1280 		offreg = WI_OFF0;
1281 		break;
1282 	case WI_BAP1:
1283 		selreg = WI_SEL1;
1284 		offreg = WI_OFF1;
1285 		break;
1286 	default:
1287 		printf(WI_PRT_FMT ": invalid data path: %x\n", WI_PRT_ARG(sc),
1288 		    chan);
1289 		return(EIO);
1290 	}
1291 
1292 	CSR_WRITE_2(sc, selreg, id);
1293 	CSR_WRITE_2(sc, offreg, off);
1294 
1295 	for (i = WI_TIMEOUT; i--; DELAY(1))
1296 		if (!(CSR_READ_2(sc, offreg) & (WI_OFF_BUSY|WI_OFF_ERR)))
1297 			break;
1298 
1299 	if (i < 0)
1300 		return(ETIMEDOUT);
1301 
1302 	return(0);
1303 }
1304 
1305 STATIC int
wi_read_data_io(sc,id,off,buf,len)1306 wi_read_data_io(sc, id, off, buf, len)
1307 	struct wi_softc		*sc;
1308 	int			id, off;
1309 	caddr_t			buf;
1310 	int			len;
1311 {
1312 	u_int8_t		*ptr;
1313 
1314 	if (wi_seek(sc, id, off, WI_BAP1))
1315 		return(EIO);
1316 
1317 	ptr = (u_int8_t *)buf;
1318 	CSR_READ_RAW_2(sc, WI_DATA1, ptr, len);
1319 
1320 	return(0);
1321 }
1322 
1323 /*
1324  * According to the comments in the HCF Light code, there is a bug in
1325  * the Hermes (or possibly in certain Hermes firmware revisions) where
1326  * the chip's internal autoincrement counter gets thrown off during
1327  * data writes: the autoincrement is missed, causing one data word to
1328  * be overwritten and subsequent words to be written to the wrong memory
1329  * locations. The end result is that we could end up transmitting bogus
1330  * frames without realizing it. The workaround for this is to write a
1331  * couple of extra guard words after the end of the transfer, then
1332  * attempt to read then back. If we fail to locate the guard words where
1333  * we expect them, we preform the transfer over again.
1334  */
1335 STATIC int
wi_write_data_io(sc,id,off,buf,len)1336 wi_write_data_io(sc, id, off, buf, len)
1337 	struct wi_softc		*sc;
1338 	int			id, off;
1339 	caddr_t			buf;
1340 	int			len;
1341 {
1342 	u_int8_t		*ptr;
1343 
1344 #ifdef WI_HERMES_AUTOINC_WAR
1345 again:
1346 #endif
1347 
1348 	if (wi_seek(sc, id, off, WI_BAP0))
1349 		return(EIO);
1350 
1351 	ptr = (u_int8_t *)buf;
1352 	CSR_WRITE_RAW_2(sc, WI_DATA0, ptr, len);
1353 
1354 #ifdef WI_HERMES_AUTOINC_WAR
1355 	CSR_WRITE_2(sc, WI_DATA0, 0x1234);
1356 	CSR_WRITE_2(sc, WI_DATA0, 0x5678);
1357 
1358 	if (wi_seek(sc, id, off + len, WI_BAP0))
1359 		return(EIO);
1360 
1361 	if (CSR_READ_2(sc, WI_DATA0) != 0x1234 ||
1362 	    CSR_READ_2(sc, WI_DATA0) != 0x5678)
1363 		goto again;
1364 #endif
1365 
1366 	return(0);
1367 }
1368 
1369 /*
1370  * Allocate a region of memory inside the NIC and zero
1371  * it out.
1372  */
1373 STATIC int
wi_alloc_nicmem_io(sc,len,id)1374 wi_alloc_nicmem_io(sc, len, id)
1375 	struct wi_softc		*sc;
1376 	int			len;
1377 	int			*id;
1378 {
1379 	int			i;
1380 
1381 	if (wi_cmd(sc, WI_CMD_ALLOC_MEM, len, 0, 0)) {
1382 		printf(WI_PRT_FMT ": failed to allocate %d bytes on NIC\n",
1383 		    WI_PRT_ARG(sc), len);
1384 		return(ENOMEM);
1385 	}
1386 
1387 	for (i = WI_TIMEOUT; i--; DELAY(1)) {
1388 		if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_ALLOC)
1389 			break;
1390 	}
1391 
1392 	if (i < 0)
1393 		return(ETIMEDOUT);
1394 
1395 	*id = CSR_READ_2(sc, WI_ALLOC_FID);
1396 	CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
1397 
1398 	if (wi_seek(sc, *id, 0, WI_BAP0))
1399 		return(EIO);
1400 
1401 	for (i = 0; i < len / 2; i++)
1402 		CSR_WRITE_2(sc, WI_DATA0, 0);
1403 
1404 	return(0);
1405 }
1406 
1407 STATIC void
wi_setmulti(sc)1408 wi_setmulti(sc)
1409 	struct wi_softc		*sc;
1410 {
1411 	struct ifnet		*ifp;
1412 	int			i = 0;
1413 	struct wi_ltv_mcast	mcast;
1414 	struct ether_multistep	step;
1415 	struct ether_multi	*enm;
1416 
1417 	ifp = &sc->sc_arpcom.ac_if;
1418 
1419 	bzero((char *)&mcast, sizeof(mcast));
1420 
1421 	mcast.wi_type = WI_RID_MCAST_LIST;
1422 	mcast.wi_len = ((ETHER_ADDR_LEN / 2) * 16) + 1;
1423 
1424 	if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
1425 		wi_write_record(sc, (struct wi_ltv_gen *)&mcast);
1426 		return;
1427 	}
1428 
1429 	ETHER_FIRST_MULTI(step, &sc->sc_arpcom, enm);
1430 	while (enm != NULL) {
1431 		if (i >= 16) {
1432 			bzero((char *)&mcast, sizeof(mcast));
1433 			break;
1434 		}
1435 
1436 		/* Punt on ranges. */
1437 		if (bcmp(enm->enm_addrlo, enm->enm_addrhi,
1438 		    sizeof(enm->enm_addrlo)) != 0)
1439 			break;
1440 		bcopy(enm->enm_addrlo, (char *)&mcast.wi_mcast[i],
1441 		    ETHER_ADDR_LEN);
1442 		i++;
1443 		ETHER_NEXT_MULTI(step, enm);
1444 	}
1445 
1446 	mcast.wi_len = (i * 3) + 1;
1447 	wi_write_record(sc, (struct wi_ltv_gen *)&mcast);
1448 
1449 	return;
1450 }
1451 
1452 STATIC int
wi_setdef(sc,wreq)1453 wi_setdef(sc, wreq)
1454 	struct wi_softc		*sc;
1455 	struct wi_req		*wreq;
1456 {
1457 	struct ifnet		*ifp;
1458 	int error = 0;
1459 
1460 	ifp = &sc->sc_arpcom.ac_if;
1461 
1462 	switch(wreq->wi_type) {
1463 	case WI_RID_MAC_NODE:
1464 		bcopy((char *)&wreq->wi_val, LLADDR(ifp->if_sadl),
1465 		    ETHER_ADDR_LEN);
1466 		bcopy((char *)&wreq->wi_val, (char *)&sc->sc_arpcom.ac_enaddr,
1467 		    ETHER_ADDR_LEN);
1468 		break;
1469 	case WI_RID_PORTTYPE:
1470 		error = wi_sync_media(sc, letoh16(wreq->wi_val[0]),
1471 		    sc->wi_tx_rate);
1472 		break;
1473 	case WI_RID_TX_RATE:
1474 		error = wi_sync_media(sc, sc->wi_ptype,
1475 		    letoh16(wreq->wi_val[0]));
1476 		break;
1477 	case WI_RID_MAX_DATALEN:
1478 		sc->wi_max_data_len = letoh16(wreq->wi_val[0]);
1479 		break;
1480 	case WI_RID_RTS_THRESH:
1481 		sc->wi_rts_thresh = letoh16(wreq->wi_val[0]);
1482 		break;
1483 	case WI_RID_SYSTEM_SCALE:
1484 		sc->wi_ap_density = letoh16(wreq->wi_val[0]);
1485 		break;
1486 	case WI_RID_CREATE_IBSS:
1487 		sc->wi_create_ibss = letoh16(wreq->wi_val[0]);
1488 		error = wi_sync_media(sc, sc->wi_ptype, sc->wi_tx_rate);
1489 		break;
1490 	case WI_RID_OWN_CHNL:
1491 		sc->wi_channel = letoh16(wreq->wi_val[0]);
1492 		break;
1493 	case WI_RID_NODENAME:
1494 		error = wi_set_ssid(&sc->wi_node_name,
1495 		    (u_int8_t *)&wreq->wi_val[1], letoh16(wreq->wi_val[0]));
1496 		break;
1497 	case WI_RID_DESIRED_SSID:
1498 		error = wi_set_ssid(&sc->wi_net_name,
1499 		    (u_int8_t *)&wreq->wi_val[1], letoh16(wreq->wi_val[0]));
1500 		break;
1501 	case WI_RID_OWN_SSID:
1502 		error = wi_set_ssid(&sc->wi_ibss_name,
1503 		    (u_int8_t *)&wreq->wi_val[1], letoh16(wreq->wi_val[0]));
1504 		break;
1505 	case WI_RID_PM_ENABLED:
1506 		sc->wi_pm_enabled = letoh16(wreq->wi_val[0]);
1507 		break;
1508 	case WI_RID_MICROWAVE_OVEN:
1509 		sc->wi_mor_enabled = letoh16(wreq->wi_val[0]);
1510 		break;
1511 	case WI_RID_MAX_SLEEP:
1512 		sc->wi_max_sleep = letoh16(wreq->wi_val[0]);
1513 		break;
1514 	case WI_RID_CNFAUTHMODE:
1515 		sc->wi_authtype = letoh16(wreq->wi_val[0]);
1516 		break;
1517 	case WI_RID_ROAMING_MODE:
1518 		sc->wi_roaming = letoh16(wreq->wi_val[0]);
1519 		break;
1520 	case WI_RID_SYMBOL_DIVERSITY:
1521 		sc->wi_diversity = letoh16(wreq->wi_val[0]);
1522 		break;
1523 	case WI_RID_CNF_ENH_SECURITY:
1524 		sc->wi_enh_security = letoh16(wreq->wi_val[0]);
1525 		break;
1526 	case WI_RID_ENCRYPTION:
1527 		sc->wi_use_wep = letoh16(wreq->wi_val[0]);
1528 		break;
1529 	case WI_RID_TX_CRYPT_KEY:
1530 		sc->wi_tx_key = letoh16(wreq->wi_val[0]);
1531 		break;
1532 	case WI_RID_DEFLT_CRYPT_KEYS:
1533 		bcopy((char *)wreq, (char *)&sc->wi_keys,
1534 		    sizeof(struct wi_ltv_keys));
1535 		break;
1536 	case WI_FRID_CRYPTO_ALG:
1537 		switch (letoh16(wreq->wi_val[0])) {
1538 		case WI_CRYPTO_FIRMWARE_WEP:
1539 			sc->wi_crypto_algorithm = WI_CRYPTO_FIRMWARE_WEP;
1540 			break;
1541 		case WI_CRYPTO_SOFTWARE_WEP:
1542 			sc->wi_crypto_algorithm = WI_CRYPTO_SOFTWARE_WEP;
1543 			break;
1544 		default:
1545 			printf(WI_PRT_FMT ": unsupported crypto algorithm %d\n",
1546 			    WI_PRT_ARG(sc), letoh16(wreq->wi_val[0]));
1547 			error = EINVAL;
1548 		}
1549 		break;
1550 	default:
1551 		error = EINVAL;
1552 		break;
1553 	}
1554 
1555 	return (error);
1556 }
1557 
1558 STATIC int
wi_ioctl(ifp,command,data)1559 wi_ioctl(ifp, command, data)
1560 	struct ifnet		*ifp;
1561 	u_long			command;
1562 	caddr_t			data;
1563 {
1564 	int			s, error = 0;
1565 	struct wi_softc		*sc;
1566 	struct wi_req		wreq;
1567 	struct ifreq		*ifr;
1568 	struct proc		*p = curproc;
1569 	struct ifaddr		*ifa = (struct ifaddr *)data;
1570 	struct ieee80211_nwid	nwid;
1571 
1572 	s = splimp();
1573 
1574 	sc = ifp->if_softc;
1575 	ifr = (struct ifreq *)data;
1576 
1577 	if (!(sc->wi_flags & WI_FLAGS_ATTACHED)) {
1578 		splx(s);
1579 		return(ENODEV);
1580 	}
1581 
1582 	DPRINTF (WID_IOCTL, ("wi_ioctl: command %lu data %p\n",
1583 	    command, data));
1584 
1585 	if ((error = ether_ioctl(ifp, &sc->sc_arpcom, command, data)) > 0) {
1586 		splx(s);
1587 		return error;
1588 	}
1589 
1590 	switch(command) {
1591 	case SIOCSWAVELAN:
1592 	case SIOCSPRISM2DEBUG:
1593 	case SIOCS80211NWID:
1594 	case SIOCS80211NWKEY:
1595 	case SIOCS80211POWER:
1596 		error = suser(p, 0);
1597 		if (error) {
1598 			splx(s);
1599 			return (error);
1600 		}
1601 	default:
1602 		break;
1603 	}
1604 
1605 	switch(command) {
1606 	case SIOCSIFADDR:
1607 		ifp->if_flags |= IFF_UP;
1608 		switch (ifa->ifa_addr->sa_family) {
1609 #ifdef INET
1610 		case AF_INET:
1611 			wi_init(sc);
1612 			arp_ifinit(&sc->sc_arpcom, ifa);
1613 			break;
1614 #endif	/* INET */
1615 		default:
1616 			wi_init(sc);
1617 			break;
1618 		}
1619 		break;
1620 
1621 	case SIOCSIFMTU:
1622 		if (ifr->ifr_mtu > ETHERMTU || ifr->ifr_mtu < ETHERMIN) {
1623 			error = EINVAL;
1624 		} else if (ifp->if_mtu != ifr->ifr_mtu) {
1625 			ifp->if_mtu = ifr->ifr_mtu;
1626 		}
1627 		break;
1628 
1629 	case SIOCSIFFLAGS:
1630 		if (ifp->if_flags & IFF_UP) {
1631 			if (ifp->if_flags & IFF_RUNNING &&
1632 			    ifp->if_flags & IFF_PROMISC &&
1633 			    !(sc->wi_if_flags & IFF_PROMISC)) {
1634 				if (sc->wi_ptype != WI_PORTTYPE_HOSTAP)
1635 					WI_SETVAL(WI_RID_PROMISC, 1);
1636 			} else if (ifp->if_flags & IFF_RUNNING &&
1637 			    !(ifp->if_flags & IFF_PROMISC) &&
1638 			    sc->wi_if_flags & IFF_PROMISC) {
1639 				if (sc->wi_ptype != WI_PORTTYPE_HOSTAP)
1640 					WI_SETVAL(WI_RID_PROMISC, 0);
1641 			} else
1642 				wi_init(sc);
1643 		} else if (ifp->if_flags & IFF_RUNNING)
1644 			wi_stop(sc);
1645 		sc->wi_if_flags = ifp->if_flags;
1646 		error = 0;
1647 		break;
1648 	case SIOCADDMULTI:
1649 	case SIOCDELMULTI:
1650 		/* Update our multicast list. */
1651 		error = (command == SIOCADDMULTI) ?
1652 		    ether_addmulti(ifr, &sc->sc_arpcom) :
1653 		    ether_delmulti(ifr, &sc->sc_arpcom);
1654 		if (error == ENETRESET) {
1655 			/*
1656 			 * Multicast list has changed; set the hardware filter
1657 			 * accordingly.
1658 			 */
1659 			wi_setmulti(sc);
1660 			error = 0;
1661 		}
1662 		break;
1663 	case SIOCSIFMEDIA:
1664 	case SIOCGIFMEDIA:
1665 		error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, command);
1666 		break;
1667 	case SIOCGWAVELAN:
1668 		error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
1669 		if (error)
1670 			break;
1671 		if (wreq.wi_len > WI_MAX_DATALEN) {
1672 			error = EINVAL;
1673 			break;
1674 		}
1675 		switch (wreq.wi_type) {
1676 		case WI_RID_IFACE_STATS:
1677 			/* XXX native byte order */
1678 			bcopy((char *)&sc->wi_stats, (char *)&wreq.wi_val,
1679 			    sizeof(sc->wi_stats));
1680 			wreq.wi_len = (sizeof(sc->wi_stats) / 2) + 1;
1681 			break;
1682 		case WI_RID_DEFLT_CRYPT_KEYS:
1683 			/* For non-root user, return all-zeroes keys */
1684 			if (suser(p, 0))
1685 				bzero((char *)&wreq,
1686 					sizeof(struct wi_ltv_keys));
1687 			else
1688 				bcopy((char *)&sc->wi_keys, (char *)&wreq,
1689 					sizeof(struct wi_ltv_keys));
1690 			break;
1691 		case WI_RID_PROCFRAME:
1692 			wreq.wi_len = 2;
1693 			wreq.wi_val[0] = htole16(sc->wi_procframe);
1694 			break;
1695 		case WI_RID_PRISM2:
1696 			wreq.wi_len = 2;
1697 			wreq.wi_val[0] = htole16(sc->sc_firmware_type ==
1698 			    WI_LUCENT ? 0 : 1);
1699 			break;
1700 		case WI_FRID_CRYPTO_ALG:
1701 			wreq.wi_val[0] =
1702 			    htole16((u_int16_t)sc->wi_crypto_algorithm);
1703 			wreq.wi_len = 1;
1704 			break;
1705 		case WI_RID_SCAN_RES:
1706 			if (sc->sc_firmware_type == WI_LUCENT) {
1707 				memcpy((char *)wreq.wi_val,
1708 				    (char *)sc->wi_scanbuf,
1709 				    sc->wi_scanbuf_len * 2);
1710 				wreq.wi_len = sc->wi_scanbuf_len;
1711 				break;
1712 			}
1713 			/* FALLTHROUGH */
1714 		default:
1715 			if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq)) {
1716 				error = EINVAL;
1717 			}
1718 			break;
1719 		}
1720 		error = copyout(&wreq, ifr->ifr_data, sizeof(wreq));
1721 		break;
1722 	case SIOCSWAVELAN:
1723 		error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
1724 		if (error)
1725 			break;
1726 		error = EINVAL;
1727 		if (wreq.wi_len > WI_MAX_DATALEN)
1728 			break;
1729 		switch (wreq.wi_type) {
1730 		case WI_RID_IFACE_STATS:
1731 			break;
1732 		case WI_RID_MGMT_XMIT:
1733 			error = wi_mgmt_xmit(sc, (caddr_t)&wreq.wi_val,
1734 			    wreq.wi_len);
1735 			break;
1736 		case WI_RID_PROCFRAME:
1737 			sc->wi_procframe = letoh16(wreq.wi_val[0]);
1738 			error = 0;
1739 			break;
1740 		case WI_RID_SCAN_REQ:
1741 			error = 0;
1742 			if (sc->sc_firmware_type == WI_LUCENT)
1743 				wi_cmd(sc, WI_CMD_INQUIRE,
1744 				    WI_INFO_SCAN_RESULTS, 0, 0);
1745 			else
1746 				error = wi_write_record(sc,
1747 				    (struct wi_ltv_gen *)&wreq);
1748 			break;
1749 		case WI_FRID_CRYPTO_ALG:
1750 			if (sc->sc_firmware_type != WI_LUCENT) {
1751 				error = wi_setdef(sc, &wreq);
1752 				if (!error && (ifp->if_flags & IFF_UP))
1753 					wi_init(sc);
1754 			}
1755 			break;
1756 		case WI_RID_SYMBOL_DIVERSITY:
1757 		case WI_RID_ROAMING_MODE:
1758 		case WI_RID_CREATE_IBSS:
1759 		case WI_RID_MICROWAVE_OVEN:
1760 		case WI_RID_OWN_SSID:
1761 		case WI_RID_CNF_ENH_SECURITY:
1762 			/*
1763 			 * Check for features that may not be supported
1764 			 * (must be just before default case).
1765 			 */
1766 			if ((wreq.wi_type == WI_RID_SYMBOL_DIVERSITY &&
1767 			    !(sc->wi_flags & WI_FLAGS_HAS_DIVERSITY)) ||
1768 			    (wreq.wi_type == WI_RID_ROAMING_MODE &&
1769 			    !(sc->wi_flags & WI_FLAGS_HAS_ROAMING)) ||
1770 			    (wreq.wi_type == WI_RID_CREATE_IBSS &&
1771 			    !(sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)) ||
1772 			    (wreq.wi_type == WI_RID_MICROWAVE_OVEN &&
1773 			    !(sc->wi_flags & WI_FLAGS_HAS_MOR)) ||
1774 			    (wreq.wi_type == WI_RID_CNF_ENH_SECURITY &&
1775 			    !(sc->wi_flags & WI_FLAGS_HAS_ENH_SECURITY)) ||
1776 			    (wreq.wi_type == WI_RID_OWN_SSID &&
1777 			    wreq.wi_len != 0))
1778 				break;
1779 			/* FALLTHROUGH */
1780 		default:
1781 			error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
1782 			if (!error)
1783 				error = wi_setdef(sc, &wreq);
1784 			if (!error && (ifp->if_flags & IFF_UP))
1785 				wi_init(sc);
1786 		}
1787 		break;
1788 	case SIOCGPRISM2DEBUG:
1789 		error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
1790 		if (error)
1791 			break;
1792 		if (!(ifp->if_flags & IFF_RUNNING) ||
1793 		    sc->sc_firmware_type == WI_LUCENT) {
1794 			error = EIO;
1795 			break;
1796 		}
1797 		error = wi_get_debug(sc, &wreq);
1798 		if (error == 0)
1799 			error = copyout(&wreq, ifr->ifr_data, sizeof(wreq));
1800 		break;
1801 	case SIOCSPRISM2DEBUG:
1802 		error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
1803 		if (error)
1804 			break;
1805 		error = wi_set_debug(sc, &wreq);
1806 		break;
1807 	case SIOCG80211NWID:
1808 		if ((ifp->if_flags & IFF_UP) && sc->wi_net_name.i_len > 0) {
1809 			/* Return the desired ID */
1810 			error = copyout(&sc->wi_net_name, ifr->ifr_data,
1811 			    sizeof(sc->wi_net_name));
1812 		} else {
1813 			wreq.wi_type = WI_RID_CURRENT_SSID;
1814 			wreq.wi_len = WI_MAX_DATALEN;
1815 			if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq) ||
1816 			    letoh16(wreq.wi_val[0]) > IEEE80211_NWID_LEN)
1817 				error = EINVAL;
1818 			else {
1819 				wi_set_ssid(&nwid, (u_int8_t *)&wreq.wi_val[1],
1820 				    letoh16(wreq.wi_val[0]));
1821 				error = copyout(&nwid, ifr->ifr_data,
1822 				    sizeof(nwid));
1823 			}
1824 		}
1825 		break;
1826 	case SIOCS80211NWID:
1827 		error = copyin(ifr->ifr_data, &nwid, sizeof(nwid));
1828 		if (error)
1829 			break;
1830 		if (nwid.i_len > IEEE80211_NWID_LEN) {
1831 			error = EINVAL;
1832 			break;
1833 		}
1834 		if (sc->wi_net_name.i_len == nwid.i_len &&
1835 		    memcmp(sc->wi_net_name.i_nwid, nwid.i_nwid, nwid.i_len) == 0)
1836 			break;
1837 		wi_set_ssid(&sc->wi_net_name, nwid.i_nwid, nwid.i_len);
1838 		WI_SETSTR(WI_RID_DESIRED_SSID, sc->wi_net_name);
1839 		if (ifp->if_flags & IFF_UP)
1840 			/* Reinitialize WaveLAN. */
1841 			wi_init(sc);
1842 		break;
1843 	case SIOCS80211NWKEY:
1844 		error = wi_set_nwkey(sc, (struct ieee80211_nwkey *)data);
1845 		break;
1846 	case SIOCG80211NWKEY:
1847 		error = wi_get_nwkey(sc, (struct ieee80211_nwkey *)data);
1848 		break;
1849 	case SIOCS80211POWER:
1850 		error = wi_set_pm(sc, (struct ieee80211_power *)data);
1851 		break;
1852 	case SIOCG80211POWER:
1853 		error = wi_get_pm(sc, (struct ieee80211_power *)data);
1854 		break;
1855 	case SIOCHOSTAP_ADD:
1856 	case SIOCHOSTAP_DEL:
1857 	case SIOCHOSTAP_GET:
1858 	case SIOCHOSTAP_GETALL:
1859 	case SIOCHOSTAP_GFLAGS:
1860 	case SIOCHOSTAP_SFLAGS:
1861 		/* Send all Host AP specific ioctl's to Host AP code. */
1862 		error = wihap_ioctl(sc, command, data);
1863 		break;
1864 	default:
1865 		error = EINVAL;
1866 		break;
1867 	}
1868 
1869 	splx(s);
1870 	return(error);
1871 }
1872 
1873 STATIC void
wi_init_io(sc)1874 wi_init_io(sc)
1875 	struct wi_softc		*sc;
1876 {
1877 	struct ifnet		*ifp = &sc->sc_arpcom.ac_if;
1878 	int			s;
1879 	struct wi_ltv_macaddr	mac;
1880 	int			id = 0;
1881 
1882 	if (!(sc->wi_flags & WI_FLAGS_ATTACHED))
1883 		return;
1884 
1885 	DPRINTF(WID_INIT, ("wi_init: sc %p\n", sc));
1886 
1887 	s = splimp();
1888 
1889 	if (ifp->if_flags & IFF_RUNNING)
1890 		wi_stop(sc);
1891 
1892 	wi_reset(sc);
1893 
1894 	/* Program max data length. */
1895 	WI_SETVAL(WI_RID_MAX_DATALEN, sc->wi_max_data_len);
1896 
1897 	/* Set the port type. */
1898 	WI_SETVAL(WI_RID_PORTTYPE, sc->wi_ptype);
1899 
1900 	/* Enable/disable IBSS creation. */
1901 	WI_SETVAL(WI_RID_CREATE_IBSS, sc->wi_create_ibss);
1902 
1903 	/* Program the RTS/CTS threshold. */
1904 	WI_SETVAL(WI_RID_RTS_THRESH, sc->wi_rts_thresh);
1905 
1906 	/* Program the TX rate */
1907 	WI_SETVAL(WI_RID_TX_RATE, sc->wi_tx_rate);
1908 
1909 	/* Access point density */
1910 	WI_SETVAL(WI_RID_SYSTEM_SCALE, sc->wi_ap_density);
1911 
1912 	/* Power Management Enabled */
1913 	WI_SETVAL(WI_RID_PM_ENABLED, sc->wi_pm_enabled);
1914 
1915 	/* Power Management Max Sleep */
1916 	WI_SETVAL(WI_RID_MAX_SLEEP, sc->wi_max_sleep);
1917 
1918 	/* Set Enhanced Security if supported. */
1919 	if (sc->wi_flags & WI_FLAGS_HAS_ENH_SECURITY)
1920 		WI_SETVAL(WI_RID_CNF_ENH_SECURITY, sc->wi_enh_security);
1921 
1922 	/* Set Roaming Mode unless this is a Symbol card. */
1923 	if (sc->wi_flags & WI_FLAGS_HAS_ROAMING)
1924 		WI_SETVAL(WI_RID_ROAMING_MODE, sc->wi_roaming);
1925 
1926 	/* Set Antenna Diversity if this is a Symbol card. */
1927 	if (sc->wi_flags & WI_FLAGS_HAS_DIVERSITY)
1928 		WI_SETVAL(WI_RID_SYMBOL_DIVERSITY, sc->wi_diversity);
1929 
1930 	/* Specify the network name */
1931 	WI_SETSTR(WI_RID_DESIRED_SSID, sc->wi_net_name);
1932 
1933 	/* Specify the IBSS name */
1934 	if (sc->wi_net_name.i_len != 0 && (sc->wi_ptype == WI_PORTTYPE_HOSTAP ||
1935 	    (sc->wi_create_ibss && sc->wi_ptype == WI_PORTTYPE_IBSS)))
1936 		WI_SETSTR(WI_RID_OWN_SSID, sc->wi_net_name);
1937 	else
1938 		WI_SETSTR(WI_RID_OWN_SSID, sc->wi_ibss_name);
1939 
1940 	/* Specify the frequency to use */
1941 	WI_SETVAL(WI_RID_OWN_CHNL, sc->wi_channel);
1942 
1943 	/* Program the nodename. */
1944 	WI_SETSTR(WI_RID_NODENAME, sc->wi_node_name);
1945 
1946 	/* Set our MAC address. */
1947 	mac.wi_len = 4;
1948 	mac.wi_type = WI_RID_MAC_NODE;
1949 	bcopy((char *)&sc->sc_arpcom.ac_enaddr,
1950 	   (char *)&mac.wi_mac_addr, ETHER_ADDR_LEN);
1951 	wi_write_record(sc, (struct wi_ltv_gen *)&mac);
1952 
1953 	/*
1954 	 * Initialize promisc mode.
1955 	 *	Being in the Host-AP mode causes
1956 	 *	great deal of pain if promisc mode is set.
1957 	 *	Therefore we avoid confusing the firmware
1958 	 *	and always reset promisc mode in Host-AP regime,
1959 	 *	it shows us all the packets anyway.
1960 	 */
1961 	if (sc->wi_ptype != WI_PORTTYPE_HOSTAP && ifp->if_flags & IFF_PROMISC)
1962 		WI_SETVAL(WI_RID_PROMISC, 1);
1963 	else
1964 		WI_SETVAL(WI_RID_PROMISC, 0);
1965 
1966 	/* Configure WEP. */
1967 	if (sc->wi_flags & WI_FLAGS_HAS_WEP) {
1968 		WI_SETVAL(WI_RID_ENCRYPTION, sc->wi_use_wep);
1969 		WI_SETVAL(WI_RID_TX_CRYPT_KEY, sc->wi_tx_key);
1970 		sc->wi_keys.wi_len = (sizeof(struct wi_ltv_keys) / 2) + 1;
1971 		sc->wi_keys.wi_type = WI_RID_DEFLT_CRYPT_KEYS;
1972 		wi_write_record(sc, (struct wi_ltv_gen *)&sc->wi_keys);
1973 		if (sc->sc_firmware_type != WI_LUCENT && sc->wi_use_wep) {
1974 			/*
1975 			 * HWB3163 EVAL-CARD Firmware version less than 0.8.2.
1976 			 *
1977 			 * If promiscuous mode is disabled, the Prism2 chip
1978 			 * does not work with WEP .
1979 			 * I'm currently investigating the details of this.
1980 			 * (ichiro@netbsd.org)
1981 			 */
1982 			 if (sc->sc_firmware_type == WI_INTERSIL &&
1983 			    sc->sc_sta_firmware_ver < 802 ) {
1984 				/* firm ver < 0.8.2 */
1985 				WI_SETVAL(WI_RID_PROMISC, 1);
1986 			 }
1987 			 WI_SETVAL(WI_RID_CNFAUTHMODE, sc->wi_authtype);
1988 		}
1989 	}
1990 
1991 	/* Set multicast filter. */
1992 	wi_setmulti(sc);
1993 
1994 	/* Enable desired port */
1995 	wi_cmd(sc, WI_CMD_ENABLE | sc->wi_portnum, 0, 0, 0);
1996 
1997 	if (wi_alloc_nicmem(sc, ETHER_MAX_LEN + sizeof(struct wi_frame) + 8, &id))
1998 		printf(WI_PRT_FMT ": tx buffer allocation failed\n",
1999 		    WI_PRT_ARG(sc));
2000 	sc->wi_tx_data_id = id;
2001 
2002 	if (wi_alloc_nicmem(sc, ETHER_MAX_LEN + sizeof(struct wi_frame) + 8, &id))
2003 		printf(WI_PRT_FMT ": mgmt. buffer allocation failed\n",
2004 		    WI_PRT_ARG(sc));
2005 	sc->wi_tx_mgmt_id = id;
2006 
2007 	/* enable interrupts */
2008 	wi_intr_enable(sc, WI_INTRS);
2009 
2010         wihap_init(sc);
2011 
2012 	splx(s);
2013 
2014 	ifp->if_flags |= IFF_RUNNING;
2015 	ifp->if_flags &= ~IFF_OACTIVE;
2016 
2017 	timeout_add(&sc->sc_timo, hz * 60);
2018 
2019 	return;
2020 }
2021 
2022 static const u_int32_t crc32tab[] = {
2023 	0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL,
2024 	0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L,
2025 	0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L,
2026 	0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L,
2027 	0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
2028 	0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L,
2029 	0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL,
2030 	0x14015c4fL, 0x63066cd9L, 0xfa0f3d63L, 0x8d080df5L,
2031 	0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 0xa2677172L,
2032 	0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
2033 	0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L,
2034 	0x32d86ce3L, 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L,
2035 	0x26d930acL, 0x51de003aL, 0xc8d75180L, 0xbfd06116L,
2036 	0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 0xb8bda50fL,
2037 	0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
2038 	0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL,
2039 	0x76dc4190L, 0x01db7106L, 0x98d220bcL, 0xefd5102aL,
2040 	0x71b18589L, 0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L,
2041 	0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 0xe10e9818L,
2042 	0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
2043 	0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL,
2044 	0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L,
2045 	0x65b0d9c6L, 0x12b7e950L, 0x8bbeb8eaL, 0xfcb9887cL,
2046 	0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L,
2047 	0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
2048 	0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL,
2049 	0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L,
2050 	0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L,
2051 	0x5005713cL, 0x270241aaL, 0xbe0b1010L, 0xc90c2086L,
2052 	0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
2053 	0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L,
2054 	0x59b33d17L, 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL,
2055 	0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL,
2056 	0xead54739L, 0x9dd277afL, 0x04db2615L, 0x73dc1683L,
2057 	0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
2058 	0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L,
2059 	0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL,
2060 	0xf762575dL, 0x806567cbL, 0x196c3671L, 0x6e6b06e7L,
2061 	0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 0x67dd4accL,
2062 	0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
2063 	0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L,
2064 	0xd1bb67f1L, 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL,
2065 	0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, 0x41047a60L,
2066 	0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 0x4669be79L,
2067 	0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
2068 	0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL,
2069 	0xc5ba3bbeL, 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L,
2070 	0xc2d7ffa7L, 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL,
2071 	0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 0x026d930aL,
2072 	0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
2073 	0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L,
2074 	0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L,
2075 	0x86d3d2d4L, 0xf1d4e242L, 0x68ddb3f8L, 0x1fda836eL,
2076 	0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 0x18b74777L,
2077 	0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
2078 	0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L,
2079 	0xa00ae278L, 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L,
2080 	0xa7672661L, 0xd06016f7L, 0x4969474dL, 0x3e6e77dbL,
2081 	0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 0x37d83bf0L,
2082 	0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
2083 	0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L,
2084 	0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL,
2085 	0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L,
2086 	0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL
2087 };
2088 
2089 STATIC void
wi_do_hostencrypt(struct wi_softc * sc,caddr_t buf,int len)2090 wi_do_hostencrypt(struct wi_softc *sc, caddr_t buf, int len)
2091 {
2092 	u_int32_t i, crc, klen;
2093 	u_int8_t key[RC4KEYLEN];
2094 	u_int8_t *dat;
2095 	struct rc4_ctx ctx;
2096 
2097 	if (!sc->wi_icv_flag) {
2098 		sc->wi_icv = arc4random();
2099 		sc->wi_icv_flag++;
2100         } else
2101 		sc->wi_icv++;
2102 	/*
2103 	 * Skip 'bad' IVs from Fluhrer/Mantin/Shamir:
2104 	 * (B, 255, N) with 3 <= B < 8
2105 	 */
2106 	if (sc->wi_icv >= 0x03ff00 &&
2107             (sc->wi_icv & 0xf8ff00) == 0x00ff00)
2108                 sc->wi_icv += 0x000100;
2109 
2110 	/* prepend 24bit IV to tx key, byte order does not matter */
2111 	bzero(key, sizeof(key));
2112 	key[0] = sc->wi_icv >> 16;
2113 	key[1] = sc->wi_icv >> 8;
2114 	key[2] = sc->wi_icv;
2115 
2116 	klen = letoh16(sc->wi_keys.wi_keys[sc->wi_tx_key].wi_keylen);
2117 	bcopy((char *)&sc->wi_keys.wi_keys[sc->wi_tx_key].wi_keydat,
2118 	    (char *)key + IEEE80211_WEP_IVLEN, klen);
2119 	klen = (klen > IEEE80211_WEP_KEYLEN) ? RC4KEYLEN : RC4KEYLEN / 2;
2120 
2121 	/* rc4 keysetup */
2122 	rc4_keysetup(&ctx, key, klen);
2123 
2124 	/* output: IV, tx keyid, rc4(data), rc4(crc32(data)) */
2125 	dat = buf;
2126 	dat[0] = key[0];
2127 	dat[1] = key[1];
2128 	dat[2] = key[2];
2129 	dat[3] = sc->wi_tx_key << 6;		/* pad and keyid */
2130 	dat += 4;
2131 
2132 	/* compute crc32 over data and encrypt */
2133 	crc = ~0;
2134 	for (i = 0; i < len; i++)
2135 		crc = crc32tab[(crc ^ dat[i]) & 0xff] ^ (crc >> 8);
2136 	crc = ~crc;
2137 	rc4_crypt(&ctx, dat, dat, len);
2138 	dat += len;
2139 
2140 	/* append little-endian crc32 and encrypt */
2141 	dat[0] = crc;
2142 	dat[1] = crc >> 8;
2143 	dat[2] = crc >> 16;
2144 	dat[3] = crc >> 24;
2145 	rc4_crypt(&ctx, dat, dat, IEEE80211_WEP_CRCLEN);
2146 }
2147 
2148 STATIC int
wi_do_hostdecrypt(struct wi_softc * sc,caddr_t buf,int len)2149 wi_do_hostdecrypt(struct wi_softc *sc, caddr_t buf, int len)
2150 {
2151 	u_int32_t i, crc, klen, kid;
2152 	u_int8_t key[RC4KEYLEN];
2153 	u_int8_t *dat;
2154 	struct rc4_ctx ctx;
2155 
2156 	if (len < IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN +
2157 	    IEEE80211_WEP_CRCLEN)
2158 		return -1;
2159 	len -= (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN +
2160 	    IEEE80211_WEP_CRCLEN);
2161 
2162 	dat = buf;
2163 
2164 	bzero(key, sizeof(key));
2165 	key[0] = dat[0];
2166 	key[1] = dat[1];
2167 	key[2] = dat[2];
2168 	kid = (dat[3] >> 6) % 4;
2169 	dat += 4;
2170 
2171 	klen = letoh16(sc->wi_keys.wi_keys[kid].wi_keylen);
2172 	bcopy((char *)&sc->wi_keys.wi_keys[kid].wi_keydat,
2173 	    (char *)key + IEEE80211_WEP_IVLEN, klen);
2174 	klen = (klen > IEEE80211_WEP_KEYLEN) ? RC4KEYLEN : RC4KEYLEN / 2;
2175 
2176 	/* rc4 keysetup */
2177 	rc4_keysetup(&ctx, key, klen);
2178 
2179 	/* decrypt and compute crc32 over data */
2180 	rc4_crypt(&ctx, dat, dat, len);
2181 	crc = ~0;
2182 	for (i = 0; i < len; i++)
2183 		crc = crc32tab[(crc ^ dat[i]) & 0xff] ^ (crc >> 8);
2184 	crc = ~crc;
2185 	dat += len;
2186 
2187 	/* decrypt little-endian crc32 and verify */
2188 	rc4_crypt(&ctx, dat, dat, IEEE80211_WEP_CRCLEN);
2189 
2190 	if ((dat[0] != crc) && (dat[1] != crc >> 8) &&
2191 	    (dat[2] != crc >> 16) && (dat[3] != crc >> 24)) {
2192 		if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG)
2193 			printf(WI_PRT_FMT ": wi_do_hostdecrypt: iv mismatch: "
2194 			    "0x%02x%02x%02x%02x vs. 0x%x\n", WI_PRT_ARG(sc),
2195 			    dat[3], dat[2], dat[1], dat[0], crc);
2196 		return -1;
2197 	}
2198 
2199 	return 0;
2200 }
2201 
2202 void
wi_start(ifp)2203 wi_start(ifp)
2204 	struct ifnet		*ifp;
2205 {
2206 	struct wi_softc		*sc;
2207 	struct mbuf		*m0;
2208 	struct wi_frame		tx_frame;
2209 	struct ether_header	*eh;
2210 	int			id, hostencrypt = 0;
2211 
2212 	sc = ifp->if_softc;
2213 
2214 	DPRINTF(WID_START, ("wi_start: ifp %p sc %p\n", ifp, sc));
2215 
2216 	if (!(sc->wi_flags & WI_FLAGS_ATTACHED))
2217 		return;
2218 
2219 	if (ifp->if_flags & IFF_OACTIVE)
2220 		return;
2221 
2222 nextpkt:
2223 	IFQ_DEQUEUE(&ifp->if_snd, m0);
2224 	if (m0 == NULL)
2225 		return;
2226 
2227 	bzero((char *)&tx_frame, sizeof(tx_frame));
2228 	tx_frame.wi_frame_ctl = htole16(WI_FTYPE_DATA | WI_STYPE_DATA);
2229 	id = sc->wi_tx_data_id;
2230 	eh = mtod(m0, struct ether_header *);
2231 
2232 	if (sc->wi_ptype == WI_PORTTYPE_HOSTAP) {
2233 		if (!wihap_check_tx(&sc->wi_hostap_info, eh->ether_dhost,
2234 		    &tx_frame.wi_tx_rate) && !(ifp->if_flags & IFF_PROMISC)) {
2235 			if (ifp->if_flags & IFF_DEBUG)
2236 				printf(WI_PRT_FMT
2237 				    ": wi_start: dropping unassoc dst %s\n",
2238 				    WI_PRT_ARG(sc),
2239 				    ether_sprintf(eh->ether_dhost));
2240 			m_freem(m0);
2241 			goto nextpkt;
2242 		}
2243 	}
2244 
2245 	/*
2246 	 * Use RFC1042 encoding for IP and ARP datagrams,
2247 	 * 802.3 for anything else.
2248 	 */
2249 	if (eh->ether_type == htons(ETHERTYPE_IP) ||
2250 	    eh->ether_type == htons(ETHERTYPE_ARP) ||
2251 	    eh->ether_type == htons(ETHERTYPE_REVARP) ||
2252 	    eh->ether_type == htons(ETHERTYPE_IPV6)) {
2253 		bcopy((char *)&eh->ether_dhost,
2254 		    (char *)&tx_frame.wi_addr1, ETHER_ADDR_LEN);
2255 		if (sc->wi_ptype == WI_PORTTYPE_HOSTAP) {
2256 			tx_frame.wi_tx_ctl = htole16(WI_ENC_TX_MGMT); /* XXX */
2257 			tx_frame.wi_frame_ctl |= htole16(WI_FCTL_FROMDS);
2258 			bcopy((char *)&sc->sc_arpcom.ac_enaddr,
2259 			    (char *)&tx_frame.wi_addr2, ETHER_ADDR_LEN);
2260 			bcopy((char *)&eh->ether_shost,
2261 			    (char *)&tx_frame.wi_addr3, ETHER_ADDR_LEN);
2262 			if (sc->wi_use_wep)
2263 				hostencrypt = 1;
2264 		} else if (sc->wi_ptype == WI_PORTTYPE_BSS && sc->wi_use_wep &&
2265 		    sc->wi_crypto_algorithm != WI_CRYPTO_FIRMWARE_WEP) {
2266 			tx_frame.wi_tx_ctl = htole16(WI_ENC_TX_MGMT); /* XXX */
2267 			tx_frame.wi_frame_ctl |= htole16(WI_FCTL_TODS);
2268 			bcopy((char *)&sc->sc_arpcom.ac_enaddr,
2269 			    (char *)&tx_frame.wi_addr2, ETHER_ADDR_LEN);
2270 			bcopy((char *)&eh->ether_dhost,
2271 			    (char *)&tx_frame.wi_addr3, ETHER_ADDR_LEN);
2272 			hostencrypt = 1;
2273 		} else
2274 			bcopy((char *)&eh->ether_shost,
2275 			    (char *)&tx_frame.wi_addr2, ETHER_ADDR_LEN);
2276 		bcopy((char *)&eh->ether_dhost,
2277 		    (char *)&tx_frame.wi_dst_addr, ETHER_ADDR_LEN);
2278 		bcopy((char *)&eh->ether_shost,
2279 		    (char *)&tx_frame.wi_src_addr, ETHER_ADDR_LEN);
2280 
2281 		tx_frame.wi_dat_len = m0->m_pkthdr.len - WI_SNAPHDR_LEN;
2282 		tx_frame.wi_dat[0] = htons(WI_SNAP_WORD0);
2283 		tx_frame.wi_dat[1] = htons(WI_SNAP_WORD1);
2284 		tx_frame.wi_len = htons(m0->m_pkthdr.len - WI_SNAPHDR_LEN);
2285 		tx_frame.wi_type = eh->ether_type;
2286 
2287 		if (hostencrypt) {
2288 
2289 			/* Do host encryption. */
2290 			tx_frame.wi_frame_ctl |= htole16(WI_FCTL_WEP);
2291 			bcopy(&tx_frame.wi_dat[0], &sc->wi_txbuf[4], 8);
2292 
2293 			m_copydata(m0, sizeof(struct ether_header),
2294 			    m0->m_pkthdr.len - sizeof(struct ether_header),
2295 			    (caddr_t)&sc->wi_txbuf[12]);
2296 
2297 			wi_do_hostencrypt(sc, (caddr_t)&sc->wi_txbuf,
2298 			    tx_frame.wi_dat_len);
2299 
2300 			tx_frame.wi_dat_len += IEEE80211_WEP_IVLEN +
2301 			    IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN;
2302 
2303 			tx_frame.wi_dat_len = htole16(tx_frame.wi_dat_len);
2304 			wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
2305 			    sizeof(struct wi_frame));
2306 			wi_write_data(sc, id, WI_802_11_OFFSET_RAW,
2307 			    (caddr_t)&sc->wi_txbuf,
2308 			    (m0->m_pkthdr.len -
2309 			     sizeof(struct ether_header)) + 18);
2310 		} else {
2311 			m_copydata(m0, sizeof(struct ether_header),
2312 			    m0->m_pkthdr.len - sizeof(struct ether_header),
2313 			    (caddr_t)&sc->wi_txbuf);
2314 
2315 			tx_frame.wi_dat_len = htole16(tx_frame.wi_dat_len);
2316 			wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
2317 			    sizeof(struct wi_frame));
2318 			wi_write_data(sc, id, WI_802_11_OFFSET,
2319 			    (caddr_t)&sc->wi_txbuf,
2320 			    (m0->m_pkthdr.len -
2321 			     sizeof(struct ether_header)) + 2);
2322 		}
2323 	} else {
2324 		tx_frame.wi_dat_len = htole16(m0->m_pkthdr.len);
2325 
2326 		if (sc->wi_ptype == WI_PORTTYPE_HOSTAP && sc->wi_use_wep) {
2327 
2328 			/* Do host encryption. (XXX - not implemented) */
2329 			printf(WI_PRT_FMT
2330 			    ": host encrypt not implemented for 802.3\n",
2331 			    WI_PRT_ARG(sc));
2332 		} else {
2333 			m_copydata(m0, 0, m0->m_pkthdr.len,
2334 			    (caddr_t)&sc->wi_txbuf);
2335 
2336 			wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
2337 			    sizeof(struct wi_frame));
2338 			wi_write_data(sc, id, WI_802_3_OFFSET,
2339 			    (caddr_t)&sc->wi_txbuf, m0->m_pkthdr.len + 2);
2340 		}
2341 	}
2342 
2343 #if NBPFILTER > 0
2344 	/*
2345 	 * If there's a BPF listener, bounce a copy of
2346 	 * this frame to him.
2347 	 */
2348 	if (ifp->if_bpf)
2349 		BPF_MTAP(ifp, m0);
2350 #endif
2351 
2352 	m_freem(m0);
2353 
2354 	ifp->if_flags |= IFF_OACTIVE;
2355 
2356 	/*
2357 	 * Set a timeout in case the chip goes out to lunch.
2358 	 */
2359 	ifp->if_timer = 5;
2360 
2361 	if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id, 0, 0))
2362 		printf(WI_PRT_FMT ": wi_start: xmit failed\n", WI_PRT_ARG(sc));
2363 
2364 	return;
2365 }
2366 
2367 STATIC int
wi_mgmt_xmit(sc,data,len)2368 wi_mgmt_xmit(sc, data, len)
2369 	struct wi_softc		*sc;
2370 	caddr_t			data;
2371 	int			len;
2372 {
2373 	struct wi_frame		tx_frame;
2374 	int			id;
2375 	struct wi_80211_hdr	*hdr;
2376 	caddr_t			dptr;
2377 
2378 	if (!(sc->wi_flags & WI_FLAGS_ATTACHED))
2379 		return(ENODEV);
2380 
2381 	hdr = (struct wi_80211_hdr *)data;
2382 	dptr = data + sizeof(struct wi_80211_hdr);
2383 
2384 	bzero((char *)&tx_frame, sizeof(tx_frame));
2385 	id = sc->wi_tx_mgmt_id;
2386 
2387 	bcopy((char *)hdr, (char *)&tx_frame.wi_frame_ctl,
2388 	   sizeof(struct wi_80211_hdr));
2389 
2390 	tx_frame.wi_tx_ctl = htole16(WI_ENC_TX_MGMT);
2391 	tx_frame.wi_dat_len = len - sizeof(struct wi_80211_hdr);
2392 	tx_frame.wi_len = htole16(tx_frame.wi_dat_len);
2393 
2394 	tx_frame.wi_dat_len = htole16(tx_frame.wi_dat_len);
2395 	wi_write_data(sc, id, 0, (caddr_t)&tx_frame, sizeof(struct wi_frame));
2396 	wi_write_data(sc, id, WI_802_11_OFFSET_RAW, dptr,
2397 	    (len - sizeof(struct wi_80211_hdr)) + 2);
2398 
2399 	if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id, 0, 0)) {
2400 		printf(WI_PRT_FMT ": wi_mgmt_xmit: xmit failed\n",
2401 		    WI_PRT_ARG(sc));
2402 		return(EIO);
2403 	}
2404 
2405 	return(0);
2406 }
2407 
2408 void
wi_stop(sc)2409 wi_stop(sc)
2410 	struct wi_softc		*sc;
2411 {
2412 	struct ifnet		*ifp;
2413 
2414 	wihap_shutdown(sc);
2415 
2416 	if (!(sc->wi_flags & WI_FLAGS_ATTACHED))
2417 		return;
2418 
2419 	DPRINTF(WID_STOP, ("wi_stop: sc %p\n", sc));
2420 
2421 	timeout_del(&sc->sc_timo);
2422 
2423 	ifp = &sc->sc_arpcom.ac_if;
2424 
2425 	wi_intr_enable(sc, 0);
2426 	wi_cmd(sc, WI_CMD_DISABLE|sc->wi_portnum, 0, 0, 0);
2427 
2428 	ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE);
2429 	ifp->if_timer = 0;
2430 
2431 	return;
2432 }
2433 
2434 
2435 void
wi_watchdog(ifp)2436 wi_watchdog(ifp)
2437 	struct ifnet		*ifp;
2438 {
2439 	struct wi_softc		*sc;
2440 
2441 	sc = ifp->if_softc;
2442 
2443 	printf(WI_PRT_FMT ": device timeout\n", WI_PRT_ARG(sc));
2444 
2445 	wi_cor_reset(sc);
2446 	wi_init(sc);
2447 
2448 	ifp->if_oerrors++;
2449 
2450 	return;
2451 }
2452 
2453 void
wi_detach(sc)2454 wi_detach(sc)
2455 	struct wi_softc *sc;
2456 {
2457 	struct ifnet *ifp;
2458 	ifp = &sc->sc_arpcom.ac_if;
2459 
2460 	if (ifp->if_flags & IFF_RUNNING)
2461 		wi_stop(sc);
2462 
2463 	if (sc->wi_flags & WI_FLAGS_ATTACHED) {
2464 		sc->wi_flags &= ~WI_FLAGS_ATTACHED;
2465 		shutdownhook_disestablish(sc->sc_sdhook);
2466 	}
2467 }
2468 
2469 STATIC void
wi_shutdown(arg)2470 wi_shutdown(arg)
2471 	void			*arg;
2472 {
2473 	struct wi_softc		*sc;
2474 
2475 	sc = arg;
2476 	wi_stop(sc);
2477 
2478 	return;
2479 }
2480 
2481 STATIC void
wi_get_id(sc)2482 wi_get_id(sc)
2483 	struct wi_softc *sc;
2484 {
2485 	struct wi_ltv_ver		ver;
2486 	const struct wi_card_ident	*id;
2487 	u_int16_t			pri_fw_ver[3];
2488 	const char			*card_name;
2489 	u_int16_t			card_id;
2490 
2491 	/* get chip identity */
2492 	bzero(&ver, sizeof(ver));
2493 	ver.wi_type = WI_RID_CARD_ID;
2494 	ver.wi_len = 5;
2495 	wi_read_record(sc, (struct wi_ltv_gen *)&ver);
2496 	card_id = letoh16(ver.wi_ver[0]);
2497 	for (id = wi_card_ident; id->firm_type != WI_NOTYPE; id++) {
2498 		if (card_id == id->card_id)
2499 			break;
2500 	}
2501 	if (id->firm_type != WI_NOTYPE) {
2502 		sc->sc_firmware_type = id->firm_type;
2503 		card_name = id->card_name;
2504 	} else if (ver.wi_ver[0] & htole16(0x8000)) {
2505 		sc->sc_firmware_type = WI_INTERSIL;
2506 		card_name = "Unknown PRISM2 chip";
2507 	} else {
2508 		sc->sc_firmware_type = WI_LUCENT;
2509 	}
2510 
2511 	/* get primary firmware version (XXX - how to do Lucent?) */
2512 	if (sc->sc_firmware_type != WI_LUCENT) {
2513 		bzero(&ver, sizeof(ver));
2514 		ver.wi_type = WI_RID_PRI_IDENTITY;
2515 		ver.wi_len = 5;
2516 		wi_read_record(sc, (struct wi_ltv_gen *)&ver);
2517 		pri_fw_ver[0] = letoh16(ver.wi_ver[2]);
2518 		pri_fw_ver[1] = letoh16(ver.wi_ver[3]);
2519 		pri_fw_ver[2] = letoh16(ver.wi_ver[1]);
2520 	}
2521 
2522 	/* get station firmware version */
2523 	bzero(&ver, sizeof(ver));
2524 	ver.wi_type = WI_RID_STA_IDENTITY;
2525 	ver.wi_len = 5;
2526 	wi_read_record(sc, (struct wi_ltv_gen *)&ver);
2527 	ver.wi_ver[1] = letoh16(ver.wi_ver[1]);
2528 	ver.wi_ver[2] = letoh16(ver.wi_ver[2]);
2529 	ver.wi_ver[3] = letoh16(ver.wi_ver[3]);
2530 	sc->sc_sta_firmware_ver = ver.wi_ver[2] * 10000 +
2531 	    ver.wi_ver[3] * 100 + ver.wi_ver[1];
2532 
2533 	if (sc->sc_firmware_type == WI_INTERSIL &&
2534 	    (sc->sc_sta_firmware_ver == 10102 || sc->sc_sta_firmware_ver == 20102)) {
2535 		struct wi_ltv_str sver;
2536 		char *p;
2537 
2538 		bzero(&sver, sizeof(sver));
2539 		sver.wi_type = WI_RID_SYMBOL_IDENTITY;
2540 		sver.wi_len = 7;
2541 		/* value should be something like "V2.00-11" */
2542 		if (wi_read_record(sc, (struct wi_ltv_gen *)&sver) == 0 &&
2543 		    *(p = (char *)sver.wi_str) >= 'A' &&
2544 		    p[2] == '.' && p[5] == '-' && p[8] == '\0') {
2545 			sc->sc_firmware_type = WI_SYMBOL;
2546 			sc->sc_sta_firmware_ver = (p[1] - '0') * 10000 +
2547 			    (p[3] - '0') * 1000 + (p[4] - '0') * 100 +
2548 			    (p[6] - '0') * 10 + (p[7] - '0');
2549 		}
2550 	}
2551 
2552 	if (sc->sc_firmware_type == WI_LUCENT) {
2553 		printf("\n%s: Firmware %d.%02d variant %d, ", WI_PRT_ARG(sc),
2554 		    ver.wi_ver[2], ver.wi_ver[3], ver.wi_ver[1]);
2555 	} else {
2556 		printf("\n%s: %s%s, Firmware %d.%d.%d (primary), %d.%d.%d (station), ",
2557 		    WI_PRT_ARG(sc),
2558 		    sc->sc_firmware_type == WI_SYMBOL ? "Symbol " : "",
2559 		    card_name, pri_fw_ver[0], pri_fw_ver[1], pri_fw_ver[2],
2560 		    sc->sc_sta_firmware_ver / 10000,
2561 		    (sc->sc_sta_firmware_ver % 10000) / 100,
2562 		    sc->sc_sta_firmware_ver % 100);
2563 	}
2564 }
2565 
2566 STATIC int
wi_sync_media(sc,ptype,txrate)2567 wi_sync_media(sc, ptype, txrate)
2568 	struct wi_softc *sc;
2569 	int ptype;
2570 	int txrate;
2571 {
2572 	int media = sc->sc_media.ifm_cur->ifm_media;
2573 	int options = IFM_OPTIONS(media);
2574 	int subtype;
2575 
2576 	switch (txrate) {
2577 	case 1:
2578 		subtype = IFM_IEEE80211_DS1;
2579 		break;
2580 	case 2:
2581 		subtype = IFM_IEEE80211_DS2;
2582 		break;
2583 	case 3:
2584 		subtype = IFM_AUTO;
2585 		break;
2586 	case 5:
2587 		subtype = IFM_IEEE80211_DS5;
2588 		break;
2589 	case 11:
2590 		subtype = IFM_IEEE80211_DS11;
2591 		break;
2592 	default:
2593 		subtype = IFM_MANUAL;		/* Unable to represent */
2594 		break;
2595 	}
2596 
2597 	options &= ~IFM_OMASK;
2598 	switch (ptype) {
2599 	case WI_PORTTYPE_BSS:
2600 		/* default port type */
2601 		break;
2602 	case WI_PORTTYPE_ADHOC:
2603 		options |= IFM_IEEE80211_ADHOC;
2604 		break;
2605 	case WI_PORTTYPE_HOSTAP:
2606 		options |= IFM_IEEE80211_HOSTAP;
2607 		break;
2608 	case WI_PORTTYPE_IBSS:
2609 		if (sc->wi_create_ibss)
2610 			options |= IFM_IEEE80211_IBSSMASTER;
2611 		else
2612 			options |= IFM_IEEE80211_IBSS;
2613 		break;
2614 	default:
2615 		subtype = IFM_MANUAL;		/* Unable to represent */
2616 		break;
2617 	}
2618 	media = IFM_MAKEWORD(IFM_TYPE(media), subtype, options,
2619 	IFM_INST(media));
2620 	if (ifmedia_match(&sc->sc_media, media, sc->sc_media.ifm_mask) == NULL)
2621 		return (EINVAL);
2622 	ifmedia_set(&sc->sc_media, media);
2623 	sc->wi_ptype = ptype;
2624 	sc->wi_tx_rate = txrate;
2625 	return (0);
2626 }
2627 
2628 STATIC int
wi_media_change(ifp)2629 wi_media_change(ifp)
2630 	struct ifnet *ifp;
2631 {
2632 	struct wi_softc *sc = ifp->if_softc;
2633 	int otype = sc->wi_ptype;
2634 	int orate = sc->wi_tx_rate;
2635 	int ocreate_ibss = sc->wi_create_ibss;
2636 
2637 	if ((sc->sc_media.ifm_cur->ifm_media & IFM_IEEE80211_HOSTAP) &&
2638 	    sc->sc_firmware_type != WI_INTERSIL)
2639 		return (EINVAL);
2640 
2641 	sc->wi_create_ibss = 0;
2642 
2643 	switch (sc->sc_media.ifm_cur->ifm_media & IFM_OMASK) {
2644 	case 0:
2645 		sc->wi_ptype = WI_PORTTYPE_BSS;
2646 		break;
2647 	case IFM_IEEE80211_ADHOC:
2648 		sc->wi_ptype = WI_PORTTYPE_ADHOC;
2649 		break;
2650 	case IFM_IEEE80211_HOSTAP:
2651 		sc->wi_ptype = WI_PORTTYPE_HOSTAP;
2652 		break;
2653 	case IFM_IEEE80211_IBSSMASTER:
2654 	case IFM_IEEE80211_IBSSMASTER|IFM_IEEE80211_IBSS:
2655 		if (!(sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS))
2656 			return (EINVAL);
2657 		sc->wi_create_ibss = 1;
2658 		/* FALLTHROUGH */
2659 	case IFM_IEEE80211_IBSS:
2660 		sc->wi_ptype = WI_PORTTYPE_IBSS;
2661 		break;
2662 	default:
2663 		/* Invalid combination. */
2664 		return (EINVAL);
2665 	}
2666 
2667 	switch (IFM_SUBTYPE(sc->sc_media.ifm_cur->ifm_media)) {
2668 	case IFM_IEEE80211_DS1:
2669 		sc->wi_tx_rate = 1;
2670 		break;
2671 	case IFM_IEEE80211_DS2:
2672 		sc->wi_tx_rate = 2;
2673 		break;
2674 	case IFM_AUTO:
2675 		sc->wi_tx_rate = 3;
2676 		break;
2677 	case IFM_IEEE80211_DS5:
2678 		sc->wi_tx_rate = 5;
2679 		break;
2680 	case IFM_IEEE80211_DS11:
2681 		sc->wi_tx_rate = 11;
2682 		break;
2683 	}
2684 
2685 	if (sc->sc_arpcom.ac_if.if_flags & IFF_UP) {
2686 		if (otype != sc->wi_ptype || orate != sc->wi_tx_rate ||
2687 		    ocreate_ibss != sc->wi_create_ibss)
2688 			wi_init(sc);
2689 	}
2690 
2691 	ifp->if_baudrate = ifmedia_baudrate(sc->sc_media.ifm_cur->ifm_media);
2692 
2693 	return (0);
2694 }
2695 
2696 STATIC void
wi_media_status(ifp,imr)2697 wi_media_status(ifp, imr)
2698 	struct ifnet *ifp;
2699 	struct ifmediareq *imr;
2700 {
2701 	struct wi_softc *sc = ifp->if_softc;
2702 	struct wi_req wreq;
2703 
2704 	if (!(sc->sc_arpcom.ac_if.if_flags & IFF_UP)) {
2705 		imr->ifm_active = IFM_IEEE80211|IFM_NONE;
2706 		imr->ifm_status = 0;
2707 		return;
2708 	}
2709 
2710 	if (sc->wi_tx_rate == 3) {
2711 		imr->ifm_active = IFM_IEEE80211|IFM_AUTO;
2712 
2713 		wreq.wi_type = WI_RID_CUR_TX_RATE;
2714 		wreq.wi_len = WI_MAX_DATALEN;
2715 		if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq) == 0) {
2716 			switch (letoh16(wreq.wi_val[0])) {
2717 			case 1:
2718 				imr->ifm_active |= IFM_IEEE80211_DS1;
2719 				break;
2720 			case 2:
2721 				imr->ifm_active |= IFM_IEEE80211_DS2;
2722 				break;
2723 			case 6:
2724 				imr->ifm_active |= IFM_IEEE80211_DS5;
2725 				break;
2726 			case 11:
2727 				imr->ifm_active |= IFM_IEEE80211_DS11;
2728 				break;
2729 			}
2730 		}
2731 	} else {
2732 		imr->ifm_active = sc->sc_media.ifm_cur->ifm_media;
2733 	}
2734 
2735 	imr->ifm_status = IFM_AVALID;
2736 	switch (sc->wi_ptype) {
2737 	case WI_PORTTYPE_ADHOC:
2738 	case WI_PORTTYPE_IBSS:
2739 		/*
2740 		 * XXX: It would be nice if we could give some actually
2741 		 * useful status like whether we joined another IBSS or
2742 		 * created one ourselves.
2743 		 */
2744 		/* FALLTHROUGH */
2745 	case WI_PORTTYPE_HOSTAP:
2746 		imr->ifm_status |= IFM_ACTIVE;
2747 		break;
2748 	default:
2749 		wreq.wi_type = WI_RID_COMMQUAL;
2750 		wreq.wi_len = WI_MAX_DATALEN;
2751 		if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq) == 0 &&
2752 		    letoh16(wreq.wi_val[0]) != 0)
2753 			imr->ifm_status |= IFM_ACTIVE;
2754 	}
2755 }
2756 
2757 STATIC int
wi_set_nwkey(sc,nwkey)2758 wi_set_nwkey(sc, nwkey)
2759 	struct wi_softc *sc;
2760 	struct ieee80211_nwkey *nwkey;
2761 {
2762 	int i, len, error;
2763 	struct wi_req wreq;
2764 	struct wi_ltv_keys *wk = (struct wi_ltv_keys *)&wreq;
2765 
2766 	if (!(sc->wi_flags & WI_FLAGS_HAS_WEP))
2767 		return ENODEV;
2768 	if (nwkey->i_defkid <= 0 || nwkey->i_defkid > IEEE80211_WEP_NKID)
2769 		return EINVAL;
2770 	memcpy(wk, &sc->wi_keys, sizeof(*wk));
2771 	for (i = 0; i < IEEE80211_WEP_NKID; i++) {
2772 		if (nwkey->i_key[i].i_keydat == NULL)
2773 			continue;
2774 		len = nwkey->i_key[i].i_keylen;
2775 		if (len > sizeof(wk->wi_keys[i].wi_keydat))
2776 			return EINVAL;
2777 		error = copyin(nwkey->i_key[i].i_keydat,
2778 		    wk->wi_keys[i].wi_keydat, len);
2779 		if (error)
2780 			return error;
2781 		wk->wi_keys[i].wi_keylen = htole16(len);
2782 	}
2783 
2784 	wk->wi_len = (sizeof(*wk) / 2) + 1;
2785 	wk->wi_type = WI_RID_DEFLT_CRYPT_KEYS;
2786 	if (sc->sc_arpcom.ac_if.if_flags & IFF_UP) {
2787 		error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
2788 		if (error)
2789 			return error;
2790 	}
2791 	if ((error = wi_setdef(sc, &wreq)))
2792 		return (error);
2793 
2794 	wreq.wi_len = 2;
2795 	wreq.wi_type = WI_RID_TX_CRYPT_KEY;
2796 	wreq.wi_val[0] = htole16(nwkey->i_defkid - 1);
2797 	if (sc->sc_arpcom.ac_if.if_flags & IFF_UP) {
2798 		error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
2799 		if (error)
2800 			return error;
2801 	}
2802 	if ((error = wi_setdef(sc, &wreq)))
2803 		return (error);
2804 
2805 	wreq.wi_type = WI_RID_ENCRYPTION;
2806 	wreq.wi_val[0] = htole16(nwkey->i_wepon);
2807 	if (sc->sc_arpcom.ac_if.if_flags & IFF_UP) {
2808 		error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
2809 		if (error)
2810 			return error;
2811 	}
2812 	if ((error = wi_setdef(sc, &wreq)))
2813 		return (error);
2814 
2815 	if (sc->sc_arpcom.ac_if.if_flags & IFF_UP)
2816 		wi_init(sc);
2817 	return 0;
2818 }
2819 
2820 STATIC int
wi_get_nwkey(sc,nwkey)2821 wi_get_nwkey(sc, nwkey)
2822 	struct wi_softc *sc;
2823 	struct ieee80211_nwkey *nwkey;
2824 {
2825 	int i, len, error;
2826 	struct wi_ltv_keys *wk = &sc->wi_keys;
2827 
2828 	if (!(sc->wi_flags & WI_FLAGS_HAS_WEP))
2829 		return ENODEV;
2830 	nwkey->i_wepon = sc->wi_use_wep;
2831 	nwkey->i_defkid = sc->wi_tx_key + 1;
2832 
2833 	/* do not show any keys to non-root user */
2834 	error = suser(curproc, 0);
2835 	for (i = 0; i < IEEE80211_WEP_NKID; i++) {
2836 		if (nwkey->i_key[i].i_keydat == NULL)
2837 			continue;
2838 		/* error holds results of suser() for the first time */
2839 		if (error)
2840 			return error;
2841 		len = letoh16(wk->wi_keys[i].wi_keylen);
2842 		if (nwkey->i_key[i].i_keylen < len)
2843 			return ENOSPC;
2844 		nwkey->i_key[i].i_keylen = len;
2845 		error = copyout(wk->wi_keys[i].wi_keydat,
2846 		    nwkey->i_key[i].i_keydat, len);
2847 		if (error)
2848 			return error;
2849 	}
2850 	return 0;
2851 }
2852 
2853 STATIC int
wi_set_pm(struct wi_softc * sc,struct ieee80211_power * power)2854 wi_set_pm(struct wi_softc *sc, struct ieee80211_power *power)
2855 {
2856 
2857 	sc->wi_pm_enabled = power->i_enabled;
2858 	sc->wi_max_sleep = power->i_maxsleep;
2859 
2860 	if (sc->sc_arpcom.ac_if.if_flags & IFF_UP)
2861 		wi_init(sc);
2862 
2863 	return (0);
2864 }
2865 
2866 STATIC int
wi_get_pm(struct wi_softc * sc,struct ieee80211_power * power)2867 wi_get_pm(struct wi_softc *sc, struct ieee80211_power *power)
2868 {
2869 
2870 	power->i_enabled = sc->wi_pm_enabled;
2871 	power->i_maxsleep = sc->wi_max_sleep;
2872 
2873 	return (0);
2874 }
2875 
2876 STATIC int
wi_set_ssid(ws,id,len)2877 wi_set_ssid(ws, id, len)
2878 	struct ieee80211_nwid *ws;
2879 	u_int8_t *id;
2880 	int len;
2881 {
2882 
2883 	if (len > IEEE80211_NWID_LEN)
2884 		return (EINVAL);
2885 	ws->i_len = len;
2886 	memcpy(ws->i_nwid, id, len);
2887 	return (0);
2888 }
2889 
2890 STATIC int
wi_get_debug(sc,wreq)2891 wi_get_debug(sc, wreq)
2892 	struct wi_softc		*sc;
2893 	struct wi_req		*wreq;
2894 {
2895 	int			error = 0;
2896 
2897 	wreq->wi_len = 1;
2898 
2899 	switch (wreq->wi_type) {
2900 	case WI_DEBUG_SLEEP:
2901 		wreq->wi_len++;
2902 		wreq->wi_val[0] = htole16(sc->wi_debug.wi_sleep);
2903 		break;
2904 	case WI_DEBUG_DELAYSUPP:
2905 		wreq->wi_len++;
2906 		wreq->wi_val[0] = htole16(sc->wi_debug.wi_delaysupp);
2907 		break;
2908 	case WI_DEBUG_TXSUPP:
2909 		wreq->wi_len++;
2910 		wreq->wi_val[0] = htole16(sc->wi_debug.wi_txsupp);
2911 		break;
2912 	case WI_DEBUG_MONITOR:
2913 		wreq->wi_len++;
2914 		wreq->wi_val[0] = htole16(sc->wi_debug.wi_monitor);
2915 		break;
2916 	case WI_DEBUG_LEDTEST:
2917 		wreq->wi_len += 3;
2918 		wreq->wi_val[0] = htole16(sc->wi_debug.wi_ledtest);
2919 		wreq->wi_val[1] = htole16(sc->wi_debug.wi_ledtest_param0);
2920 		wreq->wi_val[2] = htole16(sc->wi_debug.wi_ledtest_param1);
2921 		break;
2922 	case WI_DEBUG_CONTTX:
2923 		wreq->wi_len += 2;
2924 		wreq->wi_val[0] = htole16(sc->wi_debug.wi_conttx);
2925 		wreq->wi_val[1] = htole16(sc->wi_debug.wi_conttx_param0);
2926 		break;
2927 	case WI_DEBUG_CONTRX:
2928 		wreq->wi_len++;
2929 		wreq->wi_val[0] = htole16(sc->wi_debug.wi_contrx);
2930 		break;
2931 	case WI_DEBUG_SIGSTATE:
2932 		wreq->wi_len += 2;
2933 		wreq->wi_val[0] = htole16(sc->wi_debug.wi_sigstate);
2934 		wreq->wi_val[1] = htole16(sc->wi_debug.wi_sigstate_param0);
2935 		break;
2936 	case WI_DEBUG_CONFBITS:
2937 		wreq->wi_len += 2;
2938 		wreq->wi_val[0] = htole16(sc->wi_debug.wi_confbits);
2939 		wreq->wi_val[1] = htole16(sc->wi_debug.wi_confbits_param0);
2940 		break;
2941 	default:
2942 		error = EIO;
2943 		break;
2944 	}
2945 
2946 	return (error);
2947 }
2948 
2949 STATIC int
wi_set_debug(sc,wreq)2950 wi_set_debug(sc, wreq)
2951 	struct wi_softc		*sc;
2952 	struct wi_req		*wreq;
2953 {
2954 	int				error = 0;
2955 	u_int16_t			cmd, param0 = 0, param1 = 0;
2956 
2957 	switch (wreq->wi_type) {
2958 	case WI_DEBUG_RESET:
2959 	case WI_DEBUG_INIT:
2960 	case WI_DEBUG_CALENABLE:
2961 		break;
2962 	case WI_DEBUG_SLEEP:
2963 		sc->wi_debug.wi_sleep = 1;
2964 		break;
2965 	case WI_DEBUG_WAKE:
2966 		sc->wi_debug.wi_sleep = 0;
2967 		break;
2968 	case WI_DEBUG_CHAN:
2969 		param0 = letoh16(wreq->wi_val[0]);
2970 		break;
2971 	case WI_DEBUG_DELAYSUPP:
2972 		sc->wi_debug.wi_delaysupp = 1;
2973 		break;
2974 	case WI_DEBUG_TXSUPP:
2975 		sc->wi_debug.wi_txsupp = 1;
2976 		break;
2977 	case WI_DEBUG_MONITOR:
2978 		sc->wi_debug.wi_monitor = 1;
2979 		break;
2980 	case WI_DEBUG_LEDTEST:
2981 		param0 = letoh16(wreq->wi_val[0]);
2982 		param1 = letoh16(wreq->wi_val[1]);
2983 		sc->wi_debug.wi_ledtest = 1;
2984 		sc->wi_debug.wi_ledtest_param0 = param0;
2985 		sc->wi_debug.wi_ledtest_param1 = param1;
2986 		break;
2987 	case WI_DEBUG_CONTTX:
2988 		param0 = letoh16(wreq->wi_val[0]);
2989 		sc->wi_debug.wi_conttx = 1;
2990 		sc->wi_debug.wi_conttx_param0 = param0;
2991 		break;
2992 	case WI_DEBUG_STOPTEST:
2993 		sc->wi_debug.wi_delaysupp = 0;
2994 		sc->wi_debug.wi_txsupp = 0;
2995 		sc->wi_debug.wi_monitor = 0;
2996 		sc->wi_debug.wi_ledtest = 0;
2997 		sc->wi_debug.wi_ledtest_param0 = 0;
2998 		sc->wi_debug.wi_ledtest_param1 = 0;
2999 		sc->wi_debug.wi_conttx = 0;
3000 		sc->wi_debug.wi_conttx_param0 = 0;
3001 		sc->wi_debug.wi_contrx = 0;
3002 		sc->wi_debug.wi_sigstate = 0;
3003 		sc->wi_debug.wi_sigstate_param0 = 0;
3004 		break;
3005 	case WI_DEBUG_CONTRX:
3006 		sc->wi_debug.wi_contrx = 1;
3007 		break;
3008 	case WI_DEBUG_SIGSTATE:
3009 		param0 = letoh16(wreq->wi_val[0]);
3010 		sc->wi_debug.wi_sigstate = 1;
3011 		sc->wi_debug.wi_sigstate_param0 = param0;
3012 		break;
3013 	case WI_DEBUG_CONFBITS:
3014 		param0 = letoh16(wreq->wi_val[0]);
3015 		param1 = letoh16(wreq->wi_val[1]);
3016 		sc->wi_debug.wi_confbits = param0;
3017 		sc->wi_debug.wi_confbits_param0 = param1;
3018 		break;
3019 	default:
3020 		error = EIO;
3021 		break;
3022 	}
3023 
3024 	if (error)
3025 		return (error);
3026 
3027 	cmd = WI_CMD_DEBUG | (wreq->wi_type << 8);
3028 	error = wi_cmd(sc, cmd, param0, param1, 0);
3029 
3030 	return (error);
3031 }
3032