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