if_wi.c revision 149007
1/*	$NetBSD: wi.c,v 1.109 2003/01/09 08:52:19 dyoung 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
35/*
36 * Lucent WaveLAN/IEEE 802.11 PCMCIA driver.
37 *
38 * Original FreeBSD driver written by Bill Paul <wpaul@ctr.columbia.edu>
39 * Electrical Engineering Department
40 * Columbia University, New York City
41 */
42
43/*
44 * The WaveLAN/IEEE adapter is the second generation of the WaveLAN
45 * from Lucent. Unlike the older cards, the new ones are programmed
46 * entirely via a firmware-driven controller called the Hermes.
47 * Unfortunately, Lucent will not release the Hermes programming manual
48 * without an NDA (if at all). What they do release is an API library
49 * called the HCF (Hardware Control Functions) which is supposed to
50 * do the device-specific operations of a device driver for you. The
51 * publically available version of the HCF library (the 'HCF Light') is
52 * a) extremely gross, b) lacks certain features, particularly support
53 * for 802.11 frames, and c) is contaminated by the GNU Public License.
54 *
55 * This driver does not use the HCF or HCF Light at all. Instead, it
56 * programs the Hermes controller directly, using information gleaned
57 * from the HCF Light code and corresponding documentation.
58 *
59 * This driver supports the ISA, PCMCIA and PCI versions of the Lucent
60 * WaveLan cards (based on the Hermes chipset), as well as the newer
61 * Prism 2 chipsets with firmware from Intersil and Symbol.
62 */
63
64#include <sys/cdefs.h>
65__FBSDID("$FreeBSD: head/sys/dev/wi/if_wi.c 149007 2005-08-13 00:04:42Z sam $");
66
67#define WI_HERMES_AUTOINC_WAR	/* Work around data write autoinc bug. */
68#define WI_HERMES_STATS_WAR	/* Work around stats counter bug. */
69
70#define	NBPFILTER	1
71
72#include <sys/param.h>
73#include <sys/systm.h>
74#if __FreeBSD_version >= 500033
75#include <sys/endian.h>
76#endif
77#include <sys/sockio.h>
78#include <sys/mbuf.h>
79#include <sys/proc.h>
80#include <sys/kernel.h>
81#include <sys/socket.h>
82#include <sys/module.h>
83#include <sys/bus.h>
84#include <sys/random.h>
85#include <sys/syslog.h>
86#include <sys/sysctl.h>
87
88#include <machine/bus.h>
89#include <machine/resource.h>
90#include <machine/clock.h>
91#include <machine/atomic.h>
92#include <sys/rman.h>
93
94#include <net/if.h>
95#include <net/if_arp.h>
96#include <net/ethernet.h>
97#include <net/if_dl.h>
98#include <net/if_media.h>
99#include <net/if_types.h>
100
101#include <net80211/ieee80211_var.h>
102#include <net80211/ieee80211_ioctl.h>
103#include <net80211/ieee80211_radiotap.h>
104
105#include <netinet/in.h>
106#include <netinet/in_systm.h>
107#include <netinet/in_var.h>
108#include <netinet/ip.h>
109#include <netinet/if_ether.h>
110
111#include <net/bpf.h>
112
113#include <dev/wi/if_wavelan_ieee.h>
114#include <dev/wi/if_wireg.h>
115#include <dev/wi/if_wivar.h>
116
117static void wi_start(struct ifnet *);
118static int  wi_reset(struct wi_softc *);
119static void wi_watchdog(struct ifnet *);
120static int  wi_ioctl(struct ifnet *, u_long, caddr_t);
121static int  wi_media_change(struct ifnet *);
122static void wi_media_status(struct ifnet *, struct ifmediareq *);
123
124static void wi_rx_intr(struct wi_softc *);
125static void wi_tx_intr(struct wi_softc *);
126static void wi_tx_ex_intr(struct wi_softc *);
127static void wi_info_intr(struct wi_softc *);
128
129static int  wi_get_cfg(struct ifnet *, u_long, caddr_t);
130static int  wi_set_cfg(struct ifnet *, u_long, caddr_t);
131static int  wi_write_txrate(struct wi_softc *);
132static int  wi_write_wep(struct wi_softc *);
133static int  wi_write_multi(struct wi_softc *);
134static int  wi_alloc_fid(struct wi_softc *, int, int *);
135static void wi_read_nicid(struct wi_softc *);
136static int  wi_write_ssid(struct wi_softc *, int, u_int8_t *, int);
137
138static int  wi_cmd(struct wi_softc *, int, int, int, int);
139static int  wi_seek_bap(struct wi_softc *, int, int);
140static int  wi_read_bap(struct wi_softc *, int, int, void *, int);
141static int  wi_write_bap(struct wi_softc *, int, int, void *, int);
142static int  wi_mwrite_bap(struct wi_softc *, int, int, struct mbuf *, int);
143static int  wi_read_rid(struct wi_softc *, int, void *, int *);
144static int  wi_write_rid(struct wi_softc *, int, void *, int);
145
146static int  wi_newstate(struct ieee80211com *, enum ieee80211_state, int);
147
148static int  wi_scan_ap(struct wi_softc *, u_int16_t, u_int16_t);
149static void wi_scan_result(struct wi_softc *, int, int);
150
151static void wi_dump_pkt(struct wi_frame *, struct ieee80211_node *, int rssi);
152
153static int wi_get_debug(struct wi_softc *, struct wi_req *);
154static int wi_set_debug(struct wi_softc *, struct wi_req *);
155
156#if __FreeBSD_version >= 500000
157/* support to download firmware for symbol CF card */
158static int wi_symbol_write_firm(struct wi_softc *, const void *, int,
159		const void *, int);
160static int wi_symbol_set_hcr(struct wi_softc *, int);
161#endif
162
163static __inline int
164wi_write_val(struct wi_softc *sc, int rid, u_int16_t val)
165{
166
167	val = htole16(val);
168	return wi_write_rid(sc, rid, &val, sizeof(val));
169}
170
171SYSCTL_NODE(_hw, OID_AUTO, wi, CTLFLAG_RD, 0, "Wireless driver parameters");
172
173static	struct timeval lasttxerror;	/* time of last tx error msg */
174static	int curtxeps;			/* current tx error msgs/sec */
175static	int wi_txerate = 0;		/* tx error rate: max msgs/sec */
176SYSCTL_INT(_hw_wi, OID_AUTO, txerate, CTLFLAG_RW, &wi_txerate,
177	    0, "max tx error msgs/sec; 0 to disable msgs");
178
179#define	WI_DEBUG
180#ifdef WI_DEBUG
181static	int wi_debug = 0;
182SYSCTL_INT(_hw_wi, OID_AUTO, debug, CTLFLAG_RW, &wi_debug,
183	    0, "control debugging printfs");
184
185#define	DPRINTF(X)	if (wi_debug) printf X
186#define	DPRINTF2(X)	if (wi_debug > 1) printf X
187#define	IFF_DUMPPKTS(_ifp) \
188	(((_ifp)->if_flags & (IFF_DEBUG|IFF_LINK2)) == (IFF_DEBUG|IFF_LINK2))
189#else
190#define	DPRINTF(X)
191#define	DPRINTF2(X)
192#define	IFF_DUMPPKTS(_ifp)	0
193#endif
194
195#define WI_INTRS	(WI_EV_RX | WI_EV_ALLOC | WI_EV_INFO)
196
197struct wi_card_ident wi_card_ident[] = {
198	/* CARD_ID			CARD_NAME		FIRM_TYPE */
199	{ WI_NIC_LUCENT_ID,		WI_NIC_LUCENT_STR,	WI_LUCENT },
200	{ WI_NIC_SONY_ID,		WI_NIC_SONY_STR,	WI_LUCENT },
201	{ WI_NIC_LUCENT_EMB_ID,		WI_NIC_LUCENT_EMB_STR,	WI_LUCENT },
202	{ WI_NIC_EVB2_ID,		WI_NIC_EVB2_STR,	WI_INTERSIL },
203	{ WI_NIC_HWB3763_ID,		WI_NIC_HWB3763_STR,	WI_INTERSIL },
204	{ WI_NIC_HWB3163_ID,		WI_NIC_HWB3163_STR,	WI_INTERSIL },
205	{ WI_NIC_HWB3163B_ID,		WI_NIC_HWB3163B_STR,	WI_INTERSIL },
206	{ WI_NIC_EVB3_ID,		WI_NIC_EVB3_STR,	WI_INTERSIL },
207	{ WI_NIC_HWB1153_ID,		WI_NIC_HWB1153_STR,	WI_INTERSIL },
208	{ WI_NIC_P2_SST_ID,		WI_NIC_P2_SST_STR,	WI_INTERSIL },
209	{ WI_NIC_EVB2_SST_ID,		WI_NIC_EVB2_SST_STR,	WI_INTERSIL },
210	{ WI_NIC_3842_EVA_ID,		WI_NIC_3842_EVA_STR,	WI_INTERSIL },
211	{ WI_NIC_3842_PCMCIA_AMD_ID,	WI_NIC_3842_PCMCIA_STR,	WI_INTERSIL },
212	{ WI_NIC_3842_PCMCIA_SST_ID,	WI_NIC_3842_PCMCIA_STR,	WI_INTERSIL },
213	{ WI_NIC_3842_PCMCIA_ATL_ID,	WI_NIC_3842_PCMCIA_STR,	WI_INTERSIL },
214	{ WI_NIC_3842_PCMCIA_ATS_ID,	WI_NIC_3842_PCMCIA_STR,	WI_INTERSIL },
215	{ WI_NIC_3842_MINI_AMD_ID,	WI_NIC_3842_MINI_STR,	WI_INTERSIL },
216	{ WI_NIC_3842_MINI_SST_ID,	WI_NIC_3842_MINI_STR,	WI_INTERSIL },
217	{ WI_NIC_3842_MINI_ATL_ID,	WI_NIC_3842_MINI_STR,	WI_INTERSIL },
218	{ WI_NIC_3842_MINI_ATS_ID,	WI_NIC_3842_MINI_STR,	WI_INTERSIL },
219	{ WI_NIC_3842_PCI_AMD_ID,	WI_NIC_3842_PCI_STR,	WI_INTERSIL },
220	{ WI_NIC_3842_PCI_SST_ID,	WI_NIC_3842_PCI_STR,	WI_INTERSIL },
221	{ WI_NIC_3842_PCI_ATS_ID,	WI_NIC_3842_PCI_STR,	WI_INTERSIL },
222	{ WI_NIC_3842_PCI_ATL_ID,	WI_NIC_3842_PCI_STR,	WI_INTERSIL },
223	{ WI_NIC_P3_PCMCIA_AMD_ID,	WI_NIC_P3_PCMCIA_STR,	WI_INTERSIL },
224	{ WI_NIC_P3_PCMCIA_SST_ID,	WI_NIC_P3_PCMCIA_STR,	WI_INTERSIL },
225	{ WI_NIC_P3_PCMCIA_ATL_ID,	WI_NIC_P3_PCMCIA_STR,	WI_INTERSIL },
226	{ WI_NIC_P3_PCMCIA_ATS_ID,	WI_NIC_P3_PCMCIA_STR,	WI_INTERSIL },
227	{ WI_NIC_P3_MINI_AMD_ID,	WI_NIC_P3_MINI_STR,	WI_INTERSIL },
228	{ WI_NIC_P3_MINI_SST_ID,	WI_NIC_P3_MINI_STR,	WI_INTERSIL },
229	{ WI_NIC_P3_MINI_ATL_ID,	WI_NIC_P3_MINI_STR,	WI_INTERSIL },
230	{ WI_NIC_P3_MINI_ATS_ID,	WI_NIC_P3_MINI_STR,	WI_INTERSIL },
231	{ 0,	NULL,	0 },
232};
233
234devclass_t wi_devclass;
235
236int
237wi_attach(device_t dev)
238{
239	struct wi_softc	*sc = device_get_softc(dev);
240	struct ieee80211com *ic = &sc->sc_ic;
241	struct ifnet *ifp;
242	int i, nrates, buflen;
243	u_int16_t val;
244	u_int8_t ratebuf[2 + IEEE80211_RATE_SIZE];
245	struct ieee80211_rateset *rs;
246	static const u_int8_t empty_macaddr[IEEE80211_ADDR_LEN] = {
247		0x00, 0x00, 0x00, 0x00, 0x00, 0x00
248	};
249	int error;
250
251	ifp = sc->sc_ifp = if_alloc(IFT_ETHER);
252	if (ifp == NULL) {
253		device_printf(dev, "can not if_alloc\n");
254		wi_free(dev);
255		return (ENOSPC);
256	}
257
258	/*
259	 * NB: no locking is needed here; don't put it here
260	 *     unless you can prove it!
261	 */
262	error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET | INTR_MPSAFE,
263	    wi_intr, sc, &sc->wi_intrhand);
264
265	if (error) {
266		device_printf(dev, "bus_setup_intr() failed! (%d)\n", error);
267		wi_free(dev);
268		return (error);
269	}
270
271#if __FreeBSD_version >= 500000
272	mtx_init(&sc->sc_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
273	    MTX_DEF | MTX_RECURSE);
274#endif
275
276	sc->sc_firmware_type = WI_NOTYPE;
277	sc->wi_cmd_count = 500;
278	/* Reset the NIC. */
279	if (wi_reset(sc) != 0)
280		return ENXIO;		/* XXX */
281
282	/*
283	 * Read the station address.
284	 * And do it twice. I've seen PRISM-based cards that return
285	 * an error when trying to read it the first time, which causes
286	 * the probe to fail.
287	 */
288	buflen = IEEE80211_ADDR_LEN;
289	error = wi_read_rid(sc, WI_RID_MAC_NODE, ic->ic_myaddr, &buflen);
290	if (error != 0) {
291		buflen = IEEE80211_ADDR_LEN;
292		error = wi_read_rid(sc, WI_RID_MAC_NODE, ic->ic_myaddr, &buflen);
293	}
294	if (error || IEEE80211_ADDR_EQ(ic->ic_myaddr, empty_macaddr)) {
295		if (error != 0)
296			device_printf(dev, "mac read failed %d\n", error);
297		else {
298			device_printf(dev, "mac read failed (all zeros)\n");
299			error = ENXIO;
300		}
301		wi_free(dev);
302		return (error);
303	}
304
305	/* Read NIC identification */
306	wi_read_nicid(sc);
307
308	ifp->if_softc = sc;
309	if_initname(ifp, device_get_name(dev), device_get_unit(dev));
310	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
311	ifp->if_ioctl = wi_ioctl;
312	ifp->if_start = wi_start;
313	ifp->if_watchdog = wi_watchdog;
314	ifp->if_init = wi_init;
315	IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
316	ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
317	IFQ_SET_READY(&ifp->if_snd);
318
319	ic->ic_ifp = ifp;
320	ic->ic_phytype = IEEE80211_T_DS;
321	ic->ic_opmode = IEEE80211_M_STA;
322	ic->ic_state = IEEE80211_S_INIT;
323	ic->ic_caps = IEEE80211_C_PMGT
324		    | IEEE80211_C_WEP		/* everyone supports WEP */
325		    ;
326	ic->ic_max_aid = WI_MAX_AID;
327
328	/*
329	 * Query the card for available channels and setup the
330	 * channel table.  We assume these are all 11b channels.
331	 */
332	buflen = sizeof(val);
333	if (wi_read_rid(sc, WI_RID_CHANNEL_LIST, &val, &buflen) != 0)
334		val = htole16(0x1fff);	/* assume 1-11 */
335	KASSERT(val != 0, ("wi_attach: no available channels listed!"));
336
337	val <<= 1;			/* shift for base 1 indices */
338	for (i = 1; i < 16; i++) {
339		if (!isset((u_int8_t*)&val, i))
340			continue;
341		ic->ic_channels[i].ic_freq =
342			ieee80211_ieee2mhz(i, IEEE80211_CHAN_B);
343		ic->ic_channels[i].ic_flags = IEEE80211_CHAN_B;
344	}
345
346	/*
347	 * Read the default channel from the NIC. This may vary
348	 * depending on the country where the NIC was purchased, so
349	 * we can't hard-code a default and expect it to work for
350	 * everyone.
351	 *
352	 * If no channel is specified, let the 802.11 code select.
353	 */
354	buflen = sizeof(val);
355	if (wi_read_rid(sc, WI_RID_OWN_CHNL, &val, &buflen) == 0) {
356		val = le16toh(val);
357		KASSERT(val < IEEE80211_CHAN_MAX &&
358			ic->ic_channels[val].ic_flags != 0,
359			("wi_attach: invalid own channel %u!", val));
360		ic->ic_ibss_chan = &ic->ic_channels[val];
361	} else {
362		device_printf(dev,
363			"WI_RID_OWN_CHNL failed, using first channel!\n");
364		ic->ic_ibss_chan = &ic->ic_channels[0];
365	}
366
367	/*
368	 * Set flags based on firmware version.
369	 */
370	switch (sc->sc_firmware_type) {
371	case WI_LUCENT:
372		sc->sc_ntxbuf = 1;
373		sc->sc_flags |= WI_FLAGS_HAS_SYSSCALE;
374#ifdef WI_HERMES_AUTOINC_WAR
375		/* XXX: not confirmed, but never seen for recent firmware */
376		if (sc->sc_sta_firmware_ver <  40000) {
377			sc->sc_flags |= WI_FLAGS_BUG_AUTOINC;
378		}
379#endif
380		if (sc->sc_sta_firmware_ver >= 60000)
381			sc->sc_flags |= WI_FLAGS_HAS_MOR;
382		if (sc->sc_sta_firmware_ver >= 60006) {
383			ic->ic_caps |= IEEE80211_C_IBSS;
384			ic->ic_caps |= IEEE80211_C_MONITOR;
385		}
386		sc->sc_ibss_port = htole16(1);
387
388		sc->sc_min_rssi = WI_LUCENT_MIN_RSSI;
389		sc->sc_max_rssi = WI_LUCENT_MAX_RSSI;
390		sc->sc_dbm_offset = WI_LUCENT_DBM_OFFSET;
391		break;
392
393	case WI_INTERSIL:
394		sc->sc_ntxbuf = WI_NTXBUF;
395		sc->sc_flags |= WI_FLAGS_HAS_FRAGTHR;
396		sc->sc_flags |= WI_FLAGS_HAS_ROAMING;
397		sc->sc_flags |= WI_FLAGS_HAS_SYSSCALE;
398		/*
399		 * Old firmware are slow, so give peace a chance.
400		 */
401		if (sc->sc_sta_firmware_ver < 10000)
402			sc->wi_cmd_count = 5000;
403		if (sc->sc_sta_firmware_ver > 10101)
404			sc->sc_flags |= WI_FLAGS_HAS_DBMADJUST;
405		if (sc->sc_sta_firmware_ver >= 800) {
406			ic->ic_caps |= IEEE80211_C_IBSS;
407			ic->ic_caps |= IEEE80211_C_MONITOR;
408		}
409		/*
410		 * version 0.8.3 and newer are the only ones that are known
411		 * to currently work.  Earlier versions can be made to work,
412		 * at least according to the Linux driver.
413		 */
414		if (sc->sc_sta_firmware_ver >= 803)
415			ic->ic_caps |= IEEE80211_C_HOSTAP;
416		sc->sc_ibss_port = htole16(0);
417
418		sc->sc_min_rssi = WI_PRISM_MIN_RSSI;
419		sc->sc_max_rssi = WI_PRISM_MAX_RSSI;
420		sc->sc_dbm_offset = WI_PRISM_DBM_OFFSET;
421		break;
422
423	case WI_SYMBOL:
424		sc->sc_ntxbuf = 1;
425		sc->sc_flags |= WI_FLAGS_HAS_DIVERSITY;
426		if (sc->sc_sta_firmware_ver >= 25000)
427			ic->ic_caps |= IEEE80211_C_IBSS;
428		sc->sc_ibss_port = htole16(4);
429
430		sc->sc_min_rssi = WI_PRISM_MIN_RSSI;
431		sc->sc_max_rssi = WI_PRISM_MAX_RSSI;
432		sc->sc_dbm_offset = WI_PRISM_DBM_OFFSET;
433		break;
434	}
435
436	/*
437	 * Find out if we support WEP on this card.
438	 */
439	buflen = sizeof(val);
440	if (wi_read_rid(sc, WI_RID_WEP_AVAIL, &val, &buflen) == 0 &&
441	    val != htole16(0))
442		ic->ic_caps |= IEEE80211_C_WEP;
443
444	/* Find supported rates. */
445	buflen = sizeof(ratebuf);
446	rs = &ic->ic_sup_rates[IEEE80211_MODE_11B];
447	if (wi_read_rid(sc, WI_RID_DATA_RATES, ratebuf, &buflen) == 0) {
448		nrates = le16toh(*(u_int16_t *)ratebuf);
449		if (nrates > IEEE80211_RATE_MAXSIZE)
450			nrates = IEEE80211_RATE_MAXSIZE;
451		rs->rs_nrates = 0;
452		for (i = 0; i < nrates; i++)
453			if (ratebuf[2+i])
454				rs->rs_rates[rs->rs_nrates++] = ratebuf[2+i];
455	} else {
456		/* XXX fallback on error? */
457		rs->rs_nrates = 0;
458	}
459
460	buflen = sizeof(val);
461	if ((sc->sc_flags & WI_FLAGS_HAS_DBMADJUST) &&
462	    wi_read_rid(sc, WI_RID_DBM_ADJUST, &val, &buflen) == 0) {
463		sc->sc_dbm_offset = le16toh(val);
464	}
465
466	sc->sc_max_datalen = 2304;
467	sc->sc_system_scale = 1;
468	sc->sc_cnfauthmode = IEEE80211_AUTH_OPEN;
469	sc->sc_roaming_mode = 1;
470
471	sc->sc_portnum = WI_DEFAULT_PORT;
472	sc->sc_authtype = WI_DEFAULT_AUTHTYPE;
473
474	bzero(sc->sc_nodename, sizeof(sc->sc_nodename));
475	sc->sc_nodelen = sizeof(WI_DEFAULT_NODENAME) - 1;
476	bcopy(WI_DEFAULT_NODENAME, sc->sc_nodename, sc->sc_nodelen);
477
478	bzero(sc->sc_net_name, sizeof(sc->sc_net_name));
479	bcopy(WI_DEFAULT_NETNAME, sc->sc_net_name,
480	    sizeof(WI_DEFAULT_NETNAME) - 1);
481
482	/*
483	 * Call MI attach routine.
484	 */
485	ieee80211_ifattach(ic);
486	/* override state transition method */
487	sc->sc_newstate = ic->ic_newstate;
488	ic->ic_newstate = wi_newstate;
489	ieee80211_media_init(ic, wi_media_change, wi_media_status);
490
491#if NBPFILTER > 0
492	bpfattach2(ifp, DLT_IEEE802_11_RADIO,
493		sizeof(struct ieee80211_frame) + sizeof(sc->sc_tx_th),
494		&sc->sc_drvbpf);
495	/*
496	 * Initialize constant fields.
497	 * XXX make header lengths a multiple of 32-bits so subsequent
498	 *     headers are properly aligned; this is a kludge to keep
499	 *     certain applications happy.
500	 *
501	 * NB: the channel is setup each time we transition to the
502	 *     RUN state to avoid filling it in for each frame.
503	 */
504	sc->sc_tx_th_len = roundup(sizeof(sc->sc_tx_th), sizeof(u_int32_t));
505	sc->sc_tx_th.wt_ihdr.it_len = htole16(sc->sc_tx_th_len);
506	sc->sc_tx_th.wt_ihdr.it_present = htole32(WI_TX_RADIOTAP_PRESENT);
507
508	sc->sc_rx_th_len = roundup(sizeof(sc->sc_rx_th), sizeof(u_int32_t));
509	sc->sc_rx_th.wr_ihdr.it_len = htole16(sc->sc_rx_th_len);
510	sc->sc_rx_th.wr_ihdr.it_present = htole32(WI_RX_RADIOTAP_PRESENT);
511#endif
512
513	if (bootverbose)
514		ieee80211_announce(ic);
515
516	return (0);
517}
518
519int
520wi_detach(device_t dev)
521{
522	struct wi_softc	*sc = device_get_softc(dev);
523	struct ifnet *ifp = sc->sc_ifp;
524	WI_LOCK_DECL();
525
526	WI_LOCK(sc);
527
528	/* check if device was removed */
529	sc->wi_gone |= !bus_child_present(dev);
530
531	wi_stop(ifp, 0);
532
533#if NBPFILTER > 0
534	bpfdetach(ifp);
535#endif
536	ieee80211_ifdetach(&sc->sc_ic);
537	if_free(sc->sc_ifp);
538	WI_UNLOCK(sc);
539	bus_teardown_intr(dev, sc->irq, sc->wi_intrhand);
540	wi_free(dev);
541#if __FreeBSD_version >= 500000
542	mtx_destroy(&sc->sc_mtx);
543#endif
544	return (0);
545}
546
547#ifdef __NetBSD__
548int
549wi_activate(struct device *self, enum devact act)
550{
551	struct wi_softc *sc = (struct wi_softc *)self;
552	int rv = 0, s;
553
554	s = splnet();
555	switch (act) {
556	case DVACT_ACTIVATE:
557		rv = EOPNOTSUPP;
558		break;
559
560	case DVACT_DEACTIVATE:
561		if_deactivate(sc->sc_ifp);
562		break;
563	}
564	splx(s);
565	return rv;
566}
567
568void
569wi_power(struct wi_softc *sc, int why)
570{
571	struct ifnet *ifp = sc->sc_ifp;
572	int s;
573
574	s = splnet();
575	switch (why) {
576	case PWR_SUSPEND:
577	case PWR_STANDBY:
578		wi_stop(ifp, 1);
579		break;
580	case PWR_RESUME:
581		if (ifp->if_flags & IFF_UP) {
582			wi_init(ifp);
583			(void)wi_intr(sc);
584		}
585		break;
586	case PWR_SOFTSUSPEND:
587	case PWR_SOFTSTANDBY:
588	case PWR_SOFTRESUME:
589		break;
590	}
591	splx(s);
592}
593#endif /* __NetBSD__ */
594
595void
596wi_shutdown(device_t dev)
597{
598	struct wi_softc *sc = device_get_softc(dev);
599
600	wi_stop(sc->sc_ifp, 1);
601}
602
603void
604wi_intr(void *arg)
605{
606	struct wi_softc *sc = arg;
607	struct ifnet *ifp = sc->sc_ifp;
608	u_int16_t status;
609	WI_LOCK_DECL();
610
611	WI_LOCK(sc);
612
613	if (sc->wi_gone || !sc->sc_enabled || (ifp->if_flags & IFF_UP) == 0) {
614		CSR_WRITE_2(sc, WI_INT_EN, 0);
615		CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
616		WI_UNLOCK(sc);
617		return;
618	}
619
620	/* Disable interrupts. */
621	CSR_WRITE_2(sc, WI_INT_EN, 0);
622
623	status = CSR_READ_2(sc, WI_EVENT_STAT);
624	if (status & WI_EV_RX)
625		wi_rx_intr(sc);
626	if (status & WI_EV_ALLOC)
627		wi_tx_intr(sc);
628	if (status & WI_EV_TX_EXC)
629		wi_tx_ex_intr(sc);
630	if (status & WI_EV_INFO)
631		wi_info_intr(sc);
632	if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0 &&
633	    (sc->sc_flags & WI_FLAGS_OUTRANGE) == 0 &&
634	    !IFQ_DRV_IS_EMPTY(&ifp->if_snd))
635		wi_start(ifp);
636
637	/* Re-enable interrupts. */
638	CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
639
640	WI_UNLOCK(sc);
641
642	return;
643}
644
645void
646wi_init(void *arg)
647{
648	struct wi_softc *sc = arg;
649	struct ifnet *ifp = sc->sc_ifp;
650	struct ieee80211com *ic = &sc->sc_ic;
651	struct wi_joinreq join;
652	int i;
653	int error = 0, wasenabled;
654	struct ifaddr *ifa;
655	struct sockaddr_dl *sdl;
656	WI_LOCK_DECL();
657
658	WI_LOCK(sc);
659
660	if (sc->wi_gone) {
661		WI_UNLOCK(sc);
662		return;
663	}
664
665	if ((wasenabled = sc->sc_enabled))
666		wi_stop(ifp, 1);
667	wi_reset(sc);
668
669	/* common 802.11 configuration */
670	ic->ic_flags &= ~IEEE80211_F_IBSSON;
671	sc->sc_flags &= ~WI_FLAGS_OUTRANGE;
672	switch (ic->ic_opmode) {
673	case IEEE80211_M_STA:
674		wi_write_val(sc, WI_RID_PORTTYPE, WI_PORTTYPE_BSS);
675		break;
676	case IEEE80211_M_IBSS:
677		wi_write_val(sc, WI_RID_PORTTYPE, sc->sc_ibss_port);
678		ic->ic_flags |= IEEE80211_F_IBSSON;
679		break;
680	case IEEE80211_M_AHDEMO:
681		wi_write_val(sc, WI_RID_PORTTYPE, WI_PORTTYPE_ADHOC);
682		break;
683	case IEEE80211_M_HOSTAP:
684		/*
685		 * For PRISM cards, override the empty SSID, because in
686		 * HostAP mode the controller will lock up otherwise.
687		 */
688		if (sc->sc_firmware_type == WI_INTERSIL &&
689		    ic->ic_des_esslen == 0) {
690			ic->ic_des_essid[0] = ' ';
691			ic->ic_des_esslen = 1;
692		}
693		wi_write_val(sc, WI_RID_PORTTYPE, WI_PORTTYPE_HOSTAP);
694		break;
695	case IEEE80211_M_MONITOR:
696		if (sc->sc_firmware_type == WI_LUCENT)
697			wi_write_val(sc, WI_RID_PORTTYPE, WI_PORTTYPE_ADHOC);
698		wi_cmd(sc, WI_CMD_DEBUG | (WI_TEST_MONITOR << 8), 0, 0, 0);
699		break;
700	}
701
702	/* Intersil interprets this RID as joining ESS even in IBSS mode */
703	if (sc->sc_firmware_type == WI_LUCENT &&
704	    (ic->ic_flags & IEEE80211_F_IBSSON) && ic->ic_des_esslen > 0)
705		wi_write_val(sc, WI_RID_CREATE_IBSS, 1);
706	else
707		wi_write_val(sc, WI_RID_CREATE_IBSS, 0);
708	wi_write_val(sc, WI_RID_MAX_SLEEP, ic->ic_lintval);
709	wi_write_ssid(sc, WI_RID_DESIRED_SSID, ic->ic_des_essid,
710	    ic->ic_des_esslen);
711	wi_write_val(sc, WI_RID_OWN_CHNL,
712		ieee80211_chan2ieee(ic, ic->ic_ibss_chan));
713	wi_write_ssid(sc, WI_RID_OWN_SSID, ic->ic_des_essid, ic->ic_des_esslen);
714
715	ifa = ifaddr_byindex(ifp->if_index);
716	sdl = (struct sockaddr_dl *) ifa->ifa_addr;
717	IEEE80211_ADDR_COPY(ic->ic_myaddr, LLADDR(sdl));
718	wi_write_rid(sc, WI_RID_MAC_NODE, ic->ic_myaddr, IEEE80211_ADDR_LEN);
719
720	if (ic->ic_caps & IEEE80211_C_PMGT)
721		wi_write_val(sc, WI_RID_PM_ENABLED,
722		    (ic->ic_flags & IEEE80211_F_PMGTON) ? 1 : 0);
723
724	/* not yet common 802.11 configuration */
725	wi_write_val(sc, WI_RID_MAX_DATALEN, sc->sc_max_datalen);
726	wi_write_val(sc, WI_RID_RTS_THRESH, ic->ic_rtsthreshold);
727	if (sc->sc_flags & WI_FLAGS_HAS_FRAGTHR)
728		wi_write_val(sc, WI_RID_FRAG_THRESH, ic->ic_fragthreshold);
729
730	/* driver specific 802.11 configuration */
731	if (sc->sc_flags & WI_FLAGS_HAS_SYSSCALE)
732		wi_write_val(sc, WI_RID_SYSTEM_SCALE, sc->sc_system_scale);
733	if (sc->sc_flags & WI_FLAGS_HAS_ROAMING)
734		wi_write_val(sc, WI_RID_ROAMING_MODE, sc->sc_roaming_mode);
735	if (sc->sc_flags & WI_FLAGS_HAS_MOR)
736		wi_write_val(sc, WI_RID_MICROWAVE_OVEN, sc->sc_microwave_oven);
737	wi_write_txrate(sc);
738	wi_write_ssid(sc, WI_RID_NODENAME, sc->sc_nodename, sc->sc_nodelen);
739
740	if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
741	    sc->sc_firmware_type == WI_INTERSIL) {
742		wi_write_val(sc, WI_RID_OWN_BEACON_INT, ic->ic_bintval);
743		wi_write_val(sc, WI_RID_BASIC_RATE, 0x03);   /* 1, 2 */
744		wi_write_val(sc, WI_RID_SUPPORT_RATE, 0x0f); /* 1, 2, 5.5, 11 */
745		wi_write_val(sc, WI_RID_DTIM_PERIOD, 1);
746	}
747
748	/*
749	 * Initialize promisc mode.
750	 *	Being in the Host-AP mode causes a great
751	 *	deal of pain if primisc mode is set.
752	 *	Therefore we avoid confusing the firmware
753	 *	and always reset promisc mode in Host-AP
754	 *	mode.  Host-AP sees all the packets anyway.
755	 */
756	if (ic->ic_opmode != IEEE80211_M_HOSTAP &&
757	    (ifp->if_flags & IFF_PROMISC) != 0) {
758		wi_write_val(sc, WI_RID_PROMISC, 1);
759	} else {
760		wi_write_val(sc, WI_RID_PROMISC, 0);
761	}
762
763	/* Configure WEP. */
764	if (ic->ic_caps & IEEE80211_C_WEP) {
765		sc->sc_cnfauthmode = ic->ic_bss->ni_authmode;
766		wi_write_wep(sc);
767	}
768
769	/* Set multicast filter. */
770	wi_write_multi(sc);
771
772	/* Allocate fids for the card */
773	if (sc->sc_firmware_type != WI_SYMBOL || !wasenabled) {
774		sc->sc_buflen = IEEE80211_MAX_LEN + sizeof(struct wi_frame);
775		if (sc->sc_firmware_type == WI_SYMBOL)
776			sc->sc_buflen = 1585;	/* XXX */
777		for (i = 0; i < sc->sc_ntxbuf; i++) {
778			error = wi_alloc_fid(sc, sc->sc_buflen,
779			    &sc->sc_txd[i].d_fid);
780			if (error) {
781				device_printf(sc->sc_dev,
782				    "tx buffer allocation failed (error %u)\n",
783				    error);
784				goto out;
785			}
786			sc->sc_txd[i].d_len = 0;
787		}
788	}
789	sc->sc_txcur = sc->sc_txnext = 0;
790
791	/* Enable desired port */
792	wi_cmd(sc, WI_CMD_ENABLE | sc->sc_portnum, 0, 0, 0);
793
794	sc->sc_enabled = 1;
795	ifp->if_drv_flags |= IFF_DRV_RUNNING;
796	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
797	if (ic->ic_opmode == IEEE80211_M_AHDEMO ||
798	    ic->ic_opmode == IEEE80211_M_IBSS ||
799	    ic->ic_opmode == IEEE80211_M_MONITOR ||
800	    ic->ic_opmode == IEEE80211_M_HOSTAP)
801		ieee80211_create_ibss(ic, ic->ic_ibss_chan);
802
803	/* Enable interrupts */
804	CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
805
806	if (!wasenabled &&
807	    ic->ic_opmode == IEEE80211_M_HOSTAP &&
808	    sc->sc_firmware_type == WI_INTERSIL) {
809		/* XXX: some card need to be re-enabled for hostap */
810		wi_cmd(sc, WI_CMD_DISABLE | WI_PORT0, 0, 0, 0);
811		wi_cmd(sc, WI_CMD_ENABLE | WI_PORT0, 0, 0, 0);
812	}
813
814	if (ic->ic_opmode == IEEE80211_M_STA &&
815	    ((ic->ic_flags & IEEE80211_F_DESBSSID) ||
816	    ic->ic_des_chan != IEEE80211_CHAN_ANYC)) {
817		memset(&join, 0, sizeof(join));
818		if (ic->ic_flags & IEEE80211_F_DESBSSID)
819			IEEE80211_ADDR_COPY(&join.wi_bssid, ic->ic_des_bssid);
820		if (ic->ic_des_chan != IEEE80211_CHAN_ANYC)
821			join.wi_chan = htole16(
822				ieee80211_chan2ieee(ic, ic->ic_des_chan));
823		/* Lucent firmware does not support the JOIN RID. */
824		if (sc->sc_firmware_type != WI_LUCENT)
825			wi_write_rid(sc, WI_RID_JOIN_REQ, &join, sizeof(join));
826	}
827
828	WI_UNLOCK(sc);
829	return;
830out:
831	if (error) {
832		if_printf(ifp, "interface not running\n");
833		wi_stop(ifp, 1);
834	}
835	WI_UNLOCK(sc);
836	DPRINTF(("wi_init: return %d\n", error));
837	return;
838}
839
840void
841wi_stop(struct ifnet *ifp, int disable)
842{
843	struct wi_softc *sc = ifp->if_softc;
844	struct ieee80211com *ic = &sc->sc_ic;
845	WI_LOCK_DECL();
846
847	WI_LOCK(sc);
848
849	DELAY(100000);
850
851	ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
852	if (sc->sc_enabled && !sc->wi_gone) {
853		CSR_WRITE_2(sc, WI_INT_EN, 0);
854		wi_cmd(sc, WI_CMD_DISABLE | sc->sc_portnum, 0, 0, 0);
855		if (disable) {
856#ifdef __NetBSD__
857			if (sc->sc_disable)
858				(*sc->sc_disable)(sc);
859#endif
860			sc->sc_enabled = 0;
861		}
862	} else if (sc->wi_gone && disable)	/* gone --> not enabled */
863	    sc->sc_enabled = 0;
864
865	sc->sc_tx_timer = 0;
866	sc->sc_scan_timer = 0;
867	sc->sc_false_syns = 0;
868	sc->sc_naps = 0;
869	ifp->if_drv_flags &= ~(IFF_DRV_OACTIVE | IFF_DRV_RUNNING);
870	ifp->if_timer = 0;
871
872	WI_UNLOCK(sc);
873}
874
875static void
876wi_start(struct ifnet *ifp)
877{
878	struct wi_softc	*sc = ifp->if_softc;
879	struct ieee80211com *ic = &sc->sc_ic;
880	struct ieee80211_node *ni;
881	struct ieee80211_frame *wh;
882	struct ether_header *eh;
883	struct mbuf *m0;
884	struct wi_frame frmhdr;
885	int cur, fid, off, error;
886	WI_LOCK_DECL();
887
888	WI_LOCK(sc);
889
890	if (sc->wi_gone) {
891		WI_UNLOCK(sc);
892		return;
893	}
894	if (sc->sc_flags & WI_FLAGS_OUTRANGE) {
895		WI_UNLOCK(sc);
896		return;
897	}
898
899	memset(&frmhdr, 0, sizeof(frmhdr));
900	cur = sc->sc_txnext;
901	for (;;) {
902		IF_POLL(&ic->ic_mgtq, m0);
903		if (m0 != NULL) {
904			if (sc->sc_txd[cur].d_len != 0) {
905				ifp->if_drv_flags |= IFF_DRV_OACTIVE;
906				break;
907			}
908			IF_DEQUEUE(&ic->ic_mgtq, m0);
909			/*
910			 * Hack!  The referenced node pointer is in the
911			 * rcvif field of the packet header.  This is
912			 * placed there by ieee80211_mgmt_output because
913			 * we need to hold the reference with the frame
914			 * and there's no other way (other than packet
915			 * tags which we consider too expensive to use)
916			 * to pass it along.
917			 */
918			ni = (struct ieee80211_node *) m0->m_pkthdr.rcvif;
919			m0->m_pkthdr.rcvif = NULL;
920
921			m_copydata(m0, 4, ETHER_ADDR_LEN * 2,
922			    (caddr_t)&frmhdr.wi_ehdr);
923			frmhdr.wi_ehdr.ether_type = 0;
924                        wh = mtod(m0, struct ieee80211_frame *);
925		} else {
926			if (ic->ic_state != IEEE80211_S_RUN)
927				break;
928			IFQ_DRV_DEQUEUE(&ifp->if_snd, m0);
929			if (m0 == NULL)
930				break;
931			if (sc->sc_txd[cur].d_len != 0) {
932				IFQ_DRV_PREPEND(&ifp->if_snd, m0);
933				ifp->if_drv_flags |= IFF_DRV_OACTIVE;
934				break;
935			}
936			if (m0->m_len < sizeof(struct ether_header) &&
937			    (m0 = m_pullup(m0, sizeof(struct ether_header))) == NULL) {
938				ifp->if_oerrors++;
939				continue;
940			}
941			eh = mtod(m0, struct ether_header *);
942			ni = ieee80211_find_txnode(ic, eh->ether_dhost);
943			if (ni == NULL) {
944				m_freem(m0);
945				continue;
946			}
947			ifp->if_opackets++;
948			m_copydata(m0, 0, ETHER_HDR_LEN,
949			    (caddr_t)&frmhdr.wi_ehdr);
950#if NBPFILTER > 0
951			BPF_MTAP(ifp, m0);
952#endif
953
954			m0 = ieee80211_encap(ic, m0, ni);
955			if (m0 == NULL) {
956				ifp->if_oerrors++;
957				ieee80211_free_node(ni);
958				continue;
959			}
960                        wh = mtod(m0, struct ieee80211_frame *);
961		}
962#if NBPFILTER > 0
963		if (ic->ic_rawbpf)
964			bpf_mtap(ic->ic_rawbpf, m0);
965#endif
966		frmhdr.wi_tx_ctl = htole16(WI_ENC_TX_802_11|WI_TXCNTL_TX_EX);
967		/* XXX check key for SWCRYPT instead of using operating mode */
968		if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
969		    (wh->i_fc[1] & IEEE80211_FC1_WEP)) {
970			struct ieee80211_key *k;
971
972			k = ieee80211_crypto_encap(ic, ni, m0);
973			if (k == NULL) {
974				if (ni != NULL)
975					ieee80211_free_node(ni);
976				m_freem(m0);
977				continue;
978			}
979			frmhdr.wi_tx_ctl |= htole16(WI_TXCNTL_NOCRYPT);
980		}
981#if NBPFILTER > 0
982		if (sc->sc_drvbpf) {
983			sc->sc_tx_th.wt_rate =
984				ni->ni_rates.rs_rates[ni->ni_txrate];
985			bpf_mtap2(sc->sc_drvbpf,
986				&sc->sc_tx_th, sc->sc_tx_th_len, m0);
987		}
988#endif
989		m_copydata(m0, 0, sizeof(struct ieee80211_frame),
990		    (caddr_t)&frmhdr.wi_whdr);
991		m_adj(m0, sizeof(struct ieee80211_frame));
992		frmhdr.wi_dat_len = htole16(m0->m_pkthdr.len);
993		if (IFF_DUMPPKTS(ifp))
994			wi_dump_pkt(&frmhdr, NULL, -1);
995		fid = sc->sc_txd[cur].d_fid;
996		off = sizeof(frmhdr);
997		error = wi_write_bap(sc, fid, 0, &frmhdr, sizeof(frmhdr)) != 0
998		     || wi_mwrite_bap(sc, fid, off, m0, m0->m_pkthdr.len) != 0;
999		m_freem(m0);
1000		if (ni != NULL)
1001			ieee80211_free_node(ni);
1002		if (error) {
1003			ifp->if_oerrors++;
1004			continue;
1005		}
1006		sc->sc_txd[cur].d_len = off;
1007		if (sc->sc_txcur == cur) {
1008			if (wi_cmd(sc, WI_CMD_TX | WI_RECLAIM, fid, 0, 0)) {
1009				if_printf(ifp, "xmit failed\n");
1010				sc->sc_txd[cur].d_len = 0;
1011				continue;
1012			}
1013			sc->sc_tx_timer = 5;
1014			ifp->if_timer = 1;
1015		}
1016		sc->sc_txnext = cur = (cur + 1) % sc->sc_ntxbuf;
1017	}
1018
1019	WI_UNLOCK(sc);
1020}
1021
1022static int
1023wi_reset(struct wi_softc *sc)
1024{
1025	struct ifnet *ifp = sc->sc_ifp;
1026#define WI_INIT_TRIES 3
1027	int i;
1028	int error = 0;
1029	int tries;
1030
1031	/* Symbol firmware cannot be initialized more than once */
1032	if (sc->sc_firmware_type == WI_SYMBOL && sc->sc_reset)
1033		return (0);
1034	if (sc->sc_firmware_type == WI_SYMBOL)
1035		tries = 1;
1036	else
1037		tries = WI_INIT_TRIES;
1038
1039	for (i = 0; i < tries; i++) {
1040		if ((error = wi_cmd(sc, WI_CMD_INI, 0, 0, 0)) == 0)
1041			break;
1042		DELAY(WI_DELAY * 1000);
1043	}
1044	sc->sc_reset = 1;
1045
1046	if (i == tries) {
1047		if_printf(ifp, "init failed\n");
1048		return (error);
1049	}
1050
1051	CSR_WRITE_2(sc, WI_INT_EN, 0);
1052	CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
1053
1054	/* Calibrate timer. */
1055	wi_write_val(sc, WI_RID_TICK_TIME, 8);
1056
1057	return (0);
1058#undef WI_INIT_TRIES
1059}
1060
1061static void
1062wi_watchdog(struct ifnet *ifp)
1063{
1064	struct wi_softc	*sc = ifp->if_softc;
1065
1066	ifp->if_timer = 0;
1067	if (!sc->sc_enabled)
1068		return;
1069
1070	if (sc->sc_tx_timer) {
1071		if (--sc->sc_tx_timer == 0) {
1072			if_printf(ifp, "device timeout\n");
1073			ifp->if_oerrors++;
1074			wi_init(ifp->if_softc);
1075			return;
1076		}
1077		ifp->if_timer = 1;
1078	}
1079
1080	if (sc->sc_scan_timer) {
1081		if (--sc->sc_scan_timer <= WI_SCAN_WAIT - WI_SCAN_INQWAIT &&
1082		    sc->sc_firmware_type == WI_INTERSIL) {
1083			DPRINTF(("wi_watchdog: inquire scan\n"));
1084			wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_SCAN_RESULTS, 0, 0);
1085		}
1086		if (sc->sc_scan_timer)
1087			ifp->if_timer = 1;
1088	}
1089
1090	/* TODO: rate control */
1091	ieee80211_watchdog(&sc->sc_ic);
1092}
1093
1094static int
1095wi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1096{
1097	struct wi_softc *sc = ifp->if_softc;
1098	struct ieee80211com *ic = &sc->sc_ic;
1099	struct ifreq *ifr = (struct ifreq *)data;
1100	struct ieee80211req *ireq;
1101	u_int8_t nodename[IEEE80211_NWID_LEN];
1102	int error = 0;
1103#if __FreeBSD_version >= 500000
1104	struct thread *td = curthread;
1105#else
1106	struct proc *td = curproc;		/* Little white lie */
1107#endif
1108	struct wi_req wreq;
1109	WI_LOCK_DECL();
1110
1111	if (sc->wi_gone)
1112		return (ENODEV);
1113
1114	switch (cmd) {
1115	case SIOCSIFFLAGS:
1116		/*
1117		 * Can't do promisc and hostap at the same time.  If all that's
1118		 * changing is the promisc flag, try to short-circuit a call to
1119		 * wi_init() by just setting PROMISC in the hardware.
1120		 */
1121		WI_LOCK(sc);
1122		if (ifp->if_flags & IFF_UP) {
1123			if (ic->ic_opmode != IEEE80211_M_HOSTAP &&
1124			    ifp->if_drv_flags & IFF_DRV_RUNNING) {
1125				if (ifp->if_flags & IFF_PROMISC &&
1126				    !(sc->sc_if_flags & IFF_PROMISC)) {
1127					wi_write_val(sc, WI_RID_PROMISC, 1);
1128				} else if (!(ifp->if_flags & IFF_PROMISC) &&
1129				    sc->sc_if_flags & IFF_PROMISC) {
1130					wi_write_val(sc, WI_RID_PROMISC, 0);
1131				} else {
1132					wi_init(sc);
1133				}
1134			} else {
1135				wi_init(sc);
1136			}
1137		} else {
1138			if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
1139				wi_stop(ifp, 1);
1140			}
1141			sc->wi_gone = 0;
1142		}
1143		sc->sc_if_flags = ifp->if_flags;
1144		WI_UNLOCK(sc);
1145		error = 0;
1146		break;
1147	case SIOCADDMULTI:
1148	case SIOCDELMULTI:
1149		WI_LOCK(sc);
1150		error = wi_write_multi(sc);
1151		WI_UNLOCK(sc);
1152		break;
1153	case SIOCGIFGENERIC:
1154		WI_LOCK(sc);
1155		error = wi_get_cfg(ifp, cmd, data);
1156		WI_UNLOCK(sc);
1157		break;
1158	case SIOCSIFGENERIC:
1159		error = suser(td);
1160		if (error == 0)
1161			error = wi_set_cfg(ifp, cmd, data);
1162		break;
1163	case SIOCGPRISM2DEBUG:
1164		error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
1165		if (error)
1166			break;
1167		if (!(ifp->if_drv_flags & IFF_DRV_RUNNING) ||
1168		    sc->sc_firmware_type == WI_LUCENT) {
1169			error = EIO;
1170			break;
1171		}
1172		error = wi_get_debug(sc, &wreq);
1173		if (error == 0)
1174			error = copyout(&wreq, ifr->ifr_data, sizeof(wreq));
1175		break;
1176	case SIOCSPRISM2DEBUG:
1177		if ((error = suser(td)))
1178			return (error);
1179		error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
1180		if (error)
1181			break;
1182		WI_LOCK(sc);
1183		error = wi_set_debug(sc, &wreq);
1184		WI_UNLOCK(sc);
1185		break;
1186	case SIOCG80211:
1187		ireq = (struct ieee80211req *) data;
1188		if (ireq->i_type == IEEE80211_IOC_STATIONNAME) {
1189			ireq->i_len = sc->sc_nodelen + 1;
1190			error = copyout(sc->sc_nodename, ireq->i_data,
1191					ireq->i_len);
1192			break;
1193		}
1194		goto ioctl_common;
1195	case SIOCS80211:
1196		ireq = (struct ieee80211req *) data;
1197		if (ireq->i_type == IEEE80211_IOC_STATIONNAME) {
1198			error = suser(td);
1199			if (error)
1200				break;
1201			if (ireq->i_val != 0 ||
1202			    ireq->i_len > IEEE80211_NWID_LEN) {
1203				error = EINVAL;
1204				break;
1205			}
1206			memset(nodename, 0, IEEE80211_NWID_LEN);
1207			error = copyin(ireq->i_data, nodename, ireq->i_len);
1208			if (error)
1209				break;
1210			WI_LOCK(sc);
1211			if (sc->sc_enabled) {
1212				error = wi_write_ssid(sc, WI_RID_NODENAME,
1213					nodename, ireq->i_len);
1214			}
1215			if (error == 0) {
1216				memcpy(sc->sc_nodename, nodename,
1217					IEEE80211_NWID_LEN);
1218				sc->sc_nodelen = ireq->i_len;
1219			}
1220			WI_UNLOCK(sc);
1221			break;
1222		}
1223		goto ioctl_common;
1224	default:
1225	ioctl_common:
1226		WI_LOCK(sc);
1227		error = ieee80211_ioctl(ic, cmd, data);
1228		if (error == ENETRESET) {
1229			if (sc->sc_enabled)
1230				wi_init(sc);	/* XXX no error return */
1231			error = 0;
1232		}
1233		WI_UNLOCK(sc);
1234		break;
1235	}
1236	return (error);
1237}
1238
1239static int
1240wi_media_change(struct ifnet *ifp)
1241{
1242	struct wi_softc *sc = ifp->if_softc;
1243	int error;
1244
1245	error = ieee80211_media_change(ifp);
1246	if (error == ENETRESET) {
1247		if (sc->sc_enabled)
1248			wi_init(sc);	/* XXX no error return */
1249		error = 0;
1250	}
1251	return error;
1252}
1253
1254static void
1255wi_media_status(struct ifnet *ifp, struct ifmediareq *imr)
1256{
1257	struct wi_softc *sc = ifp->if_softc;
1258	struct ieee80211com *ic = &sc->sc_ic;
1259	u_int16_t val;
1260	int rate, len;
1261
1262	if (sc->wi_gone) {		/* hardware gone (e.g. ejected) */
1263		imr->ifm_active = IFM_IEEE80211 | IFM_NONE;
1264		imr->ifm_status = 0;
1265		return;
1266	}
1267
1268	imr->ifm_status = IFM_AVALID;
1269	imr->ifm_active = IFM_IEEE80211;
1270	if (!sc->sc_enabled) {		/* port !enabled, have no status */
1271		imr->ifm_active |= IFM_NONE;
1272		imr->ifm_status = IFM_AVALID;
1273		return;
1274	}
1275	if (ic->ic_state == IEEE80211_S_RUN &&
1276	    (sc->sc_flags & WI_FLAGS_OUTRANGE) == 0)
1277		imr->ifm_status |= IFM_ACTIVE;
1278	len = sizeof(val);
1279	if (wi_read_rid(sc, WI_RID_CUR_TX_RATE, &val, &len) == 0 &&
1280	    len == sizeof(val)) {
1281		/* convert to 802.11 rate */
1282		val = le16toh(val);
1283		rate = val * 2;
1284		if (sc->sc_firmware_type == WI_LUCENT) {
1285			if (rate == 10)
1286				rate = 11;	/* 5.5Mbps */
1287		} else {
1288			if (rate == 4*2)
1289				rate = 11;	/* 5.5Mbps */
1290			else if (rate == 8*2)
1291				rate = 22;	/* 11Mbps */
1292		}
1293	} else
1294		rate = 0;
1295	imr->ifm_active |= ieee80211_rate2media(ic, rate, IEEE80211_MODE_11B);
1296	switch (ic->ic_opmode) {
1297	case IEEE80211_M_STA:
1298		break;
1299	case IEEE80211_M_IBSS:
1300		imr->ifm_active |= IFM_IEEE80211_ADHOC;
1301		break;
1302	case IEEE80211_M_AHDEMO:
1303		imr->ifm_active |= IFM_IEEE80211_ADHOC | IFM_FLAG0;
1304		break;
1305	case IEEE80211_M_HOSTAP:
1306		imr->ifm_active |= IFM_IEEE80211_HOSTAP;
1307		break;
1308	case IEEE80211_M_MONITOR:
1309		imr->ifm_active |= IFM_IEEE80211_MONITOR;
1310		break;
1311	}
1312}
1313
1314static void
1315wi_sync_bssid(struct wi_softc *sc, u_int8_t new_bssid[IEEE80211_ADDR_LEN])
1316{
1317	struct ieee80211com *ic = &sc->sc_ic;
1318	struct ieee80211_node *ni = ic->ic_bss;
1319	struct ifnet *ifp = sc->sc_ifp;
1320
1321	if (IEEE80211_ADDR_EQ(new_bssid, ni->ni_bssid))
1322		return;
1323
1324	DPRINTF(("wi_sync_bssid: bssid %s -> ", ether_sprintf(ni->ni_bssid)));
1325	DPRINTF(("%s ?\n", ether_sprintf(new_bssid)));
1326
1327	/* In promiscuous mode, the BSSID field is not a reliable
1328	 * indicator of the firmware's BSSID. Damp spurious
1329	 * change-of-BSSID indications.
1330	 */
1331	if ((ifp->if_flags & IFF_PROMISC) != 0 &&
1332	    !ppsratecheck(&sc->sc_last_syn, &sc->sc_false_syns,
1333	                 WI_MAX_FALSE_SYNS))
1334		return;
1335
1336	sc->sc_false_syns = MAX(0, sc->sc_false_syns - 1);
1337	/*
1338	 * XXX hack; we should create a new node with the new bssid
1339	 * and replace the existing ic_bss with it but since we don't
1340	 * process management frames to collect state we cheat by
1341	 * reusing the existing node as we know wi_newstate will be
1342	 * called and it will overwrite the node state.
1343	 */
1344	ieee80211_sta_join(ic, ieee80211_ref_node(ni));
1345}
1346
1347static void
1348wi_rx_monitor(struct wi_softc *sc, int fid)
1349{
1350	struct ifnet *ifp = sc->sc_ifp;
1351	struct wi_frame *rx_frame;
1352	struct mbuf *m;
1353	int datlen, hdrlen;
1354
1355	/* first allocate mbuf for packet storage */
1356	m = m_getcl(M_DONTWAIT, MT_DATA, 0);
1357	if (m == NULL) {
1358		ifp->if_ierrors++;
1359		return;
1360	}
1361
1362	m->m_pkthdr.rcvif = ifp;
1363
1364	/* now read wi_frame first so we know how much data to read */
1365	if (wi_read_bap(sc, fid, 0, mtod(m, caddr_t), sizeof(*rx_frame))) {
1366		ifp->if_ierrors++;
1367		goto done;
1368	}
1369
1370	rx_frame = mtod(m, struct wi_frame *);
1371
1372	switch ((rx_frame->wi_status & WI_STAT_MAC_PORT) >> 8) {
1373	case 7:
1374		switch (rx_frame->wi_whdr.i_fc[0] & IEEE80211_FC0_TYPE_MASK) {
1375		case IEEE80211_FC0_TYPE_DATA:
1376			hdrlen = WI_DATA_HDRLEN;
1377			datlen = rx_frame->wi_dat_len + WI_FCS_LEN;
1378			break;
1379		case IEEE80211_FC0_TYPE_MGT:
1380			hdrlen = WI_MGMT_HDRLEN;
1381			datlen = rx_frame->wi_dat_len + WI_FCS_LEN;
1382			break;
1383		case IEEE80211_FC0_TYPE_CTL:
1384			/*
1385			 * prism2 cards don't pass control packets
1386			 * down properly or consistently, so we'll only
1387			 * pass down the header.
1388			 */
1389			hdrlen = WI_CTL_HDRLEN;
1390			datlen = 0;
1391			break;
1392		default:
1393			if_printf(ifp, "received packet of unknown type "
1394				"on port 7\n");
1395			ifp->if_ierrors++;
1396			goto done;
1397		}
1398		break;
1399	case 0:
1400		hdrlen = WI_DATA_HDRLEN;
1401		datlen = rx_frame->wi_dat_len + WI_FCS_LEN;
1402		break;
1403	default:
1404		if_printf(ifp, "received packet on invalid "
1405		    "port (wi_status=0x%x)\n", rx_frame->wi_status);
1406		ifp->if_ierrors++;
1407		goto done;
1408	}
1409
1410	if (hdrlen + datlen + 2 > MCLBYTES) {
1411		if_printf(ifp, "oversized packet received "
1412		    "(wi_dat_len=%d, wi_status=0x%x)\n",
1413		    datlen, rx_frame->wi_status);
1414		ifp->if_ierrors++;
1415		goto done;
1416	}
1417
1418	if (wi_read_bap(sc, fid, hdrlen, mtod(m, caddr_t) + hdrlen,
1419	    datlen + 2) == 0) {
1420		m->m_pkthdr.len = m->m_len = hdrlen + datlen;
1421		ifp->if_ipackets++;
1422		BPF_MTAP(ifp, m);	/* Handle BPF listeners. */
1423	} else
1424		ifp->if_ierrors++;
1425done:
1426	m_freem(m);
1427}
1428
1429static void
1430wi_rx_intr(struct wi_softc *sc)
1431{
1432	struct ieee80211com *ic = &sc->sc_ic;
1433	struct ifnet *ifp = sc->sc_ifp;
1434	struct wi_frame frmhdr;
1435	struct mbuf *m;
1436	struct ieee80211_frame *wh;
1437	struct ieee80211_node *ni;
1438	int fid, len, off, rssi;
1439	u_int8_t dir;
1440	u_int16_t status;
1441	u_int32_t rstamp;
1442
1443	fid = CSR_READ_2(sc, WI_RX_FID);
1444
1445	if (sc->wi_debug.wi_monitor) {
1446		/*
1447		 * If we are in monitor mode just
1448		 * read the data from the device.
1449		 */
1450		wi_rx_monitor(sc, fid);
1451		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
1452		return;
1453	}
1454
1455	/* First read in the frame header */
1456	if (wi_read_bap(sc, fid, 0, &frmhdr, sizeof(frmhdr))) {
1457		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
1458		ifp->if_ierrors++;
1459		DPRINTF(("wi_rx_intr: read fid %x failed\n", fid));
1460		return;
1461	}
1462
1463	if (IFF_DUMPPKTS(ifp))
1464		wi_dump_pkt(&frmhdr, NULL, frmhdr.wi_rx_signal);
1465
1466	/*
1467	 * Drop undecryptable or packets with receive errors here
1468	 */
1469	status = le16toh(frmhdr.wi_status);
1470	if (status & WI_STAT_ERRSTAT) {
1471		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
1472		ifp->if_ierrors++;
1473		DPRINTF(("wi_rx_intr: fid %x error status %x\n", fid, status));
1474		return;
1475	}
1476	rssi = frmhdr.wi_rx_signal;
1477	rstamp = (le16toh(frmhdr.wi_rx_tstamp0) << 16) |
1478	    le16toh(frmhdr.wi_rx_tstamp1);
1479
1480	len = le16toh(frmhdr.wi_dat_len);
1481	off = ALIGN(sizeof(struct ieee80211_frame));
1482
1483	/*
1484	 * Sometimes the PRISM2.x returns bogusly large frames. Except
1485	 * in monitor mode, just throw them away.
1486	 */
1487	if (off + len > MCLBYTES) {
1488		if (ic->ic_opmode != IEEE80211_M_MONITOR) {
1489			CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
1490			ifp->if_ierrors++;
1491			DPRINTF(("wi_rx_intr: oversized packet\n"));
1492			return;
1493		} else
1494			len = 0;
1495	}
1496
1497	MGETHDR(m, M_DONTWAIT, MT_DATA);
1498	if (m == NULL) {
1499		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
1500		ifp->if_ierrors++;
1501		DPRINTF(("wi_rx_intr: MGET failed\n"));
1502		return;
1503	}
1504	if (off + len > MHLEN) {
1505		MCLGET(m, M_DONTWAIT);
1506		if ((m->m_flags & M_EXT) == 0) {
1507			CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
1508			m_freem(m);
1509			ifp->if_ierrors++;
1510			DPRINTF(("wi_rx_intr: MCLGET failed\n"));
1511			return;
1512		}
1513	}
1514
1515	m->m_data += off - sizeof(struct ieee80211_frame);
1516	memcpy(m->m_data, &frmhdr.wi_whdr, sizeof(struct ieee80211_frame));
1517	wi_read_bap(sc, fid, sizeof(frmhdr),
1518	    m->m_data + sizeof(struct ieee80211_frame), len);
1519	m->m_pkthdr.len = m->m_len = sizeof(struct ieee80211_frame) + len;
1520	m->m_pkthdr.rcvif = ifp;
1521
1522	CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
1523
1524	wh = mtod(m, struct ieee80211_frame *);
1525	if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
1526		/*
1527		 * WEP is decrypted by hardware and the IV
1528		 * is stripped.  Clear WEP bit so we don't
1529		 * try to process it in ieee80211_input.
1530		 * XXX fix for TKIP, et. al.
1531		 */
1532		wh->i_fc[1] &= ~IEEE80211_FC1_WEP;
1533	}
1534
1535#if NBPFILTER > 0
1536	if (sc->sc_drvbpf) {
1537		/* XXX replace divide by table */
1538		sc->sc_rx_th.wr_rate = frmhdr.wi_rx_rate / 5;
1539		sc->sc_rx_th.wr_antsignal = frmhdr.wi_rx_signal;
1540		sc->sc_rx_th.wr_antnoise = frmhdr.wi_rx_silence;
1541		sc->sc_rx_th.wr_flags = 0;
1542		if (frmhdr.wi_status & WI_STAT_PCF)
1543			sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_CFP;
1544		/* XXX IEEE80211_RADIOTAP_F_WEP */
1545		bpf_mtap2(sc->sc_drvbpf,
1546			&sc->sc_rx_th, sc->sc_rx_th_len, m);
1547	}
1548#endif
1549
1550	/* synchronize driver's BSSID with firmware's BSSID */
1551	dir = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK;
1552	if (ic->ic_opmode == IEEE80211_M_IBSS && dir == IEEE80211_FC1_DIR_NODS)
1553		wi_sync_bssid(sc, wh->i_addr3);
1554
1555	/*
1556	 * Locate the node for sender, track state, and
1557	 * then pass this node (referenced) up to the 802.11
1558	 * layer for its use.
1559	 */
1560	ni = ieee80211_find_rxnode(ic, (struct ieee80211_frame_min *) wh);
1561	/*
1562	 * Send frame up for processing.
1563	 */
1564	ieee80211_input(ic, m, ni, rssi, rstamp);
1565	/*
1566	 * The frame may have caused the node to be marked for
1567	 * reclamation (e.g. in response to a DEAUTH message)
1568	 * so use free_node here instead of unref_node.
1569	 */
1570	ieee80211_free_node(ni);
1571}
1572
1573static void
1574wi_tx_ex_intr(struct wi_softc *sc)
1575{
1576	struct ifnet *ifp = sc->sc_ifp;
1577	struct wi_frame frmhdr;
1578	int fid;
1579
1580	fid = CSR_READ_2(sc, WI_TX_CMP_FID);
1581	/* Read in the frame header */
1582	if (wi_read_bap(sc, fid, 0, &frmhdr, sizeof(frmhdr)) == 0) {
1583		u_int16_t status = le16toh(frmhdr.wi_status);
1584
1585		/*
1586		 * Spontaneous station disconnects appear as xmit
1587		 * errors.  Don't announce them and/or count them
1588		 * as an output error.
1589		 */
1590		if ((status & WI_TXSTAT_DISCONNECT) == 0) {
1591			if (ppsratecheck(&lasttxerror, &curtxeps, wi_txerate)) {
1592				if_printf(ifp, "tx failed");
1593				if (status & WI_TXSTAT_RET_ERR)
1594					printf(", retry limit exceeded");
1595				if (status & WI_TXSTAT_AGED_ERR)
1596					printf(", max transmit lifetime exceeded");
1597				if (status & WI_TXSTAT_DISCONNECT)
1598					printf(", port disconnected");
1599				if (status & WI_TXSTAT_FORM_ERR)
1600					printf(", invalid format (data len %u src %6D)",
1601						le16toh(frmhdr.wi_dat_len),
1602						frmhdr.wi_ehdr.ether_shost, ":");
1603				if (status & ~0xf)
1604					printf(", status=0x%x", status);
1605				printf("\n");
1606			}
1607			ifp->if_oerrors++;
1608		} else {
1609			DPRINTF(("port disconnected\n"));
1610			ifp->if_collisions++;	/* XXX */
1611		}
1612	} else
1613		DPRINTF(("wi_tx_ex_intr: read fid %x failed\n", fid));
1614	CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX_EXC);
1615}
1616
1617static void
1618wi_tx_intr(struct wi_softc *sc)
1619{
1620	struct ifnet *ifp = sc->sc_ifp;
1621	int fid, cur;
1622
1623	if (sc->wi_gone)
1624		return;
1625
1626	fid = CSR_READ_2(sc, WI_ALLOC_FID);
1627	CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
1628
1629	cur = sc->sc_txcur;
1630	if (sc->sc_txd[cur].d_fid != fid) {
1631		if_printf(ifp, "bad alloc %x != %x, cur %d nxt %d\n",
1632		    fid, sc->sc_txd[cur].d_fid, cur, sc->sc_txnext);
1633		return;
1634	}
1635	sc->sc_tx_timer = 0;
1636	sc->sc_txd[cur].d_len = 0;
1637	sc->sc_txcur = cur = (cur + 1) % sc->sc_ntxbuf;
1638	if (sc->sc_txd[cur].d_len == 0)
1639		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
1640	else {
1641		if (wi_cmd(sc, WI_CMD_TX | WI_RECLAIM, sc->sc_txd[cur].d_fid,
1642		    0, 0)) {
1643			if_printf(ifp, "xmit failed\n");
1644			sc->sc_txd[cur].d_len = 0;
1645		} else {
1646			sc->sc_tx_timer = 5;
1647			ifp->if_timer = 1;
1648		}
1649	}
1650}
1651
1652static void
1653wi_info_intr(struct wi_softc *sc)
1654{
1655	struct ieee80211com *ic = &sc->sc_ic;
1656	struct ifnet *ifp = sc->sc_ifp;
1657	int i, fid, len, off;
1658	u_int16_t ltbuf[2];
1659	u_int16_t stat;
1660	u_int32_t *ptr;
1661
1662	fid = CSR_READ_2(sc, WI_INFO_FID);
1663	wi_read_bap(sc, fid, 0, ltbuf, sizeof(ltbuf));
1664
1665	switch (le16toh(ltbuf[1])) {
1666
1667	case WI_INFO_LINK_STAT:
1668		wi_read_bap(sc, fid, sizeof(ltbuf), &stat, sizeof(stat));
1669		DPRINTF(("wi_info_intr: LINK_STAT 0x%x\n", le16toh(stat)));
1670		switch (le16toh(stat)) {
1671		case WI_INFO_LINK_STAT_CONNECTED:
1672			sc->sc_flags &= ~WI_FLAGS_OUTRANGE;
1673			if (ic->ic_state == IEEE80211_S_RUN &&
1674			    ic->ic_opmode != IEEE80211_M_IBSS)
1675				break;
1676			/* FALLTHROUGH */
1677		case WI_INFO_LINK_STAT_AP_CHG:
1678			ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
1679			break;
1680		case WI_INFO_LINK_STAT_AP_INR:
1681			sc->sc_flags &= ~WI_FLAGS_OUTRANGE;
1682			break;
1683		case WI_INFO_LINK_STAT_AP_OOR:
1684			if (sc->sc_firmware_type == WI_SYMBOL &&
1685			    sc->sc_scan_timer > 0) {
1686				if (wi_cmd(sc, WI_CMD_INQUIRE,
1687				    WI_INFO_HOST_SCAN_RESULTS, 0, 0) != 0)
1688					sc->sc_scan_timer = 0;
1689				break;
1690			}
1691			if (ic->ic_opmode == IEEE80211_M_STA)
1692				sc->sc_flags |= WI_FLAGS_OUTRANGE;
1693			break;
1694		case WI_INFO_LINK_STAT_DISCONNECTED:
1695		case WI_INFO_LINK_STAT_ASSOC_FAILED:
1696			if (ic->ic_opmode == IEEE80211_M_STA)
1697				ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
1698			break;
1699		}
1700		break;
1701
1702	case WI_INFO_COUNTERS:
1703		/* some card versions have a larger stats structure */
1704		len = min(le16toh(ltbuf[0]) - 1, sizeof(sc->sc_stats) / 4);
1705		ptr = (u_int32_t *)&sc->sc_stats;
1706		off = sizeof(ltbuf);
1707		for (i = 0; i < len; i++, off += 2, ptr++) {
1708			wi_read_bap(sc, fid, off, &stat, sizeof(stat));
1709#ifdef WI_HERMES_STATS_WAR
1710			if (stat & 0xf000)
1711				stat = ~stat;
1712#endif
1713			*ptr += stat;
1714		}
1715		ifp->if_collisions = sc->sc_stats.wi_tx_single_retries +
1716		    sc->sc_stats.wi_tx_multi_retries +
1717		    sc->sc_stats.wi_tx_retry_limit;
1718		break;
1719
1720	case WI_INFO_SCAN_RESULTS:
1721	case WI_INFO_HOST_SCAN_RESULTS:
1722		wi_scan_result(sc, fid, le16toh(ltbuf[0]));
1723		break;
1724
1725	default:
1726		DPRINTF(("wi_info_intr: got fid %x type %x len %d\n", fid,
1727		    le16toh(ltbuf[1]), le16toh(ltbuf[0])));
1728		break;
1729	}
1730	CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO);
1731}
1732
1733static int
1734wi_write_multi(struct wi_softc *sc)
1735{
1736	struct ifnet *ifp = sc->sc_ifp;
1737	int n;
1738	struct ifmultiaddr *ifma;
1739	struct wi_mcast mlist;
1740
1741	if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
1742allmulti:
1743		memset(&mlist, 0, sizeof(mlist));
1744		return wi_write_rid(sc, WI_RID_MCAST_LIST, &mlist,
1745		    sizeof(mlist));
1746	}
1747
1748	n = 0;
1749	IF_ADDR_LOCK(ifp);
1750#if __FreeBSD_version < 500000
1751	LIST_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
1752#else
1753	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
1754#endif
1755		if (ifma->ifma_addr->sa_family != AF_LINK)
1756			continue;
1757		if (n >= 16)
1758			goto allmulti;
1759		IEEE80211_ADDR_COPY(&mlist.wi_mcast[n],
1760		    (LLADDR((struct sockaddr_dl *)ifma->ifma_addr)));
1761		n++;
1762	}
1763	IF_ADDR_UNLOCK(ifp);
1764	return wi_write_rid(sc, WI_RID_MCAST_LIST, &mlist,
1765	    IEEE80211_ADDR_LEN * n);
1766}
1767
1768static void
1769wi_read_nicid(struct wi_softc *sc)
1770{
1771	struct wi_card_ident *id;
1772	char *p;
1773	int len;
1774	u_int16_t ver[4];
1775
1776	/* getting chip identity */
1777	memset(ver, 0, sizeof(ver));
1778	len = sizeof(ver);
1779	wi_read_rid(sc, WI_RID_CARD_ID, ver, &len);
1780	device_printf(sc->sc_dev, "using ");
1781
1782	sc->sc_firmware_type = WI_NOTYPE;
1783	for (id = wi_card_ident; id->card_name != NULL; id++) {
1784		if (le16toh(ver[0]) == id->card_id) {
1785			printf("%s", id->card_name);
1786			sc->sc_firmware_type = id->firm_type;
1787			break;
1788		}
1789	}
1790	if (sc->sc_firmware_type == WI_NOTYPE) {
1791		if (le16toh(ver[0]) & 0x8000) {
1792			printf("Unknown PRISM2 chip");
1793			sc->sc_firmware_type = WI_INTERSIL;
1794		} else {
1795			printf("Unknown Lucent chip");
1796			sc->sc_firmware_type = WI_LUCENT;
1797		}
1798	}
1799
1800	/* get primary firmware version (Only Prism chips) */
1801	if (sc->sc_firmware_type != WI_LUCENT) {
1802		memset(ver, 0, sizeof(ver));
1803		len = sizeof(ver);
1804		wi_read_rid(sc, WI_RID_PRI_IDENTITY, ver, &len);
1805		sc->sc_pri_firmware_ver = le16toh(ver[2]) * 10000 +
1806		    le16toh(ver[3]) * 100 + le16toh(ver[1]);
1807	}
1808
1809	/* get station firmware version */
1810	memset(ver, 0, sizeof(ver));
1811	len = sizeof(ver);
1812	wi_read_rid(sc, WI_RID_STA_IDENTITY, ver, &len);
1813	sc->sc_sta_firmware_ver = le16toh(ver[2]) * 10000 +
1814	    le16toh(ver[3]) * 100 + le16toh(ver[1]);
1815	if (sc->sc_firmware_type == WI_INTERSIL &&
1816	    (sc->sc_sta_firmware_ver == 10102 ||
1817	     sc->sc_sta_firmware_ver == 20102)) {
1818		char ident[12];
1819		memset(ident, 0, sizeof(ident));
1820		len = sizeof(ident);
1821		/* value should be the format like "V2.00-11" */
1822		if (wi_read_rid(sc, WI_RID_SYMBOL_IDENTITY, ident, &len) == 0 &&
1823		    *(p = (char *)ident) >= 'A' &&
1824		    p[2] == '.' && p[5] == '-' && p[8] == '\0') {
1825			sc->sc_firmware_type = WI_SYMBOL;
1826			sc->sc_sta_firmware_ver = (p[1] - '0') * 10000 +
1827			    (p[3] - '0') * 1000 + (p[4] - '0') * 100 +
1828			    (p[6] - '0') * 10 + (p[7] - '0');
1829		}
1830	}
1831	printf("\n");
1832	device_printf(sc->sc_dev, "%s Firmware: ",
1833	     sc->sc_firmware_type == WI_LUCENT ? "Lucent" :
1834	    (sc->sc_firmware_type == WI_SYMBOL ? "Symbol" : "Intersil"));
1835	if (sc->sc_firmware_type != WI_LUCENT)	/* XXX */
1836		printf("Primary (%u.%u.%u), ",
1837		    sc->sc_pri_firmware_ver / 10000,
1838		    (sc->sc_pri_firmware_ver % 10000) / 100,
1839		    sc->sc_pri_firmware_ver % 100);
1840	printf("Station (%u.%u.%u)\n",
1841	    sc->sc_sta_firmware_ver / 10000,
1842	    (sc->sc_sta_firmware_ver % 10000) / 100,
1843	    sc->sc_sta_firmware_ver % 100);
1844}
1845
1846static int
1847wi_write_ssid(struct wi_softc *sc, int rid, u_int8_t *buf, int buflen)
1848{
1849	struct wi_ssid ssid;
1850
1851	if (buflen > IEEE80211_NWID_LEN)
1852		return ENOBUFS;
1853	memset(&ssid, 0, sizeof(ssid));
1854	ssid.wi_len = htole16(buflen);
1855	memcpy(ssid.wi_ssid, buf, buflen);
1856	return wi_write_rid(sc, rid, &ssid, sizeof(ssid));
1857}
1858
1859static int
1860wi_get_cfg(struct ifnet *ifp, u_long cmd, caddr_t data)
1861{
1862	struct wi_softc *sc = ifp->if_softc;
1863	struct ieee80211com *ic = &sc->sc_ic;
1864	struct ifreq *ifr = (struct ifreq *)data;
1865	struct wi_req wreq;
1866	struct wi_scan_res *res;
1867	size_t reslen;
1868	int len, n, error, mif, val, off, i;
1869
1870	error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
1871	if (error)
1872		return error;
1873	len = (wreq.wi_len - 1) * 2;
1874	if (len < sizeof(u_int16_t))
1875		return ENOSPC;
1876	if (len > sizeof(wreq.wi_val))
1877		len = sizeof(wreq.wi_val);
1878
1879	switch (wreq.wi_type) {
1880
1881	case WI_RID_IFACE_STATS:
1882		memcpy(wreq.wi_val, &sc->sc_stats, sizeof(sc->sc_stats));
1883		if (len < sizeof(sc->sc_stats))
1884			error = ENOSPC;
1885		else
1886			len = sizeof(sc->sc_stats);
1887		break;
1888
1889	case WI_RID_ENCRYPTION:
1890	case WI_RID_TX_CRYPT_KEY:
1891	case WI_RID_DEFLT_CRYPT_KEYS:
1892	case WI_RID_TX_RATE:
1893		return ieee80211_cfgget(ic, cmd, data);
1894
1895	case WI_RID_MICROWAVE_OVEN:
1896		if (sc->sc_enabled && (sc->sc_flags & WI_FLAGS_HAS_MOR)) {
1897			error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val,
1898			    &len);
1899			break;
1900		}
1901		wreq.wi_val[0] = htole16(sc->sc_microwave_oven);
1902		len = sizeof(u_int16_t);
1903		break;
1904
1905	case WI_RID_DBM_ADJUST:
1906		if (sc->sc_enabled && (sc->sc_flags & WI_FLAGS_HAS_DBMADJUST)) {
1907			error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val,
1908			    &len);
1909			break;
1910		}
1911		wreq.wi_val[0] = htole16(sc->sc_dbm_offset);
1912		len = sizeof(u_int16_t);
1913		break;
1914
1915	case WI_RID_ROAMING_MODE:
1916		if (sc->sc_enabled && (sc->sc_flags & WI_FLAGS_HAS_ROAMING)) {
1917			error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val,
1918			    &len);
1919			break;
1920		}
1921		wreq.wi_val[0] = htole16(sc->sc_roaming_mode);
1922		len = sizeof(u_int16_t);
1923		break;
1924
1925	case WI_RID_SYSTEM_SCALE:
1926		if (sc->sc_enabled && (sc->sc_flags & WI_FLAGS_HAS_SYSSCALE)) {
1927			error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val,
1928			    &len);
1929			break;
1930		}
1931		wreq.wi_val[0] = htole16(sc->sc_system_scale);
1932		len = sizeof(u_int16_t);
1933		break;
1934
1935	case WI_RID_FRAG_THRESH:
1936		if (sc->sc_enabled && (sc->sc_flags & WI_FLAGS_HAS_FRAGTHR)) {
1937			error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val,
1938			    &len);
1939			break;
1940		}
1941		wreq.wi_val[0] = htole16(ic->ic_fragthreshold);
1942		len = sizeof(u_int16_t);
1943		break;
1944
1945	case WI_RID_READ_APS:
1946		if (ic->ic_opmode == IEEE80211_M_HOSTAP)
1947			return ieee80211_cfgget(ic, cmd, data);
1948		if (sc->sc_scan_timer > 0) {
1949			error = EINPROGRESS;
1950			break;
1951		}
1952		n = sc->sc_naps;
1953		if (len < sizeof(n)) {
1954			error = ENOSPC;
1955			break;
1956		}
1957		if (len < sizeof(n) + sizeof(struct wi_apinfo) * n)
1958			n = (len - sizeof(n)) / sizeof(struct wi_apinfo);
1959		len = sizeof(n) + sizeof(struct wi_apinfo) * n;
1960		memcpy(wreq.wi_val, &n, sizeof(n));
1961		memcpy((caddr_t)wreq.wi_val + sizeof(n), sc->sc_aps,
1962		    sizeof(struct wi_apinfo) * n);
1963		break;
1964
1965	case WI_RID_PRISM2:
1966		wreq.wi_val[0] = sc->sc_firmware_type != WI_LUCENT;
1967		len = sizeof(u_int16_t);
1968		break;
1969
1970	case WI_RID_MIF:
1971		mif = wreq.wi_val[0];
1972		error = wi_cmd(sc, WI_CMD_READMIF, mif, 0, 0);
1973		val = CSR_READ_2(sc, WI_RESP0);
1974		wreq.wi_val[0] = val;
1975		len = sizeof(u_int16_t);
1976		break;
1977
1978	case WI_RID_ZERO_CACHE:
1979	case WI_RID_PROCFRAME:		/* ignore for compatibility */
1980		/* XXX ??? */
1981		break;
1982
1983	case WI_RID_READ_CACHE:
1984		return ieee80211_cfgget(ic, cmd, data);
1985
1986	case WI_RID_SCAN_RES:		/* compatibility interface */
1987		if (ic->ic_opmode == IEEE80211_M_HOSTAP)
1988			return ieee80211_cfgget(ic, cmd, data);
1989		if (sc->sc_scan_timer > 0) {
1990			error = EINPROGRESS;
1991			break;
1992		}
1993		n = sc->sc_naps;
1994		if (sc->sc_firmware_type == WI_LUCENT) {
1995			off = 0;
1996			reslen = WI_WAVELAN_RES_SIZE;
1997		} else {
1998			off = sizeof(struct wi_scan_p2_hdr);
1999			reslen = WI_PRISM2_RES_SIZE;
2000		}
2001		if (len < off + reslen * n)
2002			n = (len - off) / reslen;
2003		len = off + reslen * n;
2004		if (off != 0) {
2005			struct wi_scan_p2_hdr *p2 = (struct wi_scan_p2_hdr *)wreq.wi_val;
2006			/*
2007			 * Prepend Prism-specific header.
2008			 */
2009			if (len < sizeof(struct wi_scan_p2_hdr)) {
2010				error = ENOSPC;
2011				break;
2012			}
2013			p2 = (struct wi_scan_p2_hdr *)wreq.wi_val;
2014			p2->wi_rsvd = 0;
2015			p2->wi_reason = n;	/* XXX */
2016		}
2017		for (i = 0; i < n; i++, off += reslen) {
2018			const struct wi_apinfo *ap = &sc->sc_aps[i];
2019
2020			res = (struct wi_scan_res *)((char *)wreq.wi_val + off);
2021			res->wi_chan = ap->channel;
2022			res->wi_noise = ap->noise;
2023			res->wi_signal = ap->signal;
2024			IEEE80211_ADDR_COPY(res->wi_bssid, ap->bssid);
2025			res->wi_interval = ap->interval;
2026			res->wi_capinfo = ap->capinfo;
2027			res->wi_ssid_len = ap->namelen;
2028			memcpy(res->wi_ssid, ap->name,
2029				IEEE80211_NWID_LEN);
2030			if (sc->sc_firmware_type != WI_LUCENT) {
2031				/* XXX not saved from Prism cards */
2032				memset(res->wi_srates, 0,
2033					sizeof(res->wi_srates));
2034				res->wi_rate = ap->rate;
2035				res->wi_rsvd = 0;
2036			}
2037		}
2038		break;
2039
2040	default:
2041		if (sc->sc_enabled) {
2042			error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val,
2043			    &len);
2044			break;
2045		}
2046		switch (wreq.wi_type) {
2047		case WI_RID_MAX_DATALEN:
2048			wreq.wi_val[0] = htole16(sc->sc_max_datalen);
2049			len = sizeof(u_int16_t);
2050			break;
2051		case WI_RID_RTS_THRESH:
2052			wreq.wi_val[0] = htole16(ic->ic_rtsthreshold);
2053			len = sizeof(u_int16_t);
2054			break;
2055		case WI_RID_CNFAUTHMODE:
2056			wreq.wi_val[0] = htole16(sc->sc_cnfauthmode);
2057			len = sizeof(u_int16_t);
2058			break;
2059		case WI_RID_NODENAME:
2060			if (len < sc->sc_nodelen + sizeof(u_int16_t)) {
2061				error = ENOSPC;
2062				break;
2063			}
2064			len = sc->sc_nodelen + sizeof(u_int16_t);
2065			wreq.wi_val[0] = htole16((sc->sc_nodelen + 1) / 2);
2066			memcpy(&wreq.wi_val[1], sc->sc_nodename,
2067			    sc->sc_nodelen);
2068			break;
2069		default:
2070			return ieee80211_cfgget(ic, cmd, data);
2071		}
2072		break;
2073	}
2074	if (error)
2075		return error;
2076	wreq.wi_len = (len + 1) / 2 + 1;
2077	return copyout(&wreq, ifr->ifr_data, (wreq.wi_len + 1) * 2);
2078}
2079
2080static int
2081wi_set_cfg(struct ifnet *ifp, u_long cmd, caddr_t data)
2082{
2083	struct wi_softc *sc = ifp->if_softc;
2084	struct ieee80211com *ic = &sc->sc_ic;
2085	struct ifreq *ifr = (struct ifreq *)data;
2086	struct wi_req wreq;
2087	struct mbuf *m;
2088	int i, len, error, mif, val;
2089	struct ieee80211_rateset *rs;
2090	WI_LOCK_DECL();
2091
2092	error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
2093	if (error)
2094		return error;
2095	len = wreq.wi_len ? (wreq.wi_len - 1) * 2 : 0;
2096	switch (wreq.wi_type) {
2097	case WI_RID_DBM_ADJUST:
2098		return ENODEV;
2099
2100	case WI_RID_NODENAME:
2101		if (le16toh(wreq.wi_val[0]) * 2 > len ||
2102		    le16toh(wreq.wi_val[0]) > sizeof(sc->sc_nodename)) {
2103			error = ENOSPC;
2104			break;
2105		}
2106		WI_LOCK(sc);
2107		if (sc->sc_enabled)
2108			error = wi_write_rid(sc, wreq.wi_type, wreq.wi_val,
2109			    len);
2110		if (error == 0) {
2111			sc->sc_nodelen = le16toh(wreq.wi_val[0]) * 2;
2112			memcpy(sc->sc_nodename, &wreq.wi_val[1],
2113				sc->sc_nodelen);
2114		}
2115		WI_UNLOCK(sc);
2116		break;
2117
2118	case WI_RID_MICROWAVE_OVEN:
2119	case WI_RID_ROAMING_MODE:
2120	case WI_RID_SYSTEM_SCALE:
2121	case WI_RID_FRAG_THRESH:
2122		/* XXX unlocked reads */
2123		if (wreq.wi_type == WI_RID_MICROWAVE_OVEN &&
2124		    (sc->sc_flags & WI_FLAGS_HAS_MOR) == 0)
2125			break;
2126		if (wreq.wi_type == WI_RID_ROAMING_MODE &&
2127		    (sc->sc_flags & WI_FLAGS_HAS_ROAMING) == 0)
2128			break;
2129		if (wreq.wi_type == WI_RID_SYSTEM_SCALE &&
2130		    (sc->sc_flags & WI_FLAGS_HAS_SYSSCALE) == 0)
2131			break;
2132		if (wreq.wi_type == WI_RID_FRAG_THRESH &&
2133		    (sc->sc_flags & WI_FLAGS_HAS_FRAGTHR) == 0)
2134			break;
2135		/* FALLTHROUGH */
2136	case WI_RID_RTS_THRESH:
2137	case WI_RID_CNFAUTHMODE:
2138	case WI_RID_MAX_DATALEN:
2139		WI_LOCK(sc);
2140		if (sc->sc_enabled) {
2141			error = wi_write_rid(sc, wreq.wi_type, wreq.wi_val,
2142			    sizeof(u_int16_t));
2143			if (error != 0) {
2144				WI_UNLOCK(sc);
2145				break;
2146			}
2147		}
2148		switch (wreq.wi_type) {
2149		case WI_RID_FRAG_THRESH:
2150			ic->ic_fragthreshold = le16toh(wreq.wi_val[0]);
2151			break;
2152		case WI_RID_RTS_THRESH:
2153			ic->ic_rtsthreshold = le16toh(wreq.wi_val[0]);
2154			break;
2155		case WI_RID_MICROWAVE_OVEN:
2156			sc->sc_microwave_oven = le16toh(wreq.wi_val[0]);
2157			break;
2158		case WI_RID_ROAMING_MODE:
2159			sc->sc_roaming_mode = le16toh(wreq.wi_val[0]);
2160			break;
2161		case WI_RID_SYSTEM_SCALE:
2162			sc->sc_system_scale = le16toh(wreq.wi_val[0]);
2163			break;
2164		case WI_RID_CNFAUTHMODE:
2165			sc->sc_cnfauthmode = le16toh(wreq.wi_val[0]);
2166			break;
2167		case WI_RID_MAX_DATALEN:
2168			sc->sc_max_datalen = le16toh(wreq.wi_val[0]);
2169			break;
2170		}
2171		WI_UNLOCK(sc);
2172		break;
2173
2174	case WI_RID_TX_RATE:
2175		WI_LOCK(sc);
2176		switch (le16toh(wreq.wi_val[0])) {
2177		case 3:
2178			ic->ic_fixed_rate = IEEE80211_FIXED_RATE_NONE;
2179			break;
2180		default:
2181			rs = &ic->ic_sup_rates[IEEE80211_MODE_11B];
2182			for (i = 0; i < rs->rs_nrates; i++) {
2183				if ((rs->rs_rates[i] & IEEE80211_RATE_VAL)
2184				    / 2 == le16toh(wreq.wi_val[0]))
2185					break;
2186			}
2187			if (i == rs->rs_nrates) {
2188				WI_UNLOCK(sc);
2189				return EINVAL;
2190			}
2191			ic->ic_fixed_rate = i;
2192		}
2193		if (sc->sc_enabled)
2194			error = wi_write_txrate(sc);
2195		WI_UNLOCK(sc);
2196		break;
2197
2198	case WI_RID_SCAN_APS:
2199		WI_LOCK(sc);
2200		if (sc->sc_enabled && ic->ic_opmode != IEEE80211_M_HOSTAP)
2201			error = wi_scan_ap(sc, 0x3fff, 0x000f);
2202		WI_UNLOCK(sc);
2203		break;
2204
2205	case WI_RID_SCAN_REQ:		/* compatibility interface */
2206		WI_LOCK(sc);
2207		if (sc->sc_enabled && ic->ic_opmode != IEEE80211_M_HOSTAP)
2208			error = wi_scan_ap(sc, wreq.wi_val[0], wreq.wi_val[1]);
2209		WI_UNLOCK(sc);
2210		break;
2211
2212	case WI_RID_MGMT_XMIT:
2213		WI_LOCK(sc);
2214		if (!sc->sc_enabled)
2215			error = ENETDOWN;
2216		else if (ic->ic_mgtq.ifq_len > 5)
2217			error = EAGAIN;
2218		else {
2219			/* NB: m_devget uses M_DONTWAIT so can hold the lock */
2220			/* XXX wi_len looks in u_int8_t, not in u_int16_t */
2221			m = m_devget((char *)&wreq.wi_val, wreq.wi_len, 0,
2222				ifp, NULL);
2223			if (m != NULL)
2224				IF_ENQUEUE(&ic->ic_mgtq, m);
2225			else
2226				error = ENOMEM;
2227		}
2228		WI_UNLOCK(sc);
2229		break;
2230
2231	case WI_RID_MIF:
2232		mif = wreq.wi_val[0];
2233		val = wreq.wi_val[1];
2234		WI_LOCK(sc);
2235		error = wi_cmd(sc, WI_CMD_WRITEMIF, mif, val, 0);
2236		WI_UNLOCK(sc);
2237		break;
2238
2239	case WI_RID_PROCFRAME:		/* ignore for compatibility */
2240		break;
2241
2242	case WI_RID_OWN_SSID:
2243		if (le16toh(wreq.wi_val[0]) * 2 > len ||
2244		    le16toh(wreq.wi_val[0]) > IEEE80211_NWID_LEN) {
2245			error = ENOSPC;
2246			break;
2247		}
2248		WI_LOCK(sc);
2249		memset(ic->ic_des_essid, 0, IEEE80211_NWID_LEN);
2250		ic->ic_des_esslen = le16toh(wreq.wi_val[0]) * 2;
2251		memcpy(ic->ic_des_essid, &wreq.wi_val[1], ic->ic_des_esslen);
2252		if (sc->sc_enabled)
2253			wi_init(sc);	/* XXX no error return */
2254		WI_UNLOCK(sc);
2255		break;
2256
2257	default:
2258		WI_LOCK(sc);
2259		if (sc->sc_enabled)
2260			error = wi_write_rid(sc, wreq.wi_type, wreq.wi_val,
2261			    len);
2262		if (error == 0) {
2263			/* XXX ieee80211_cfgset does a copyin */
2264			error = ieee80211_cfgset(ic, cmd, data);
2265			if (error == ENETRESET) {
2266				if (sc->sc_enabled)
2267					wi_init(sc);
2268				error = 0;
2269			}
2270		}
2271		WI_UNLOCK(sc);
2272		break;
2273	}
2274	return error;
2275}
2276
2277static int
2278wi_write_txrate(struct wi_softc *sc)
2279{
2280	struct ieee80211com *ic = &sc->sc_ic;
2281	int i;
2282	u_int16_t rate;
2283
2284	if (ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE)
2285		rate = 0;	/* auto */
2286	else
2287		rate = (ic->ic_sup_rates[IEEE80211_MODE_11B].rs_rates[ic->ic_fixed_rate] &
2288		    IEEE80211_RATE_VAL) / 2;
2289
2290	/* rate: 0, 1, 2, 5, 11 */
2291
2292	switch (sc->sc_firmware_type) {
2293	case WI_LUCENT:
2294		switch (rate) {
2295		case 0:			/* auto == 11mbps auto */
2296			rate = 3;
2297			break;
2298		/* case 1, 2 map to 1, 2*/
2299		case 5:			/* 5.5Mbps -> 4 */
2300			rate = 4;
2301			break;
2302		case 11:		/* 11mbps -> 5 */
2303			rate = 5;
2304			break;
2305		default:
2306			break;
2307		}
2308		break;
2309	default:
2310		/* Choose a bit according to this table.
2311		 *
2312		 * bit | data rate
2313		 * ----+-------------------
2314		 * 0   | 1Mbps
2315		 * 1   | 2Mbps
2316		 * 2   | 5.5Mbps
2317		 * 3   | 11Mbps
2318		 */
2319		for (i = 8; i > 0; i >>= 1) {
2320			if (rate >= i)
2321				break;
2322		}
2323		if (i == 0)
2324			rate = 0xf;	/* auto */
2325		else
2326			rate = i;
2327		break;
2328	}
2329	return wi_write_val(sc, WI_RID_TX_RATE, rate);
2330}
2331
2332static int
2333wi_write_wep(struct wi_softc *sc)
2334{
2335	struct ieee80211com *ic = &sc->sc_ic;
2336	int error = 0;
2337	int i, keylen;
2338	u_int16_t val;
2339	struct wi_key wkey[IEEE80211_WEP_NKID];
2340
2341	switch (sc->sc_firmware_type) {
2342	case WI_LUCENT:
2343		val = (ic->ic_flags & IEEE80211_F_PRIVACY) ? 1 : 0;
2344		error = wi_write_val(sc, WI_RID_ENCRYPTION, val);
2345		if (error)
2346			break;
2347		if ((ic->ic_flags & IEEE80211_F_PRIVACY) == 0)
2348			break;
2349		error = wi_write_val(sc, WI_RID_TX_CRYPT_KEY, ic->ic_def_txkey);
2350		if (error)
2351			break;
2352		memset(wkey, 0, sizeof(wkey));
2353		for (i = 0; i < IEEE80211_WEP_NKID; i++) {
2354			keylen = ic->ic_nw_keys[i].wk_keylen;
2355			wkey[i].wi_keylen = htole16(keylen);
2356			memcpy(wkey[i].wi_keydat, ic->ic_nw_keys[i].wk_key,
2357			    keylen);
2358		}
2359		error = wi_write_rid(sc, WI_RID_DEFLT_CRYPT_KEYS,
2360		    wkey, sizeof(wkey));
2361		break;
2362
2363	case WI_INTERSIL:
2364	case WI_SYMBOL:
2365		if (ic->ic_flags & IEEE80211_F_PRIVACY) {
2366			/*
2367			 * ONLY HWB3163 EVAL-CARD Firmware version
2368			 * less than 0.8 variant2
2369			 *
2370			 *   If promiscuous mode disable, Prism2 chip
2371			 *  does not work with WEP .
2372			 * It is under investigation for details.
2373			 * (ichiro@netbsd.org)
2374			 */
2375			if (sc->sc_firmware_type == WI_INTERSIL &&
2376			    sc->sc_sta_firmware_ver < 802 ) {
2377				/* firm ver < 0.8 variant 2 */
2378				wi_write_val(sc, WI_RID_PROMISC, 1);
2379			}
2380			wi_write_val(sc, WI_RID_CNFAUTHMODE,
2381			    sc->sc_cnfauthmode);
2382			val = PRIVACY_INVOKED | EXCLUDE_UNENCRYPTED;
2383			/*
2384			 * Encryption firmware has a bug for HostAP mode.
2385			 */
2386			if (sc->sc_firmware_type == WI_INTERSIL &&
2387			    ic->ic_opmode == IEEE80211_M_HOSTAP)
2388				val |= HOST_ENCRYPT;
2389		} else {
2390			wi_write_val(sc, WI_RID_CNFAUTHMODE,
2391			    IEEE80211_AUTH_OPEN);
2392			val = HOST_ENCRYPT | HOST_DECRYPT;
2393		}
2394		error = wi_write_val(sc, WI_RID_P2_ENCRYPTION, val);
2395		if (error)
2396			break;
2397		if ((val & PRIVACY_INVOKED) == 0)
2398			break;
2399		error = wi_write_val(sc, WI_RID_P2_TX_CRYPT_KEY,
2400		    ic->ic_def_txkey);
2401		if (error)
2402			break;
2403		if (val & HOST_DECRYPT)
2404			break;
2405		/*
2406		 * It seems that the firmware accept 104bit key only if
2407		 * all the keys have 104bit length.  We get the length of
2408		 * the transmit key and use it for all other keys.
2409		 * Perhaps we should use software WEP for such situation.
2410		 */
2411		if (ic->ic_def_txkey != IEEE80211_KEYIX_NONE)
2412			keylen = ic->ic_nw_keys[ic->ic_def_txkey].wk_keylen;
2413		else	/* XXX should not hapen */
2414			keylen = IEEE80211_WEP_KEYLEN;
2415		if (keylen > IEEE80211_WEP_KEYLEN)
2416			keylen = 13;	/* 104bit keys */
2417		else
2418			keylen = IEEE80211_WEP_KEYLEN;
2419		for (i = 0; i < IEEE80211_WEP_NKID; i++) {
2420			error = wi_write_rid(sc, WI_RID_P2_CRYPT_KEY0 + i,
2421			    ic->ic_nw_keys[i].wk_key, keylen);
2422			if (error)
2423				break;
2424		}
2425		break;
2426	}
2427	return error;
2428}
2429
2430static int
2431wi_cmd(struct wi_softc *sc, int cmd, int val0, int val1, int val2)
2432{
2433	int			i, s = 0;
2434	static volatile int count  = 0;
2435
2436	if (sc->wi_gone)
2437		return (ENODEV);
2438
2439	if (count > 0)
2440		panic("Hey partner, hold on there!");
2441	count++;
2442
2443	/* wait for the busy bit to clear */
2444	for (i = sc->wi_cmd_count; i > 0; i--) {	/* 500ms */
2445		if (!(CSR_READ_2(sc, WI_COMMAND) & WI_CMD_BUSY))
2446			break;
2447		DELAY(1*1000);	/* 1ms */
2448	}
2449	if (i == 0) {
2450		device_printf(sc->sc_dev, "wi_cmd: busy bit won't clear.\n" );
2451		sc->wi_gone = 1;
2452		count--;
2453		return(ETIMEDOUT);
2454	}
2455
2456	CSR_WRITE_2(sc, WI_PARAM0, val0);
2457	CSR_WRITE_2(sc, WI_PARAM1, val1);
2458	CSR_WRITE_2(sc, WI_PARAM2, val2);
2459	CSR_WRITE_2(sc, WI_COMMAND, cmd);
2460
2461	if (cmd == WI_CMD_INI) {
2462		/* XXX: should sleep here. */
2463		DELAY(100*1000);		/* 100ms delay for init */
2464	}
2465	for (i = 0; i < WI_TIMEOUT; i++) {
2466		/*
2467		 * Wait for 'command complete' bit to be
2468		 * set in the event status register.
2469		 */
2470		s = CSR_READ_2(sc, WI_EVENT_STAT);
2471		if (s & WI_EV_CMD) {
2472			/* Ack the event and read result code. */
2473			s = CSR_READ_2(sc, WI_STATUS);
2474			CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_CMD);
2475			if (s & WI_STAT_CMD_RESULT) {
2476				count--;
2477				return(EIO);
2478			}
2479			break;
2480		}
2481		DELAY(WI_DELAY);
2482	}
2483
2484	count--;
2485	if (i == WI_TIMEOUT) {
2486		device_printf(sc->sc_dev,
2487		    "timeout in wi_cmd 0x%04x; event status 0x%04x\n", cmd, s);
2488		if (s == 0xffff)
2489			sc->wi_gone = 1;
2490		return(ETIMEDOUT);
2491	}
2492	return (0);
2493}
2494
2495static int
2496wi_seek_bap(struct wi_softc *sc, int id, int off)
2497{
2498	int i, status;
2499
2500	CSR_WRITE_2(sc, WI_SEL0, id);
2501	CSR_WRITE_2(sc, WI_OFF0, off);
2502
2503	for (i = 0; ; i++) {
2504		status = CSR_READ_2(sc, WI_OFF0);
2505		if ((status & WI_OFF_BUSY) == 0)
2506			break;
2507		if (i == WI_TIMEOUT) {
2508			device_printf(sc->sc_dev, "timeout in wi_seek to %x/%x\n",
2509			    id, off);
2510			sc->sc_bap_off = WI_OFF_ERR;	/* invalidate */
2511			if (status == 0xffff)
2512				sc->wi_gone = 1;
2513			return ETIMEDOUT;
2514		}
2515		DELAY(1);
2516	}
2517	if (status & WI_OFF_ERR) {
2518		device_printf(sc->sc_dev, "failed in wi_seek to %x/%x\n", id, off);
2519		sc->sc_bap_off = WI_OFF_ERR;	/* invalidate */
2520		return EIO;
2521	}
2522	sc->sc_bap_id = id;
2523	sc->sc_bap_off = off;
2524	return 0;
2525}
2526
2527static int
2528wi_read_bap(struct wi_softc *sc, int id, int off, void *buf, int buflen)
2529{
2530	u_int16_t *ptr;
2531	int i, error, cnt;
2532
2533	if (buflen == 0)
2534		return 0;
2535	if (id != sc->sc_bap_id || off != sc->sc_bap_off) {
2536		if ((error = wi_seek_bap(sc, id, off)) != 0)
2537			return error;
2538	}
2539	cnt = (buflen + 1) / 2;
2540	ptr = (u_int16_t *)buf;
2541	for (i = 0; i < cnt; i++)
2542		*ptr++ = CSR_READ_2(sc, WI_DATA0);
2543	sc->sc_bap_off += cnt * 2;
2544	return 0;
2545}
2546
2547static int
2548wi_write_bap(struct wi_softc *sc, int id, int off, void *buf, int buflen)
2549{
2550	u_int16_t *ptr;
2551	int i, error, cnt;
2552
2553	if (buflen == 0)
2554		return 0;
2555
2556#ifdef WI_HERMES_AUTOINC_WAR
2557  again:
2558#endif
2559	if (id != sc->sc_bap_id || off != sc->sc_bap_off) {
2560		if ((error = wi_seek_bap(sc, id, off)) != 0)
2561			return error;
2562	}
2563	cnt = (buflen + 1) / 2;
2564	ptr = (u_int16_t *)buf;
2565	for (i = 0; i < cnt; i++)
2566		CSR_WRITE_2(sc, WI_DATA0, ptr[i]);
2567	sc->sc_bap_off += cnt * 2;
2568
2569#ifdef WI_HERMES_AUTOINC_WAR
2570	/*
2571	 * According to the comments in the HCF Light code, there is a bug
2572	 * in the Hermes (or possibly in certain Hermes firmware revisions)
2573	 * where the chip's internal autoincrement counter gets thrown off
2574	 * during data writes:  the autoincrement is missed, causing one
2575	 * data word to be overwritten and subsequent words to be written to
2576	 * the wrong memory locations. The end result is that we could end
2577	 * up transmitting bogus frames without realizing it. The workaround
2578	 * for this is to write a couple of extra guard words after the end
2579	 * of the transfer, then attempt to read then back. If we fail to
2580	 * locate the guard words where we expect them, we preform the
2581	 * transfer over again.
2582	 */
2583	if ((sc->sc_flags & WI_FLAGS_BUG_AUTOINC) && (id & 0xf000) == 0) {
2584		CSR_WRITE_2(sc, WI_DATA0, 0x1234);
2585		CSR_WRITE_2(sc, WI_DATA0, 0x5678);
2586		wi_seek_bap(sc, id, sc->sc_bap_off);
2587		sc->sc_bap_off = WI_OFF_ERR;	/* invalidate */
2588		if (CSR_READ_2(sc, WI_DATA0) != 0x1234 ||
2589		    CSR_READ_2(sc, WI_DATA0) != 0x5678) {
2590			device_printf(sc->sc_dev,
2591				"detect auto increment bug, try again\n");
2592			goto again;
2593		}
2594	}
2595#endif
2596	return 0;
2597}
2598
2599static int
2600wi_mwrite_bap(struct wi_softc *sc, int id, int off, struct mbuf *m0, int totlen)
2601{
2602	int error, len;
2603	struct mbuf *m;
2604
2605	for (m = m0; m != NULL && totlen > 0; m = m->m_next) {
2606		if (m->m_len == 0)
2607			continue;
2608
2609		len = min(m->m_len, totlen);
2610
2611		if (((u_long)m->m_data) % 2 != 0 || len % 2 != 0) {
2612			m_copydata(m, 0, totlen, (caddr_t)&sc->sc_txbuf);
2613			return wi_write_bap(sc, id, off, (caddr_t)&sc->sc_txbuf,
2614			    totlen);
2615		}
2616
2617		if ((error = wi_write_bap(sc, id, off, m->m_data, len)) != 0)
2618			return error;
2619
2620		off += m->m_len;
2621		totlen -= len;
2622	}
2623	return 0;
2624}
2625
2626static int
2627wi_alloc_fid(struct wi_softc *sc, int len, int *idp)
2628{
2629	int i;
2630
2631	if (wi_cmd(sc, WI_CMD_ALLOC_MEM, len, 0, 0)) {
2632		device_printf(sc->sc_dev, "failed to allocate %d bytes on NIC\n",
2633		    len);
2634		return ENOMEM;
2635	}
2636
2637	for (i = 0; i < WI_TIMEOUT; i++) {
2638		if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_ALLOC)
2639			break;
2640		DELAY(1);
2641	}
2642	if (i == WI_TIMEOUT) {
2643		device_printf(sc->sc_dev, "timeout in alloc\n");
2644		return ETIMEDOUT;
2645	}
2646	*idp = CSR_READ_2(sc, WI_ALLOC_FID);
2647	CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
2648	return 0;
2649}
2650
2651static int
2652wi_read_rid(struct wi_softc *sc, int rid, void *buf, int *buflenp)
2653{
2654	int error, len;
2655	u_int16_t ltbuf[2];
2656
2657	/* Tell the NIC to enter record read mode. */
2658	error = wi_cmd(sc, WI_CMD_ACCESS | WI_ACCESS_READ, rid, 0, 0);
2659	if (error)
2660		return error;
2661
2662	error = wi_read_bap(sc, rid, 0, ltbuf, sizeof(ltbuf));
2663	if (error)
2664		return error;
2665
2666	if (le16toh(ltbuf[1]) != rid) {
2667		device_printf(sc->sc_dev, "record read mismatch, rid=%x, got=%x\n",
2668		    rid, le16toh(ltbuf[1]));
2669		return EIO;
2670	}
2671	len = (le16toh(ltbuf[0]) - 1) * 2;	 /* already got rid */
2672	if (*buflenp < len) {
2673		device_printf(sc->sc_dev, "record buffer is too small, "
2674		    "rid=%x, size=%d, len=%d\n",
2675		    rid, *buflenp, len);
2676		return ENOSPC;
2677	}
2678	*buflenp = len;
2679	return wi_read_bap(sc, rid, sizeof(ltbuf), buf, len);
2680}
2681
2682static int
2683wi_write_rid(struct wi_softc *sc, int rid, void *buf, int buflen)
2684{
2685	int error;
2686	u_int16_t ltbuf[2];
2687
2688	ltbuf[0] = htole16((buflen + 1) / 2 + 1);	 /* includes rid */
2689	ltbuf[1] = htole16(rid);
2690
2691	error = wi_write_bap(sc, rid, 0, ltbuf, sizeof(ltbuf));
2692	if (error)
2693		return error;
2694	error = wi_write_bap(sc, rid, sizeof(ltbuf), buf, buflen);
2695	if (error)
2696		return error;
2697
2698	return wi_cmd(sc, WI_CMD_ACCESS | WI_ACCESS_WRITE, rid, 0, 0);
2699}
2700
2701static int
2702wi_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
2703{
2704	struct ifnet *ifp = ic->ic_ifp;
2705	struct wi_softc *sc = ifp->if_softc;
2706	struct ieee80211_node *ni;
2707	int buflen;
2708	u_int16_t val;
2709	struct wi_ssid ssid;
2710	u_int8_t old_bssid[IEEE80211_ADDR_LEN];
2711
2712	DPRINTF(("%s: %s -> %s\n", __func__,
2713		ieee80211_state_name[ic->ic_state],
2714		ieee80211_state_name[nstate]));
2715
2716	/*
2717	 * Internal to the driver the INIT and RUN states are used
2718	 * so bypass the net80211 state machine for other states.
2719	 * Beware however that this requires use to net80211 state
2720	 * management that otherwise would be handled for us.
2721	 */
2722	switch (nstate) {
2723	case IEEE80211_S_INIT:
2724		sc->sc_flags &= ~WI_FLAGS_OUTRANGE;
2725		return (*sc->sc_newstate)(ic, nstate, arg);
2726
2727	case IEEE80211_S_SCAN:
2728	case IEEE80211_S_AUTH:
2729	case IEEE80211_S_ASSOC:
2730		ic->ic_state = nstate;	/* NB: skip normal ieee80211 handling */
2731		break;
2732
2733	case IEEE80211_S_RUN:
2734		ni = ic->ic_bss;
2735		sc->sc_flags &= ~WI_FLAGS_OUTRANGE;
2736		buflen = IEEE80211_ADDR_LEN;
2737		IEEE80211_ADDR_COPY(old_bssid, ni->ni_bssid);
2738		wi_read_rid(sc, WI_RID_CURRENT_BSSID, ni->ni_bssid, &buflen);
2739		IEEE80211_ADDR_COPY(ni->ni_macaddr, ni->ni_bssid);
2740		buflen = sizeof(val);
2741		wi_read_rid(sc, WI_RID_CURRENT_CHAN, &val, &buflen);
2742		/* XXX validate channel */
2743		ni->ni_chan = &ic->ic_channels[le16toh(val)];
2744		ic->ic_curchan = ni->ni_chan;
2745		ic->ic_ibss_chan = ni->ni_chan;
2746#if NBPFILTER > 0
2747		sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq =
2748			htole16(ni->ni_chan->ic_freq);
2749		sc->sc_tx_th.wt_chan_flags = sc->sc_rx_th.wr_chan_flags =
2750			htole16(ni->ni_chan->ic_flags);
2751#endif
2752		if (ic->ic_opmode != IEEE80211_M_HOSTAP) {
2753			/*
2754			 * XXX hack; unceremoniously clear
2755			 * IEEE80211_F_DROPUNENC when operating with
2756			 * wep enabled so we don't drop unencoded frames
2757			 * at the 802.11 layer.  This is necessary because
2758			 * we must strip the WEP bit from the 802.11 header
2759			 * before passing frames to ieee80211_input because
2760			 * the card has already stripped the WEP crypto
2761			 * header from the packet.
2762			 */
2763			if (ic->ic_flags & IEEE80211_F_PRIVACY)
2764				ic->ic_flags &= ~IEEE80211_F_DROPUNENC;
2765			/* XXX check return value */
2766			buflen = sizeof(ssid);
2767			wi_read_rid(sc, WI_RID_CURRENT_SSID, &ssid, &buflen);
2768			ni->ni_esslen = le16toh(ssid.wi_len);
2769			if (ni->ni_esslen > IEEE80211_NWID_LEN)
2770				ni->ni_esslen = IEEE80211_NWID_LEN;	/*XXX*/
2771			memcpy(ni->ni_essid, ssid.wi_ssid, ni->ni_esslen);
2772		}
2773		return (*sc->sc_newstate)(ic, nstate, arg);
2774	}
2775	return 0;
2776}
2777
2778static int
2779wi_scan_ap(struct wi_softc *sc, u_int16_t chanmask, u_int16_t txrate)
2780{
2781	int error = 0;
2782	u_int16_t val[2];
2783
2784	if (!sc->sc_enabled)
2785		return ENXIO;
2786	switch (sc->sc_firmware_type) {
2787	case WI_LUCENT:
2788		(void)wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_SCAN_RESULTS, 0, 0);
2789		break;
2790	case WI_INTERSIL:
2791		val[0] = htole16(chanmask);	/* channel */
2792		val[1] = htole16(txrate);	/* tx rate */
2793		error = wi_write_rid(sc, WI_RID_SCAN_REQ, val, sizeof(val));
2794		break;
2795	case WI_SYMBOL:
2796		/*
2797		 * XXX only supported on 3.x ?
2798		 */
2799		val[0] = BSCAN_BCAST | BSCAN_ONETIME;
2800		error = wi_write_rid(sc, WI_RID_BCAST_SCAN_REQ,
2801		    val, sizeof(val[0]));
2802		break;
2803	}
2804	if (error == 0) {
2805		sc->sc_scan_timer = WI_SCAN_WAIT;
2806		sc->sc_ifp->if_timer = 1;
2807		DPRINTF(("wi_scan_ap: start scanning, "
2808			"chamask 0x%x txrate 0x%x\n", chanmask, txrate));
2809	}
2810	return error;
2811}
2812
2813static void
2814wi_scan_result(struct wi_softc *sc, int fid, int cnt)
2815{
2816#define	N(a)	(sizeof (a) / sizeof (a[0]))
2817	int i, naps, off, szbuf;
2818	struct wi_scan_header ws_hdr;	/* Prism2 header */
2819	struct wi_scan_data_p2 ws_dat;	/* Prism2 scantable*/
2820	struct wi_apinfo *ap;
2821
2822	off = sizeof(u_int16_t) * 2;
2823	memset(&ws_hdr, 0, sizeof(ws_hdr));
2824	switch (sc->sc_firmware_type) {
2825	case WI_INTERSIL:
2826		wi_read_bap(sc, fid, off, &ws_hdr, sizeof(ws_hdr));
2827		off += sizeof(ws_hdr);
2828		szbuf = sizeof(struct wi_scan_data_p2);
2829		break;
2830	case WI_SYMBOL:
2831		szbuf = sizeof(struct wi_scan_data_p2) + 6;
2832		break;
2833	case WI_LUCENT:
2834		szbuf = sizeof(struct wi_scan_data);
2835		break;
2836	default:
2837		device_printf(sc->sc_dev,
2838			"wi_scan_result: unknown firmware type %u\n",
2839			sc->sc_firmware_type);
2840		naps = 0;
2841		goto done;
2842	}
2843	naps = (cnt * 2 + 2 - off) / szbuf;
2844	if (naps > N(sc->sc_aps))
2845		naps = N(sc->sc_aps);
2846	sc->sc_naps = naps;
2847	/* Read Data */
2848	ap = sc->sc_aps;
2849	memset(&ws_dat, 0, sizeof(ws_dat));
2850	for (i = 0; i < naps; i++, ap++) {
2851		wi_read_bap(sc, fid, off, &ws_dat,
2852		    (sizeof(ws_dat) < szbuf ? sizeof(ws_dat) : szbuf));
2853		DPRINTF2(("wi_scan_result: #%d: off %d bssid %s\n", i, off,
2854		    ether_sprintf(ws_dat.wi_bssid)));
2855		off += szbuf;
2856		ap->scanreason = le16toh(ws_hdr.wi_reason);
2857		memcpy(ap->bssid, ws_dat.wi_bssid, sizeof(ap->bssid));
2858		ap->channel = le16toh(ws_dat.wi_chid);
2859		ap->signal  = le16toh(ws_dat.wi_signal);
2860		ap->noise   = le16toh(ws_dat.wi_noise);
2861		ap->quality = ap->signal - ap->noise;
2862		ap->capinfo = le16toh(ws_dat.wi_capinfo);
2863		ap->interval = le16toh(ws_dat.wi_interval);
2864		ap->rate    = le16toh(ws_dat.wi_rate);
2865		ap->namelen = le16toh(ws_dat.wi_namelen);
2866		if (ap->namelen > sizeof(ap->name))
2867			ap->namelen = sizeof(ap->name);
2868		memcpy(ap->name, ws_dat.wi_name, ap->namelen);
2869	}
2870done:
2871	/* Done scanning */
2872	sc->sc_scan_timer = 0;
2873	DPRINTF(("wi_scan_result: scan complete: ap %d\n", naps));
2874#undef N
2875}
2876
2877static void
2878wi_dump_pkt(struct wi_frame *wh, struct ieee80211_node *ni, int rssi)
2879{
2880	ieee80211_dump_pkt((u_int8_t *) &wh->wi_whdr, sizeof(wh->wi_whdr),
2881	    ni ? ni->ni_rates.rs_rates[ni->ni_txrate] & IEEE80211_RATE_VAL : -1, rssi);
2882	printf(" status 0x%x rx_tstamp1 %u rx_tstamp0 0x%u rx_silence %u\n",
2883		le16toh(wh->wi_status), le16toh(wh->wi_rx_tstamp1),
2884		le16toh(wh->wi_rx_tstamp0), wh->wi_rx_silence);
2885	printf(" rx_signal %u rx_rate %u rx_flow %u\n",
2886		wh->wi_rx_signal, wh->wi_rx_rate, wh->wi_rx_flow);
2887	printf(" tx_rtry %u tx_rate %u tx_ctl 0x%x dat_len %u\n",
2888		wh->wi_tx_rtry, wh->wi_tx_rate,
2889		le16toh(wh->wi_tx_ctl), le16toh(wh->wi_dat_len));
2890	printf(" ehdr dst %6D src %6D type 0x%x\n",
2891		wh->wi_ehdr.ether_dhost, ":", wh->wi_ehdr.ether_shost, ":",
2892		wh->wi_ehdr.ether_type);
2893}
2894
2895int
2896wi_alloc(device_t dev, int rid)
2897{
2898	struct wi_softc	*sc = device_get_softc(dev);
2899
2900	if (sc->wi_bus_type != WI_BUS_PCI_NATIVE) {
2901		sc->iobase_rid = rid;
2902		sc->iobase = bus_alloc_resource(dev, SYS_RES_IOPORT,
2903		    &sc->iobase_rid, 0, ~0, (1 << 6),
2904		    rman_make_alignment_flags(1 << 6) | RF_ACTIVE);
2905		if (!sc->iobase) {
2906			device_printf(dev, "No I/O space?!\n");
2907			return (ENXIO);
2908		}
2909
2910		sc->wi_io_addr = rman_get_start(sc->iobase);
2911		sc->wi_btag = rman_get_bustag(sc->iobase);
2912		sc->wi_bhandle = rman_get_bushandle(sc->iobase);
2913	} else {
2914		sc->mem_rid = rid;
2915		sc->mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
2916		    &sc->mem_rid, RF_ACTIVE);
2917
2918		if (!sc->mem) {
2919			device_printf(dev, "No Mem space on prism2.5?\n");
2920			return (ENXIO);
2921		}
2922
2923		sc->wi_btag = rman_get_bustag(sc->mem);
2924		sc->wi_bhandle = rman_get_bushandle(sc->mem);
2925	}
2926
2927
2928	sc->irq_rid = 0;
2929	sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irq_rid,
2930	    RF_ACTIVE |
2931	    ((sc->wi_bus_type == WI_BUS_PCCARD) ? 0 : RF_SHAREABLE));
2932
2933	if (!sc->irq) {
2934		wi_free(dev);
2935		device_printf(dev, "No irq?!\n");
2936		return (ENXIO);
2937	}
2938
2939	sc->sc_dev = dev;
2940	sc->sc_unit = device_get_unit(dev);
2941
2942	return (0);
2943}
2944
2945void
2946wi_free(device_t dev)
2947{
2948	struct wi_softc	*sc = device_get_softc(dev);
2949
2950	if (sc->iobase != NULL) {
2951		bus_release_resource(dev, SYS_RES_IOPORT, sc->iobase_rid, sc->iobase);
2952		sc->iobase = NULL;
2953	}
2954	if (sc->irq != NULL) {
2955		bus_release_resource(dev, SYS_RES_IRQ, sc->irq_rid, sc->irq);
2956		sc->irq = NULL;
2957	}
2958	if (sc->mem != NULL) {
2959		bus_release_resource(dev, SYS_RES_MEMORY, sc->mem_rid, sc->mem);
2960		sc->mem = NULL;
2961	}
2962
2963	return;
2964}
2965
2966static int
2967wi_get_debug(struct wi_softc *sc, struct wi_req *wreq)
2968{
2969	int error = 0;
2970
2971	wreq->wi_len = 1;
2972
2973	switch (wreq->wi_type) {
2974	case WI_DEBUG_SLEEP:
2975		wreq->wi_len++;
2976		wreq->wi_val[0] = sc->wi_debug.wi_sleep;
2977		break;
2978	case WI_DEBUG_DELAYSUPP:
2979		wreq->wi_len++;
2980		wreq->wi_val[0] = sc->wi_debug.wi_delaysupp;
2981		break;
2982	case WI_DEBUG_TXSUPP:
2983		wreq->wi_len++;
2984		wreq->wi_val[0] = sc->wi_debug.wi_txsupp;
2985		break;
2986	case WI_DEBUG_MONITOR:
2987		wreq->wi_len++;
2988		wreq->wi_val[0] = sc->wi_debug.wi_monitor;
2989		break;
2990	case WI_DEBUG_LEDTEST:
2991		wreq->wi_len += 3;
2992		wreq->wi_val[0] = sc->wi_debug.wi_ledtest;
2993		wreq->wi_val[1] = sc->wi_debug.wi_ledtest_param0;
2994		wreq->wi_val[2] = sc->wi_debug.wi_ledtest_param1;
2995		break;
2996	case WI_DEBUG_CONTTX:
2997		wreq->wi_len += 2;
2998		wreq->wi_val[0] = sc->wi_debug.wi_conttx;
2999		wreq->wi_val[1] = sc->wi_debug.wi_conttx_param0;
3000		break;
3001	case WI_DEBUG_CONTRX:
3002		wreq->wi_len++;
3003		wreq->wi_val[0] = sc->wi_debug.wi_contrx;
3004		break;
3005	case WI_DEBUG_SIGSTATE:
3006		wreq->wi_len += 2;
3007		wreq->wi_val[0] = sc->wi_debug.wi_sigstate;
3008		wreq->wi_val[1] = sc->wi_debug.wi_sigstate_param0;
3009		break;
3010	case WI_DEBUG_CONFBITS:
3011		wreq->wi_len += 2;
3012		wreq->wi_val[0] = sc->wi_debug.wi_confbits;
3013		wreq->wi_val[1] = sc->wi_debug.wi_confbits_param0;
3014		break;
3015	default:
3016		error = EIO;
3017		break;
3018	}
3019
3020	return (error);
3021}
3022
3023static int
3024wi_set_debug(struct wi_softc *sc, struct wi_req *wreq)
3025{
3026	int error = 0;
3027	u_int16_t		cmd, param0 = 0, param1 = 0;
3028
3029	switch (wreq->wi_type) {
3030	case WI_DEBUG_RESET:
3031	case WI_DEBUG_INIT:
3032	case WI_DEBUG_CALENABLE:
3033		break;
3034	case WI_DEBUG_SLEEP:
3035		sc->wi_debug.wi_sleep = 1;
3036		break;
3037	case WI_DEBUG_WAKE:
3038		sc->wi_debug.wi_sleep = 0;
3039		break;
3040	case WI_DEBUG_CHAN:
3041		param0 = wreq->wi_val[0];
3042		break;
3043	case WI_DEBUG_DELAYSUPP:
3044		sc->wi_debug.wi_delaysupp = 1;
3045		break;
3046	case WI_DEBUG_TXSUPP:
3047		sc->wi_debug.wi_txsupp = 1;
3048		break;
3049	case WI_DEBUG_MONITOR:
3050		sc->wi_debug.wi_monitor = 1;
3051		break;
3052	case WI_DEBUG_LEDTEST:
3053		param0 = wreq->wi_val[0];
3054		param1 = wreq->wi_val[1];
3055		sc->wi_debug.wi_ledtest = 1;
3056		sc->wi_debug.wi_ledtest_param0 = param0;
3057		sc->wi_debug.wi_ledtest_param1 = param1;
3058		break;
3059	case WI_DEBUG_CONTTX:
3060		param0 = wreq->wi_val[0];
3061		sc->wi_debug.wi_conttx = 1;
3062		sc->wi_debug.wi_conttx_param0 = param0;
3063		break;
3064	case WI_DEBUG_STOPTEST:
3065		sc->wi_debug.wi_delaysupp = 0;
3066		sc->wi_debug.wi_txsupp = 0;
3067		sc->wi_debug.wi_monitor = 0;
3068		sc->wi_debug.wi_ledtest = 0;
3069		sc->wi_debug.wi_ledtest_param0 = 0;
3070		sc->wi_debug.wi_ledtest_param1 = 0;
3071		sc->wi_debug.wi_conttx = 0;
3072		sc->wi_debug.wi_conttx_param0 = 0;
3073		sc->wi_debug.wi_contrx = 0;
3074		sc->wi_debug.wi_sigstate = 0;
3075		sc->wi_debug.wi_sigstate_param0 = 0;
3076		break;
3077	case WI_DEBUG_CONTRX:
3078		sc->wi_debug.wi_contrx = 1;
3079		break;
3080	case WI_DEBUG_SIGSTATE:
3081		param0 = wreq->wi_val[0];
3082		sc->wi_debug.wi_sigstate = 1;
3083		sc->wi_debug.wi_sigstate_param0 = param0;
3084		break;
3085	case WI_DEBUG_CONFBITS:
3086		param0 = wreq->wi_val[0];
3087		param1 = wreq->wi_val[1];
3088		sc->wi_debug.wi_confbits = param0;
3089		sc->wi_debug.wi_confbits_param0 = param1;
3090		break;
3091	default:
3092		error = EIO;
3093		break;
3094	}
3095
3096	if (error)
3097		return (error);
3098
3099	cmd = WI_CMD_DEBUG | (wreq->wi_type << 8);
3100	error = wi_cmd(sc, cmd, param0, param1, 0);
3101
3102	return (error);
3103}
3104
3105#if __FreeBSD_version >= 500000
3106/*
3107 * Special routines to download firmware for Symbol CF card.
3108 * XXX: This should be modified generic into any PRISM-2 based card.
3109 */
3110
3111#define	WI_SBCF_PDIADDR		0x3100
3112
3113/* unaligned load little endian */
3114#define	GETLE32(p)	((p)[0] | ((p)[1]<<8) | ((p)[2]<<16) | ((p)[3]<<24))
3115#define	GETLE16(p)	((p)[0] | ((p)[1]<<8))
3116
3117int
3118wi_symbol_load_firm(struct wi_softc *sc, const void *primsym, int primlen,
3119    const void *secsym, int seclen)
3120{
3121	uint8_t ebuf[256];
3122	int i;
3123
3124	/* load primary code and run it */
3125	wi_symbol_set_hcr(sc, WI_HCR_EEHOLD);
3126	if (wi_symbol_write_firm(sc, primsym, primlen, NULL, 0))
3127		return EIO;
3128	wi_symbol_set_hcr(sc, WI_HCR_RUN);
3129	for (i = 0; ; i++) {
3130		if (i == 10)
3131			return ETIMEDOUT;
3132		tsleep(sc, PWAIT, "wiinit", 1);
3133		if (CSR_READ_2(sc, WI_CNTL) == WI_CNTL_AUX_ENA_STAT)
3134			break;
3135		/* write the magic key value to unlock aux port */
3136		CSR_WRITE_2(sc, WI_PARAM0, WI_AUX_KEY0);
3137		CSR_WRITE_2(sc, WI_PARAM1, WI_AUX_KEY1);
3138		CSR_WRITE_2(sc, WI_PARAM2, WI_AUX_KEY2);
3139		CSR_WRITE_2(sc, WI_CNTL, WI_CNTL_AUX_ENA_CNTL);
3140	}
3141
3142	/* issue read EEPROM command: XXX copied from wi_cmd() */
3143	CSR_WRITE_2(sc, WI_PARAM0, 0);
3144	CSR_WRITE_2(sc, WI_PARAM1, 0);
3145	CSR_WRITE_2(sc, WI_PARAM2, 0);
3146	CSR_WRITE_2(sc, WI_COMMAND, WI_CMD_READEE);
3147        for (i = 0; i < WI_TIMEOUT; i++) {
3148                if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_CMD)
3149                        break;
3150                DELAY(1);
3151        }
3152        CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_CMD);
3153
3154	CSR_WRITE_2(sc, WI_AUX_PAGE, WI_SBCF_PDIADDR / WI_AUX_PGSZ);
3155	CSR_WRITE_2(sc, WI_AUX_OFFSET, WI_SBCF_PDIADDR % WI_AUX_PGSZ);
3156	CSR_READ_MULTI_STREAM_2(sc, WI_AUX_DATA,
3157	    (uint16_t *)ebuf, sizeof(ebuf) / 2);
3158	if (GETLE16(ebuf) > sizeof(ebuf))
3159		return EIO;
3160	if (wi_symbol_write_firm(sc, secsym, seclen, ebuf + 4, GETLE16(ebuf)))
3161		return EIO;
3162	return 0;
3163}
3164
3165static int
3166wi_symbol_write_firm(struct wi_softc *sc, const void *buf, int buflen,
3167    const void *ebuf, int ebuflen)
3168{
3169	const uint8_t *p, *ep, *q, *eq;
3170	char *tp;
3171	uint32_t addr, id, eid;
3172	int i, len, elen, nblk, pdrlen;
3173
3174	/*
3175	 * Parse the header of the firmware image.
3176	 */
3177	p = buf;
3178	ep = p + buflen;
3179	while (p < ep && *p++ != ' ');	/* FILE: */
3180	while (p < ep && *p++ != ' ');	/* filename */
3181	while (p < ep && *p++ != ' ');	/* type of the firmware */
3182	nblk = strtoul(p, &tp, 10);
3183	p = tp;
3184	pdrlen = strtoul(p + 1, &tp, 10);
3185	p = tp;
3186	while (p < ep && *p++ != 0x1a);	/* skip rest of header */
3187
3188	/*
3189	 * Block records: address[4], length[2], data[length];
3190	 */
3191	for (i = 0; i < nblk; i++) {
3192		addr = GETLE32(p);	p += 4;
3193		len  = GETLE16(p);	p += 2;
3194		CSR_WRITE_2(sc, WI_AUX_PAGE, addr / WI_AUX_PGSZ);
3195		CSR_WRITE_2(sc, WI_AUX_OFFSET, addr % WI_AUX_PGSZ);
3196		CSR_WRITE_MULTI_STREAM_2(sc, WI_AUX_DATA,
3197		    (const uint16_t *)p, len / 2);
3198		p += len;
3199	}
3200
3201	/*
3202	 * PDR: id[4], address[4], length[4];
3203	 */
3204	for (i = 0; i < pdrlen; ) {
3205		id   = GETLE32(p);	p += 4; i += 4;
3206		addr = GETLE32(p);	p += 4; i += 4;
3207		len  = GETLE32(p);	p += 4; i += 4;
3208		/* replace PDR entry with the values from EEPROM, if any */
3209		for (q = ebuf, eq = q + ebuflen; q < eq; q += elen * 2) {
3210			elen = GETLE16(q);	q += 2;
3211			eid  = GETLE16(q);	q += 2;
3212			elen--;		/* elen includes eid */
3213			if (eid == 0)
3214				break;
3215			if (eid != id)
3216				continue;
3217			CSR_WRITE_2(sc, WI_AUX_PAGE, addr / WI_AUX_PGSZ);
3218			CSR_WRITE_2(sc, WI_AUX_OFFSET, addr % WI_AUX_PGSZ);
3219			CSR_WRITE_MULTI_STREAM_2(sc, WI_AUX_DATA,
3220			    (const uint16_t *)q, len / 2);
3221			break;
3222		}
3223	}
3224	return 0;
3225}
3226
3227static int
3228wi_symbol_set_hcr(struct wi_softc *sc, int mode)
3229{
3230	uint16_t hcr;
3231
3232	CSR_WRITE_2(sc, WI_COR, WI_COR_RESET);
3233	tsleep(sc, PWAIT, "wiinit", 1);
3234	hcr = CSR_READ_2(sc, WI_HCR);
3235	hcr = (hcr & WI_HCR_4WIRE) | (mode & ~WI_HCR_4WIRE);
3236	CSR_WRITE_2(sc, WI_HCR, hcr);
3237	tsleep(sc, PWAIT, "wiinit", 1);
3238	CSR_WRITE_2(sc, WI_COR, WI_COR_IOMODE);
3239	tsleep(sc, PWAIT, "wiinit", 1);
3240	return 0;
3241}
3242#endif
3243