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