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