if_wi.c revision 148843
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 148843 2005-08-08 03:30:57Z 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_flags & IFF_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_flags |= IFF_RUNNING;
796	ifp->if_flags &= ~IFF_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_flags &= ~(IFF_OACTIVE | IFF_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_flags |= IFF_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_flags |= IFF_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_flags & IFF_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_flags & IFF_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_flags & IFF_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 || !sc->sc_enabled) {
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 (ic->ic_state == IEEE80211_S_RUN &&
1271	    (sc->sc_flags & WI_FLAGS_OUTRANGE) == 0)
1272		imr->ifm_status |= IFM_ACTIVE;
1273	len = sizeof(val);
1274	if (wi_read_rid(sc, WI_RID_CUR_TX_RATE, &val, &len) == 0 &&
1275	    len == sizeof(val)) {
1276		/* convert to 802.11 rate */
1277		val = le16toh(val);
1278		rate = val * 2;
1279		if (sc->sc_firmware_type == WI_LUCENT) {
1280			if (rate == 10)
1281				rate = 11;	/* 5.5Mbps */
1282		} else {
1283			if (rate == 4*2)
1284				rate = 11;	/* 5.5Mbps */
1285			else if (rate == 8*2)
1286				rate = 22;	/* 11Mbps */
1287		}
1288	} else
1289		rate = 0;
1290	imr->ifm_active |= ieee80211_rate2media(ic, rate, IEEE80211_MODE_11B);
1291	switch (ic->ic_opmode) {
1292	case IEEE80211_M_STA:
1293		break;
1294	case IEEE80211_M_IBSS:
1295		imr->ifm_active |= IFM_IEEE80211_ADHOC;
1296		break;
1297	case IEEE80211_M_AHDEMO:
1298		imr->ifm_active |= IFM_IEEE80211_ADHOC | IFM_FLAG0;
1299		break;
1300	case IEEE80211_M_HOSTAP:
1301		imr->ifm_active |= IFM_IEEE80211_HOSTAP;
1302		break;
1303	case IEEE80211_M_MONITOR:
1304		imr->ifm_active |= IFM_IEEE80211_MONITOR;
1305		break;
1306	}
1307}
1308
1309static void
1310wi_sync_bssid(struct wi_softc *sc, u_int8_t new_bssid[IEEE80211_ADDR_LEN])
1311{
1312	struct ieee80211com *ic = &sc->sc_ic;
1313	struct ieee80211_node *ni = ic->ic_bss;
1314	struct ifnet *ifp = sc->sc_ifp;
1315
1316	if (IEEE80211_ADDR_EQ(new_bssid, ni->ni_bssid))
1317		return;
1318
1319	DPRINTF(("wi_sync_bssid: bssid %s -> ", ether_sprintf(ni->ni_bssid)));
1320	DPRINTF(("%s ?\n", ether_sprintf(new_bssid)));
1321
1322	/* In promiscuous mode, the BSSID field is not a reliable
1323	 * indicator of the firmware's BSSID. Damp spurious
1324	 * change-of-BSSID indications.
1325	 */
1326	if ((ifp->if_flags & IFF_PROMISC) != 0 &&
1327	    !ppsratecheck(&sc->sc_last_syn, &sc->sc_false_syns,
1328	                 WI_MAX_FALSE_SYNS))
1329		return;
1330
1331	sc->sc_false_syns = MAX(0, sc->sc_false_syns - 1);
1332	/*
1333	 * XXX hack; we should create a new node with the new bssid
1334	 * and replace the existing ic_bss with it but since we don't
1335	 * process management frames to collect state we cheat by
1336	 * reusing the existing node as we know wi_newstate will be
1337	 * called and it will overwrite the node state.
1338	 */
1339	ieee80211_sta_join(ic, ieee80211_ref_node(ni));
1340}
1341
1342static void
1343wi_rx_monitor(struct wi_softc *sc, int fid)
1344{
1345	struct ifnet *ifp = sc->sc_ifp;
1346	struct wi_frame *rx_frame;
1347	struct mbuf *m;
1348	int datlen, hdrlen;
1349
1350	/* first allocate mbuf for packet storage */
1351	m = m_getcl(M_DONTWAIT, MT_DATA, 0);
1352	if (m == NULL) {
1353		ifp->if_ierrors++;
1354		return;
1355	}
1356
1357	m->m_pkthdr.rcvif = ifp;
1358
1359	/* now read wi_frame first so we know how much data to read */
1360	if (wi_read_bap(sc, fid, 0, mtod(m, caddr_t), sizeof(*rx_frame))) {
1361		ifp->if_ierrors++;
1362		goto done;
1363	}
1364
1365	rx_frame = mtod(m, struct wi_frame *);
1366
1367	switch ((rx_frame->wi_status & WI_STAT_MAC_PORT) >> 8) {
1368	case 7:
1369		switch (rx_frame->wi_whdr.i_fc[0] & IEEE80211_FC0_TYPE_MASK) {
1370		case IEEE80211_FC0_TYPE_DATA:
1371			hdrlen = WI_DATA_HDRLEN;
1372			datlen = rx_frame->wi_dat_len + WI_FCS_LEN;
1373			break;
1374		case IEEE80211_FC0_TYPE_MGT:
1375			hdrlen = WI_MGMT_HDRLEN;
1376			datlen = rx_frame->wi_dat_len + WI_FCS_LEN;
1377			break;
1378		case IEEE80211_FC0_TYPE_CTL:
1379			/*
1380			 * prism2 cards don't pass control packets
1381			 * down properly or consistently, so we'll only
1382			 * pass down the header.
1383			 */
1384			hdrlen = WI_CTL_HDRLEN;
1385			datlen = 0;
1386			break;
1387		default:
1388			if_printf(ifp, "received packet of unknown type "
1389				"on port 7\n");
1390			ifp->if_ierrors++;
1391			goto done;
1392		}
1393		break;
1394	case 0:
1395		hdrlen = WI_DATA_HDRLEN;
1396		datlen = rx_frame->wi_dat_len + WI_FCS_LEN;
1397		break;
1398	default:
1399		if_printf(ifp, "received packet on invalid "
1400		    "port (wi_status=0x%x)\n", rx_frame->wi_status);
1401		ifp->if_ierrors++;
1402		goto done;
1403	}
1404
1405	if (hdrlen + datlen + 2 > MCLBYTES) {
1406		if_printf(ifp, "oversized packet received "
1407		    "(wi_dat_len=%d, wi_status=0x%x)\n",
1408		    datlen, rx_frame->wi_status);
1409		ifp->if_ierrors++;
1410		goto done;
1411	}
1412
1413	if (wi_read_bap(sc, fid, hdrlen, mtod(m, caddr_t) + hdrlen,
1414	    datlen + 2) == 0) {
1415		m->m_pkthdr.len = m->m_len = hdrlen + datlen;
1416		ifp->if_ipackets++;
1417		BPF_MTAP(ifp, m);	/* Handle BPF listeners. */
1418	} else
1419		ifp->if_ierrors++;
1420done:
1421	m_freem(m);
1422}
1423
1424static void
1425wi_rx_intr(struct wi_softc *sc)
1426{
1427	struct ieee80211com *ic = &sc->sc_ic;
1428	struct ifnet *ifp = sc->sc_ifp;
1429	struct wi_frame frmhdr;
1430	struct mbuf *m;
1431	struct ieee80211_frame *wh;
1432	struct ieee80211_node *ni;
1433	int fid, len, off, rssi;
1434	u_int8_t dir;
1435	u_int16_t status;
1436	u_int32_t rstamp;
1437
1438	fid = CSR_READ_2(sc, WI_RX_FID);
1439
1440	if (sc->wi_debug.wi_monitor) {
1441		/*
1442		 * If we are in monitor mode just
1443		 * read the data from the device.
1444		 */
1445		wi_rx_monitor(sc, fid);
1446		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
1447		return;
1448	}
1449
1450	/* First read in the frame header */
1451	if (wi_read_bap(sc, fid, 0, &frmhdr, sizeof(frmhdr))) {
1452		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
1453		ifp->if_ierrors++;
1454		DPRINTF(("wi_rx_intr: read fid %x failed\n", fid));
1455		return;
1456	}
1457
1458	if (IFF_DUMPPKTS(ifp))
1459		wi_dump_pkt(&frmhdr, NULL, frmhdr.wi_rx_signal);
1460
1461	/*
1462	 * Drop undecryptable or packets with receive errors here
1463	 */
1464	status = le16toh(frmhdr.wi_status);
1465	if (status & WI_STAT_ERRSTAT) {
1466		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
1467		ifp->if_ierrors++;
1468		DPRINTF(("wi_rx_intr: fid %x error status %x\n", fid, status));
1469		return;
1470	}
1471	rssi = frmhdr.wi_rx_signal;
1472	rstamp = (le16toh(frmhdr.wi_rx_tstamp0) << 16) |
1473	    le16toh(frmhdr.wi_rx_tstamp1);
1474
1475	len = le16toh(frmhdr.wi_dat_len);
1476	off = ALIGN(sizeof(struct ieee80211_frame));
1477
1478	/*
1479	 * Sometimes the PRISM2.x returns bogusly large frames. Except
1480	 * in monitor mode, just throw them away.
1481	 */
1482	if (off + len > MCLBYTES) {
1483		if (ic->ic_opmode != IEEE80211_M_MONITOR) {
1484			CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
1485			ifp->if_ierrors++;
1486			DPRINTF(("wi_rx_intr: oversized packet\n"));
1487			return;
1488		} else
1489			len = 0;
1490	}
1491
1492	MGETHDR(m, M_DONTWAIT, MT_DATA);
1493	if (m == NULL) {
1494		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
1495		ifp->if_ierrors++;
1496		DPRINTF(("wi_rx_intr: MGET failed\n"));
1497		return;
1498	}
1499	if (off + len > MHLEN) {
1500		MCLGET(m, M_DONTWAIT);
1501		if ((m->m_flags & M_EXT) == 0) {
1502			CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
1503			m_freem(m);
1504			ifp->if_ierrors++;
1505			DPRINTF(("wi_rx_intr: MCLGET failed\n"));
1506			return;
1507		}
1508	}
1509
1510	m->m_data += off - sizeof(struct ieee80211_frame);
1511	memcpy(m->m_data, &frmhdr.wi_whdr, sizeof(struct ieee80211_frame));
1512	wi_read_bap(sc, fid, sizeof(frmhdr),
1513	    m->m_data + sizeof(struct ieee80211_frame), len);
1514	m->m_pkthdr.len = m->m_len = sizeof(struct ieee80211_frame) + len;
1515	m->m_pkthdr.rcvif = ifp;
1516
1517	CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
1518
1519	wh = mtod(m, struct ieee80211_frame *);
1520	if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
1521		/*
1522		 * WEP is decrypted by hardware and the IV
1523		 * is stripped.  Clear WEP bit so we don't
1524		 * try to process it in ieee80211_input.
1525		 * XXX fix for TKIP, et. al.
1526		 */
1527		wh->i_fc[1] &= ~IEEE80211_FC1_WEP;
1528	}
1529
1530#if NBPFILTER > 0
1531	if (sc->sc_drvbpf) {
1532		/* XXX replace divide by table */
1533		sc->sc_rx_th.wr_rate = frmhdr.wi_rx_rate / 5;
1534		sc->sc_rx_th.wr_antsignal = frmhdr.wi_rx_signal;
1535		sc->sc_rx_th.wr_antnoise = frmhdr.wi_rx_silence;
1536		sc->sc_rx_th.wr_flags = 0;
1537		if (frmhdr.wi_status & WI_STAT_PCF)
1538			sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_CFP;
1539		/* XXX IEEE80211_RADIOTAP_F_WEP */
1540		bpf_mtap2(sc->sc_drvbpf,
1541			&sc->sc_rx_th, sc->sc_rx_th_len, m);
1542	}
1543#endif
1544
1545	/* synchronize driver's BSSID with firmware's BSSID */
1546	dir = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK;
1547	if (ic->ic_opmode == IEEE80211_M_IBSS && dir == IEEE80211_FC1_DIR_NODS)
1548		wi_sync_bssid(sc, wh->i_addr3);
1549
1550	/*
1551	 * Locate the node for sender, track state, and
1552	 * then pass this node (referenced) up to the 802.11
1553	 * layer for its use.
1554	 */
1555	ni = ieee80211_find_rxnode(ic, (struct ieee80211_frame_min *) wh);
1556	/*
1557	 * Send frame up for processing.
1558	 */
1559	ieee80211_input(ic, m, ni, rssi, rstamp);
1560	/*
1561	 * The frame may have caused the node to be marked for
1562	 * reclamation (e.g. in response to a DEAUTH message)
1563	 * so use free_node here instead of unref_node.
1564	 */
1565	ieee80211_free_node(ni);
1566}
1567
1568static void
1569wi_tx_ex_intr(struct wi_softc *sc)
1570{
1571	struct ifnet *ifp = sc->sc_ifp;
1572	struct wi_frame frmhdr;
1573	int fid;
1574
1575	fid = CSR_READ_2(sc, WI_TX_CMP_FID);
1576	/* Read in the frame header */
1577	if (wi_read_bap(sc, fid, 0, &frmhdr, sizeof(frmhdr)) == 0) {
1578		u_int16_t status = le16toh(frmhdr.wi_status);
1579
1580		/*
1581		 * Spontaneous station disconnects appear as xmit
1582		 * errors.  Don't announce them and/or count them
1583		 * as an output error.
1584		 */
1585		if ((status & WI_TXSTAT_DISCONNECT) == 0) {
1586			if (ppsratecheck(&lasttxerror, &curtxeps, wi_txerate)) {
1587				if_printf(ifp, "tx failed");
1588				if (status & WI_TXSTAT_RET_ERR)
1589					printf(", retry limit exceeded");
1590				if (status & WI_TXSTAT_AGED_ERR)
1591					printf(", max transmit lifetime exceeded");
1592				if (status & WI_TXSTAT_DISCONNECT)
1593					printf(", port disconnected");
1594				if (status & WI_TXSTAT_FORM_ERR)
1595					printf(", invalid format (data len %u src %6D)",
1596						le16toh(frmhdr.wi_dat_len),
1597						frmhdr.wi_ehdr.ether_shost, ":");
1598				if (status & ~0xf)
1599					printf(", status=0x%x", status);
1600				printf("\n");
1601			}
1602			ifp->if_oerrors++;
1603		} else {
1604			DPRINTF(("port disconnected\n"));
1605			ifp->if_collisions++;	/* XXX */
1606		}
1607	} else
1608		DPRINTF(("wi_tx_ex_intr: read fid %x failed\n", fid));
1609	CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX_EXC);
1610}
1611
1612static void
1613wi_tx_intr(struct wi_softc *sc)
1614{
1615	struct ifnet *ifp = sc->sc_ifp;
1616	int fid, cur;
1617
1618	if (sc->wi_gone)
1619		return;
1620
1621	fid = CSR_READ_2(sc, WI_ALLOC_FID);
1622	CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
1623
1624	cur = sc->sc_txcur;
1625	if (sc->sc_txd[cur].d_fid != fid) {
1626		if_printf(ifp, "bad alloc %x != %x, cur %d nxt %d\n",
1627		    fid, sc->sc_txd[cur].d_fid, cur, sc->sc_txnext);
1628		return;
1629	}
1630	sc->sc_tx_timer = 0;
1631	sc->sc_txd[cur].d_len = 0;
1632	sc->sc_txcur = cur = (cur + 1) % sc->sc_ntxbuf;
1633	if (sc->sc_txd[cur].d_len == 0)
1634		ifp->if_flags &= ~IFF_OACTIVE;
1635	else {
1636		if (wi_cmd(sc, WI_CMD_TX | WI_RECLAIM, sc->sc_txd[cur].d_fid,
1637		    0, 0)) {
1638			if_printf(ifp, "xmit failed\n");
1639			sc->sc_txd[cur].d_len = 0;
1640		} else {
1641			sc->sc_tx_timer = 5;
1642			ifp->if_timer = 1;
1643		}
1644	}
1645}
1646
1647static void
1648wi_info_intr(struct wi_softc *sc)
1649{
1650	struct ieee80211com *ic = &sc->sc_ic;
1651	struct ifnet *ifp = sc->sc_ifp;
1652	int i, fid, len, off;
1653	u_int16_t ltbuf[2];
1654	u_int16_t stat;
1655	u_int32_t *ptr;
1656
1657	fid = CSR_READ_2(sc, WI_INFO_FID);
1658	wi_read_bap(sc, fid, 0, ltbuf, sizeof(ltbuf));
1659
1660	switch (le16toh(ltbuf[1])) {
1661
1662	case WI_INFO_LINK_STAT:
1663		wi_read_bap(sc, fid, sizeof(ltbuf), &stat, sizeof(stat));
1664		DPRINTF(("wi_info_intr: LINK_STAT 0x%x\n", le16toh(stat)));
1665		switch (le16toh(stat)) {
1666		case WI_INFO_LINK_STAT_CONNECTED:
1667			sc->sc_flags &= ~WI_FLAGS_OUTRANGE;
1668			if (ic->ic_state == IEEE80211_S_RUN &&
1669			    ic->ic_opmode != IEEE80211_M_IBSS)
1670				break;
1671			/* FALLTHROUGH */
1672		case WI_INFO_LINK_STAT_AP_CHG:
1673			ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
1674			break;
1675		case WI_INFO_LINK_STAT_AP_INR:
1676			sc->sc_flags &= ~WI_FLAGS_OUTRANGE;
1677			break;
1678		case WI_INFO_LINK_STAT_AP_OOR:
1679			if (sc->sc_firmware_type == WI_SYMBOL &&
1680			    sc->sc_scan_timer > 0) {
1681				if (wi_cmd(sc, WI_CMD_INQUIRE,
1682				    WI_INFO_HOST_SCAN_RESULTS, 0, 0) != 0)
1683					sc->sc_scan_timer = 0;
1684				break;
1685			}
1686			if (ic->ic_opmode == IEEE80211_M_STA)
1687				sc->sc_flags |= WI_FLAGS_OUTRANGE;
1688			break;
1689		case WI_INFO_LINK_STAT_DISCONNECTED:
1690		case WI_INFO_LINK_STAT_ASSOC_FAILED:
1691			if (ic->ic_opmode == IEEE80211_M_STA)
1692				ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
1693			break;
1694		}
1695		break;
1696
1697	case WI_INFO_COUNTERS:
1698		/* some card versions have a larger stats structure */
1699		len = min(le16toh(ltbuf[0]) - 1, sizeof(sc->sc_stats) / 4);
1700		ptr = (u_int32_t *)&sc->sc_stats;
1701		off = sizeof(ltbuf);
1702		for (i = 0; i < len; i++, off += 2, ptr++) {
1703			wi_read_bap(sc, fid, off, &stat, sizeof(stat));
1704#ifdef WI_HERMES_STATS_WAR
1705			if (stat & 0xf000)
1706				stat = ~stat;
1707#endif
1708			*ptr += stat;
1709		}
1710		ifp->if_collisions = sc->sc_stats.wi_tx_single_retries +
1711		    sc->sc_stats.wi_tx_multi_retries +
1712		    sc->sc_stats.wi_tx_retry_limit;
1713		break;
1714
1715	case WI_INFO_SCAN_RESULTS:
1716	case WI_INFO_HOST_SCAN_RESULTS:
1717		wi_scan_result(sc, fid, le16toh(ltbuf[0]));
1718		break;
1719
1720	default:
1721		DPRINTF(("wi_info_intr: got fid %x type %x len %d\n", fid,
1722		    le16toh(ltbuf[1]), le16toh(ltbuf[0])));
1723		break;
1724	}
1725	CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO);
1726}
1727
1728static int
1729wi_write_multi(struct wi_softc *sc)
1730{
1731	struct ifnet *ifp = sc->sc_ifp;
1732	int n;
1733	struct ifmultiaddr *ifma;
1734	struct wi_mcast mlist;
1735
1736	if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
1737allmulti:
1738		memset(&mlist, 0, sizeof(mlist));
1739		return wi_write_rid(sc, WI_RID_MCAST_LIST, &mlist,
1740		    sizeof(mlist));
1741	}
1742
1743	n = 0;
1744	IF_ADDR_LOCK(ifp);
1745#if __FreeBSD_version < 500000
1746	LIST_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
1747#else
1748	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
1749#endif
1750		if (ifma->ifma_addr->sa_family != AF_LINK)
1751			continue;
1752		if (n >= 16)
1753			goto allmulti;
1754		IEEE80211_ADDR_COPY(&mlist.wi_mcast[n],
1755		    (LLADDR((struct sockaddr_dl *)ifma->ifma_addr)));
1756		n++;
1757	}
1758	IF_ADDR_UNLOCK(ifp);
1759	return wi_write_rid(sc, WI_RID_MCAST_LIST, &mlist,
1760	    IEEE80211_ADDR_LEN * n);
1761}
1762
1763static void
1764wi_read_nicid(struct wi_softc *sc)
1765{
1766	struct wi_card_ident *id;
1767	char *p;
1768	int len;
1769	u_int16_t ver[4];
1770
1771	/* getting chip identity */
1772	memset(ver, 0, sizeof(ver));
1773	len = sizeof(ver);
1774	wi_read_rid(sc, WI_RID_CARD_ID, ver, &len);
1775	device_printf(sc->sc_dev, "using ");
1776
1777	sc->sc_firmware_type = WI_NOTYPE;
1778	for (id = wi_card_ident; id->card_name != NULL; id++) {
1779		if (le16toh(ver[0]) == id->card_id) {
1780			printf("%s", id->card_name);
1781			sc->sc_firmware_type = id->firm_type;
1782			break;
1783		}
1784	}
1785	if (sc->sc_firmware_type == WI_NOTYPE) {
1786		if (le16toh(ver[0]) & 0x8000) {
1787			printf("Unknown PRISM2 chip");
1788			sc->sc_firmware_type = WI_INTERSIL;
1789		} else {
1790			printf("Unknown Lucent chip");
1791			sc->sc_firmware_type = WI_LUCENT;
1792		}
1793	}
1794
1795	/* get primary firmware version (Only Prism chips) */
1796	if (sc->sc_firmware_type != WI_LUCENT) {
1797		memset(ver, 0, sizeof(ver));
1798		len = sizeof(ver);
1799		wi_read_rid(sc, WI_RID_PRI_IDENTITY, ver, &len);
1800		sc->sc_pri_firmware_ver = le16toh(ver[2]) * 10000 +
1801		    le16toh(ver[3]) * 100 + le16toh(ver[1]);
1802	}
1803
1804	/* get station firmware version */
1805	memset(ver, 0, sizeof(ver));
1806	len = sizeof(ver);
1807	wi_read_rid(sc, WI_RID_STA_IDENTITY, ver, &len);
1808	sc->sc_sta_firmware_ver = le16toh(ver[2]) * 10000 +
1809	    le16toh(ver[3]) * 100 + le16toh(ver[1]);
1810	if (sc->sc_firmware_type == WI_INTERSIL &&
1811	    (sc->sc_sta_firmware_ver == 10102 ||
1812	     sc->sc_sta_firmware_ver == 20102)) {
1813		char ident[12];
1814		memset(ident, 0, sizeof(ident));
1815		len = sizeof(ident);
1816		/* value should be the format like "V2.00-11" */
1817		if (wi_read_rid(sc, WI_RID_SYMBOL_IDENTITY, ident, &len) == 0 &&
1818		    *(p = (char *)ident) >= 'A' &&
1819		    p[2] == '.' && p[5] == '-' && p[8] == '\0') {
1820			sc->sc_firmware_type = WI_SYMBOL;
1821			sc->sc_sta_firmware_ver = (p[1] - '0') * 10000 +
1822			    (p[3] - '0') * 1000 + (p[4] - '0') * 100 +
1823			    (p[6] - '0') * 10 + (p[7] - '0');
1824		}
1825	}
1826	printf("\n");
1827	device_printf(sc->sc_dev, "%s Firmware: ",
1828	     sc->sc_firmware_type == WI_LUCENT ? "Lucent" :
1829	    (sc->sc_firmware_type == WI_SYMBOL ? "Symbol" : "Intersil"));
1830	if (sc->sc_firmware_type != WI_LUCENT)	/* XXX */
1831		printf("Primary (%u.%u.%u), ",
1832		    sc->sc_pri_firmware_ver / 10000,
1833		    (sc->sc_pri_firmware_ver % 10000) / 100,
1834		    sc->sc_pri_firmware_ver % 100);
1835	printf("Station (%u.%u.%u)\n",
1836	    sc->sc_sta_firmware_ver / 10000,
1837	    (sc->sc_sta_firmware_ver % 10000) / 100,
1838	    sc->sc_sta_firmware_ver % 100);
1839}
1840
1841static int
1842wi_write_ssid(struct wi_softc *sc, int rid, u_int8_t *buf, int buflen)
1843{
1844	struct wi_ssid ssid;
1845
1846	if (buflen > IEEE80211_NWID_LEN)
1847		return ENOBUFS;
1848	memset(&ssid, 0, sizeof(ssid));
1849	ssid.wi_len = htole16(buflen);
1850	memcpy(ssid.wi_ssid, buf, buflen);
1851	return wi_write_rid(sc, rid, &ssid, sizeof(ssid));
1852}
1853
1854static int
1855wi_get_cfg(struct ifnet *ifp, u_long cmd, caddr_t data)
1856{
1857	struct wi_softc *sc = ifp->if_softc;
1858	struct ieee80211com *ic = &sc->sc_ic;
1859	struct ifreq *ifr = (struct ifreq *)data;
1860	struct wi_req wreq;
1861	struct wi_scan_res *res;
1862	size_t reslen;
1863	int len, n, error, mif, val, off, i;
1864
1865	error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
1866	if (error)
1867		return error;
1868	len = (wreq.wi_len - 1) * 2;
1869	if (len < sizeof(u_int16_t))
1870		return ENOSPC;
1871	if (len > sizeof(wreq.wi_val))
1872		len = sizeof(wreq.wi_val);
1873
1874	switch (wreq.wi_type) {
1875
1876	case WI_RID_IFACE_STATS:
1877		memcpy(wreq.wi_val, &sc->sc_stats, sizeof(sc->sc_stats));
1878		if (len < sizeof(sc->sc_stats))
1879			error = ENOSPC;
1880		else
1881			len = sizeof(sc->sc_stats);
1882		break;
1883
1884	case WI_RID_ENCRYPTION:
1885	case WI_RID_TX_CRYPT_KEY:
1886	case WI_RID_DEFLT_CRYPT_KEYS:
1887	case WI_RID_TX_RATE:
1888		return ieee80211_cfgget(ic, cmd, data);
1889
1890	case WI_RID_MICROWAVE_OVEN:
1891		if (sc->sc_enabled && (sc->sc_flags & WI_FLAGS_HAS_MOR)) {
1892			error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val,
1893			    &len);
1894			break;
1895		}
1896		wreq.wi_val[0] = htole16(sc->sc_microwave_oven);
1897		len = sizeof(u_int16_t);
1898		break;
1899
1900	case WI_RID_DBM_ADJUST:
1901		if (sc->sc_enabled && (sc->sc_flags & WI_FLAGS_HAS_DBMADJUST)) {
1902			error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val,
1903			    &len);
1904			break;
1905		}
1906		wreq.wi_val[0] = htole16(sc->sc_dbm_offset);
1907		len = sizeof(u_int16_t);
1908		break;
1909
1910	case WI_RID_ROAMING_MODE:
1911		if (sc->sc_enabled && (sc->sc_flags & WI_FLAGS_HAS_ROAMING)) {
1912			error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val,
1913			    &len);
1914			break;
1915		}
1916		wreq.wi_val[0] = htole16(sc->sc_roaming_mode);
1917		len = sizeof(u_int16_t);
1918		break;
1919
1920	case WI_RID_SYSTEM_SCALE:
1921		if (sc->sc_enabled && (sc->sc_flags & WI_FLAGS_HAS_SYSSCALE)) {
1922			error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val,
1923			    &len);
1924			break;
1925		}
1926		wreq.wi_val[0] = htole16(sc->sc_system_scale);
1927		len = sizeof(u_int16_t);
1928		break;
1929
1930	case WI_RID_FRAG_THRESH:
1931		if (sc->sc_enabled && (sc->sc_flags & WI_FLAGS_HAS_FRAGTHR)) {
1932			error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val,
1933			    &len);
1934			break;
1935		}
1936		wreq.wi_val[0] = htole16(ic->ic_fragthreshold);
1937		len = sizeof(u_int16_t);
1938		break;
1939
1940	case WI_RID_READ_APS:
1941		if (ic->ic_opmode == IEEE80211_M_HOSTAP)
1942			return ieee80211_cfgget(ic, cmd, data);
1943		if (sc->sc_scan_timer > 0) {
1944			error = EINPROGRESS;
1945			break;
1946		}
1947		n = sc->sc_naps;
1948		if (len < sizeof(n)) {
1949			error = ENOSPC;
1950			break;
1951		}
1952		if (len < sizeof(n) + sizeof(struct wi_apinfo) * n)
1953			n = (len - sizeof(n)) / sizeof(struct wi_apinfo);
1954		len = sizeof(n) + sizeof(struct wi_apinfo) * n;
1955		memcpy(wreq.wi_val, &n, sizeof(n));
1956		memcpy((caddr_t)wreq.wi_val + sizeof(n), sc->sc_aps,
1957		    sizeof(struct wi_apinfo) * n);
1958		break;
1959
1960	case WI_RID_PRISM2:
1961		wreq.wi_val[0] = sc->sc_firmware_type != WI_LUCENT;
1962		len = sizeof(u_int16_t);
1963		break;
1964
1965	case WI_RID_MIF:
1966		mif = wreq.wi_val[0];
1967		error = wi_cmd(sc, WI_CMD_READMIF, mif, 0, 0);
1968		val = CSR_READ_2(sc, WI_RESP0);
1969		wreq.wi_val[0] = val;
1970		len = sizeof(u_int16_t);
1971		break;
1972
1973	case WI_RID_ZERO_CACHE:
1974	case WI_RID_PROCFRAME:		/* ignore for compatibility */
1975		/* XXX ??? */
1976		break;
1977
1978	case WI_RID_READ_CACHE:
1979		return ieee80211_cfgget(ic, cmd, data);
1980
1981	case WI_RID_SCAN_RES:		/* compatibility interface */
1982		if (ic->ic_opmode == IEEE80211_M_HOSTAP)
1983			return ieee80211_cfgget(ic, cmd, data);
1984		if (sc->sc_scan_timer > 0) {
1985			error = EINPROGRESS;
1986			break;
1987		}
1988		n = sc->sc_naps;
1989		if (sc->sc_firmware_type == WI_LUCENT) {
1990			off = 0;
1991			reslen = WI_WAVELAN_RES_SIZE;
1992		} else {
1993			off = sizeof(struct wi_scan_p2_hdr);
1994			reslen = WI_PRISM2_RES_SIZE;
1995		}
1996		if (len < off + reslen * n)
1997			n = (len - off) / reslen;
1998		len = off + reslen * n;
1999		if (off != 0) {
2000			struct wi_scan_p2_hdr *p2 = (struct wi_scan_p2_hdr *)wreq.wi_val;
2001			/*
2002			 * Prepend Prism-specific header.
2003			 */
2004			if (len < sizeof(struct wi_scan_p2_hdr)) {
2005				error = ENOSPC;
2006				break;
2007			}
2008			p2 = (struct wi_scan_p2_hdr *)wreq.wi_val;
2009			p2->wi_rsvd = 0;
2010			p2->wi_reason = n;	/* XXX */
2011		}
2012		for (i = 0; i < n; i++, off += reslen) {
2013			const struct wi_apinfo *ap = &sc->sc_aps[i];
2014
2015			res = (struct wi_scan_res *)((char *)wreq.wi_val + off);
2016			res->wi_chan = ap->channel;
2017			res->wi_noise = ap->noise;
2018			res->wi_signal = ap->signal;
2019			IEEE80211_ADDR_COPY(res->wi_bssid, ap->bssid);
2020			res->wi_interval = ap->interval;
2021			res->wi_capinfo = ap->capinfo;
2022			res->wi_ssid_len = ap->namelen;
2023			memcpy(res->wi_ssid, ap->name,
2024				IEEE80211_NWID_LEN);
2025			if (sc->sc_firmware_type != WI_LUCENT) {
2026				/* XXX not saved from Prism cards */
2027				memset(res->wi_srates, 0,
2028					sizeof(res->wi_srates));
2029				res->wi_rate = ap->rate;
2030				res->wi_rsvd = 0;
2031			}
2032		}
2033		break;
2034
2035	default:
2036		if (sc->sc_enabled) {
2037			error = wi_read_rid(sc, wreq.wi_type, wreq.wi_val,
2038			    &len);
2039			break;
2040		}
2041		switch (wreq.wi_type) {
2042		case WI_RID_MAX_DATALEN:
2043			wreq.wi_val[0] = htole16(sc->sc_max_datalen);
2044			len = sizeof(u_int16_t);
2045			break;
2046		case WI_RID_RTS_THRESH:
2047			wreq.wi_val[0] = htole16(ic->ic_rtsthreshold);
2048			len = sizeof(u_int16_t);
2049			break;
2050		case WI_RID_CNFAUTHMODE:
2051			wreq.wi_val[0] = htole16(sc->sc_cnfauthmode);
2052			len = sizeof(u_int16_t);
2053			break;
2054		case WI_RID_NODENAME:
2055			if (len < sc->sc_nodelen + sizeof(u_int16_t)) {
2056				error = ENOSPC;
2057				break;
2058			}
2059			len = sc->sc_nodelen + sizeof(u_int16_t);
2060			wreq.wi_val[0] = htole16((sc->sc_nodelen + 1) / 2);
2061			memcpy(&wreq.wi_val[1], sc->sc_nodename,
2062			    sc->sc_nodelen);
2063			break;
2064		default:
2065			return ieee80211_cfgget(ic, cmd, data);
2066		}
2067		break;
2068	}
2069	if (error)
2070		return error;
2071	wreq.wi_len = (len + 1) / 2 + 1;
2072	return copyout(&wreq, ifr->ifr_data, (wreq.wi_len + 1) * 2);
2073}
2074
2075static int
2076wi_set_cfg(struct ifnet *ifp, u_long cmd, caddr_t data)
2077{
2078	struct wi_softc *sc = ifp->if_softc;
2079	struct ieee80211com *ic = &sc->sc_ic;
2080	struct ifreq *ifr = (struct ifreq *)data;
2081	struct wi_req wreq;
2082	struct mbuf *m;
2083	int i, len, error, mif, val;
2084	struct ieee80211_rateset *rs;
2085	WI_LOCK_DECL();
2086
2087	error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
2088	if (error)
2089		return error;
2090	len = wreq.wi_len ? (wreq.wi_len - 1) * 2 : 0;
2091	switch (wreq.wi_type) {
2092	case WI_RID_DBM_ADJUST:
2093		return ENODEV;
2094
2095	case WI_RID_NODENAME:
2096		if (le16toh(wreq.wi_val[0]) * 2 > len ||
2097		    le16toh(wreq.wi_val[0]) > sizeof(sc->sc_nodename)) {
2098			error = ENOSPC;
2099			break;
2100		}
2101		WI_LOCK(sc);
2102		if (sc->sc_enabled)
2103			error = wi_write_rid(sc, wreq.wi_type, wreq.wi_val,
2104			    len);
2105		if (error == 0) {
2106			sc->sc_nodelen = le16toh(wreq.wi_val[0]) * 2;
2107			memcpy(sc->sc_nodename, &wreq.wi_val[1],
2108				sc->sc_nodelen);
2109		}
2110		WI_UNLOCK(sc);
2111		break;
2112
2113	case WI_RID_MICROWAVE_OVEN:
2114	case WI_RID_ROAMING_MODE:
2115	case WI_RID_SYSTEM_SCALE:
2116	case WI_RID_FRAG_THRESH:
2117		/* XXX unlocked reads */
2118		if (wreq.wi_type == WI_RID_MICROWAVE_OVEN &&
2119		    (sc->sc_flags & WI_FLAGS_HAS_MOR) == 0)
2120			break;
2121		if (wreq.wi_type == WI_RID_ROAMING_MODE &&
2122		    (sc->sc_flags & WI_FLAGS_HAS_ROAMING) == 0)
2123			break;
2124		if (wreq.wi_type == WI_RID_SYSTEM_SCALE &&
2125		    (sc->sc_flags & WI_FLAGS_HAS_SYSSCALE) == 0)
2126			break;
2127		if (wreq.wi_type == WI_RID_FRAG_THRESH &&
2128		    (sc->sc_flags & WI_FLAGS_HAS_FRAGTHR) == 0)
2129			break;
2130		/* FALLTHROUGH */
2131	case WI_RID_RTS_THRESH:
2132	case WI_RID_CNFAUTHMODE:
2133	case WI_RID_MAX_DATALEN:
2134		WI_LOCK(sc);
2135		if (sc->sc_enabled) {
2136			error = wi_write_rid(sc, wreq.wi_type, wreq.wi_val,
2137			    sizeof(u_int16_t));
2138			if (error != 0) {
2139				WI_UNLOCK(sc);
2140				break;
2141			}
2142		}
2143		switch (wreq.wi_type) {
2144		case WI_RID_FRAG_THRESH:
2145			ic->ic_fragthreshold = le16toh(wreq.wi_val[0]);
2146			break;
2147		case WI_RID_RTS_THRESH:
2148			ic->ic_rtsthreshold = le16toh(wreq.wi_val[0]);
2149			break;
2150		case WI_RID_MICROWAVE_OVEN:
2151			sc->sc_microwave_oven = le16toh(wreq.wi_val[0]);
2152			break;
2153		case WI_RID_ROAMING_MODE:
2154			sc->sc_roaming_mode = le16toh(wreq.wi_val[0]);
2155			break;
2156		case WI_RID_SYSTEM_SCALE:
2157			sc->sc_system_scale = le16toh(wreq.wi_val[0]);
2158			break;
2159		case WI_RID_CNFAUTHMODE:
2160			sc->sc_cnfauthmode = le16toh(wreq.wi_val[0]);
2161			break;
2162		case WI_RID_MAX_DATALEN:
2163			sc->sc_max_datalen = le16toh(wreq.wi_val[0]);
2164			break;
2165		}
2166		WI_UNLOCK(sc);
2167		break;
2168
2169	case WI_RID_TX_RATE:
2170		WI_LOCK(sc);
2171		switch (le16toh(wreq.wi_val[0])) {
2172		case 3:
2173			ic->ic_fixed_rate = IEEE80211_FIXED_RATE_NONE;
2174			break;
2175		default:
2176			rs = &ic->ic_sup_rates[IEEE80211_MODE_11B];
2177			for (i = 0; i < rs->rs_nrates; i++) {
2178				if ((rs->rs_rates[i] & IEEE80211_RATE_VAL)
2179				    / 2 == le16toh(wreq.wi_val[0]))
2180					break;
2181			}
2182			if (i == rs->rs_nrates) {
2183				WI_UNLOCK(sc);
2184				return EINVAL;
2185			}
2186			ic->ic_fixed_rate = i;
2187		}
2188		if (sc->sc_enabled)
2189			error = wi_write_txrate(sc);
2190		WI_UNLOCK(sc);
2191		break;
2192
2193	case WI_RID_SCAN_APS:
2194		WI_LOCK(sc);
2195		if (sc->sc_enabled && ic->ic_opmode != IEEE80211_M_HOSTAP)
2196			error = wi_scan_ap(sc, 0x3fff, 0x000f);
2197		WI_UNLOCK(sc);
2198		break;
2199
2200	case WI_RID_SCAN_REQ:		/* compatibility interface */
2201		WI_LOCK(sc);
2202		if (sc->sc_enabled && ic->ic_opmode != IEEE80211_M_HOSTAP)
2203			error = wi_scan_ap(sc, wreq.wi_val[0], wreq.wi_val[1]);
2204		WI_UNLOCK(sc);
2205		break;
2206
2207	case WI_RID_MGMT_XMIT:
2208		WI_LOCK(sc);
2209		if (!sc->sc_enabled)
2210			error = ENETDOWN;
2211		else if (ic->ic_mgtq.ifq_len > 5)
2212			error = EAGAIN;
2213		else {
2214			/* NB: m_devget uses M_DONTWAIT so can hold the lock */
2215			/* XXX wi_len looks in u_int8_t, not in u_int16_t */
2216			m = m_devget((char *)&wreq.wi_val, wreq.wi_len, 0,
2217				ifp, NULL);
2218			if (m != NULL)
2219				IF_ENQUEUE(&ic->ic_mgtq, m);
2220			else
2221				error = ENOMEM;
2222		}
2223		WI_UNLOCK(sc);
2224		break;
2225
2226	case WI_RID_MIF:
2227		mif = wreq.wi_val[0];
2228		val = wreq.wi_val[1];
2229		WI_LOCK(sc);
2230		error = wi_cmd(sc, WI_CMD_WRITEMIF, mif, val, 0);
2231		WI_UNLOCK(sc);
2232		break;
2233
2234	case WI_RID_PROCFRAME:		/* ignore for compatibility */
2235		break;
2236
2237	case WI_RID_OWN_SSID:
2238		if (le16toh(wreq.wi_val[0]) * 2 > len ||
2239		    le16toh(wreq.wi_val[0]) > IEEE80211_NWID_LEN) {
2240			error = ENOSPC;
2241			break;
2242		}
2243		WI_LOCK(sc);
2244		memset(ic->ic_des_essid, 0, IEEE80211_NWID_LEN);
2245		ic->ic_des_esslen = le16toh(wreq.wi_val[0]) * 2;
2246		memcpy(ic->ic_des_essid, &wreq.wi_val[1], ic->ic_des_esslen);
2247		if (sc->sc_enabled)
2248			wi_init(sc);	/* XXX no error return */
2249		WI_UNLOCK(sc);
2250		break;
2251
2252	default:
2253		WI_LOCK(sc);
2254		if (sc->sc_enabled)
2255			error = wi_write_rid(sc, wreq.wi_type, wreq.wi_val,
2256			    len);
2257		if (error == 0) {
2258			/* XXX ieee80211_cfgset does a copyin */
2259			error = ieee80211_cfgset(ic, cmd, data);
2260			if (error == ENETRESET) {
2261				if (sc->sc_enabled)
2262					wi_init(sc);
2263				error = 0;
2264			}
2265		}
2266		WI_UNLOCK(sc);
2267		break;
2268	}
2269	return error;
2270}
2271
2272static int
2273wi_write_txrate(struct wi_softc *sc)
2274{
2275	struct ieee80211com *ic = &sc->sc_ic;
2276	int i;
2277	u_int16_t rate;
2278
2279	if (ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE)
2280		rate = 0;	/* auto */
2281	else
2282		rate = (ic->ic_sup_rates[IEEE80211_MODE_11B].rs_rates[ic->ic_fixed_rate] &
2283		    IEEE80211_RATE_VAL) / 2;
2284
2285	/* rate: 0, 1, 2, 5, 11 */
2286
2287	switch (sc->sc_firmware_type) {
2288	case WI_LUCENT:
2289		switch (rate) {
2290		case 0:			/* auto == 11mbps auto */
2291			rate = 3;
2292			break;
2293		/* case 1, 2 map to 1, 2*/
2294		case 5:			/* 5.5Mbps -> 4 */
2295			rate = 4;
2296			break;
2297		case 11:		/* 11mbps -> 5 */
2298			rate = 5;
2299			break;
2300		default:
2301			break;
2302		}
2303		break;
2304	default:
2305		/* Choose a bit according to this table.
2306		 *
2307		 * bit | data rate
2308		 * ----+-------------------
2309		 * 0   | 1Mbps
2310		 * 1   | 2Mbps
2311		 * 2   | 5.5Mbps
2312		 * 3   | 11Mbps
2313		 */
2314		for (i = 8; i > 0; i >>= 1) {
2315			if (rate >= i)
2316				break;
2317		}
2318		if (i == 0)
2319			rate = 0xf;	/* auto */
2320		else
2321			rate = i;
2322		break;
2323	}
2324	return wi_write_val(sc, WI_RID_TX_RATE, rate);
2325}
2326
2327static int
2328wi_write_wep(struct wi_softc *sc)
2329{
2330	struct ieee80211com *ic = &sc->sc_ic;
2331	int error = 0;
2332	int i, keylen;
2333	u_int16_t val;
2334	struct wi_key wkey[IEEE80211_WEP_NKID];
2335
2336	switch (sc->sc_firmware_type) {
2337	case WI_LUCENT:
2338		val = (ic->ic_flags & IEEE80211_F_PRIVACY) ? 1 : 0;
2339		error = wi_write_val(sc, WI_RID_ENCRYPTION, val);
2340		if (error)
2341			break;
2342		if ((ic->ic_flags & IEEE80211_F_PRIVACY) == 0)
2343			break;
2344		error = wi_write_val(sc, WI_RID_TX_CRYPT_KEY, ic->ic_def_txkey);
2345		if (error)
2346			break;
2347		memset(wkey, 0, sizeof(wkey));
2348		for (i = 0; i < IEEE80211_WEP_NKID; i++) {
2349			keylen = ic->ic_nw_keys[i].wk_keylen;
2350			wkey[i].wi_keylen = htole16(keylen);
2351			memcpy(wkey[i].wi_keydat, ic->ic_nw_keys[i].wk_key,
2352			    keylen);
2353		}
2354		error = wi_write_rid(sc, WI_RID_DEFLT_CRYPT_KEYS,
2355		    wkey, sizeof(wkey));
2356		break;
2357
2358	case WI_INTERSIL:
2359	case WI_SYMBOL:
2360		if (ic->ic_flags & IEEE80211_F_PRIVACY) {
2361			/*
2362			 * ONLY HWB3163 EVAL-CARD Firmware version
2363			 * less than 0.8 variant2
2364			 *
2365			 *   If promiscuous mode disable, Prism2 chip
2366			 *  does not work with WEP .
2367			 * It is under investigation for details.
2368			 * (ichiro@netbsd.org)
2369			 */
2370			if (sc->sc_firmware_type == WI_INTERSIL &&
2371			    sc->sc_sta_firmware_ver < 802 ) {
2372				/* firm ver < 0.8 variant 2 */
2373				wi_write_val(sc, WI_RID_PROMISC, 1);
2374			}
2375			wi_write_val(sc, WI_RID_CNFAUTHMODE,
2376			    sc->sc_cnfauthmode);
2377			val = PRIVACY_INVOKED | EXCLUDE_UNENCRYPTED;
2378			/*
2379			 * Encryption firmware has a bug for HostAP mode.
2380			 */
2381			if (sc->sc_firmware_type == WI_INTERSIL &&
2382			    ic->ic_opmode == IEEE80211_M_HOSTAP)
2383				val |= HOST_ENCRYPT;
2384		} else {
2385			wi_write_val(sc, WI_RID_CNFAUTHMODE,
2386			    IEEE80211_AUTH_OPEN);
2387			val = HOST_ENCRYPT | HOST_DECRYPT;
2388		}
2389		error = wi_write_val(sc, WI_RID_P2_ENCRYPTION, val);
2390		if (error)
2391			break;
2392		if ((val & PRIVACY_INVOKED) == 0)
2393			break;
2394		error = wi_write_val(sc, WI_RID_P2_TX_CRYPT_KEY,
2395		    ic->ic_def_txkey);
2396		if (error)
2397			break;
2398		if (val & HOST_DECRYPT)
2399			break;
2400		/*
2401		 * It seems that the firmware accept 104bit key only if
2402		 * all the keys have 104bit length.  We get the length of
2403		 * the transmit key and use it for all other keys.
2404		 * Perhaps we should use software WEP for such situation.
2405		 */
2406		if (ic->ic_def_txkey != IEEE80211_KEYIX_NONE)
2407			keylen = ic->ic_nw_keys[ic->ic_def_txkey].wk_keylen;
2408		else	/* XXX should not hapen */
2409			keylen = IEEE80211_WEP_KEYLEN;
2410		if (keylen > IEEE80211_WEP_KEYLEN)
2411			keylen = 13;	/* 104bit keys */
2412		else
2413			keylen = IEEE80211_WEP_KEYLEN;
2414		for (i = 0; i < IEEE80211_WEP_NKID; i++) {
2415			error = wi_write_rid(sc, WI_RID_P2_CRYPT_KEY0 + i,
2416			    ic->ic_nw_keys[i].wk_key, keylen);
2417			if (error)
2418				break;
2419		}
2420		break;
2421	}
2422	return error;
2423}
2424
2425static int
2426wi_cmd(struct wi_softc *sc, int cmd, int val0, int val1, int val2)
2427{
2428	int			i, s = 0;
2429	static volatile int count  = 0;
2430
2431	if (sc->wi_gone)
2432		return (ENODEV);
2433
2434	if (count > 0)
2435		panic("Hey partner, hold on there!");
2436	count++;
2437
2438	/* wait for the busy bit to clear */
2439	for (i = sc->wi_cmd_count; i > 0; i--) {	/* 500ms */
2440		if (!(CSR_READ_2(sc, WI_COMMAND) & WI_CMD_BUSY))
2441			break;
2442		DELAY(1*1000);	/* 1ms */
2443	}
2444	if (i == 0) {
2445		device_printf(sc->sc_dev, "wi_cmd: busy bit won't clear.\n" );
2446		sc->wi_gone = 1;
2447		count--;
2448		return(ETIMEDOUT);
2449	}
2450
2451	CSR_WRITE_2(sc, WI_PARAM0, val0);
2452	CSR_WRITE_2(sc, WI_PARAM1, val1);
2453	CSR_WRITE_2(sc, WI_PARAM2, val2);
2454	CSR_WRITE_2(sc, WI_COMMAND, cmd);
2455
2456	if (cmd == WI_CMD_INI) {
2457		/* XXX: should sleep here. */
2458		DELAY(100*1000);		/* 100ms delay for init */
2459	}
2460	for (i = 0; i < WI_TIMEOUT; i++) {
2461		/*
2462		 * Wait for 'command complete' bit to be
2463		 * set in the event status register.
2464		 */
2465		s = CSR_READ_2(sc, WI_EVENT_STAT);
2466		if (s & WI_EV_CMD) {
2467			/* Ack the event and read result code. */
2468			s = CSR_READ_2(sc, WI_STATUS);
2469			CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_CMD);
2470			if (s & WI_STAT_CMD_RESULT) {
2471				count--;
2472				return(EIO);
2473			}
2474			break;
2475		}
2476		DELAY(WI_DELAY);
2477	}
2478
2479	count--;
2480	if (i == WI_TIMEOUT) {
2481		device_printf(sc->sc_dev,
2482		    "timeout in wi_cmd 0x%04x; event status 0x%04x\n", cmd, s);
2483		if (s == 0xffff)
2484			sc->wi_gone = 1;
2485		return(ETIMEDOUT);
2486	}
2487	return (0);
2488}
2489
2490static int
2491wi_seek_bap(struct wi_softc *sc, int id, int off)
2492{
2493	int i, status;
2494
2495	CSR_WRITE_2(sc, WI_SEL0, id);
2496	CSR_WRITE_2(sc, WI_OFF0, off);
2497
2498	for (i = 0; ; i++) {
2499		status = CSR_READ_2(sc, WI_OFF0);
2500		if ((status & WI_OFF_BUSY) == 0)
2501			break;
2502		if (i == WI_TIMEOUT) {
2503			device_printf(sc->sc_dev, "timeout in wi_seek to %x/%x\n",
2504			    id, off);
2505			sc->sc_bap_off = WI_OFF_ERR;	/* invalidate */
2506			if (status == 0xffff)
2507				sc->wi_gone = 1;
2508			return ETIMEDOUT;
2509		}
2510		DELAY(1);
2511	}
2512	if (status & WI_OFF_ERR) {
2513		device_printf(sc->sc_dev, "failed in wi_seek to %x/%x\n", id, off);
2514		sc->sc_bap_off = WI_OFF_ERR;	/* invalidate */
2515		return EIO;
2516	}
2517	sc->sc_bap_id = id;
2518	sc->sc_bap_off = off;
2519	return 0;
2520}
2521
2522static int
2523wi_read_bap(struct wi_softc *sc, int id, int off, void *buf, int buflen)
2524{
2525	u_int16_t *ptr;
2526	int i, error, cnt;
2527
2528	if (buflen == 0)
2529		return 0;
2530	if (id != sc->sc_bap_id || off != sc->sc_bap_off) {
2531		if ((error = wi_seek_bap(sc, id, off)) != 0)
2532			return error;
2533	}
2534	cnt = (buflen + 1) / 2;
2535	ptr = (u_int16_t *)buf;
2536	for (i = 0; i < cnt; i++)
2537		*ptr++ = CSR_READ_2(sc, WI_DATA0);
2538	sc->sc_bap_off += cnt * 2;
2539	return 0;
2540}
2541
2542static int
2543wi_write_bap(struct wi_softc *sc, int id, int off, void *buf, int buflen)
2544{
2545	u_int16_t *ptr;
2546	int i, error, cnt;
2547
2548	if (buflen == 0)
2549		return 0;
2550
2551#ifdef WI_HERMES_AUTOINC_WAR
2552  again:
2553#endif
2554	if (id != sc->sc_bap_id || off != sc->sc_bap_off) {
2555		if ((error = wi_seek_bap(sc, id, off)) != 0)
2556			return error;
2557	}
2558	cnt = (buflen + 1) / 2;
2559	ptr = (u_int16_t *)buf;
2560	for (i = 0; i < cnt; i++)
2561		CSR_WRITE_2(sc, WI_DATA0, ptr[i]);
2562	sc->sc_bap_off += cnt * 2;
2563
2564#ifdef WI_HERMES_AUTOINC_WAR
2565	/*
2566	 * According to the comments in the HCF Light code, there is a bug
2567	 * in the Hermes (or possibly in certain Hermes firmware revisions)
2568	 * where the chip's internal autoincrement counter gets thrown off
2569	 * during data writes:  the autoincrement is missed, causing one
2570	 * data word to be overwritten and subsequent words to be written to
2571	 * the wrong memory locations. The end result is that we could end
2572	 * up transmitting bogus frames without realizing it. The workaround
2573	 * for this is to write a couple of extra guard words after the end
2574	 * of the transfer, then attempt to read then back. If we fail to
2575	 * locate the guard words where we expect them, we preform the
2576	 * transfer over again.
2577	 */
2578	if ((sc->sc_flags & WI_FLAGS_BUG_AUTOINC) && (id & 0xf000) == 0) {
2579		CSR_WRITE_2(sc, WI_DATA0, 0x1234);
2580		CSR_WRITE_2(sc, WI_DATA0, 0x5678);
2581		wi_seek_bap(sc, id, sc->sc_bap_off);
2582		sc->sc_bap_off = WI_OFF_ERR;	/* invalidate */
2583		if (CSR_READ_2(sc, WI_DATA0) != 0x1234 ||
2584		    CSR_READ_2(sc, WI_DATA0) != 0x5678) {
2585			device_printf(sc->sc_dev,
2586				"detect auto increment bug, try again\n");
2587			goto again;
2588		}
2589	}
2590#endif
2591	return 0;
2592}
2593
2594static int
2595wi_mwrite_bap(struct wi_softc *sc, int id, int off, struct mbuf *m0, int totlen)
2596{
2597	int error, len;
2598	struct mbuf *m;
2599
2600	for (m = m0; m != NULL && totlen > 0; m = m->m_next) {
2601		if (m->m_len == 0)
2602			continue;
2603
2604		len = min(m->m_len, totlen);
2605
2606		if (((u_long)m->m_data) % 2 != 0 || len % 2 != 0) {
2607			m_copydata(m, 0, totlen, (caddr_t)&sc->sc_txbuf);
2608			return wi_write_bap(sc, id, off, (caddr_t)&sc->sc_txbuf,
2609			    totlen);
2610		}
2611
2612		if ((error = wi_write_bap(sc, id, off, m->m_data, len)) != 0)
2613			return error;
2614
2615		off += m->m_len;
2616		totlen -= len;
2617	}
2618	return 0;
2619}
2620
2621static int
2622wi_alloc_fid(struct wi_softc *sc, int len, int *idp)
2623{
2624	int i;
2625
2626	if (wi_cmd(sc, WI_CMD_ALLOC_MEM, len, 0, 0)) {
2627		device_printf(sc->sc_dev, "failed to allocate %d bytes on NIC\n",
2628		    len);
2629		return ENOMEM;
2630	}
2631
2632	for (i = 0; i < WI_TIMEOUT; i++) {
2633		if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_ALLOC)
2634			break;
2635		DELAY(1);
2636	}
2637	if (i == WI_TIMEOUT) {
2638		device_printf(sc->sc_dev, "timeout in alloc\n");
2639		return ETIMEDOUT;
2640	}
2641	*idp = CSR_READ_2(sc, WI_ALLOC_FID);
2642	CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
2643	return 0;
2644}
2645
2646static int
2647wi_read_rid(struct wi_softc *sc, int rid, void *buf, int *buflenp)
2648{
2649	int error, len;
2650	u_int16_t ltbuf[2];
2651
2652	/* Tell the NIC to enter record read mode. */
2653	error = wi_cmd(sc, WI_CMD_ACCESS | WI_ACCESS_READ, rid, 0, 0);
2654	if (error)
2655		return error;
2656
2657	error = wi_read_bap(sc, rid, 0, ltbuf, sizeof(ltbuf));
2658	if (error)
2659		return error;
2660
2661	if (le16toh(ltbuf[1]) != rid) {
2662		device_printf(sc->sc_dev, "record read mismatch, rid=%x, got=%x\n",
2663		    rid, le16toh(ltbuf[1]));
2664		return EIO;
2665	}
2666	len = (le16toh(ltbuf[0]) - 1) * 2;	 /* already got rid */
2667	if (*buflenp < len) {
2668		device_printf(sc->sc_dev, "record buffer is too small, "
2669		    "rid=%x, size=%d, len=%d\n",
2670		    rid, *buflenp, len);
2671		return ENOSPC;
2672	}
2673	*buflenp = len;
2674	return wi_read_bap(sc, rid, sizeof(ltbuf), buf, len);
2675}
2676
2677static int
2678wi_write_rid(struct wi_softc *sc, int rid, void *buf, int buflen)
2679{
2680	int error;
2681	u_int16_t ltbuf[2];
2682
2683	ltbuf[0] = htole16((buflen + 1) / 2 + 1);	 /* includes rid */
2684	ltbuf[1] = htole16(rid);
2685
2686	error = wi_write_bap(sc, rid, 0, ltbuf, sizeof(ltbuf));
2687	if (error)
2688		return error;
2689	error = wi_write_bap(sc, rid, sizeof(ltbuf), buf, buflen);
2690	if (error)
2691		return error;
2692
2693	return wi_cmd(sc, WI_CMD_ACCESS | WI_ACCESS_WRITE, rid, 0, 0);
2694}
2695
2696static int
2697wi_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
2698{
2699	struct ifnet *ifp = ic->ic_ifp;
2700	struct wi_softc *sc = ifp->if_softc;
2701	struct ieee80211_node *ni;
2702	int buflen;
2703	u_int16_t val;
2704	struct wi_ssid ssid;
2705	u_int8_t old_bssid[IEEE80211_ADDR_LEN];
2706
2707	DPRINTF(("%s: %s -> %s\n", __func__,
2708		ieee80211_state_name[ic->ic_state],
2709		ieee80211_state_name[nstate]));
2710
2711	/*
2712	 * Internal to the driver the INIT and RUN states are used
2713	 * so bypass the net80211 state machine for other states.
2714	 * Beware however that this requires use to net80211 state
2715	 * management that otherwise would be handled for us.
2716	 */
2717	switch (nstate) {
2718	case IEEE80211_S_INIT:
2719		sc->sc_flags &= ~WI_FLAGS_OUTRANGE;
2720		return (*sc->sc_newstate)(ic, nstate, arg);
2721
2722	case IEEE80211_S_SCAN:
2723	case IEEE80211_S_AUTH:
2724	case IEEE80211_S_ASSOC:
2725		ic->ic_state = nstate;	/* NB: skip normal ieee80211 handling */
2726		break;
2727
2728	case IEEE80211_S_RUN:
2729		ni = ic->ic_bss;
2730		sc->sc_flags &= ~WI_FLAGS_OUTRANGE;
2731		buflen = IEEE80211_ADDR_LEN;
2732		IEEE80211_ADDR_COPY(old_bssid, ni->ni_bssid);
2733		wi_read_rid(sc, WI_RID_CURRENT_BSSID, ni->ni_bssid, &buflen);
2734		IEEE80211_ADDR_COPY(ni->ni_macaddr, ni->ni_bssid);
2735		buflen = sizeof(val);
2736		wi_read_rid(sc, WI_RID_CURRENT_CHAN, &val, &buflen);
2737		/* XXX validate channel */
2738		ni->ni_chan = &ic->ic_channels[le16toh(val)];
2739		ic->ic_ibss_chan = ni->ni_chan;
2740#if NBPFILTER > 0
2741		sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq =
2742			htole16(ni->ni_chan->ic_freq);
2743		sc->sc_tx_th.wt_chan_flags = sc->sc_rx_th.wr_chan_flags =
2744			htole16(ni->ni_chan->ic_flags);
2745#endif
2746		if (ic->ic_opmode != IEEE80211_M_HOSTAP) {
2747			/*
2748			 * XXX hack; unceremoniously clear
2749			 * IEEE80211_F_DROPUNENC when operating with
2750			 * wep enabled so we don't drop unencoded frames
2751			 * at the 802.11 layer.  This is necessary because
2752			 * we must strip the WEP bit from the 802.11 header
2753			 * before passing frames to ieee80211_input because
2754			 * the card has already stripped the WEP crypto
2755			 * header from the packet.
2756			 */
2757			if (ic->ic_flags & IEEE80211_F_PRIVACY)
2758				ic->ic_flags &= ~IEEE80211_F_DROPUNENC;
2759			/* XXX check return value */
2760			buflen = sizeof(ssid);
2761			wi_read_rid(sc, WI_RID_CURRENT_SSID, &ssid, &buflen);
2762			ni->ni_esslen = le16toh(ssid.wi_len);
2763			if (ni->ni_esslen > IEEE80211_NWID_LEN)
2764				ni->ni_esslen = IEEE80211_NWID_LEN;	/*XXX*/
2765			memcpy(ni->ni_essid, ssid.wi_ssid, ni->ni_esslen);
2766		}
2767		return (*sc->sc_newstate)(ic, nstate, arg);
2768	}
2769	return 0;
2770}
2771
2772static int
2773wi_scan_ap(struct wi_softc *sc, u_int16_t chanmask, u_int16_t txrate)
2774{
2775	int error = 0;
2776	u_int16_t val[2];
2777
2778	if (!sc->sc_enabled)
2779		return ENXIO;
2780	switch (sc->sc_firmware_type) {
2781	case WI_LUCENT:
2782		(void)wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_SCAN_RESULTS, 0, 0);
2783		break;
2784	case WI_INTERSIL:
2785		val[0] = htole16(chanmask);	/* channel */
2786		val[1] = htole16(txrate);	/* tx rate */
2787		error = wi_write_rid(sc, WI_RID_SCAN_REQ, val, sizeof(val));
2788		break;
2789	case WI_SYMBOL:
2790		/*
2791		 * XXX only supported on 3.x ?
2792		 */
2793		val[0] = BSCAN_BCAST | BSCAN_ONETIME;
2794		error = wi_write_rid(sc, WI_RID_BCAST_SCAN_REQ,
2795		    val, sizeof(val[0]));
2796		break;
2797	}
2798	if (error == 0) {
2799		sc->sc_scan_timer = WI_SCAN_WAIT;
2800		sc->sc_ifp->if_timer = 1;
2801		DPRINTF(("wi_scan_ap: start scanning, "
2802			"chamask 0x%x txrate 0x%x\n", chanmask, txrate));
2803	}
2804	return error;
2805}
2806
2807static void
2808wi_scan_result(struct wi_softc *sc, int fid, int cnt)
2809{
2810#define	N(a)	(sizeof (a) / sizeof (a[0]))
2811	int i, naps, off, szbuf;
2812	struct wi_scan_header ws_hdr;	/* Prism2 header */
2813	struct wi_scan_data_p2 ws_dat;	/* Prism2 scantable*/
2814	struct wi_apinfo *ap;
2815
2816	off = sizeof(u_int16_t) * 2;
2817	memset(&ws_hdr, 0, sizeof(ws_hdr));
2818	switch (sc->sc_firmware_type) {
2819	case WI_INTERSIL:
2820		wi_read_bap(sc, fid, off, &ws_hdr, sizeof(ws_hdr));
2821		off += sizeof(ws_hdr);
2822		szbuf = sizeof(struct wi_scan_data_p2);
2823		break;
2824	case WI_SYMBOL:
2825		szbuf = sizeof(struct wi_scan_data_p2) + 6;
2826		break;
2827	case WI_LUCENT:
2828		szbuf = sizeof(struct wi_scan_data);
2829		break;
2830	default:
2831		device_printf(sc->sc_dev,
2832			"wi_scan_result: unknown firmware type %u\n",
2833			sc->sc_firmware_type);
2834		naps = 0;
2835		goto done;
2836	}
2837	naps = (cnt * 2 + 2 - off) / szbuf;
2838	if (naps > N(sc->sc_aps))
2839		naps = N(sc->sc_aps);
2840	sc->sc_naps = naps;
2841	/* Read Data */
2842	ap = sc->sc_aps;
2843	memset(&ws_dat, 0, sizeof(ws_dat));
2844	for (i = 0; i < naps; i++, ap++) {
2845		wi_read_bap(sc, fid, off, &ws_dat,
2846		    (sizeof(ws_dat) < szbuf ? sizeof(ws_dat) : szbuf));
2847		DPRINTF2(("wi_scan_result: #%d: off %d bssid %s\n", i, off,
2848		    ether_sprintf(ws_dat.wi_bssid)));
2849		off += szbuf;
2850		ap->scanreason = le16toh(ws_hdr.wi_reason);
2851		memcpy(ap->bssid, ws_dat.wi_bssid, sizeof(ap->bssid));
2852		ap->channel = le16toh(ws_dat.wi_chid);
2853		ap->signal  = le16toh(ws_dat.wi_signal);
2854		ap->noise   = le16toh(ws_dat.wi_noise);
2855		ap->quality = ap->signal - ap->noise;
2856		ap->capinfo = le16toh(ws_dat.wi_capinfo);
2857		ap->interval = le16toh(ws_dat.wi_interval);
2858		ap->rate    = le16toh(ws_dat.wi_rate);
2859		ap->namelen = le16toh(ws_dat.wi_namelen);
2860		if (ap->namelen > sizeof(ap->name))
2861			ap->namelen = sizeof(ap->name);
2862		memcpy(ap->name, ws_dat.wi_name, ap->namelen);
2863	}
2864done:
2865	/* Done scanning */
2866	sc->sc_scan_timer = 0;
2867	DPRINTF(("wi_scan_result: scan complete: ap %d\n", naps));
2868#undef N
2869}
2870
2871static void
2872wi_dump_pkt(struct wi_frame *wh, struct ieee80211_node *ni, int rssi)
2873{
2874	ieee80211_dump_pkt((u_int8_t *) &wh->wi_whdr, sizeof(wh->wi_whdr),
2875	    ni ? ni->ni_rates.rs_rates[ni->ni_txrate] & IEEE80211_RATE_VAL : -1, rssi);
2876	printf(" status 0x%x rx_tstamp1 %u rx_tstamp0 0x%u rx_silence %u\n",
2877		le16toh(wh->wi_status), le16toh(wh->wi_rx_tstamp1),
2878		le16toh(wh->wi_rx_tstamp0), wh->wi_rx_silence);
2879	printf(" rx_signal %u rx_rate %u rx_flow %u\n",
2880		wh->wi_rx_signal, wh->wi_rx_rate, wh->wi_rx_flow);
2881	printf(" tx_rtry %u tx_rate %u tx_ctl 0x%x dat_len %u\n",
2882		wh->wi_tx_rtry, wh->wi_tx_rate,
2883		le16toh(wh->wi_tx_ctl), le16toh(wh->wi_dat_len));
2884	printf(" ehdr dst %6D src %6D type 0x%x\n",
2885		wh->wi_ehdr.ether_dhost, ":", wh->wi_ehdr.ether_shost, ":",
2886		wh->wi_ehdr.ether_type);
2887}
2888
2889int
2890wi_alloc(device_t dev, int rid)
2891{
2892	struct wi_softc	*sc = device_get_softc(dev);
2893
2894	if (sc->wi_bus_type != WI_BUS_PCI_NATIVE) {
2895		sc->iobase_rid = rid;
2896		sc->iobase = bus_alloc_resource(dev, SYS_RES_IOPORT,
2897		    &sc->iobase_rid, 0, ~0, (1 << 6),
2898		    rman_make_alignment_flags(1 << 6) | RF_ACTIVE);
2899		if (!sc->iobase) {
2900			device_printf(dev, "No I/O space?!\n");
2901			return (ENXIO);
2902		}
2903
2904		sc->wi_io_addr = rman_get_start(sc->iobase);
2905		sc->wi_btag = rman_get_bustag(sc->iobase);
2906		sc->wi_bhandle = rman_get_bushandle(sc->iobase);
2907	} else {
2908		sc->mem_rid = rid;
2909		sc->mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
2910		    &sc->mem_rid, RF_ACTIVE);
2911
2912		if (!sc->mem) {
2913			device_printf(dev, "No Mem space on prism2.5?\n");
2914			return (ENXIO);
2915		}
2916
2917		sc->wi_btag = rman_get_bustag(sc->mem);
2918		sc->wi_bhandle = rman_get_bushandle(sc->mem);
2919	}
2920
2921
2922	sc->irq_rid = 0;
2923	sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irq_rid,
2924	    RF_ACTIVE |
2925	    ((sc->wi_bus_type == WI_BUS_PCCARD) ? 0 : RF_SHAREABLE));
2926
2927	if (!sc->irq) {
2928		wi_free(dev);
2929		device_printf(dev, "No irq?!\n");
2930		return (ENXIO);
2931	}
2932
2933	sc->sc_dev = dev;
2934	sc->sc_unit = device_get_unit(dev);
2935
2936	return (0);
2937}
2938
2939void
2940wi_free(device_t dev)
2941{
2942	struct wi_softc	*sc = device_get_softc(dev);
2943
2944	if (sc->iobase != NULL) {
2945		bus_release_resource(dev, SYS_RES_IOPORT, sc->iobase_rid, sc->iobase);
2946		sc->iobase = NULL;
2947	}
2948	if (sc->irq != NULL) {
2949		bus_release_resource(dev, SYS_RES_IRQ, sc->irq_rid, sc->irq);
2950		sc->irq = NULL;
2951	}
2952	if (sc->mem != NULL) {
2953		bus_release_resource(dev, SYS_RES_MEMORY, sc->mem_rid, sc->mem);
2954		sc->mem = NULL;
2955	}
2956
2957	return;
2958}
2959
2960static int
2961wi_get_debug(struct wi_softc *sc, struct wi_req *wreq)
2962{
2963	int error = 0;
2964
2965	wreq->wi_len = 1;
2966
2967	switch (wreq->wi_type) {
2968	case WI_DEBUG_SLEEP:
2969		wreq->wi_len++;
2970		wreq->wi_val[0] = sc->wi_debug.wi_sleep;
2971		break;
2972	case WI_DEBUG_DELAYSUPP:
2973		wreq->wi_len++;
2974		wreq->wi_val[0] = sc->wi_debug.wi_delaysupp;
2975		break;
2976	case WI_DEBUG_TXSUPP:
2977		wreq->wi_len++;
2978		wreq->wi_val[0] = sc->wi_debug.wi_txsupp;
2979		break;
2980	case WI_DEBUG_MONITOR:
2981		wreq->wi_len++;
2982		wreq->wi_val[0] = sc->wi_debug.wi_monitor;
2983		break;
2984	case WI_DEBUG_LEDTEST:
2985		wreq->wi_len += 3;
2986		wreq->wi_val[0] = sc->wi_debug.wi_ledtest;
2987		wreq->wi_val[1] = sc->wi_debug.wi_ledtest_param0;
2988		wreq->wi_val[2] = sc->wi_debug.wi_ledtest_param1;
2989		break;
2990	case WI_DEBUG_CONTTX:
2991		wreq->wi_len += 2;
2992		wreq->wi_val[0] = sc->wi_debug.wi_conttx;
2993		wreq->wi_val[1] = sc->wi_debug.wi_conttx_param0;
2994		break;
2995	case WI_DEBUG_CONTRX:
2996		wreq->wi_len++;
2997		wreq->wi_val[0] = sc->wi_debug.wi_contrx;
2998		break;
2999	case WI_DEBUG_SIGSTATE:
3000		wreq->wi_len += 2;
3001		wreq->wi_val[0] = sc->wi_debug.wi_sigstate;
3002		wreq->wi_val[1] = sc->wi_debug.wi_sigstate_param0;
3003		break;
3004	case WI_DEBUG_CONFBITS:
3005		wreq->wi_len += 2;
3006		wreq->wi_val[0] = sc->wi_debug.wi_confbits;
3007		wreq->wi_val[1] = sc->wi_debug.wi_confbits_param0;
3008		break;
3009	default:
3010		error = EIO;
3011		break;
3012	}
3013
3014	return (error);
3015}
3016
3017static int
3018wi_set_debug(struct wi_softc *sc, struct wi_req *wreq)
3019{
3020	int error = 0;
3021	u_int16_t		cmd, param0 = 0, param1 = 0;
3022
3023	switch (wreq->wi_type) {
3024	case WI_DEBUG_RESET:
3025	case WI_DEBUG_INIT:
3026	case WI_DEBUG_CALENABLE:
3027		break;
3028	case WI_DEBUG_SLEEP:
3029		sc->wi_debug.wi_sleep = 1;
3030		break;
3031	case WI_DEBUG_WAKE:
3032		sc->wi_debug.wi_sleep = 0;
3033		break;
3034	case WI_DEBUG_CHAN:
3035		param0 = wreq->wi_val[0];
3036		break;
3037	case WI_DEBUG_DELAYSUPP:
3038		sc->wi_debug.wi_delaysupp = 1;
3039		break;
3040	case WI_DEBUG_TXSUPP:
3041		sc->wi_debug.wi_txsupp = 1;
3042		break;
3043	case WI_DEBUG_MONITOR:
3044		sc->wi_debug.wi_monitor = 1;
3045		break;
3046	case WI_DEBUG_LEDTEST:
3047		param0 = wreq->wi_val[0];
3048		param1 = wreq->wi_val[1];
3049		sc->wi_debug.wi_ledtest = 1;
3050		sc->wi_debug.wi_ledtest_param0 = param0;
3051		sc->wi_debug.wi_ledtest_param1 = param1;
3052		break;
3053	case WI_DEBUG_CONTTX:
3054		param0 = wreq->wi_val[0];
3055		sc->wi_debug.wi_conttx = 1;
3056		sc->wi_debug.wi_conttx_param0 = param0;
3057		break;
3058	case WI_DEBUG_STOPTEST:
3059		sc->wi_debug.wi_delaysupp = 0;
3060		sc->wi_debug.wi_txsupp = 0;
3061		sc->wi_debug.wi_monitor = 0;
3062		sc->wi_debug.wi_ledtest = 0;
3063		sc->wi_debug.wi_ledtest_param0 = 0;
3064		sc->wi_debug.wi_ledtest_param1 = 0;
3065		sc->wi_debug.wi_conttx = 0;
3066		sc->wi_debug.wi_conttx_param0 = 0;
3067		sc->wi_debug.wi_contrx = 0;
3068		sc->wi_debug.wi_sigstate = 0;
3069		sc->wi_debug.wi_sigstate_param0 = 0;
3070		break;
3071	case WI_DEBUG_CONTRX:
3072		sc->wi_debug.wi_contrx = 1;
3073		break;
3074	case WI_DEBUG_SIGSTATE:
3075		param0 = wreq->wi_val[0];
3076		sc->wi_debug.wi_sigstate = 1;
3077		sc->wi_debug.wi_sigstate_param0 = param0;
3078		break;
3079	case WI_DEBUG_CONFBITS:
3080		param0 = wreq->wi_val[0];
3081		param1 = wreq->wi_val[1];
3082		sc->wi_debug.wi_confbits = param0;
3083		sc->wi_debug.wi_confbits_param0 = param1;
3084		break;
3085	default:
3086		error = EIO;
3087		break;
3088	}
3089
3090	if (error)
3091		return (error);
3092
3093	cmd = WI_CMD_DEBUG | (wreq->wi_type << 8);
3094	error = wi_cmd(sc, cmd, param0, param1, 0);
3095
3096	return (error);
3097}
3098
3099#if __FreeBSD_version >= 500000
3100/*
3101 * Special routines to download firmware for Symbol CF card.
3102 * XXX: This should be modified generic into any PRISM-2 based card.
3103 */
3104
3105#define	WI_SBCF_PDIADDR		0x3100
3106
3107/* unaligned load little endian */
3108#define	GETLE32(p)	((p)[0] | ((p)[1]<<8) | ((p)[2]<<16) | ((p)[3]<<24))
3109#define	GETLE16(p)	((p)[0] | ((p)[1]<<8))
3110
3111int
3112wi_symbol_load_firm(struct wi_softc *sc, const void *primsym, int primlen,
3113    const void *secsym, int seclen)
3114{
3115	uint8_t ebuf[256];
3116	int i;
3117
3118	/* load primary code and run it */
3119	wi_symbol_set_hcr(sc, WI_HCR_EEHOLD);
3120	if (wi_symbol_write_firm(sc, primsym, primlen, NULL, 0))
3121		return EIO;
3122	wi_symbol_set_hcr(sc, WI_HCR_RUN);
3123	for (i = 0; ; i++) {
3124		if (i == 10)
3125			return ETIMEDOUT;
3126		tsleep(sc, PWAIT, "wiinit", 1);
3127		if (CSR_READ_2(sc, WI_CNTL) == WI_CNTL_AUX_ENA_STAT)
3128			break;
3129		/* write the magic key value to unlock aux port */
3130		CSR_WRITE_2(sc, WI_PARAM0, WI_AUX_KEY0);
3131		CSR_WRITE_2(sc, WI_PARAM1, WI_AUX_KEY1);
3132		CSR_WRITE_2(sc, WI_PARAM2, WI_AUX_KEY2);
3133		CSR_WRITE_2(sc, WI_CNTL, WI_CNTL_AUX_ENA_CNTL);
3134	}
3135
3136	/* issue read EEPROM command: XXX copied from wi_cmd() */
3137	CSR_WRITE_2(sc, WI_PARAM0, 0);
3138	CSR_WRITE_2(sc, WI_PARAM1, 0);
3139	CSR_WRITE_2(sc, WI_PARAM2, 0);
3140	CSR_WRITE_2(sc, WI_COMMAND, WI_CMD_READEE);
3141        for (i = 0; i < WI_TIMEOUT; i++) {
3142                if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_CMD)
3143                        break;
3144                DELAY(1);
3145        }
3146        CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_CMD);
3147
3148	CSR_WRITE_2(sc, WI_AUX_PAGE, WI_SBCF_PDIADDR / WI_AUX_PGSZ);
3149	CSR_WRITE_2(sc, WI_AUX_OFFSET, WI_SBCF_PDIADDR % WI_AUX_PGSZ);
3150	CSR_READ_MULTI_STREAM_2(sc, WI_AUX_DATA,
3151	    (uint16_t *)ebuf, sizeof(ebuf) / 2);
3152	if (GETLE16(ebuf) > sizeof(ebuf))
3153		return EIO;
3154	if (wi_symbol_write_firm(sc, secsym, seclen, ebuf + 4, GETLE16(ebuf)))
3155		return EIO;
3156	return 0;
3157}
3158
3159static int
3160wi_symbol_write_firm(struct wi_softc *sc, const void *buf, int buflen,
3161    const void *ebuf, int ebuflen)
3162{
3163	const uint8_t *p, *ep, *q, *eq;
3164	char *tp;
3165	uint32_t addr, id, eid;
3166	int i, len, elen, nblk, pdrlen;
3167
3168	/*
3169	 * Parse the header of the firmware image.
3170	 */
3171	p = buf;
3172	ep = p + buflen;
3173	while (p < ep && *p++ != ' ');	/* FILE: */
3174	while (p < ep && *p++ != ' ');	/* filename */
3175	while (p < ep && *p++ != ' ');	/* type of the firmware */
3176	nblk = strtoul(p, &tp, 10);
3177	p = tp;
3178	pdrlen = strtoul(p + 1, &tp, 10);
3179	p = tp;
3180	while (p < ep && *p++ != 0x1a);	/* skip rest of header */
3181
3182	/*
3183	 * Block records: address[4], length[2], data[length];
3184	 */
3185	for (i = 0; i < nblk; i++) {
3186		addr = GETLE32(p);	p += 4;
3187		len  = GETLE16(p);	p += 2;
3188		CSR_WRITE_2(sc, WI_AUX_PAGE, addr / WI_AUX_PGSZ);
3189		CSR_WRITE_2(sc, WI_AUX_OFFSET, addr % WI_AUX_PGSZ);
3190		CSR_WRITE_MULTI_STREAM_2(sc, WI_AUX_DATA,
3191		    (const uint16_t *)p, len / 2);
3192		p += len;
3193	}
3194
3195	/*
3196	 * PDR: id[4], address[4], length[4];
3197	 */
3198	for (i = 0; i < pdrlen; ) {
3199		id   = GETLE32(p);	p += 4; i += 4;
3200		addr = GETLE32(p);	p += 4; i += 4;
3201		len  = GETLE32(p);	p += 4; i += 4;
3202		/* replace PDR entry with the values from EEPROM, if any */
3203		for (q = ebuf, eq = q + ebuflen; q < eq; q += elen * 2) {
3204			elen = GETLE16(q);	q += 2;
3205			eid  = GETLE16(q);	q += 2;
3206			elen--;		/* elen includes eid */
3207			if (eid == 0)
3208				break;
3209			if (eid != id)
3210				continue;
3211			CSR_WRITE_2(sc, WI_AUX_PAGE, addr / WI_AUX_PGSZ);
3212			CSR_WRITE_2(sc, WI_AUX_OFFSET, addr % WI_AUX_PGSZ);
3213			CSR_WRITE_MULTI_STREAM_2(sc, WI_AUX_DATA,
3214			    (const uint16_t *)q, len / 2);
3215			break;
3216		}
3217	}
3218	return 0;
3219}
3220
3221static int
3222wi_symbol_set_hcr(struct wi_softc *sc, int mode)
3223{
3224	uint16_t hcr;
3225
3226	CSR_WRITE_2(sc, WI_COR, WI_COR_RESET);
3227	tsleep(sc, PWAIT, "wiinit", 1);
3228	hcr = CSR_READ_2(sc, WI_HCR);
3229	hcr = (hcr & WI_HCR_4WIRE) | (mode & ~WI_HCR_4WIRE);
3230	CSR_WRITE_2(sc, WI_HCR, hcr);
3231	tsleep(sc, PWAIT, "wiinit", 1);
3232	CSR_WRITE_2(sc, WI_COR, WI_COR_IOMODE);
3233	tsleep(sc, PWAIT, "wiinit", 1);
3234	return 0;
3235}
3236#endif
3237