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