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