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