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