if_wi.c revision 94484
1/*
2 * Copyright (c) 1997, 1998, 1999
3 *	Bill Paul <wpaul@ctr.columbia.edu>.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *	This product includes software developed by Bill Paul.
16 * 4. Neither the name of the author nor the names of any co-contributors
17 *    may be used to endorse or promote products derived from this software
18 *    without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
30 * THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33/*
34 * Lucent WaveLAN/IEEE 802.11 PCMCIA driver for FreeBSD.
35 *
36 * Written by Bill Paul <wpaul@ctr.columbia.edu>
37 * Electrical Engineering Department
38 * Columbia University, New York City
39 */
40
41/*
42 * The WaveLAN/IEEE adapter is the second generation of the WaveLAN
43 * from Lucent. Unlike the older cards, the new ones are programmed
44 * entirely via a firmware-driven controller called the Hermes.
45 * Unfortunately, Lucent will not release the Hermes programming manual
46 * without an NDA (if at all). What they do release is an API library
47 * called the HCF (Hardware Control Functions) which is supposed to
48 * do the device-specific operations of a device driver for you. The
49 * publically available version of the HCF library (the 'HCF Light') is
50 * a) extremely gross, b) lacks certain features, particularly support
51 * for 802.11 frames, and c) is contaminated by the GNU Public License.
52 *
53 * This driver does not use the HCF or HCF Light at all. Instead, it
54 * programs the Hermes controller directly, using information gleaned
55 * from the HCF Light code and corresponding documentation.
56 *
57 * This driver supports both the PCMCIA and ISA versions of the
58 * WaveLAN/IEEE cards. Note however that the ISA card isn't really
59 * anything of the sort: it's actually a PCMCIA bridge adapter
60 * that fits into an ISA slot, into which a PCMCIA WaveLAN card is
61 * inserted. Consequently, you need to use the pccard support for
62 * both the ISA and PCMCIA adapters.
63 */
64
65#include <sys/param.h>
66#include <sys/systm.h>
67#include <sys/sockio.h>
68#include <sys/mbuf.h>
69#include <sys/proc.h>
70#include <sys/kernel.h>
71#include <sys/socket.h>
72#include <sys/module.h>
73#include <sys/bus.h>
74#include <sys/syslog.h>
75#include <sys/sysctl.h>
76
77#include <machine/bus.h>
78#include <machine/resource.h>
79#include <sys/rman.h>
80
81#include <net/if.h>
82#include <net/if_arp.h>
83#include <net/ethernet.h>
84#include <net/if_dl.h>
85#include <net/if_media.h>
86#include <net/if_types.h>
87#include <net/if_ieee80211.h>
88
89#include <netinet/in.h>
90#include <netinet/in_systm.h>
91#include <netinet/in_var.h>
92#include <netinet/ip.h>
93#include <netinet/if_ether.h>
94
95#include <net/bpf.h>
96
97#include <dev/wi/if_wavelan_ieee.h>
98#ifdef WI_HOSTAP
99#include <dev/wi/wi_hostap.h>
100#include <sys/random.h>
101#endif
102#include <dev/wi/if_wivar.h>
103#include <dev/wi/if_wireg.h>
104
105#if !defined(lint)
106static const char rcsid[] =
107  "$FreeBSD: head/sys/dev/wi/if_wi.c 94484 2002-04-12 05:46:36Z alfred $";
108#endif
109
110static void wi_intr(void *);
111static void wi_reset(struct wi_softc *);
112static int wi_ioctl(struct ifnet *, u_long, caddr_t);
113static void wi_init(void *);
114static void wi_start(struct ifnet *);
115static void wi_stop(struct wi_softc *);
116static void wi_watchdog(struct ifnet *);
117static void wi_rxeof(struct wi_softc *);
118static void wi_txeof(struct wi_softc *, int);
119static void wi_update_stats(struct wi_softc *);
120static void wi_setmulti(struct wi_softc *);
121
122static int wi_cmd(struct wi_softc *, int, int, int, int);
123static int wi_read_record(struct wi_softc *, struct wi_ltv_gen *);
124static int wi_write_record(struct wi_softc *, struct wi_ltv_gen *);
125static int wi_read_data(struct wi_softc *, int, int, caddr_t, int);
126static int wi_write_data(struct wi_softc *, int, int, caddr_t, int);
127static int wi_seek(struct wi_softc *, int, int, int);
128static int wi_alloc_nicmem(struct wi_softc *, int, int *);
129static void wi_inquire(void *);
130static void wi_setdef(struct wi_softc *, struct wi_req *);
131
132#ifdef WICACHE
133static
134void wi_cache_store(struct wi_softc *, struct ether_header *,
135	struct mbuf *, unsigned short);
136#endif
137
138static int wi_get_cur_ssid(struct wi_softc *, char *, int *);
139static void wi_get_id(struct wi_softc *);
140static int wi_media_change(struct ifnet *);
141static void wi_media_status(struct ifnet *, struct ifmediareq *);
142
143static int wi_get_debug(struct wi_softc *, struct wi_req *);
144static int wi_set_debug(struct wi_softc *, struct wi_req *);
145
146devclass_t wi_devclass;
147
148struct wi_card_ident wi_card_ident[] = {
149	/* CARD_ID			CARD_NAME		FIRM_TYPE */
150	{ WI_NIC_LUCENT_ID,		WI_NIC_LUCENT_STR,	WI_LUCENT },
151	{ WI_NIC_SONY_ID,		WI_NIC_SONY_STR,	WI_LUCENT },
152	{ WI_NIC_LUCENT_EMB_ID,		WI_NIC_LUCENT_EMB_STR,	WI_LUCENT },
153	{ WI_NIC_EVB2_ID,		WI_NIC_EVB2_STR,	WI_INTERSIL },
154	{ WI_NIC_HWB3763_ID,		WI_NIC_HWB3763_STR,	WI_INTERSIL },
155	{ WI_NIC_HWB3163_ID,		WI_NIC_HWB3163_STR,	WI_INTERSIL },
156	{ WI_NIC_HWB3163B_ID,		WI_NIC_HWB3163B_STR,	WI_INTERSIL },
157	{ WI_NIC_EVB3_ID,		WI_NIC_EVB3_STR,	WI_INTERSIL },
158	{ WI_NIC_HWB1153_ID,		WI_NIC_HWB1153_STR,	WI_INTERSIL },
159	{ WI_NIC_P2_SST_ID,		WI_NIC_P2_SST_STR,	WI_INTERSIL },
160	{ WI_NIC_EVB2_SST_ID,		WI_NIC_EVB2_SST_STR,	WI_INTERSIL },
161	{ WI_NIC_3842_EVA_ID,		WI_NIC_3842_EVA_STR,	WI_INTERSIL },
162	{ WI_NIC_3842_PCMCIA_AMD_ID,	WI_NIC_3842_PCMCIA_STR,	WI_INTERSIL },
163	{ WI_NIC_3842_PCMCIA_SST_ID,	WI_NIC_3842_PCMCIA_STR,	WI_INTERSIL },
164	{ WI_NIC_3842_PCMCIA_ATM_ID,	WI_NIC_3842_PCMCIA_STR,	WI_INTERSIL },
165	{ WI_NIC_3842_MINI_AMD_ID,	WI_NIC_3842_MINI_STR,	WI_INTERSIL },
166	{ WI_NIC_3842_MINI_SST_ID,	WI_NIC_3842_MINI_STR,	WI_INTERSIL },
167	{ WI_NIC_3842_MINI_ATM_ID,	WI_NIC_3842_MINI_STR,	WI_INTERSIL },
168	{ WI_NIC_3842_PCI_AMD_ID,	WI_NIC_3842_PCI_STR,	WI_INTERSIL },
169	{ WI_NIC_3842_PCI_SST_ID,	WI_NIC_3842_PCI_STR,	WI_INTERSIL },
170	{ WI_NIC_3842_PCI_ATM_ID,	WI_NIC_3842_PCI_STR,	WI_INTERSIL },
171	{ WI_NIC_P3_PCMCIA_AMD_ID,	WI_NIC_P3_PCMCIA_STR,	WI_INTERSIL },
172	{ WI_NIC_P3_PCMCIA_SST_ID,	WI_NIC_P3_PCMCIA_STR,	WI_INTERSIL },
173	{ WI_NIC_P3_MINI_AMD_ID,	WI_NIC_P3_MINI_STR,	WI_INTERSIL },
174	{ WI_NIC_P3_MINI_SST_ID,	WI_NIC_P3_MINI_STR,	WI_INTERSIL },
175	{ 0,	NULL,	0 },
176};
177
178int
179wi_generic_detach(dev)
180	device_t		dev;
181{
182	struct wi_softc		*sc;
183	struct ifnet		*ifp;
184
185	sc = device_get_softc(dev);
186	WI_LOCK(sc);
187	ifp = &sc->arpcom.ac_if;
188
189	if (sc->wi_gone) {
190		device_printf(dev, "already unloaded\n");
191		WI_UNLOCK(sc);
192		return(ENODEV);
193	}
194
195	wi_stop(sc);
196
197	/* Delete all remaining media. */
198	ifmedia_removeall(&sc->ifmedia);
199
200	ether_ifdetach(ifp, ETHER_BPF_SUPPORTED);
201	bus_teardown_intr(dev, sc->irq, sc->wi_intrhand);
202	wi_free(dev);
203	sc->wi_gone = 1;
204
205	WI_UNLOCK(sc);
206	mtx_destroy(&sc->wi_mtx);
207
208	return(0);
209}
210
211int
212wi_generic_attach(device_t dev)
213{
214	struct wi_softc		*sc;
215	struct wi_ltv_macaddr	mac;
216	struct wi_ltv_gen	gen;
217	struct ifnet		*ifp;
218	int			error;
219
220	/* XXX maybe we need the splimp stuff here XXX */
221	sc = device_get_softc(dev);
222	ifp = &sc->arpcom.ac_if;
223
224	error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET,
225	    wi_intr, sc, &sc->wi_intrhand);
226
227	if (error) {
228		device_printf(dev, "bus_setup_intr() failed! (%d)\n", error);
229		wi_free(dev);
230		return (error);
231	}
232
233	mtx_init(&sc->wi_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
234	    MTX_DEF | MTX_RECURSE);
235	WI_LOCK(sc);
236
237	/* Reset the NIC. */
238	wi_reset(sc);
239
240	/*
241	 * Read the station address.
242	 * And do it twice. I've seen PRISM-based cards that return
243	 * an error when trying to read it the first time, which causes
244	 * the probe to fail.
245	 */
246	mac.wi_type = WI_RID_MAC_NODE;
247	mac.wi_len = 4;
248	wi_read_record(sc, (struct wi_ltv_gen *)&mac);
249	if ((error = wi_read_record(sc, (struct wi_ltv_gen *)&mac)) != 0) {
250		device_printf(dev, "mac read failed %d\n", error);
251		wi_free(dev);
252		return (error);
253	}
254	bcopy((char *)&mac.wi_mac_addr,
255	   (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN);
256
257	device_printf(dev, "802.11 address: %6D\n", sc->arpcom.ac_enaddr, ":");
258
259	wi_get_id(sc);
260
261	ifp->if_softc = sc;
262	ifp->if_unit = sc->wi_unit;
263	ifp->if_name = "wi";
264	ifp->if_mtu = ETHERMTU;
265	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
266	ifp->if_ioctl = wi_ioctl;
267	ifp->if_output = ether_output;
268	ifp->if_start = wi_start;
269	ifp->if_watchdog = wi_watchdog;
270	ifp->if_init = wi_init;
271	ifp->if_baudrate = 10000000;
272	ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
273
274	bzero(sc->wi_node_name, sizeof(sc->wi_node_name));
275	bcopy(WI_DEFAULT_NODENAME, sc->wi_node_name,
276	    sizeof(WI_DEFAULT_NODENAME) - 1);
277
278	bzero(sc->wi_net_name, sizeof(sc->wi_net_name));
279	bcopy(WI_DEFAULT_NETNAME, sc->wi_net_name,
280	    sizeof(WI_DEFAULT_NETNAME) - 1);
281
282	bzero(sc->wi_ibss_name, sizeof(sc->wi_ibss_name));
283	bcopy(WI_DEFAULT_IBSS, sc->wi_ibss_name,
284	    sizeof(WI_DEFAULT_IBSS) - 1);
285
286	sc->wi_portnum = WI_DEFAULT_PORT;
287	sc->wi_ptype = WI_PORTTYPE_BSS;
288	sc->wi_ap_density = WI_DEFAULT_AP_DENSITY;
289	sc->wi_rts_thresh = WI_DEFAULT_RTS_THRESH;
290	sc->wi_tx_rate = WI_DEFAULT_TX_RATE;
291	sc->wi_max_data_len = WI_DEFAULT_DATALEN;
292	sc->wi_create_ibss = WI_DEFAULT_CREATE_IBSS;
293	sc->wi_pm_enabled = WI_DEFAULT_PM_ENABLED;
294	sc->wi_max_sleep = WI_DEFAULT_MAX_SLEEP;
295	sc->wi_roaming = WI_DEFAULT_ROAMING;
296	sc->wi_authtype = WI_DEFAULT_AUTHTYPE;
297	sc->wi_authmode = IEEE80211_AUTH_OPEN;
298
299	/*
300	 * Read the default channel from the NIC. This may vary
301	 * depending on the country where the NIC was purchased, so
302	 * we can't hard-code a default and expect it to work for
303	 * everyone.
304	 */
305	gen.wi_type = WI_RID_OWN_CHNL;
306	gen.wi_len = 2;
307	wi_read_record(sc, &gen);
308	sc->wi_channel = gen.wi_val;
309
310	/*
311	 * Find out if we support WEP on this card.
312	 */
313	gen.wi_type = WI_RID_WEP_AVAIL;
314	gen.wi_len = 2;
315	wi_read_record(sc, &gen);
316	sc->wi_has_wep = gen.wi_val;
317
318	if (bootverbose) {
319		device_printf(sc->dev, "%s:wi_has_wep = %d\n",
320		  __func__, sc->wi_has_wep);
321	}
322
323	/*
324	 * Find supported rates.
325	 */
326	gen.wi_type = WI_RID_TX_RATE;
327	gen.wi_len = 2;
328	wi_read_record(sc, &gen);
329	sc->wi_supprates = gen.wi_val;
330
331	bzero((char *)&sc->wi_stats, sizeof(sc->wi_stats));
332
333	wi_init(sc);
334	wi_stop(sc);
335
336	ifmedia_init(&sc->ifmedia, 0, wi_media_change, wi_media_status);
337	/* XXX: Should read from card capabilities */
338#define ADD(m, c)       ifmedia_add(&sc->ifmedia, (m), (c), NULL)
339	ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
340	    IFM_IEEE80211_ADHOC, 0), 0);
341	ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1, 0, 0), 0);
342	ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
343	    IFM_IEEE80211_ADHOC, 0), 0);
344	ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2, 0, 0), 0);
345	ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
346	    IFM_IEEE80211_ADHOC, 0), 0);
347	ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5, 0, 0), 0);
348	ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
349	    IFM_IEEE80211_ADHOC, 0), 0);
350	ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11, 0, 0), 0);
351	ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO,
352		IFM_IEEE80211_ADHOC, 0), 0);
353	ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 0, 0), 0);
354#ifdef IFM_IEEE80211_HOSTAP
355	if (sc->sc_firmware_type == WI_INTERSIL) {
356		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
357		    IFM_IEEE80211_HOSTAP, 0), 0);
358		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
359		    IFM_IEEE80211_HOSTAP, 0), 0);
360		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
361		    IFM_IEEE80211_HOSTAP, 0), 0);
362		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
363		    IFM_IEEE80211_HOSTAP, 0), 0);
364		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO,
365		    IFM_IEEE80211_HOSTAP, 0), 0);
366	}
367#endif
368#undef	ADD
369	ifmedia_set(&sc->ifmedia, IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO,
370	    0, 0));
371
372
373	/*
374	 * Call MI attach routine.
375	 */
376	ether_ifattach(ifp, ETHER_BPF_SUPPORTED);
377	callout_handle_init(&sc->wi_stat_ch);
378	WI_UNLOCK(sc);
379
380	return(0);
381}
382
383static void
384wi_get_id(sc)
385	struct wi_softc *sc;
386{
387	struct wi_ltv_ver       ver;
388	struct wi_card_ident	*id;
389
390	/* getting chip identity */
391	memset(&ver, 0, sizeof(ver));
392	ver.wi_type = WI_RID_CARD_ID;
393	ver.wi_len = 5;
394	wi_read_record(sc, (struct wi_ltv_gen *)&ver);
395	device_printf(sc->dev, "using ");
396	sc->sc_firmware_type = WI_NOTYPE;
397	for (id = wi_card_ident; id->card_name != NULL; id++) {
398		if (le16toh(ver.wi_ver[0]) == id->card_id) {
399			printf("%s", id->card_name);
400			sc->sc_firmware_type = id->firm_type;
401			break;
402		}
403	}
404	if (sc->sc_firmware_type == WI_NOTYPE) {
405		if (le16toh(ver.wi_ver[0]) & 0x8000) {
406			printf("Unknown PRISM2 chip");
407			sc->sc_firmware_type = WI_INTERSIL;
408		} else {
409			printf("Unknown Lucent chip");
410			sc->sc_firmware_type = WI_LUCENT;
411		}
412	}
413
414	if (sc->sc_firmware_type != WI_LUCENT) {
415		/* get primary firmware version */
416		memset(&ver, 0, sizeof(ver));
417		ver.wi_type = WI_RID_PRI_IDENTITY;
418		ver.wi_len = 5;
419		wi_read_record(sc, (struct wi_ltv_gen *)&ver);
420		ver.wi_ver[1] = le16toh(ver.wi_ver[1]);
421		ver.wi_ver[2] = le16toh(ver.wi_ver[2]);
422		ver.wi_ver[3] = le16toh(ver.wi_ver[3]);
423		sc->sc_pri_firmware_ver = ver.wi_ver[2] * 10000 +
424		    ver.wi_ver[3] * 100 + ver.wi_ver[1];
425	}
426
427	/* get station firmware version */
428	memset(&ver, 0, sizeof(ver));
429	ver.wi_type = WI_RID_STA_IDENTITY;
430	ver.wi_len = 5;
431	wi_read_record(sc, (struct wi_ltv_gen *)&ver);
432	ver.wi_ver[1] = le16toh(ver.wi_ver[1]);
433	ver.wi_ver[2] = le16toh(ver.wi_ver[2]);
434	ver.wi_ver[3] = le16toh(ver.wi_ver[3]);
435	sc->sc_sta_firmware_ver = ver.wi_ver[2] * 10000 +
436	    ver.wi_ver[3] * 100 + ver.wi_ver[1];
437	if (sc->sc_firmware_type == WI_INTERSIL &&
438	    (sc->sc_sta_firmware_ver == 10102 ||
439	     sc->sc_sta_firmware_ver == 20102)) {
440		struct wi_ltv_str sver;
441		char *p;
442
443		memset(&sver, 0, sizeof(sver));
444		sver.wi_type = WI_RID_SYMBOL_IDENTITY;
445		sver.wi_len = 7;
446		/* value should be "V2.00-11" */
447		if (wi_read_record(sc, (struct wi_ltv_gen *)&sver) == 0 &&
448		    *(p = (char *)sver.wi_str) == 'V' &&
449		    p[2] == '.' && p[5] == '-' && p[8] == '\0') {
450			sc->sc_firmware_type = WI_SYMBOL;
451			sc->sc_sta_firmware_ver = (p[1] - '0') * 10000 +
452			    (p[3] - '0') * 1000 + (p[4] - '0') * 100 +
453			    (p[6] - '0') * 10 + (p[7] - '0');
454		}
455	}
456	printf("\n");
457	device_printf(sc->dev, "%s Firmware: ",
458	     sc->sc_firmware_type == WI_LUCENT ? "Lucent" :
459	    (sc->sc_firmware_type == WI_SYMBOL ? "Symbol" : "Intersil"));
460
461	/*
462	 * The primary firmware is only valid on Prism based chipsets
463	 * (INTERSIL or SYMBOL).
464	 */
465	if (sc->sc_firmware_type != WI_LUCENT)
466	    printf("Primary %u.%02u.%02u, ", sc->sc_pri_firmware_ver / 10000,
467		    (sc->sc_pri_firmware_ver % 10000) / 100,
468		    sc->sc_pri_firmware_ver % 100);
469	printf("Station %u.%02u.%02u\n",
470	    sc->sc_sta_firmware_ver / 10000, (sc->sc_sta_firmware_ver % 10000) / 100,
471	    sc->sc_sta_firmware_ver % 100);
472	return;
473}
474
475static void
476wi_rxeof(sc)
477	struct wi_softc		*sc;
478{
479	struct ifnet		*ifp;
480	struct ether_header	*eh;
481	struct mbuf		*m;
482	int			id;
483
484	ifp = &sc->arpcom.ac_if;
485
486	id = CSR_READ_2(sc, WI_RX_FID);
487
488	/*
489	 * if we have the procframe flag set, disregard all this and just
490	 * read the data from the device.
491	 */
492	if (sc->wi_procframe || sc->wi_debug.wi_monitor) {
493		struct wi_frame		*rx_frame;
494		int			datlen, hdrlen;
495
496		/* first allocate mbuf for packet storage */
497		MGETHDR(m, M_DONTWAIT, MT_DATA);
498		if (m == NULL) {
499			ifp->if_ierrors++;
500			return;
501		}
502		MCLGET(m, M_DONTWAIT);
503		if (!(m->m_flags & M_EXT)) {
504			m_freem(m);
505			ifp->if_ierrors++;
506			return;
507		}
508
509		m->m_pkthdr.rcvif = ifp;
510
511		/* now read wi_frame first so we know how much data to read */
512		if (wi_read_data(sc, id, 0, mtod(m, caddr_t),
513		    sizeof(struct wi_frame))) {
514			m_freem(m);
515			ifp->if_ierrors++;
516			return;
517		}
518
519		rx_frame = mtod(m, struct wi_frame *);
520
521		switch ((rx_frame->wi_status & WI_STAT_MAC_PORT) >> 8) {
522		case 7:
523			switch (rx_frame->wi_frame_ctl & WI_FCTL_FTYPE) {
524			case WI_FTYPE_DATA:
525				hdrlen = WI_DATA_HDRLEN;
526				datlen = rx_frame->wi_dat_len + WI_FCS_LEN;
527				break;
528			case WI_FTYPE_MGMT:
529				hdrlen = WI_MGMT_HDRLEN;
530				datlen = rx_frame->wi_dat_len + WI_FCS_LEN;
531				break;
532			case WI_FTYPE_CTL:
533				/*
534				 * prism2 cards don't pass control packets
535				 * down properly or consistently, so we'll only
536				 * pass down the header.
537				 */
538				hdrlen = WI_CTL_HDRLEN;
539				datlen = 0;
540				break;
541			default:
542				device_printf(sc->dev, "received packet of "
543				    "unknown type on port 7\n");
544				m_freem(m);
545				ifp->if_ierrors++;
546				return;
547			}
548			break;
549		case 0:
550			hdrlen = WI_DATA_HDRLEN;
551			datlen = rx_frame->wi_dat_len + WI_FCS_LEN;
552			break;
553		default:
554			device_printf(sc->dev, "received packet on invalid "
555			    "port (wi_status=0x%x)\n", rx_frame->wi_status);
556			m_freem(m);
557			ifp->if_ierrors++;
558			return;
559		}
560
561		if ((hdrlen + datlen + 2) > MCLBYTES) {
562			device_printf(sc->dev, "oversized packet received "
563			    "(wi_dat_len=%d, wi_status=0x%x)\n",
564			    datlen, rx_frame->wi_status);
565			m_freem(m);
566			ifp->if_ierrors++;
567			return;
568		}
569
570		if (wi_read_data(sc, id, hdrlen, mtod(m, caddr_t) + hdrlen,
571		    datlen + 2)) {
572			m_freem(m);
573			ifp->if_ierrors++;
574			return;
575		}
576
577		m->m_pkthdr.len = m->m_len = hdrlen + datlen;
578
579		ifp->if_ipackets++;
580
581		/* Handle BPF listeners. */
582		if (ifp->if_bpf)
583			bpf_mtap(ifp, m);
584
585		m_freem(m);
586	} else {
587		struct wi_frame		rx_frame;
588
589		/* First read in the frame header */
590		if (wi_read_data(sc, id, 0, (caddr_t)&rx_frame,
591		    sizeof(rx_frame))) {
592			ifp->if_ierrors++;
593			return;
594		}
595
596		if (rx_frame.wi_status & WI_STAT_ERRSTAT) {
597			ifp->if_ierrors++;
598			return;
599		}
600
601		MGETHDR(m, M_DONTWAIT, MT_DATA);
602		if (m == NULL) {
603			ifp->if_ierrors++;
604			return;
605		}
606		MCLGET(m, M_DONTWAIT);
607		if (!(m->m_flags & M_EXT)) {
608			m_freem(m);
609			ifp->if_ierrors++;
610			return;
611		}
612
613		eh = mtod(m, struct ether_header *);
614		m->m_pkthdr.rcvif = ifp;
615
616#ifdef WI_HOSTAP
617		if (rx_frame.wi_status == WI_STAT_MGMT &&
618		    sc->wi_ptype == WI_PORTTYPE_AP) {
619			if ((WI_802_11_OFFSET_RAW + rx_frame.wi_dat_len + 2) >
620			    MCLBYTES) {
621				device_printf(sc->dev, "oversized mgmt packet "
622				    "received in hostap mode "
623				    "(wi_dat_len=%d, wi_status=0x%x)\n",
624				    rx_frame.wi_dat_len, rx_frame.wi_status);
625				m_freem(m);
626				ifp->if_ierrors++;
627				return;
628			}
629
630			/* Put the whole header in there. */
631			bcopy(&rx_frame, mtod(m, void *),
632			    sizeof(struct wi_frame));
633			if (wi_read_data(sc, id, WI_802_11_OFFSET_RAW,
634			    mtod(m, caddr_t) + WI_802_11_OFFSET_RAW,
635			    rx_frame.wi_dat_len + 2)) {
636				m_freem(m);
637				ifp->if_ierrors++;
638				return;
639			}
640			m->m_pkthdr.len = m->m_len =
641			    WI_802_11_OFFSET_RAW + rx_frame.wi_dat_len;
642			/* XXX: consider giving packet to bhp? */
643			wihap_mgmt_input(sc, &rx_frame, m);
644			return;
645		}
646#endif /* WI_HOSTAP */
647
648		if (rx_frame.wi_status == WI_STAT_1042 ||
649		    rx_frame.wi_status == WI_STAT_TUNNEL ||
650		    rx_frame.wi_status == WI_STAT_WMP_MSG) {
651			if((rx_frame.wi_dat_len + WI_SNAPHDR_LEN) > MCLBYTES) {
652				device_printf(sc->dev,
653				    "oversized packet received "
654				    "(wi_dat_len=%d, wi_status=0x%x)\n",
655				    rx_frame.wi_dat_len, rx_frame.wi_status);
656				m_freem(m);
657				ifp->if_ierrors++;
658				return;
659			}
660			m->m_pkthdr.len = m->m_len =
661			    rx_frame.wi_dat_len + WI_SNAPHDR_LEN;
662
663#if 0
664			bcopy((char *)&rx_frame.wi_addr1,
665			    (char *)&eh->ether_dhost, ETHER_ADDR_LEN);
666			if (sc->wi_ptype == WI_PORTTYPE_ADHOC) {
667				bcopy((char *)&rx_frame.wi_addr2,
668				    (char *)&eh->ether_shost, ETHER_ADDR_LEN);
669			} else {
670				bcopy((char *)&rx_frame.wi_addr3,
671				    (char *)&eh->ether_shost, ETHER_ADDR_LEN);
672			}
673#else
674			bcopy((char *)&rx_frame.wi_dst_addr,
675				(char *)&eh->ether_dhost, ETHER_ADDR_LEN);
676			bcopy((char *)&rx_frame.wi_src_addr,
677				(char *)&eh->ether_shost, ETHER_ADDR_LEN);
678#endif
679
680			bcopy((char *)&rx_frame.wi_type,
681			    (char *)&eh->ether_type, ETHER_TYPE_LEN);
682
683			if (wi_read_data(sc, id, WI_802_11_OFFSET,
684			    mtod(m, caddr_t) + sizeof(struct ether_header),
685			    m->m_len + 2)) {
686				m_freem(m);
687				ifp->if_ierrors++;
688				return;
689			}
690		} else {
691			if((rx_frame.wi_dat_len +
692			    sizeof(struct ether_header)) > MCLBYTES) {
693				device_printf(sc->dev,
694				    "oversized packet received "
695				    "(wi_dat_len=%d, wi_status=0x%x)\n",
696				    rx_frame.wi_dat_len, rx_frame.wi_status);
697				m_freem(m);
698				ifp->if_ierrors++;
699				return;
700			}
701			m->m_pkthdr.len = m->m_len =
702			    rx_frame.wi_dat_len + sizeof(struct ether_header);
703
704			if (wi_read_data(sc, id, WI_802_3_OFFSET,
705			    mtod(m, caddr_t), m->m_len + 2)) {
706				m_freem(m);
707				ifp->if_ierrors++;
708				return;
709			}
710		}
711
712		ifp->if_ipackets++;
713
714#ifdef WI_HOSTAP
715		if (sc->wi_ptype == WI_PORTTYPE_AP) {
716			/*
717			 * Give host AP code first crack at data
718			 * packets.  If it decides to handle it (or
719			 * drop it), it will return a non-zero.
720			 * Otherwise, it is destined for this host.
721			 */
722			if (wihap_data_input(sc, &rx_frame, m))
723				return;
724		}
725#endif
726		/* Receive packet. */
727		m_adj(m, sizeof(struct ether_header));
728#ifdef WICACHE
729		wi_cache_store(sc, eh, m, rx_frame.wi_q_info);
730#endif
731		ether_input(ifp, eh, m);
732	}
733}
734
735static void
736wi_txeof(sc, status)
737	struct wi_softc		*sc;
738	int			status;
739{
740	struct ifnet		*ifp;
741
742	ifp = &sc->arpcom.ac_if;
743
744	ifp->if_timer = 0;
745	ifp->if_flags &= ~IFF_OACTIVE;
746
747	if (status & WI_EV_TX_EXC)
748		ifp->if_oerrors++;
749	else
750		ifp->if_opackets++;
751
752	return;
753}
754
755void
756wi_inquire(xsc)
757	void			*xsc;
758{
759	struct wi_softc		*sc;
760	struct ifnet		*ifp;
761	int s;
762
763	sc = xsc;
764	ifp = &sc->arpcom.ac_if;
765
766	sc->wi_stat_ch = timeout(wi_inquire, sc, hz * 60);
767
768	/* Don't do this while we're transmitting */
769	if (ifp->if_flags & IFF_OACTIVE)
770		return;
771
772	s = splimp();
773	wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_COUNTERS, 0, 0);
774	splx(s);
775
776	return;
777}
778
779void
780wi_update_stats(sc)
781	struct wi_softc		*sc;
782{
783	struct wi_ltv_gen	gen;
784	u_int16_t		id;
785	struct ifnet		*ifp;
786	u_int32_t		*ptr;
787	int			len, i;
788	u_int16_t		t;
789
790	ifp = &sc->arpcom.ac_if;
791
792	id = CSR_READ_2(sc, WI_INFO_FID);
793
794	wi_read_data(sc, id, 0, (char *)&gen, 4);
795
796	/*
797	 * if we just got our scan results, copy it over into the scan buffer
798	 * so we can return it to anyone that asks for it. (add a little
799	 * compatibility with the prism2 scanning mechanism)
800	 */
801	if (gen.wi_type == WI_INFO_SCAN_RESULTS)
802	{
803		sc->wi_scanbuf_len = gen.wi_len;
804		wi_read_data(sc, id, 4, (char *)sc->wi_scanbuf,
805		    sc->wi_scanbuf_len * 2);
806
807		return;
808	}
809	else if (gen.wi_type != WI_INFO_COUNTERS)
810		return;
811
812	len = (gen.wi_len - 1 < sizeof(sc->wi_stats) / 4) ?
813		gen.wi_len - 1 : sizeof(sc->wi_stats) / 4;
814	ptr = (u_int32_t *)&sc->wi_stats;
815
816	for (i = 0; i < len - 1; i++) {
817		t = CSR_READ_2(sc, WI_DATA1);
818#ifdef WI_HERMES_STATS_WAR
819		if (t > 0xF000)
820			t = ~t & 0xFFFF;
821#endif
822		ptr[i] += t;
823	}
824
825	ifp->if_collisions = sc->wi_stats.wi_tx_single_retries +
826	    sc->wi_stats.wi_tx_multi_retries +
827	    sc->wi_stats.wi_tx_retry_limit;
828
829	return;
830}
831
832static void
833wi_intr(xsc)
834	void		*xsc;
835{
836	struct wi_softc		*sc = xsc;
837	struct ifnet		*ifp;
838	u_int16_t		status;
839
840	WI_LOCK(sc);
841
842	ifp = &sc->arpcom.ac_if;
843
844	if (sc->wi_gone || !(ifp->if_flags & IFF_UP)) {
845		CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
846		CSR_WRITE_2(sc, WI_INT_EN, 0);
847		WI_UNLOCK(sc);
848		return;
849	}
850
851	/* Disable interrupts. */
852	CSR_WRITE_2(sc, WI_INT_EN, 0);
853
854	status = CSR_READ_2(sc, WI_EVENT_STAT);
855	CSR_WRITE_2(sc, WI_EVENT_ACK, ~WI_INTRS);
856
857	if (status & WI_EV_RX) {
858		wi_rxeof(sc);
859		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
860	}
861
862	if (status & WI_EV_TX) {
863		wi_txeof(sc, status);
864		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX);
865	}
866
867	if (status & WI_EV_ALLOC) {
868		int			id;
869
870		id = CSR_READ_2(sc, WI_ALLOC_FID);
871		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
872		if (id == sc->wi_tx_data_id)
873			wi_txeof(sc, status);
874	}
875
876	if (status & WI_EV_INFO) {
877		wi_update_stats(sc);
878		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO);
879	}
880
881	if (status & WI_EV_TX_EXC) {
882		wi_txeof(sc, status);
883		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX_EXC);
884	}
885
886	if (status & WI_EV_INFO_DROP) {
887		CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO_DROP);
888	}
889
890	/* Re-enable interrupts. */
891	CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
892
893	if (ifp->if_snd.ifq_head != NULL) {
894		wi_start(ifp);
895	}
896
897	WI_UNLOCK(sc);
898
899	return;
900}
901
902static int
903wi_cmd(sc, cmd, val0, val1, val2)
904	struct wi_softc		*sc;
905	int			cmd;
906	int			val0;
907	int			val1;
908	int			val2;
909{
910	int			i, s = 0;
911
912	/* wait for the busy bit to clear */
913	for (i = 500; i > 0; i--) {	/* 5s */
914		if (!(CSR_READ_2(sc, WI_COMMAND) & WI_CMD_BUSY)) {
915			break;
916		}
917		DELAY(10*1000);	/* 10 m sec */
918	}
919	if (i == 0) {
920		device_printf(sc->dev, "wi_cmd: busy bit won't clear.\n" );
921		return(ETIMEDOUT);
922	}
923
924	CSR_WRITE_2(sc, WI_PARAM0, val0);
925	CSR_WRITE_2(sc, WI_PARAM1, val1);
926	CSR_WRITE_2(sc, WI_PARAM2, val2);
927	CSR_WRITE_2(sc, WI_COMMAND, cmd);
928
929	for (i = 0; i < WI_TIMEOUT; i++) {
930		/*
931		 * Wait for 'command complete' bit to be
932		 * set in the event status register.
933		 */
934		s = CSR_READ_2(sc, WI_EVENT_STAT);
935		if (s & WI_EV_CMD) {
936			/* Ack the event and read result code. */
937			s = CSR_READ_2(sc, WI_STATUS);
938			CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_CMD);
939#ifdef foo
940			if ((s & WI_CMD_CODE_MASK) != (cmd & WI_CMD_CODE_MASK))
941				return(EIO);
942#endif
943			if (s & WI_STAT_CMD_RESULT)
944				return(EIO);
945			break;
946		}
947		DELAY(WI_DELAY);
948	}
949
950	if (i == WI_TIMEOUT) {
951		device_printf(sc->dev,
952		    "timeout in wi_cmd 0x%04x; event status 0x%04x\n", cmd, s);
953		return(ETIMEDOUT);
954	}
955
956	return(0);
957}
958
959static void
960wi_reset(sc)
961	struct wi_softc		*sc;
962{
963#define WI_INIT_TRIES 3
964	int i;
965	int tries;
966
967	/* Symbol firmware cannot be initialized more than once */
968	if (sc->sc_firmware_type == WI_SYMBOL && sc->sc_enabled)
969		return;
970	if (sc->sc_firmware_type == WI_SYMBOL)
971		tries = 1;
972	else
973		tries = WI_INIT_TRIES;
974
975	for (i = 0; i < tries; i++) {
976		if (wi_cmd(sc, WI_CMD_INI, 0, 0, 0) == 0)
977			break;
978		DELAY(WI_DELAY * 1000);
979	}
980	sc->sc_enabled = 1;
981
982	if (i == tries) {
983		device_printf(sc->dev, "init failed\n");
984		return;
985	}
986
987	CSR_WRITE_2(sc, WI_INT_EN, 0);
988	CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
989
990	/* Calibrate timer. */
991	WI_SETVAL(WI_RID_TICK_TIME, 8);
992
993	return;
994}
995
996/*
997 * Read an LTV record from the NIC.
998 */
999static int
1000wi_read_record(sc, ltv)
1001	struct wi_softc		*sc;
1002	struct wi_ltv_gen	*ltv;
1003{
1004	u_int16_t		*ptr;
1005	int			i, len, code;
1006	struct wi_ltv_gen	*oltv, p2ltv;
1007
1008	oltv = ltv;
1009	if (sc->sc_firmware_type != WI_LUCENT) {
1010		switch (ltv->wi_type) {
1011		case WI_RID_ENCRYPTION:
1012			p2ltv.wi_type = WI_RID_P2_ENCRYPTION;
1013			p2ltv.wi_len = 2;
1014			ltv = &p2ltv;
1015			break;
1016		case WI_RID_TX_CRYPT_KEY:
1017			p2ltv.wi_type = WI_RID_P2_TX_CRYPT_KEY;
1018			p2ltv.wi_len = 2;
1019			ltv = &p2ltv;
1020			break;
1021		}
1022	}
1023
1024	/* Tell the NIC to enter record read mode. */
1025	if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_READ, ltv->wi_type, 0, 0))
1026		return(EIO);
1027
1028	/* Seek to the record. */
1029	if (wi_seek(sc, ltv->wi_type, 0, WI_BAP1))
1030		return(EIO);
1031
1032	/*
1033	 * Read the length and record type and make sure they
1034	 * match what we expect (this verifies that we have enough
1035	 * room to hold all of the returned data).
1036	 */
1037	len = CSR_READ_2(sc, WI_DATA1);
1038	if (len > ltv->wi_len)
1039		return(ENOSPC);
1040	code = CSR_READ_2(sc, WI_DATA1);
1041	if (code != ltv->wi_type)
1042		return(EIO);
1043
1044	ltv->wi_len = len;
1045	ltv->wi_type = code;
1046
1047	/* Now read the data. */
1048	ptr = &ltv->wi_val;
1049	for (i = 0; i < ltv->wi_len - 1; i++)
1050		ptr[i] = CSR_READ_2(sc, WI_DATA1);
1051
1052	if (sc->sc_firmware_type != WI_LUCENT) {
1053		switch (oltv->wi_type) {
1054		case WI_RID_TX_RATE:
1055		case WI_RID_CUR_TX_RATE:
1056			switch (ltv->wi_val) {
1057			case 1: oltv->wi_val = 1; break;
1058			case 2: oltv->wi_val = 2; break;
1059			case 3:	oltv->wi_val = 6; break;
1060			case 4: oltv->wi_val = 5; break;
1061			case 7: oltv->wi_val = 7; break;
1062			case 8: oltv->wi_val = 11; break;
1063			case 15: oltv->wi_val = 3; break;
1064			default: oltv->wi_val = 0x100 + ltv->wi_val; break;
1065			}
1066			break;
1067		case WI_RID_ENCRYPTION:
1068			oltv->wi_len = 2;
1069			if (ltv->wi_val & 0x01)
1070				oltv->wi_val = 1;
1071			else
1072				oltv->wi_val = 0;
1073			break;
1074		case WI_RID_TX_CRYPT_KEY:
1075			oltv->wi_len = 2;
1076			oltv->wi_val = ltv->wi_val;
1077			break;
1078		case WI_RID_CNFAUTHMODE:
1079                        oltv->wi_len = 2;
1080			if (le16toh(ltv->wi_val) & 0x01)
1081				oltv->wi_val = htole16(1);
1082			else if (le16toh(ltv->wi_val) & 0x02)
1083				oltv->wi_val = htole16(2);
1084			break;
1085		}
1086	}
1087
1088	return(0);
1089}
1090
1091/*
1092 * Same as read, except we inject data instead of reading it.
1093 */
1094static int
1095wi_write_record(sc, ltv)
1096	struct wi_softc		*sc;
1097	struct wi_ltv_gen	*ltv;
1098{
1099	u_int16_t		*ptr;
1100	int			i;
1101	struct wi_ltv_gen	p2ltv;
1102
1103	if (sc->sc_firmware_type != WI_LUCENT) {
1104		switch (ltv->wi_type) {
1105		case WI_RID_TX_RATE:
1106			p2ltv.wi_type = WI_RID_TX_RATE;
1107			p2ltv.wi_len = 2;
1108			switch (ltv->wi_val) {
1109			case 1: p2ltv.wi_val = 1; break;
1110			case 2: p2ltv.wi_val = 2; break;
1111			case 3:	p2ltv.wi_val = 15; break;
1112			case 5: p2ltv.wi_val = 4; break;
1113			case 6: p2ltv.wi_val = 3; break;
1114			case 7: p2ltv.wi_val = 7; break;
1115			case 11: p2ltv.wi_val = 8; break;
1116			default: return EINVAL;
1117			}
1118			ltv = &p2ltv;
1119			break;
1120		case WI_RID_ENCRYPTION:
1121			p2ltv.wi_type = WI_RID_P2_ENCRYPTION;
1122			p2ltv.wi_len = 2;
1123			if (le16toh(ltv->wi_val)) {
1124				p2ltv.wi_val =htole16(PRIVACY_INVOKED |
1125				    EXCLUDE_UNENCRYPTED);
1126#ifdef WI_HOSTAP
1127				if (sc->wi_ptype == WI_PORTTYPE_AP)
1128					/*
1129					 * Disable tx encryption...
1130					 * it's broken.
1131					 */
1132					p2ltv.wi_val |= htole16(HOST_ENCRYPT);
1133#endif
1134			} else
1135				p2ltv.wi_val =
1136				    htole16(HOST_ENCRYPT | HOST_DECRYPT);
1137			ltv = &p2ltv;
1138			break;
1139		case WI_RID_TX_CRYPT_KEY:
1140			p2ltv.wi_type = WI_RID_P2_TX_CRYPT_KEY;
1141			p2ltv.wi_len = 2;
1142			p2ltv.wi_val = ltv->wi_val;
1143			ltv = &p2ltv;
1144			break;
1145		case WI_RID_DEFLT_CRYPT_KEYS:
1146		    {
1147			int error;
1148			int keylen;
1149			struct wi_ltv_str	ws;
1150			struct wi_ltv_keys	*wk =
1151			    (struct wi_ltv_keys *)ltv;
1152
1153			keylen = wk->wi_keys[sc->wi_tx_key].wi_keylen;
1154
1155			for (i = 0; i < 4; i++) {
1156				bzero(&ws, sizeof(ws));
1157				ws.wi_len = (keylen > 5) ? 8 : 4;
1158				ws.wi_type = WI_RID_P2_CRYPT_KEY0 + i;
1159				memcpy(ws.wi_str,
1160				    &wk->wi_keys[i].wi_keydat, keylen);
1161				error = wi_write_record(sc,
1162				    (struct wi_ltv_gen *)&ws);
1163				if (error)
1164					return error;
1165			}
1166			return 0;
1167		    }
1168		case WI_RID_CNFAUTHMODE:
1169			p2ltv.wi_type = WI_RID_CNFAUTHMODE;
1170			p2ltv.wi_len = 2;
1171			if (le16toh(ltv->wi_val) == 1)
1172				p2ltv.wi_val = htole16(0x01);
1173			else if (le16toh(ltv->wi_val) == 2)
1174				p2ltv.wi_val = htole16(0x02);
1175			ltv = &p2ltv;
1176			break;
1177		}
1178	}
1179
1180	if (wi_seek(sc, ltv->wi_type, 0, WI_BAP1))
1181		return(EIO);
1182
1183	CSR_WRITE_2(sc, WI_DATA1, ltv->wi_len);
1184	CSR_WRITE_2(sc, WI_DATA1, ltv->wi_type);
1185
1186	ptr = &ltv->wi_val;
1187	for (i = 0; i < ltv->wi_len - 1; i++)
1188		CSR_WRITE_2(sc, WI_DATA1, ptr[i]);
1189
1190	if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_WRITE, ltv->wi_type, 0, 0))
1191		return(EIO);
1192
1193	return(0);
1194}
1195
1196static int
1197wi_seek(sc, id, off, chan)
1198	struct wi_softc		*sc;
1199	int			id, off, chan;
1200{
1201	int			i;
1202	int			selreg, offreg;
1203	int			status;
1204
1205	switch (chan) {
1206	case WI_BAP0:
1207		selreg = WI_SEL0;
1208		offreg = WI_OFF0;
1209		break;
1210	case WI_BAP1:
1211		selreg = WI_SEL1;
1212		offreg = WI_OFF1;
1213		break;
1214	default:
1215		device_printf(sc->dev, "invalid data path: %x\n", chan);
1216		return(EIO);
1217	}
1218
1219	CSR_WRITE_2(sc, selreg, id);
1220	CSR_WRITE_2(sc, offreg, off);
1221
1222	for (i = 0; i < WI_TIMEOUT; i++) {
1223		status = CSR_READ_2(sc, offreg);
1224		if (!(status & (WI_OFF_BUSY|WI_OFF_ERR)))
1225			break;
1226		DELAY(WI_DELAY);
1227	}
1228
1229	if (i == WI_TIMEOUT) {
1230		device_printf(sc->dev, "timeout in wi_seek to %x/%x; last status %x\n",
1231			id, off, status);
1232		return(ETIMEDOUT);
1233	}
1234
1235	return(0);
1236}
1237
1238static int
1239wi_read_data(sc, id, off, buf, len)
1240	struct wi_softc		*sc;
1241	int			id, off;
1242	caddr_t			buf;
1243	int			len;
1244{
1245	int			i;
1246	u_int16_t		*ptr;
1247
1248	if (wi_seek(sc, id, off, WI_BAP1))
1249		return(EIO);
1250
1251	ptr = (u_int16_t *)buf;
1252	for (i = 0; i < len / 2; i++)
1253		ptr[i] = CSR_READ_2(sc, WI_DATA1);
1254
1255	return(0);
1256}
1257
1258/*
1259 * According to the comments in the HCF Light code, there is a bug in
1260 * the Hermes (or possibly in certain Hermes firmware revisions) where
1261 * the chip's internal autoincrement counter gets thrown off during
1262 * data writes: the autoincrement is missed, causing one data word to
1263 * be overwritten and subsequent words to be written to the wrong memory
1264 * locations. The end result is that we could end up transmitting bogus
1265 * frames without realizing it. The workaround for this is to write a
1266 * couple of extra guard words after the end of the transfer, then
1267 * attempt to read then back. If we fail to locate the guard words where
1268 * we expect them, we preform the transfer over again.
1269 */
1270static int
1271wi_write_data(sc, id, off, buf, len)
1272	struct wi_softc		*sc;
1273	int			id, off;
1274	caddr_t			buf;
1275	int			len;
1276{
1277	int			i;
1278	u_int16_t		*ptr;
1279#ifdef WI_HERMES_AUTOINC_WAR
1280	int			retries;
1281
1282	retries = 512;
1283again:
1284#endif
1285
1286	if (wi_seek(sc, id, off, WI_BAP0))
1287		return(EIO);
1288
1289	ptr = (u_int16_t *)buf;
1290	for (i = 0; i < (len / 2); i++)
1291		CSR_WRITE_2(sc, WI_DATA0, ptr[i]);
1292
1293#ifdef WI_HERMES_AUTOINC_WAR
1294	CSR_WRITE_2(sc, WI_DATA0, 0x1234);
1295	CSR_WRITE_2(sc, WI_DATA0, 0x5678);
1296
1297	if (wi_seek(sc, id, off + len, WI_BAP0))
1298		return(EIO);
1299
1300	if (CSR_READ_2(sc, WI_DATA0) != 0x1234 ||
1301	    CSR_READ_2(sc, WI_DATA0) != 0x5678) {
1302		if (--retries >= 0)
1303			goto again;
1304		device_printf(sc->dev, "wi_write_data device timeout\n");
1305		return (EIO);
1306	}
1307#endif
1308
1309	return(0);
1310}
1311
1312/*
1313 * Allocate a region of memory inside the NIC and zero
1314 * it out.
1315 */
1316static int
1317wi_alloc_nicmem(sc, len, id)
1318	struct wi_softc		*sc;
1319	int			len;
1320	int			*id;
1321{
1322	int			i;
1323
1324	if (wi_cmd(sc, WI_CMD_ALLOC_MEM, len, 0, 0)) {
1325		device_printf(sc->dev,
1326		    "failed to allocate %d bytes on NIC\n", len);
1327		return(ENOMEM);
1328	}
1329
1330	for (i = 0; i < WI_TIMEOUT; i++) {
1331		if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_ALLOC)
1332			break;
1333		DELAY(WI_DELAY);
1334	}
1335
1336	if (i == WI_TIMEOUT) {
1337		device_printf(sc->dev, "time out allocating memory on card\n");
1338		return(ETIMEDOUT);
1339	}
1340
1341	CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
1342	*id = CSR_READ_2(sc, WI_ALLOC_FID);
1343
1344	if (wi_seek(sc, *id, 0, WI_BAP0)) {
1345		device_printf(sc->dev, "seek failed while allocating memory on card\n");
1346		return(EIO);
1347	}
1348
1349	for (i = 0; i < len / 2; i++)
1350		CSR_WRITE_2(sc, WI_DATA0, 0);
1351
1352	return(0);
1353}
1354
1355static void
1356wi_setmulti(sc)
1357	struct wi_softc		*sc;
1358{
1359	struct ifnet		*ifp;
1360	int			i = 0;
1361	struct ifmultiaddr	*ifma;
1362	struct wi_ltv_mcast	mcast;
1363
1364	ifp = &sc->arpcom.ac_if;
1365
1366	bzero((char *)&mcast, sizeof(mcast));
1367
1368	mcast.wi_type = WI_RID_MCAST_LIST;
1369	mcast.wi_len = (3 * 16) + 1;
1370
1371	if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
1372		wi_write_record(sc, (struct wi_ltv_gen *)&mcast);
1373		return;
1374	}
1375
1376	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
1377		if (ifma->ifma_addr->sa_family != AF_LINK)
1378			continue;
1379		if (i < 16) {
1380			bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
1381			    (char *)&mcast.wi_mcast[i], ETHER_ADDR_LEN);
1382			i++;
1383		} else {
1384			bzero((char *)&mcast, sizeof(mcast));
1385			break;
1386		}
1387	}
1388
1389	mcast.wi_len = (i * 3) + 1;
1390	wi_write_record(sc, (struct wi_ltv_gen *)&mcast);
1391
1392	return;
1393}
1394
1395static void
1396wi_setdef(sc, wreq)
1397	struct wi_softc		*sc;
1398	struct wi_req		*wreq;
1399{
1400	struct sockaddr_dl	*sdl;
1401	struct ifaddr		*ifa;
1402	struct ifnet		*ifp;
1403
1404	ifp = &sc->arpcom.ac_if;
1405
1406	switch(wreq->wi_type) {
1407	case WI_RID_MAC_NODE:
1408		ifa = ifaddr_byindex(ifp->if_index);
1409		sdl = (struct sockaddr_dl *)ifa->ifa_addr;
1410		bcopy((char *)&wreq->wi_val, (char *)&sc->arpcom.ac_enaddr,
1411		   ETHER_ADDR_LEN);
1412		bcopy((char *)&wreq->wi_val, LLADDR(sdl), ETHER_ADDR_LEN);
1413		break;
1414	case WI_RID_PORTTYPE:
1415		sc->wi_ptype = le16toh(wreq->wi_val[0]);
1416		break;
1417	case WI_RID_TX_RATE:
1418		sc->wi_tx_rate = le16toh(wreq->wi_val[0]);
1419		break;
1420	case WI_RID_MAX_DATALEN:
1421		sc->wi_max_data_len = le16toh(wreq->wi_val[0]);
1422		break;
1423	case WI_RID_RTS_THRESH:
1424		sc->wi_rts_thresh = le16toh(wreq->wi_val[0]);
1425		break;
1426	case WI_RID_SYSTEM_SCALE:
1427		sc->wi_ap_density = le16toh(wreq->wi_val[0]);
1428		break;
1429	case WI_RID_CREATE_IBSS:
1430		sc->wi_create_ibss = le16toh(wreq->wi_val[0]);
1431		break;
1432	case WI_RID_OWN_CHNL:
1433		sc->wi_channel = le16toh(wreq->wi_val[0]);
1434		break;
1435	case WI_RID_NODENAME:
1436		bzero(sc->wi_node_name, sizeof(sc->wi_node_name));
1437		bcopy((char *)&wreq->wi_val[1], sc->wi_node_name, 30);
1438		break;
1439	case WI_RID_DESIRED_SSID:
1440		bzero(sc->wi_net_name, sizeof(sc->wi_net_name));
1441		bcopy((char *)&wreq->wi_val[1], sc->wi_net_name, 30);
1442		break;
1443	case WI_RID_OWN_SSID:
1444		bzero(sc->wi_ibss_name, sizeof(sc->wi_ibss_name));
1445		bcopy((char *)&wreq->wi_val[1], sc->wi_ibss_name, 30);
1446		break;
1447	case WI_RID_PM_ENABLED:
1448		sc->wi_pm_enabled = le16toh(wreq->wi_val[0]);
1449		break;
1450	case WI_RID_MICROWAVE_OVEN:
1451		sc->wi_mor_enabled = le16toh(wreq->wi_val[0]);
1452		break;
1453	case WI_RID_MAX_SLEEP:
1454		sc->wi_max_sleep = le16toh(wreq->wi_val[0]);
1455		break;
1456	case WI_RID_CNFAUTHMODE:
1457		sc->wi_authtype = le16toh(wreq->wi_val[0]);
1458		break;
1459	case WI_RID_ROAMING_MODE:
1460		sc->wi_roaming = le16toh(wreq->wi_val[0]);
1461		break;
1462	case WI_RID_ENCRYPTION:
1463		sc->wi_use_wep = le16toh(wreq->wi_val[0]);
1464		break;
1465	case WI_RID_TX_CRYPT_KEY:
1466		sc->wi_tx_key = le16toh(wreq->wi_val[0]);
1467		break;
1468	case WI_RID_DEFLT_CRYPT_KEYS:
1469		bcopy((char *)wreq, (char *)&sc->wi_keys,
1470		    sizeof(struct wi_ltv_keys));
1471		break;
1472	default:
1473		break;
1474	}
1475
1476	/* Reinitialize WaveLAN. */
1477	wi_init(sc);
1478
1479	return;
1480}
1481
1482static int
1483wi_ioctl(ifp, command, data)
1484	struct ifnet		*ifp;
1485	u_long			command;
1486	caddr_t			data;
1487{
1488	int			error = 0;
1489	int			len;
1490	u_int8_t		tmpkey[14];
1491	char			tmpssid[IEEE80211_NWID_LEN];
1492	struct wi_softc		*sc;
1493	struct wi_req		wreq;
1494	struct ifreq		*ifr;
1495	struct ieee80211req	*ireq;
1496	struct thread		*td = curthread;
1497
1498	sc = ifp->if_softc;
1499	WI_LOCK(sc);
1500	ifr = (struct ifreq *)data;
1501	ireq = (struct ieee80211req *)data;
1502
1503	if (sc->wi_gone) {
1504		error = ENODEV;
1505		goto out;
1506	}
1507
1508	switch(command) {
1509	case SIOCSIFADDR:
1510	case SIOCGIFADDR:
1511	case SIOCSIFMTU:
1512		error = ether_ioctl(ifp, command, data);
1513		break;
1514	case SIOCSIFFLAGS:
1515		if (ifp->if_flags & IFF_UP) {
1516			if (ifp->if_flags & IFF_RUNNING &&
1517			    ifp->if_flags & IFF_PROMISC &&
1518			    !(sc->wi_if_flags & IFF_PROMISC)) {
1519				WI_SETVAL(WI_RID_PROMISC, 1);
1520			} else if (ifp->if_flags & IFF_RUNNING &&
1521			    !(ifp->if_flags & IFF_PROMISC) &&
1522			    sc->wi_if_flags & IFF_PROMISC) {
1523				WI_SETVAL(WI_RID_PROMISC, 0);
1524			} else
1525				wi_init(sc);
1526		} else {
1527			if (ifp->if_flags & IFF_RUNNING) {
1528				wi_stop(sc);
1529			}
1530		}
1531		sc->wi_if_flags = ifp->if_flags;
1532		error = 0;
1533		break;
1534	case SIOCSIFMEDIA:
1535	case SIOCGIFMEDIA:
1536		error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, command);
1537		break;
1538	case SIOCADDMULTI:
1539	case SIOCDELMULTI:
1540		wi_setmulti(sc);
1541		error = 0;
1542		break;
1543	case SIOCGWAVELAN:
1544		error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
1545		if (error)
1546			break;
1547		if (wreq.wi_len > WI_MAX_DATALEN) {
1548			error = EINVAL;
1549			break;
1550		}
1551		/* Don't show WEP keys to non-root users. */
1552		if (wreq.wi_type == WI_RID_DEFLT_CRYPT_KEYS && suser(td))
1553			break;
1554		if (wreq.wi_type == WI_RID_IFACE_STATS) {
1555			bcopy((char *)&sc->wi_stats, (char *)&wreq.wi_val,
1556			    sizeof(sc->wi_stats));
1557			wreq.wi_len = (sizeof(sc->wi_stats) / 2) + 1;
1558		} else if (wreq.wi_type == WI_RID_DEFLT_CRYPT_KEYS) {
1559			bcopy((char *)&sc->wi_keys, (char *)&wreq,
1560			    sizeof(struct wi_ltv_keys));
1561		}
1562#ifdef WICACHE
1563		else if (wreq.wi_type == WI_RID_ZERO_CACHE) {
1564			sc->wi_sigitems = sc->wi_nextitem = 0;
1565		} else if (wreq.wi_type == WI_RID_READ_CACHE) {
1566			char *pt = (char *)&wreq.wi_val;
1567			bcopy((char *)&sc->wi_sigitems,
1568			    (char *)pt, sizeof(int));
1569			pt += (sizeof (int));
1570			wreq.wi_len = sizeof(int) / 2;
1571			bcopy((char *)&sc->wi_sigcache, (char *)pt,
1572			    sizeof(struct wi_sigcache) * sc->wi_sigitems);
1573			wreq.wi_len += ((sizeof(struct wi_sigcache) *
1574			    sc->wi_sigitems) / 2) + 1;
1575		}
1576#endif
1577		else if (wreq.wi_type == WI_RID_PROCFRAME) {
1578			wreq.wi_len = 2;
1579			wreq.wi_val[0] = sc->wi_procframe;
1580		} else if (wreq.wi_type == WI_RID_PRISM2) {
1581			wreq.wi_len = 2;
1582			wreq.wi_val[0] = sc->sc_firmware_type != WI_LUCENT;
1583		} else if (wreq.wi_type == WI_RID_SCAN_RES &&
1584		    sc->sc_firmware_type == WI_LUCENT) {
1585			memcpy((char *)wreq.wi_val, (char *)sc->wi_scanbuf,
1586			    sc->wi_scanbuf_len * 2);
1587			wreq.wi_len = sc->wi_scanbuf_len;
1588		} else {
1589			if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq)) {
1590				error = EINVAL;
1591				break;
1592			}
1593		}
1594		error = copyout(&wreq, ifr->ifr_data, sizeof(wreq));
1595		break;
1596	case SIOCSWAVELAN:
1597		if ((error = suser(td)))
1598			goto out;
1599		error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
1600		if (error)
1601			break;
1602		if (wreq.wi_len > WI_MAX_DATALEN) {
1603			error = EINVAL;
1604			break;
1605		}
1606		if (wreq.wi_type == WI_RID_IFACE_STATS) {
1607			error = EINVAL;
1608			break;
1609		} else if (wreq.wi_type == WI_RID_MGMT_XMIT) {
1610			error = wi_mgmt_xmit(sc, (caddr_t)&wreq.wi_val,
1611			    wreq.wi_len);
1612		} else if (wreq.wi_type == WI_RID_PROCFRAME) {
1613			sc->wi_procframe = wreq.wi_val[0];
1614		/*
1615		 * if we're getting a scan request from a wavelan card
1616		 * (non-prism2), send out a cmd_inquire to the card to scan
1617		 * results for the scan will be received through the info
1618		 * interrupt handler. otherwise the scan request can be
1619		 * directly handled by a prism2 card's rid interface.
1620		 */
1621		} else if (wreq.wi_type == WI_RID_SCAN_REQ &&
1622		    sc->sc_firmware_type == WI_LUCENT) {
1623			wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_SCAN_RESULTS, 0, 0);
1624		} else {
1625			error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
1626			if (!error)
1627				wi_setdef(sc, &wreq);
1628		}
1629		break;
1630	case SIOCGPRISM2DEBUG:
1631		error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
1632		if (error)
1633			break;
1634		if (!(ifp->if_flags & IFF_RUNNING) ||
1635		    sc->sc_firmware_type == WI_LUCENT) {
1636			error = EIO;
1637			break;
1638		}
1639		error = wi_get_debug(sc, &wreq);
1640		if (error == 0)
1641			error = copyout(&wreq, ifr->ifr_data, sizeof(wreq));
1642		break;
1643	case SIOCSPRISM2DEBUG:
1644		if ((error = suser(td)))
1645			goto out;
1646		error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
1647		if (error)
1648			break;
1649		error = wi_set_debug(sc, &wreq);
1650		break;
1651	case SIOCG80211:
1652		switch(ireq->i_type) {
1653		case IEEE80211_IOC_SSID:
1654			if(ireq->i_val == -1) {
1655				bzero(tmpssid, IEEE80211_NWID_LEN);
1656				error = wi_get_cur_ssid(sc, tmpssid, &len);
1657				if (error != 0)
1658					break;
1659				error = copyout(tmpssid, ireq->i_data,
1660					IEEE80211_NWID_LEN);
1661				ireq->i_len = len;
1662			} else if (ireq->i_val == 0) {
1663				error = copyout(sc->wi_net_name,
1664				    ireq->i_data,
1665				    IEEE80211_NWID_LEN);
1666				ireq->i_len = IEEE80211_NWID_LEN;
1667			} else
1668				error = EINVAL;
1669			break;
1670		case IEEE80211_IOC_NUMSSIDS:
1671			ireq->i_val = 1;
1672			break;
1673		case IEEE80211_IOC_WEP:
1674			if(!sc->wi_has_wep) {
1675				ireq->i_val = IEEE80211_WEP_NOSUP;
1676			} else {
1677				if(sc->wi_use_wep) {
1678					ireq->i_val =
1679					    IEEE80211_WEP_MIXED;
1680				} else {
1681					ireq->i_val =
1682					    IEEE80211_WEP_OFF;
1683				}
1684			}
1685			break;
1686		case IEEE80211_IOC_WEPKEY:
1687			if(!sc->wi_has_wep ||
1688			    ireq->i_val < 0 || ireq->i_val > 3) {
1689				error = EINVAL;
1690				break;
1691			}
1692			len = sc->wi_keys.wi_keys[ireq->i_val].wi_keylen;
1693			if (suser(td))
1694				bcopy(sc->wi_keys.wi_keys[ireq->i_val].wi_keydat,
1695				    tmpkey, len);
1696			else
1697				bzero(tmpkey, len);
1698
1699			ireq->i_len = len;
1700			error = copyout(tmpkey, ireq->i_data, len);
1701
1702			break;
1703		case IEEE80211_IOC_NUMWEPKEYS:
1704			if(!sc->wi_has_wep)
1705				error = EINVAL;
1706			else
1707				ireq->i_val = 4;
1708			break;
1709		case IEEE80211_IOC_WEPTXKEY:
1710			if(!sc->wi_has_wep)
1711				error = EINVAL;
1712			else
1713				ireq->i_val = sc->wi_tx_key;
1714			break;
1715		case IEEE80211_IOC_AUTHMODE:
1716			ireq->i_val = sc->wi_authmode;
1717			break;
1718		case IEEE80211_IOC_STATIONNAME:
1719			error = copyout(sc->wi_node_name,
1720			    ireq->i_data, IEEE80211_NWID_LEN);
1721			ireq->i_len = IEEE80211_NWID_LEN;
1722			break;
1723		case IEEE80211_IOC_CHANNEL:
1724			wreq.wi_type = WI_RID_CURRENT_CHAN;
1725			wreq.wi_len = WI_MAX_DATALEN;
1726			if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq))
1727				error = EINVAL;
1728			else {
1729				ireq->i_val = wreq.wi_val[0];
1730			}
1731			break;
1732		case IEEE80211_IOC_POWERSAVE:
1733			if(sc->wi_pm_enabled)
1734				ireq->i_val = IEEE80211_POWERSAVE_ON;
1735			else
1736				ireq->i_val = IEEE80211_POWERSAVE_OFF;
1737			break;
1738		case IEEE80211_IOC_POWERSAVESLEEP:
1739			ireq->i_val = sc->wi_max_sleep;
1740			break;
1741		default:
1742			error = EINVAL;
1743		}
1744		break;
1745	case SIOCS80211:
1746		if ((error = suser(td)))
1747			goto out;
1748		switch(ireq->i_type) {
1749		case IEEE80211_IOC_SSID:
1750			if (ireq->i_val != 0 ||
1751			    ireq->i_len > IEEE80211_NWID_LEN) {
1752				error = EINVAL;
1753				break;
1754			}
1755			/* We set both of them */
1756			bzero(sc->wi_net_name, IEEE80211_NWID_LEN);
1757			error = copyin(ireq->i_data,
1758			    sc->wi_net_name, ireq->i_len);
1759			bcopy(sc->wi_net_name, sc->wi_ibss_name, IEEE80211_NWID_LEN);
1760			break;
1761		case IEEE80211_IOC_WEP:
1762			/*
1763			 * These cards only support one mode so
1764			 * we just turn wep on what ever is
1765			 * passed in if it's not OFF.
1766			 */
1767			if (ireq->i_val == IEEE80211_WEP_OFF) {
1768				sc->wi_use_wep = 0;
1769			} else {
1770				sc->wi_use_wep = 1;
1771			}
1772			break;
1773		case IEEE80211_IOC_WEPKEY:
1774			if (ireq->i_val < 0 || ireq->i_val > 3 ||
1775				ireq->i_len > 13) {
1776				error = EINVAL;
1777				break;
1778			}
1779			bzero(sc->wi_keys.wi_keys[ireq->i_val].wi_keydat, 13);
1780			error = copyin(ireq->i_data,
1781			    sc->wi_keys.wi_keys[ireq->i_val].wi_keydat,
1782			    ireq->i_len);
1783			if(error)
1784				break;
1785			sc->wi_keys.wi_keys[ireq->i_val].wi_keylen =
1786				    ireq->i_len;
1787			break;
1788		case IEEE80211_IOC_WEPTXKEY:
1789			if (ireq->i_val < 0 || ireq->i_val > 3) {
1790				error = EINVAL;
1791				break;
1792			}
1793			sc->wi_tx_key = ireq->i_val;
1794			break;
1795		case IEEE80211_IOC_AUTHMODE:
1796			sc->wi_authmode = ireq->i_val;
1797			break;
1798		case IEEE80211_IOC_STATIONNAME:
1799			if (ireq->i_len > 32) {
1800				error = EINVAL;
1801				break;
1802			}
1803			bzero(sc->wi_node_name, 32);
1804			error = copyin(ireq->i_data,
1805			    sc->wi_node_name, ireq->i_len);
1806			break;
1807		case IEEE80211_IOC_CHANNEL:
1808			/*
1809			 * The actual range is 1-14, but if you
1810			 * set it to 0 you get the default. So
1811			 * we let that work too.
1812			 */
1813			if (ireq->i_val < 0 || ireq->i_val > 14) {
1814				error = EINVAL;
1815				break;
1816			}
1817			sc->wi_channel = ireq->i_val;
1818			break;
1819		case IEEE80211_IOC_POWERSAVE:
1820			switch (ireq->i_val) {
1821			case IEEE80211_POWERSAVE_OFF:
1822				sc->wi_pm_enabled = 0;
1823				break;
1824			case IEEE80211_POWERSAVE_ON:
1825				sc->wi_pm_enabled = 1;
1826				break;
1827			default:
1828				error = EINVAL;
1829				break;
1830			}
1831			break;
1832		case IEEE80211_IOC_POWERSAVESLEEP:
1833			if (ireq->i_val < 0) {
1834				error = EINVAL;
1835				break;
1836			}
1837			sc->wi_max_sleep = ireq->i_val;
1838			break;
1839		default:
1840			error = EINVAL;
1841			break;
1842		}
1843
1844		/* Reinitialize WaveLAN. */
1845		wi_init(sc);
1846
1847	break;
1848#ifdef WI_HOSTAP
1849	case SIOCHOSTAP_ADD:
1850	case SIOCHOSTAP_DEL:
1851	case SIOCHOSTAP_GET:
1852	case SIOCHOSTAP_GETALL:
1853	case SIOCHOSTAP_GFLAGS:
1854	case SIOCHOSTAP_SFLAGS:
1855		/* Send all Host AP specific ioctl's to Host AP code. */
1856		error = wihap_ioctl(sc, command, data);
1857		break;
1858#endif
1859	default:
1860		error = EINVAL;
1861		break;
1862	}
1863out:
1864	WI_UNLOCK(sc);
1865
1866	return(error);
1867}
1868
1869static void
1870wi_init(xsc)
1871	void			*xsc;
1872{
1873	struct wi_softc		*sc = xsc;
1874	struct ifnet		*ifp = &sc->arpcom.ac_if;
1875	struct wi_ltv_macaddr	mac;
1876	int			id = 0;
1877
1878	WI_LOCK(sc);
1879
1880	if (sc->wi_gone) {
1881		WI_UNLOCK(sc);
1882		return;
1883	}
1884
1885	if (ifp->if_flags & IFF_RUNNING)
1886		wi_stop(sc);
1887
1888	wi_reset(sc);
1889
1890	/* Program max data length. */
1891	WI_SETVAL(WI_RID_MAX_DATALEN, sc->wi_max_data_len);
1892
1893	/* Enable/disable IBSS creation. */
1894	WI_SETVAL(WI_RID_CREATE_IBSS, sc->wi_create_ibss);
1895
1896	/* Set the port type. */
1897	WI_SETVAL(WI_RID_PORTTYPE, sc->wi_ptype);
1898
1899	/* Program the RTS/CTS threshold. */
1900	WI_SETVAL(WI_RID_RTS_THRESH, sc->wi_rts_thresh);
1901
1902	/* Program the TX rate */
1903	WI_SETVAL(WI_RID_TX_RATE, sc->wi_tx_rate);
1904
1905	/* Access point density */
1906	WI_SETVAL(WI_RID_SYSTEM_SCALE, sc->wi_ap_density);
1907
1908	/* Power Management Enabled */
1909	WI_SETVAL(WI_RID_PM_ENABLED, sc->wi_pm_enabled);
1910
1911	/* Power Managment Max Sleep */
1912	WI_SETVAL(WI_RID_MAX_SLEEP, sc->wi_max_sleep);
1913
1914	/* Roaming type */
1915	WI_SETVAL(WI_RID_ROAMING_MODE, sc->wi_roaming);
1916
1917	/* Specify the IBSS name */
1918	WI_SETSTR(WI_RID_OWN_SSID, sc->wi_ibss_name);
1919
1920	/* Specify the network name */
1921	WI_SETSTR(WI_RID_DESIRED_SSID, sc->wi_net_name);
1922
1923	/* Specify the frequency to use */
1924	WI_SETVAL(WI_RID_OWN_CHNL, sc->wi_channel);
1925
1926	/* Program the nodename. */
1927	WI_SETSTR(WI_RID_NODENAME, sc->wi_node_name);
1928
1929	/* Specify the authentication mode. */
1930	WI_SETVAL(WI_RID_CNFAUTHMODE, sc->wi_authmode);
1931
1932	/* Set our MAC address. */
1933	mac.wi_len = 4;
1934	mac.wi_type = WI_RID_MAC_NODE;
1935	bcopy((char *)&sc->arpcom.ac_enaddr,
1936	   (char *)&mac.wi_mac_addr, ETHER_ADDR_LEN);
1937	wi_write_record(sc, (struct wi_ltv_gen *)&mac);
1938
1939	/* Configure WEP. */
1940	if (sc->wi_has_wep) {
1941		WI_SETVAL(WI_RID_ENCRYPTION, sc->wi_use_wep);
1942		WI_SETVAL(WI_RID_TX_CRYPT_KEY, sc->wi_tx_key);
1943		sc->wi_keys.wi_len = (sizeof(struct wi_ltv_keys) / 2) + 1;
1944		sc->wi_keys.wi_type = WI_RID_DEFLT_CRYPT_KEYS;
1945		wi_write_record(sc, (struct wi_ltv_gen *)&sc->wi_keys);
1946		if (sc->sc_firmware_type != WI_LUCENT && sc->wi_use_wep) {
1947			/*
1948			 * ONLY HWB3163 EVAL-CARD Firmware version
1949			 * less than 0.8 variant2
1950			 *
1951			 *   If promiscuous mode disable, Prism2 chip
1952			 *  does not work with WEP .
1953			 * It is under investigation for details.
1954			 * (ichiro@netbsd.org)
1955			 */
1956			if (sc->sc_firmware_type == WI_INTERSIL &&
1957			    sc->sc_sta_firmware_ver < 802 ) {
1958				/* firm ver < 0.8 variant 2 */
1959				WI_SETVAL(WI_RID_PROMISC, 1);
1960			}
1961			WI_SETVAL(WI_RID_CNFAUTHMODE, sc->wi_authtype);
1962		}
1963	}
1964
1965	/* Initialize promisc mode. */
1966	if (ifp->if_flags & IFF_PROMISC) {
1967		WI_SETVAL(WI_RID_PROMISC, 1);
1968	} else {
1969		WI_SETVAL(WI_RID_PROMISC, 0);
1970	}
1971
1972	/* Set multicast filter. */
1973	wi_setmulti(sc);
1974
1975	/* Enable desired port */
1976	wi_cmd(sc, WI_CMD_ENABLE | sc->wi_portnum, 0, 0, 0);
1977
1978	if (wi_alloc_nicmem(sc, ETHER_MAX_LEN + sizeof(struct wi_frame) + 8, &id))
1979		device_printf(sc->dev, "tx buffer allocation failed\n");
1980	sc->wi_tx_data_id = id;
1981
1982	if (wi_alloc_nicmem(sc, ETHER_MAX_LEN + sizeof(struct wi_frame) + 8, &id))
1983		device_printf(sc->dev, "mgmt. buffer allocation failed\n");
1984	sc->wi_tx_mgmt_id = id;
1985
1986	/* enable interrupts */
1987	CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
1988
1989#ifdef WI_HOSTAP
1990	wihap_init(sc);
1991
1992	/*
1993	 * Initialize ICV to something random.  XXX: this doesn't work
1994	 * if init happens in early boot-up.  Fix later.
1995	 */
1996	read_random(&sc->wi_icv, sizeof(sc->wi_icv));
1997#endif
1998	ifp->if_flags |= IFF_RUNNING;
1999	ifp->if_flags &= ~IFF_OACTIVE;
2000
2001	sc->wi_stat_ch = timeout(wi_inquire, sc, hz * 60);
2002	WI_UNLOCK(sc);
2003
2004	return;
2005}
2006
2007#ifdef WI_HOSTAP
2008static u_int32_t crc32_tab[] = {
2009	0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
2010	0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
2011	0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
2012	0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
2013	0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
2014	0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
2015	0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
2016	0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
2017	0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
2018	0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
2019	0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
2020	0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
2021	0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
2022	0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
2023	0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
2024	0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
2025	0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
2026	0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
2027	0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
2028	0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
2029	0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
2030	0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
2031	0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
2032	0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
2033	0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
2034	0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
2035	0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
2036	0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
2037	0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
2038	0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
2039	0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
2040	0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
2041	0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
2042	0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
2043	0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
2044	0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
2045	0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
2046	0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
2047	0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
2048	0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
2049	0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
2050	0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
2051	0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
2052	0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
2053	0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
2054	0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
2055	0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
2056	0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
2057	0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
2058	0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
2059	0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
2060	0x2d02ef8dL
2061};
2062
2063#define RC4STATE 256
2064#define RC4KEYLEN 16
2065#define RC4SWAP(x,y) \
2066    do { u_int8_t t = state[x]; state[x] = state[y]; state[y] = t; } while(0)
2067
2068static void
2069wi_do_hostencrypt(struct wi_softc *sc, caddr_t buf, int len)
2070{
2071	u_int32_t i, crc, klen;
2072	u_int8_t state[RC4STATE], key[RC4KEYLEN];
2073	u_int8_t x, y, *dat;
2074
2075	if (!sc->wi_icv_flag) {
2076		sc->wi_icv = arc4random();
2077		sc->wi_icv_flag++;
2078        } else
2079		sc->wi_icv++;
2080	/*
2081	 * Skip 'bad' IVs from Fluhrer/Mantin/Shamir:
2082	 * (B, 255, N) with 3 <= B < 8
2083	 */
2084	if (sc->wi_icv >= 0x03ff00 &&
2085            (sc->wi_icv & 0xf8ff00) == 0x00ff00)
2086                sc->wi_icv += 0x000100;
2087
2088	/* prepend 24bit IV to tx key, byte order does not matter */
2089	key[0] = sc->wi_icv >> 16;
2090	key[1] = sc->wi_icv >> 8;
2091	key[2] = sc->wi_icv;
2092
2093	klen = sc->wi_keys.wi_keys[sc->wi_tx_key].wi_keylen +
2094	    IEEE80211_WEP_IVLEN;
2095	klen = (klen >= RC4KEYLEN) ? RC4KEYLEN : RC4KEYLEN/2;
2096	bcopy((char *)&sc->wi_keys.wi_keys[sc->wi_tx_key].wi_keydat,
2097	    (char *)key + IEEE80211_WEP_IVLEN, klen - IEEE80211_WEP_IVLEN);
2098
2099	/* rc4 keysetup */
2100	x = y = 0;
2101	for (i = 0; i < RC4STATE; i++)
2102		state[i] = i;
2103	for (i = 0; i < RC4STATE; i++) {
2104		y = (key[x] + state[i] + y) % RC4STATE;
2105		RC4SWAP(i, y);
2106		x = (x + 1) % klen;
2107	}
2108
2109	/* output: IV, tx keyid, rc4(data), rc4(crc32(data)) */
2110	dat = buf;
2111	dat[0] = key[0];
2112	dat[1] = key[1];
2113	dat[2] = key[2];
2114	dat[3] = sc->wi_tx_key << 6;		/* pad and keyid */
2115	dat += 4;
2116
2117	/* compute rc4 over data, crc32 over data */
2118	crc = ~0;
2119	x = y = 0;
2120	for (i = 0; i < len; i++) {
2121		x = (x + 1) % RC4STATE;
2122		y = (state[x] + y) % RC4STATE;
2123		RC4SWAP(x, y);
2124		crc = crc32_tab[(crc ^ dat[i]) & 0xff] ^ (crc >> 8);
2125		dat[i] ^= state[(state[x] + state[y]) % RC4STATE];
2126	}
2127	crc = ~crc;
2128	dat += len;
2129
2130	/* append little-endian crc32 and encrypt */
2131	dat[0] = crc;
2132	dat[1] = crc >> 8;
2133	dat[2] = crc >> 16;
2134	dat[3] = crc >> 24;
2135	for (i = 0; i < IEEE80211_WEP_CRCLEN; i++) {
2136		x = (x + 1) % RC4STATE;
2137		y = (state[x] + y) % RC4STATE;
2138		RC4SWAP(x, y);
2139		dat[i] ^= state[(state[x] + state[y]) % RC4STATE];
2140	}
2141}
2142#endif /* WI_HOSTAP */
2143
2144static void
2145wi_start(ifp)
2146	struct ifnet		*ifp;
2147{
2148	struct wi_softc		*sc;
2149	struct mbuf		*m0;
2150	struct wi_frame		tx_frame;
2151	struct ether_header	*eh;
2152	int			id;
2153
2154	sc = ifp->if_softc;
2155	WI_LOCK(sc);
2156
2157	if (sc->wi_gone) {
2158		WI_UNLOCK(sc);
2159		return;
2160	}
2161
2162	if (ifp->if_flags & IFF_OACTIVE) {
2163		WI_UNLOCK(sc);
2164		return;
2165	}
2166
2167#ifdef WI_HOSTAP
2168nextpkt:
2169#endif
2170	IF_DEQUEUE(&ifp->if_snd, m0);
2171	if (m0 == NULL) {
2172		WI_UNLOCK(sc);
2173		return;
2174	}
2175
2176	bzero((char *)&tx_frame, sizeof(tx_frame));
2177	tx_frame.wi_frame_ctl = htole16(WI_FTYPE_DATA);
2178	id = sc->wi_tx_data_id;
2179	eh = mtod(m0, struct ether_header *);
2180
2181#ifdef WI_HOSTAP
2182	if (sc->wi_ptype == WI_PORTTYPE_AP) {
2183		if (!wihap_check_tx(&sc->wi_hostap_info,
2184		    eh->ether_dhost, &tx_frame.wi_tx_rate)) {
2185			if (ifp->if_flags & IFF_DEBUG)
2186				printf("wi_start: dropping unassoc "
2187				       "dst %6D\n", eh->ether_dhost, ":");
2188			m_freem(m0);
2189			goto nextpkt;
2190		}
2191	}
2192#endif
2193	/*
2194	 * Use RFC1042 encoding for IP and ARP datagrams,
2195	 * 802.3 for anything else.
2196	 */
2197	if (ntohs(eh->ether_type) > ETHER_MAX_LEN) {
2198		bcopy((char *)&eh->ether_dhost,
2199		    (char *)&tx_frame.wi_addr1, ETHER_ADDR_LEN);
2200#ifdef WI_HOSTAP
2201		if (sc->wi_ptype == WI_PORTTYPE_AP) {
2202			tx_frame.wi_tx_ctl = WI_ENC_TX_MGMT; /* XXX */
2203			tx_frame.wi_frame_ctl |= WI_FCTL_FROMDS;
2204			if (sc->wi_use_wep)
2205				tx_frame.wi_frame_ctl |= WI_FCTL_WEP;
2206			bcopy((char *)&sc->arpcom.ac_enaddr,
2207			      (char *)&tx_frame.wi_addr2, ETHER_ADDR_LEN);
2208			bcopy((char *)&eh->ether_shost,
2209			      (char *)&tx_frame.wi_addr3, ETHER_ADDR_LEN);
2210		}
2211		else
2212#endif
2213			bcopy((char *)&eh->ether_shost,
2214			    (char *)&tx_frame.wi_addr2, ETHER_ADDR_LEN);
2215		bcopy((char *)&eh->ether_dhost,
2216		    (char *)&tx_frame.wi_dst_addr, ETHER_ADDR_LEN);
2217		bcopy((char *)&eh->ether_shost,
2218		    (char *)&tx_frame.wi_src_addr, ETHER_ADDR_LEN);
2219
2220		tx_frame.wi_dat_len = m0->m_pkthdr.len - WI_SNAPHDR_LEN;
2221		tx_frame.wi_dat[0] = htons(WI_SNAP_WORD0);
2222		tx_frame.wi_dat[1] = htons(WI_SNAP_WORD1);
2223		tx_frame.wi_len = htons(m0->m_pkthdr.len - WI_SNAPHDR_LEN);
2224		tx_frame.wi_type = eh->ether_type;
2225
2226#ifdef WI_HOSTAP
2227		if (sc->wi_ptype == WI_PORTTYPE_AP && sc->wi_use_wep) {
2228			/* Do host encryption. */
2229			bcopy(&tx_frame.wi_dat[0], &sc->wi_txbuf[4], 8);
2230			m_copydata(m0, sizeof(struct ether_header),
2231			    m0->m_pkthdr.len - sizeof(struct ether_header),
2232			    (caddr_t)&sc->wi_txbuf[12]);
2233			wi_do_hostencrypt(sc, &sc->wi_txbuf[0],
2234			    tx_frame.wi_dat_len);
2235			tx_frame.wi_dat_len += IEEE80211_WEP_IVLEN +
2236			    IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN;
2237			wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
2238			    sizeof(struct wi_frame));
2239			wi_write_data(sc, id, WI_802_11_OFFSET_RAW,
2240			    (caddr_t)&sc->wi_txbuf, (m0->m_pkthdr.len -
2241			    sizeof(struct ether_header)) + 18);
2242		}
2243		else
2244#endif
2245		{
2246			m_copydata(m0, sizeof(struct ether_header),
2247			    m0->m_pkthdr.len - sizeof(struct ether_header),
2248			    (caddr_t)&sc->wi_txbuf);
2249			wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
2250			    sizeof(struct wi_frame));
2251			wi_write_data(sc, id, WI_802_11_OFFSET,
2252			    (caddr_t)&sc->wi_txbuf, (m0->m_pkthdr.len -
2253			    sizeof(struct ether_header)) + 2);
2254		}
2255	} else {
2256		tx_frame.wi_dat_len = m0->m_pkthdr.len;
2257
2258#ifdef WI_HOSTAP
2259		if (sc->wi_ptype == WI_PORTTYPE_AP && sc->wi_use_wep) {
2260			/* Do host encryption. */
2261			printf( "XXX: host encrypt not implemented for 802.3\n" );
2262		}
2263		else
2264#endif
2265		{
2266			eh->ether_type = htons(m0->m_pkthdr.len -
2267			    WI_SNAPHDR_LEN);
2268			m_copydata(m0, 0, m0->m_pkthdr.len,
2269			    (caddr_t)&sc->wi_txbuf);
2270
2271			wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
2272			    sizeof(struct wi_frame));
2273			wi_write_data(sc, id, WI_802_3_OFFSET,
2274			    (caddr_t)&sc->wi_txbuf, m0->m_pkthdr.len + 2);
2275		}
2276	}
2277
2278	/*
2279	 * If there's a BPF listner, bounce a copy of
2280 	 * this frame to him. Also, don't send this to the bpf sniffer
2281 	 * if we're in procframe or monitor sniffing mode.
2282	 */
2283 	if (!(sc->wi_procframe || sc->wi_debug.wi_monitor) && ifp->if_bpf)
2284		bpf_mtap(ifp, m0);
2285
2286	m_freem(m0);
2287
2288	if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id, 0, 0))
2289		device_printf(sc->dev, "xmit failed\n");
2290
2291	ifp->if_flags |= IFF_OACTIVE;
2292
2293	/*
2294	 * Set a timeout in case the chip goes out to lunch.
2295	 */
2296	ifp->if_timer = 5;
2297
2298	WI_UNLOCK(sc);
2299	return;
2300}
2301
2302int
2303wi_mgmt_xmit(sc, data, len)
2304	struct wi_softc		*sc;
2305	caddr_t			data;
2306	int			len;
2307{
2308	struct wi_frame		tx_frame;
2309	int			id;
2310	struct wi_80211_hdr	*hdr;
2311	caddr_t			dptr;
2312
2313	if (sc->wi_gone)
2314		return(ENODEV);
2315
2316	hdr = (struct wi_80211_hdr *)data;
2317	dptr = data + sizeof(struct wi_80211_hdr);
2318
2319	bzero((char *)&tx_frame, sizeof(tx_frame));
2320	id = sc->wi_tx_mgmt_id;
2321
2322	bcopy((char *)hdr, (char *)&tx_frame.wi_frame_ctl,
2323	   sizeof(struct wi_80211_hdr));
2324
2325	tx_frame.wi_tx_ctl = WI_ENC_TX_MGMT;
2326	tx_frame.wi_dat_len = len - sizeof(struct wi_80211_hdr);
2327	tx_frame.wi_len = htons(tx_frame.wi_dat_len);
2328
2329	wi_write_data(sc, id, 0, (caddr_t)&tx_frame, sizeof(struct wi_frame));
2330	wi_write_data(sc, id, WI_802_11_OFFSET_RAW, dptr,
2331	    len - sizeof(struct wi_80211_hdr) + 2);
2332
2333	if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id, 0, 0)) {
2334		device_printf(sc->dev, "xmit failed\n");
2335		return(EIO);
2336	}
2337
2338	return(0);
2339}
2340
2341static void
2342wi_stop(sc)
2343	struct wi_softc		*sc;
2344{
2345	struct ifnet		*ifp;
2346
2347	WI_LOCK(sc);
2348
2349	if (sc->wi_gone) {
2350		WI_UNLOCK(sc);
2351		return;
2352	}
2353
2354#ifdef WI_HOSTAP
2355	wihap_shutdown(sc);
2356#endif
2357
2358	ifp = &sc->arpcom.ac_if;
2359
2360	/*
2361	 * If the card is gone and the memory port isn't mapped, we will
2362	 * (hopefully) get 0xffff back from the status read, which is not
2363	 * a valid status value.
2364	 */
2365	if (CSR_READ_2(sc, WI_STATUS) != 0xffff) {
2366		CSR_WRITE_2(sc, WI_INT_EN, 0);
2367		wi_cmd(sc, WI_CMD_DISABLE|sc->wi_portnum, 0, 0, 0);
2368	}
2369
2370	untimeout(wi_inquire, sc, sc->wi_stat_ch);
2371
2372	ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE);
2373
2374	WI_UNLOCK(sc);
2375	return;
2376}
2377
2378static void
2379wi_watchdog(ifp)
2380	struct ifnet		*ifp;
2381{
2382	struct wi_softc		*sc;
2383
2384	sc = ifp->if_softc;
2385
2386	device_printf(sc->dev, "watchdog timeout\n");
2387
2388	wi_init(sc);
2389
2390	ifp->if_oerrors++;
2391
2392	return;
2393}
2394
2395int
2396wi_alloc(dev, rid)
2397	device_t		dev;
2398	int			rid;
2399{
2400	struct wi_softc		*sc = device_get_softc(dev);
2401
2402	if (sc->wi_bus_type != WI_BUS_PCI_NATIVE) {
2403		sc->iobase_rid = rid;
2404		sc->iobase = bus_alloc_resource(dev, SYS_RES_IOPORT,
2405		    &sc->iobase_rid, 0, ~0, (1 << 6),
2406		    rman_make_alignment_flags(1 << 6) | RF_ACTIVE);
2407		if (!sc->iobase) {
2408			device_printf(dev, "No I/O space?!\n");
2409			return (ENXIO);
2410		}
2411
2412		sc->wi_io_addr = rman_get_start(sc->iobase);
2413		sc->wi_btag = rman_get_bustag(sc->iobase);
2414		sc->wi_bhandle = rman_get_bushandle(sc->iobase);
2415	} else {
2416		sc->mem_rid = rid;
2417		sc->mem = bus_alloc_resource(dev, SYS_RES_MEMORY,
2418		    &sc->mem_rid, 0, ~0, 1, RF_ACTIVE);
2419
2420		if (!sc->mem) {
2421			device_printf(dev, "No Mem space on prism2.5?\n");
2422			return (ENXIO);
2423		}
2424
2425		sc->wi_btag = rman_get_bustag(sc->mem);
2426		sc->wi_bhandle = rman_get_bushandle(sc->mem);
2427	}
2428
2429
2430	sc->irq_rid = 0;
2431	sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irq_rid,
2432	    0, ~0, 1, RF_ACTIVE |
2433	    ((sc->wi_bus_type == WI_BUS_PCCARD) ? 0 : RF_SHAREABLE));
2434
2435	if (!sc->irq) {
2436		wi_free(dev);
2437		device_printf(dev, "No irq?!\n");
2438		return (ENXIO);
2439	}
2440
2441	sc->dev = dev;
2442	sc->wi_unit = device_get_unit(dev);
2443
2444	return (0);
2445}
2446
2447void
2448wi_free(dev)
2449	device_t		dev;
2450{
2451	struct wi_softc		*sc = device_get_softc(dev);
2452
2453	if (sc->iobase != NULL) {
2454		bus_release_resource(dev, SYS_RES_IOPORT, sc->iobase_rid, sc->iobase);
2455		sc->iobase = NULL;
2456	}
2457	if (sc->irq != NULL) {
2458		bus_release_resource(dev, SYS_RES_IRQ, sc->irq_rid, sc->irq);
2459		sc->irq = NULL;
2460	}
2461	if (sc->mem != NULL) {
2462		bus_release_resource(dev, SYS_RES_MEMORY, sc->mem_rid, sc->mem);
2463		sc->mem = NULL;
2464	}
2465
2466	return;
2467}
2468
2469void
2470wi_shutdown(dev)
2471	device_t		dev;
2472{
2473	struct wi_softc		*sc;
2474
2475	sc = device_get_softc(dev);
2476	wi_stop(sc);
2477
2478	return;
2479}
2480
2481#ifdef WICACHE
2482/* wavelan signal strength cache code.
2483 * store signal/noise/quality on per MAC src basis in
2484 * a small fixed cache.  The cache wraps if > MAX slots
2485 * used.  The cache may be zeroed out to start over.
2486 * Two simple filters exist to reduce computation:
2487 * 1. ip only (literally 0x800) which may be used
2488 * to ignore some packets.  It defaults to ip only.
2489 * it could be used to focus on broadcast, non-IP 802.11 beacons.
2490 * 2. multicast/broadcast only.  This may be used to
2491 * ignore unicast packets and only cache signal strength
2492 * for multicast/broadcast packets (beacons); e.g., Mobile-IP
2493 * beacons and not unicast traffic.
2494 *
2495 * The cache stores (MAC src(index), IP src (major clue), signal,
2496 *	quality, noise)
2497 *
2498 * No apologies for storing IP src here.  It's easy and saves much
2499 * trouble elsewhere.  The cache is assumed to be INET dependent,
2500 * although it need not be.
2501 */
2502
2503#ifdef documentation
2504
2505int wi_sigitems;                                /* number of cached entries */
2506struct wi_sigcache wi_sigcache[MAXWICACHE];  /*  array of cache entries */
2507int wi_nextitem;                                /*  index/# of entries */
2508
2509
2510#endif
2511
2512/* control variables for cache filtering.  Basic idea is
2513 * to reduce cost (e.g., to only Mobile-IP agent beacons
2514 * which are broadcast or multicast).  Still you might
2515 * want to measure signal strength with unicast ping packets
2516 * on a pt. to pt. ant. setup.
2517 */
2518/* set true if you want to limit cache items to broadcast/mcast
2519 * only packets (not unicast).  Useful for mobile-ip beacons which
2520 * are broadcast/multicast at network layer.  Default is all packets
2521 * so ping/unicast will work say with pt. to pt. antennae setup.
2522 */
2523static int wi_cache_mcastonly = 0;
2524SYSCTL_INT(_machdep, OID_AUTO, wi_cache_mcastonly, CTLFLAG_RW,
2525	&wi_cache_mcastonly, 0, "");
2526
2527/* set true if you want to limit cache items to IP packets only
2528*/
2529static int wi_cache_iponly = 1;
2530SYSCTL_INT(_machdep, OID_AUTO, wi_cache_iponly, CTLFLAG_RW,
2531	&wi_cache_iponly, 0, "");
2532
2533/*
2534 * Original comments:
2535 * -----------------
2536 * wi_cache_store, per rx packet store signal
2537 * strength in MAC (src) indexed cache.
2538 *
2539 * follows linux driver in how signal strength is computed.
2540 * In ad hoc mode, we use the rx_quality field.
2541 * signal and noise are trimmed to fit in the range from 47..138.
2542 * rx_quality field MSB is signal strength.
2543 * rx_quality field LSB is noise.
2544 * "quality" is (signal - noise) as is log value.
2545 * note: quality CAN be negative.
2546 *
2547 * In BSS mode, we use the RID for communication quality.
2548 * TBD:  BSS mode is currently untested.
2549 *
2550 * Bill's comments:
2551 * ---------------
2552 * Actually, we use the rx_quality field all the time for both "ad-hoc"
2553 * and BSS modes. Why? Because reading an RID is really, really expensive:
2554 * there's a bunch of PIO operations that have to be done to read a record
2555 * from the NIC, and reading the comms quality RID each time a packet is
2556 * received can really hurt performance. We don't have to do this anyway:
2557 * the comms quality field only reflects the values in the rx_quality field
2558 * anyway. The comms quality RID is only meaningful in infrastructure mode,
2559 * but the values it contains are updated based on the rx_quality from
2560 * frames received from the access point.
2561 *
2562 * Also, according to Lucent, the signal strength and noise level values
2563 * can be converted to dBms by subtracting 149, so I've modified the code
2564 * to do that instead of the scaling it did originally.
2565 */
2566static void
2567wi_cache_store(struct wi_softc *sc, struct ether_header *eh,
2568                     struct mbuf *m, unsigned short rx_quality)
2569{
2570	struct ip *ip = 0;
2571	int i;
2572	static int cache_slot = 0; 	/* use this cache entry */
2573	static int wrapindex = 0;       /* next "free" cache entry */
2574	int sig, noise;
2575	int sawip=0;
2576
2577	/*
2578	 * filters:
2579	 * 1. ip only
2580	 * 2. configurable filter to throw out unicast packets,
2581	 * keep multicast only.
2582	 */
2583
2584	if ((ntohs(eh->ether_type) == ETHERTYPE_IP)) {
2585		sawip = 1;
2586	}
2587
2588	/*
2589	 * filter for ip packets only
2590	*/
2591	if (wi_cache_iponly && !sawip) {
2592		return;
2593	}
2594
2595	/*
2596	 *  filter for broadcast/multicast only
2597	 */
2598	if (wi_cache_mcastonly && ((eh->ether_dhost[0] & 1) == 0)) {
2599		return;
2600	}
2601
2602#ifdef SIGDEBUG
2603	printf("wi%d: q value %x (MSB=0x%x, LSB=0x%x) \n", sc->wi_unit,
2604	    rx_quality & 0xffff, rx_quality >> 8, rx_quality & 0xff);
2605#endif
2606
2607	/*
2608	 *  find the ip header.  we want to store the ip_src
2609	 * address.
2610	 */
2611	if (sawip)
2612		ip = mtod(m, struct ip *);
2613
2614	/*
2615	 * do a linear search for a matching MAC address
2616	 * in the cache table
2617	 * . MAC address is 6 bytes,
2618	 * . var w_nextitem holds total number of entries already cached
2619	 */
2620	for(i = 0; i < sc->wi_nextitem; i++) {
2621		if (! bcmp(eh->ether_shost , sc->wi_sigcache[i].macsrc,  6 )) {
2622			/*
2623			 * Match!,
2624			 * so we already have this entry,
2625			 * update the data
2626			 */
2627			break;
2628		}
2629	}
2630
2631	/*
2632	 *  did we find a matching mac address?
2633	 * if yes, then overwrite a previously existing cache entry
2634	 */
2635	if (i < sc->wi_nextitem )   {
2636		cache_slot = i;
2637	}
2638	/*
2639	 * else, have a new address entry,so
2640	 * add this new entry,
2641	 * if table full, then we need to replace LRU entry
2642	 */
2643	else    {
2644
2645		/*
2646		 * check for space in cache table
2647		 * note: wi_nextitem also holds number of entries
2648		 * added in the cache table
2649		 */
2650		if ( sc->wi_nextitem < MAXWICACHE ) {
2651			cache_slot = sc->wi_nextitem;
2652			sc->wi_nextitem++;
2653			sc->wi_sigitems = sc->wi_nextitem;
2654		}
2655        	/* no space found, so simply wrap with wrap index
2656		 * and "zap" the next entry
2657		 */
2658		else {
2659			if (wrapindex == MAXWICACHE) {
2660				wrapindex = 0;
2661			}
2662			cache_slot = wrapindex++;
2663		}
2664	}
2665
2666	/*
2667	 * invariant: cache_slot now points at some slot
2668	 * in cache.
2669	 */
2670	if (cache_slot < 0 || cache_slot >= MAXWICACHE) {
2671		log(LOG_ERR, "wi_cache_store, bad index: %d of "
2672		    "[0..%d], gross cache error\n",
2673		    cache_slot, MAXWICACHE);
2674		return;
2675	}
2676
2677	/*
2678	 *  store items in cache
2679	 *  .ip source address
2680	 *  .mac src
2681	 *  .signal, etc.
2682	 */
2683	if (sawip)
2684		sc->wi_sigcache[cache_slot].ipsrc = ip->ip_src.s_addr;
2685	bcopy( eh->ether_shost, sc->wi_sigcache[cache_slot].macsrc,  6);
2686
2687	sig = (rx_quality >> 8) & 0xFF;
2688	noise = rx_quality & 0xFF;
2689	sc->wi_sigcache[cache_slot].signal = sig - 149;
2690	sc->wi_sigcache[cache_slot].noise = noise - 149;
2691	sc->wi_sigcache[cache_slot].quality = sig - noise;
2692
2693	return;
2694}
2695#endif
2696
2697static int
2698wi_get_cur_ssid(sc, ssid, len)
2699	struct wi_softc		*sc;
2700	char			*ssid;
2701	int			*len;
2702{
2703	int			error = 0;
2704	struct wi_req		wreq;
2705
2706	wreq.wi_len = WI_MAX_DATALEN;
2707	switch (sc->wi_ptype) {
2708#ifdef WI_HOSTAP
2709	case WI_PORTTYPE_AP:
2710		*len = IEEE80211_NWID_LEN;
2711		bcopy(sc->wi_net_name, ssid, IEEE80211_NWID_LEN);
2712		break;
2713#endif
2714	case WI_PORTTYPE_ADHOC:
2715		wreq.wi_type = WI_RID_CURRENT_SSID;
2716		error = wi_read_record(sc, (struct wi_ltv_gen *)&wreq);
2717		if (error != 0)
2718			break;
2719		if (wreq.wi_val[0] > IEEE80211_NWID_LEN) {
2720			error = EINVAL;
2721			break;
2722		}
2723		*len = wreq.wi_val[0];
2724		bcopy(&wreq.wi_val[1], ssid, IEEE80211_NWID_LEN);
2725		break;
2726	case WI_PORTTYPE_BSS:
2727		wreq.wi_type = WI_RID_COMMQUAL;
2728		error = wi_read_record(sc, (struct wi_ltv_gen *)&wreq);
2729		if (error != 0)
2730			break;
2731		if (wreq.wi_val[0] != 0) /* associated */ {
2732			wreq.wi_type = WI_RID_CURRENT_SSID;
2733			wreq.wi_len = WI_MAX_DATALEN;
2734			error = wi_read_record(sc, (struct wi_ltv_gen *)&wreq);
2735			if (error != 0)
2736				break;
2737			if (wreq.wi_val[0] > IEEE80211_NWID_LEN) {
2738				error = EINVAL;
2739				break;
2740			}
2741			*len = wreq.wi_val[0];
2742			bcopy(&wreq.wi_val[1], ssid, IEEE80211_NWID_LEN);
2743		} else {
2744			*len = IEEE80211_NWID_LEN;
2745			bcopy(sc->wi_net_name, ssid, IEEE80211_NWID_LEN);
2746		}
2747		break;
2748	default:
2749		error = EINVAL;
2750		break;
2751	}
2752
2753	return error;
2754}
2755
2756static int
2757wi_media_change(ifp)
2758	struct ifnet		*ifp;
2759{
2760	struct wi_softc		*sc = ifp->if_softc;
2761	int			otype = sc->wi_ptype;
2762	int			orate = sc->wi_tx_rate;
2763
2764	if ((sc->ifmedia.ifm_cur->ifm_media & IFM_IEEE80211_ADHOC) != 0)
2765		sc->wi_ptype = WI_PORTTYPE_ADHOC;
2766#if defined(WI_HOSTAP) && defined(IFM_IEEE80211_HOSTAP)
2767	else if ((sc->ifmedia.ifm_cur->ifm_media & IFM_IEEE80211_HOSTAP) != 0)
2768		sc->wi_ptype = WI_PORTTYPE_AP;
2769#endif
2770	else
2771		sc->wi_ptype = WI_PORTTYPE_BSS;
2772
2773	switch (IFM_SUBTYPE(sc->ifmedia.ifm_cur->ifm_media)) {
2774	case IFM_IEEE80211_DS1:
2775		sc->wi_tx_rate = 1;
2776		break;
2777	case IFM_IEEE80211_DS2:
2778		sc->wi_tx_rate = 2;
2779		break;
2780	case IFM_IEEE80211_DS5:
2781		sc->wi_tx_rate = 5;
2782		break;
2783	case IFM_IEEE80211_DS11:
2784		sc->wi_tx_rate = 11;
2785		break;
2786	case IFM_AUTO:
2787		sc->wi_tx_rate = 3;
2788		break;
2789	}
2790
2791	if (otype != sc->wi_ptype ||
2792	    orate != sc->wi_tx_rate)
2793		wi_init(sc);
2794
2795	return(0);
2796}
2797
2798static void
2799wi_media_status(ifp, imr)
2800	struct ifnet		*ifp;
2801	struct ifmediareq	*imr;
2802{
2803	struct wi_req		wreq;
2804	struct wi_softc		*sc = ifp->if_softc;
2805
2806	if (sc->wi_tx_rate == 3) {
2807		imr->ifm_active = IFM_IEEE80211|IFM_AUTO;
2808		if (sc->wi_ptype == WI_PORTTYPE_ADHOC)
2809			imr->ifm_active |= IFM_IEEE80211_ADHOC;
2810#if defined(WI_HOSTAP) && defined(IFM_IEEE80211_HOSTAP)
2811		else if (sc->wi_ptype == WI_PORTTYPE_AP)
2812			imr->ifm_active |= IFM_IEEE80211_HOSTAP;
2813#endif
2814		wreq.wi_type = WI_RID_CUR_TX_RATE;
2815		wreq.wi_len = WI_MAX_DATALEN;
2816		if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq) == 0) {
2817			switch(wreq.wi_val[0]) {
2818			case 1:
2819				imr->ifm_active |= IFM_IEEE80211_DS1;
2820				break;
2821			case 2:
2822				imr->ifm_active |= IFM_IEEE80211_DS2;
2823				break;
2824			case 6:
2825				imr->ifm_active |= IFM_IEEE80211_DS5;
2826				break;
2827			case 11:
2828				imr->ifm_active |= IFM_IEEE80211_DS11;
2829				break;
2830				}
2831		}
2832	} else {
2833		imr->ifm_active = sc->ifmedia.ifm_cur->ifm_media;
2834	}
2835
2836	imr->ifm_status = IFM_AVALID;
2837	if (sc->wi_ptype == WI_PORTTYPE_ADHOC)
2838		/*
2839		 * XXX: It would be nice if we could give some actually
2840		 * useful status like whether we joined another IBSS or
2841		 * created one ourselves.
2842		 */
2843		imr->ifm_status |= IFM_ACTIVE;
2844#ifdef WI_HOSTAP
2845	else if (sc->wi_ptype == WI_PORTTYPE_AP)
2846		imr->ifm_status |= IFM_ACTIVE;
2847#endif
2848	else {
2849		wreq.wi_type = WI_RID_COMMQUAL;
2850		wreq.wi_len = WI_MAX_DATALEN;
2851		if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq) == 0 &&
2852		    wreq.wi_val[0] != 0)
2853			imr->ifm_status |= IFM_ACTIVE;
2854	}
2855}
2856
2857static int
2858wi_get_debug(sc, wreq)
2859	struct wi_softc		*sc;
2860	struct wi_req		*wreq;
2861{
2862	int			error = 0;
2863
2864	wreq->wi_len = 1;
2865
2866	switch (wreq->wi_type) {
2867	case WI_DEBUG_SLEEP:
2868		wreq->wi_len++;
2869		wreq->wi_val[0] = sc->wi_debug.wi_sleep;
2870		break;
2871	case WI_DEBUG_DELAYSUPP:
2872		wreq->wi_len++;
2873		wreq->wi_val[0] = sc->wi_debug.wi_delaysupp;
2874		break;
2875	case WI_DEBUG_TXSUPP:
2876		wreq->wi_len++;
2877		wreq->wi_val[0] = sc->wi_debug.wi_txsupp;
2878		break;
2879	case WI_DEBUG_MONITOR:
2880		wreq->wi_len++;
2881		wreq->wi_val[0] = sc->wi_debug.wi_monitor;
2882		break;
2883	case WI_DEBUG_LEDTEST:
2884		wreq->wi_len += 3;
2885		wreq->wi_val[0] = sc->wi_debug.wi_ledtest;
2886		wreq->wi_val[1] = sc->wi_debug.wi_ledtest_param0;
2887		wreq->wi_val[2] = sc->wi_debug.wi_ledtest_param1;
2888		break;
2889	case WI_DEBUG_CONTTX:
2890		wreq->wi_len += 2;
2891		wreq->wi_val[0] = sc->wi_debug.wi_conttx;
2892		wreq->wi_val[1] = sc->wi_debug.wi_conttx_param0;
2893		break;
2894	case WI_DEBUG_CONTRX:
2895		wreq->wi_len++;
2896		wreq->wi_val[0] = sc->wi_debug.wi_contrx;
2897		break;
2898	case WI_DEBUG_SIGSTATE:
2899		wreq->wi_len += 2;
2900		wreq->wi_val[0] = sc->wi_debug.wi_sigstate;
2901		wreq->wi_val[1] = sc->wi_debug.wi_sigstate_param0;
2902		break;
2903	case WI_DEBUG_CONFBITS:
2904		wreq->wi_len += 2;
2905		wreq->wi_val[0] = sc->wi_debug.wi_confbits;
2906		wreq->wi_val[1] = sc->wi_debug.wi_confbits_param0;
2907		break;
2908	default:
2909		error = EIO;
2910		break;
2911	}
2912
2913	return (error);
2914}
2915
2916static int
2917wi_set_debug(sc, wreq)
2918	struct wi_softc		*sc;
2919	struct wi_req		*wreq;
2920{
2921	int			error = 0;
2922	u_int16_t		cmd, param0 = 0, param1 = 0;
2923
2924	switch (wreq->wi_type) {
2925	case WI_DEBUG_RESET:
2926	case WI_DEBUG_INIT:
2927	case WI_DEBUG_CALENABLE:
2928		break;
2929	case WI_DEBUG_SLEEP:
2930		sc->wi_debug.wi_sleep = 1;
2931		break;
2932	case WI_DEBUG_WAKE:
2933		sc->wi_debug.wi_sleep = 0;
2934		break;
2935	case WI_DEBUG_CHAN:
2936		param0 = wreq->wi_val[0];
2937		break;
2938	case WI_DEBUG_DELAYSUPP:
2939		sc->wi_debug.wi_delaysupp = 1;
2940		break;
2941	case WI_DEBUG_TXSUPP:
2942		sc->wi_debug.wi_txsupp = 1;
2943		break;
2944	case WI_DEBUG_MONITOR:
2945		sc->wi_debug.wi_monitor = 1;
2946		break;
2947	case WI_DEBUG_LEDTEST:
2948		param0 = wreq->wi_val[0];
2949		param1 = wreq->wi_val[1];
2950		sc->wi_debug.wi_ledtest = 1;
2951		sc->wi_debug.wi_ledtest_param0 = param0;
2952		sc->wi_debug.wi_ledtest_param1 = param1;
2953		break;
2954	case WI_DEBUG_CONTTX:
2955		param0 = wreq->wi_val[0];
2956		sc->wi_debug.wi_conttx = 1;
2957		sc->wi_debug.wi_conttx_param0 = param0;
2958		break;
2959	case WI_DEBUG_STOPTEST:
2960		sc->wi_debug.wi_delaysupp = 0;
2961		sc->wi_debug.wi_txsupp = 0;
2962		sc->wi_debug.wi_monitor = 0;
2963		sc->wi_debug.wi_ledtest = 0;
2964		sc->wi_debug.wi_ledtest_param0 = 0;
2965		sc->wi_debug.wi_ledtest_param1 = 0;
2966		sc->wi_debug.wi_conttx = 0;
2967		sc->wi_debug.wi_conttx_param0 = 0;
2968		sc->wi_debug.wi_contrx = 0;
2969		sc->wi_debug.wi_sigstate = 0;
2970		sc->wi_debug.wi_sigstate_param0 = 0;
2971		break;
2972	case WI_DEBUG_CONTRX:
2973		sc->wi_debug.wi_contrx = 1;
2974		break;
2975	case WI_DEBUG_SIGSTATE:
2976		param0 = wreq->wi_val[0];
2977		sc->wi_debug.wi_sigstate = 1;
2978		sc->wi_debug.wi_sigstate_param0 = param0;
2979		break;
2980	case WI_DEBUG_CONFBITS:
2981		param0 = wreq->wi_val[0];
2982		param1 = wreq->wi_val[1];
2983		sc->wi_debug.wi_confbits = param0;
2984		sc->wi_debug.wi_confbits_param0 = param1;
2985		break;
2986	default:
2987		error = EIO;
2988		break;
2989	}
2990
2991	if (error)
2992		return (error);
2993
2994	cmd = WI_CMD_DEBUG | (wreq->wi_type << 8);
2995	error = wi_cmd(sc, cmd, param0, param1, 0);
2996
2997	return (error);
2998}
2999