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