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