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