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